2003-05-28 Jeff Johnston <jjohnstn@redhat.com>
Tom Fitzsimmons <fitzsim@redhat.com> * configure.in: Add iconvdata support for x86 linux. * configure: Regenerated. * libc/sys/linux/Makefile.am: Add EL/IX level 3 network, dynamic library, iconv, and linuxthreads support. * libc/sys/linux/configure.in: Ditto. * libc/sys/linux/Makefile.in: Regenerated. * libc/sys/linux/configure: Ditto. * iconvdata/EUC-JP.irreversible: New file. * iconvdata/Makefile.am: Ditto. * iconvdata/Makefile.in: Ditto. * iconvdata/SJIS.irreversible: Ditto. * iconvdata/aclocal.m4: Ditto. * iconvdata/configure: Ditto. * iconvdata/configure.in: Ditto. * iconvdata/dummy.c: Ditto. * iconvdata/euc-jp.c: Ditto. * iconvdata/gconv-modules: Ditto. * iconvdata/jis0201.c: Ditto. * iconvdata/jis0201.h: Ditto. * iconvdata/jis0208.c: Ditto. * iconvdata/jis0208.h: Ditto. * iconvdata/jis0212.c: Ditto. * iconvdata/jis0212.h: Ditto. * iconvdata/sjis.c: Ditto. * libc/include/errno.h: Protect definition of error_t. * libc/sys/linux/gethostid.c: New file. * libc/sys/linux/sethostid.c: Ditto. * libc/sys/linux/dl/Makefile.am: Ditto. * libc/sys/linux/dl/Makefile.in: Ditto. * libc/sys/linux/dl/abi-tag.h: Ditto. * libc/sys/linux/dl/atomicity.h: Ditto. * libc/sys/linux/dl/dl-addr.c: Ditto. * libc/sys/linux/dl/dl-cache.c: Ditto. * libc/sys/linux/dl/dl-cache.h: Ditto. * libc/sys/linux/dl/dl-close.c: Ditto. * libc/sys/linux/dl/dl-debug.c: Ditto. * libc/sys/linux/dl/dl-deps.c: Ditto. * libc/sys/linux/dl/dl-dst.h: Ditto. * libc/sys/linux/dl/dl-error.c: Ditto. * libc/sys/linux/dl/dl-fini.c: Ditto. * libc/sys/linux/dl/dl-init.c: Ditto. * libc/sys/linux/dl/dl-iteratephdr.c: Ditto. * libc/sys/linux/dl/dl-libc.c: Ditto. * libc/sys/linux/dl/dl-librecon.h: Ditto. * libc/sys/linux/dl/dl-load.c: Ditto. * libc/sys/linux/dl/dl-lookup.c: Ditto. * libc/sys/linux/dl/dl-lookupcfg.h: Ditto. * libc/sys/linux/dl/dl-minimal.c: Ditto. * libc/sys/linux/dl/dl-misc.c: Ditto. * libc/sys/linux/dl/dl-object.c: Ditto. * libc/sys/linux/dl/dl-open.c: Ditto. * libc/sys/linux/dl/dl-osinfo.h: Ditto. * libc/sys/linux/dl/dl-profile.c: Ditto. * libc/sys/linux/dl/dl-profstub.c: Ditto. * libc/sys/linux/dl/dl-reloc.c: Ditto. * libc/sys/linux/dl/dl-runtime.c: Ditto. * libc/sys/linux/dl/dl-support.c: Ditto. * libc/sys/linux/dl/dl-sym.c: Ditto. * libc/sys/linux/dl/dl-version.c: Ditto. * libc/sys/linux/dl/dlfcn.h: Ditto. * libc/sys/linux/dl/do-lookup.h: Ditto. * libc/sys/linux/dl/do-rel.h: Ditto. * libc/sys/linux/dl/dynamic-link.h: Ditto. * libc/sys/linux/dl/kernel-features.h: Ditto. * libc/sys/linux/dl/ldsodefs.h: Ditto. * libc/sys/linux/dl/libintl.h: Ditto. * libc/sys/linux/dl/trusted-dirs.h: Ditto. * libc/sys/linux/dl/unsecvars.h: Ditto. * libc/sys/linux/iconv/Makefile.am: Ditto. * libc/sys/linux/iconv/Makefile.in: Ditto. * libc/sys/linux/iconv/categories.def: Ditto. * libc/sys/linux/iconv/dummy-repertoire.c: Ditto. * libc/sys/linux/iconv/gconv.c: Ditto. * libc/sys/linux/iconv/gconv_builtin.c: Ditto. * libc/sys/linux/iconv/gconv_builtin.h: Ditto. * libc/sys/linux/iconv/gconv_cache.c: Ditto. * libc/sys/linux/iconv/gconv_charset.h: Ditto. * libc/sys/linux/iconv/gconv_close.c: Ditto. * libc/sys/linux/iconv/gconv_conf.c: Ditto. * libc/sys/linux/iconv/gconv_db.c: Ditto. * libc/sys/linux/iconv/gconv_dl.c: Ditto. * libc/sys/linux/iconv/gconv_int.h: Ditto. * libc/sys/linux/iconv/gconv_open.c: Ditto. * libc/sys/linux/iconv/gconv_simple.c: Ditto. * libc/sys/linux/iconv/gconv_trans.c: Ditto. * libc/sys/linux/iconv/hash-string.h: Ditto. * libc/sys/linux/iconv/iconv.c: Ditto. * libc/sys/linux/iconv/iconv.h: Ditto. * libc/sys/linux/iconv/iconv_charmap.c: Ditto. * libc/sys/linux/iconv/iconv_close.c: Ditto. * libc/sys/linux/iconv/iconv_open.c: Ditto. * libc/sys/linux/iconv/iconvconfig.c: Ditto. * libc/sys/linux/iconv/iconvconfig.h: Ditto. * libc/sys/linux/iconv/loadinfo.h: Ditto. * libc/sys/linux/iconv/localeinfo.h: Ditto. * libc/sys/linux/iconv/loop.c: Ditto. * libc/sys/linux/iconv/skeleton.c: Ditto. * libc/sys/linux/iconv/strtab.c: Ditto. * libc/sys/linux/include/dl-hash.h: Ditto. * libc/sys/linux/include/dlfcn.h: Ditto. * libc/sys/linux/include/fnmatch.h: Ditto. * libc/sys/linux/include/gconv.h: Ditto. * libc/sys/linux/include/glob.h: Ditto. * libc/sys/linux/include/hesiod.h: Ditto. * libc/sys/linux/include/ifaddrs.h: Ditto. * libc/sys/linux/include/libc_private.h: Ditto. * libc/sys/linux/include/link.h: Ditto. * libc/sys/linux/include/namespace.h: Ditto. * libc/sys/linux/include/netconfig.h: Ditto. * libc/sys/linux/include/netdb.h: Ditto. * libc/sys/linux/include/nsswitch.h: Ditto. * libc/sys/linux/include/regex.h: Ditto. * libc/sys/linux/include/resolv.h: Ditto. * libc/sys/linux/include/rune.h: Ditto. * libc/sys/linux/include/runetype.h: Ditto. * libc/sys/linux/include/semaphore.h: Ditto. * libc/sys/linux/include/setlocale.h: Ditto. * libc/sys/linux/include/un-namespace.h: Ditto. * libc/sys/linux/include/wordexp.h: Ditto. * libc/sys/linux/include/arpa/ftp.h: Ditto. * libc/sys/linux/include/arpa/inet.h: Ditto. * libc/sys/linux/include/arpa/nameser.h: Ditto. * libc/sys/linux/include/arpa/nameser_compat.h: Ditto. * libc/sys/linux/include/arpa/telnet.h: Ditto. * libc/sys/linux/include/arpa/tftp.h: Ditto. * libc/sys/linux/include/net/bpf.h: Ditto. * libc/sys/linux/include/net/bpf_compat.h: Ditto. * libc/sys/linux/include/net/bpfdesc.h: Ditto. * libc/sys/linux/include/net/bridge.h: Ditto. * libc/sys/linux/include/net/ethernet.h: Ditto. * libc/sys/linux/include/net/fddi.h: Ditto. * libc/sys/linux/include/net/if.h: Ditto. * libc/sys/linux/include/net/if_arc.h: Ditto. * libc/sys/linux/include/net/if_arp.h: Ditto. * libc/sys/linux/include/net/if_atm.h: Ditto. * libc/sys/linux/include/net/if_dl.h: Ditto. * libc/sys/linux/include/net/if_gif.h: Ditto. * libc/sys/linux/include/net/if_ieee80211.h: Ditto. * libc/sys/linux/include/net/if_llc.h: Ditto. * libc/sys/linux/include/net/if_media.h: Ditto. * libc/sys/linux/include/net/if_mib.h: Ditto. * libc/sys/linux/include/net/if_ppp.h: Ditto. * libc/sys/linux/include/net/if_pppvar.h: Ditto. * libc/sys/linux/include/net/if_slvar.h: Ditto. * libc/sys/linux/include/net/if_sppp.h: Ditto. * libc/sys/linux/include/net/if_stf.h: Ditto. * libc/sys/linux/include/net/if_tap.h: Ditto. * libc/sys/linux/include/net/if_tapvar.h: Ditto. * libc/sys/linux/include/net/if_tun.h: Ditto. * libc/sys/linux/include/net/if_tunvar.h: Ditto. * libc/sys/linux/include/net/if_types.h: Ditto. * libc/sys/linux/include/net/if_var.h: Ditto. * libc/sys/linux/include/net/if_vlan_var.h: Ditto. * libc/sys/linux/include/net/intrq.h: Ditto. * libc/sys/linux/include/net/iso88025.h: Ditto. * libc/sys/linux/include/net/net_osdep.h: Ditto. * libc/sys/linux/include/net/netisr.h: Ditto. * libc/sys/linux/include/net/pfil.h: Ditto. * libc/sys/linux/include/net/pfkeyv2.h: Ditto. * libc/sys/linux/include/net/ppp_comp.h: Ditto. * libc/sys/linux/include/net/ppp_defs.h: Ditto. * libc/sys/linux/include/net/radix.h: Ditto. * libc/sys/linux/include/net/raw_cb.h: Ditto. * libc/sys/linux/include/net/route.h: Ditto. * libc/sys/linux/include/net/slcompress.h: Ditto. * libc/sys/linux/include/net/slip.h: Ditto. * libc/sys/linux/include/net/zlib.h: Ditto. * libc/sys/linux/include/netinet/icmp6.h: Ditto. * libc/sys/linux/include/netinet/icmp_var.h: Ditto. * libc/sys/linux/include/netinet/if_atm.h: Ditto. * libc/sys/linux/include/netinet/if_ether.h: Ditto. * libc/sys/linux/include/netinet/igmp.h: Ditto. * libc/sys/linux/include/netinet/igmp_var.h: Ditto. * libc/sys/linux/include/netinet/in.h: Ditto. * libc/sys/linux/include/netinet/in_gif.h: Ditto. * libc/sys/linux/include/netinet/in_pcb.h: Ditto. * libc/sys/linux/include/netinet/in_systm.h: Ditto. * libc/sys/linux/include/netinet/in_var.h: Ditto. * libc/sys/linux/include/netinet/ip.h: Ditto. * libc/sys/linux/include/netinet/ip6.h: Ditto. * libc/sys/linux/include/netinet/ip_dummynet.h: Ditto. * libc/sys/linux/include/netinet/ip_ecn.h: Ditto. * libc/sys/linux/include/netinet/ip_encap.h: Ditto. * libc/sys/linux/include/netinet/ip_flow.h: Ditto. * libc/sys/linux/include/netinet/ip_fw.h: Ditto. * libc/sys/linux/include/netinet/ip_icmp.h: Ditto. * libc/sys/linux/include/netinet/ip_mroute.h: Ditto. * libc/sys/linux/include/netinet/ip_var.h: Ditto. * libc/sys/linux/include/netinet/ipprotosw.h: Ditto. * libc/sys/linux/include/netinet/tcp.h: Ditto. * libc/sys/linux/include/netinet/tcp_debug.h: Ditto. * libc/sys/linux/include/netinet/tcp_fsm.h: Ditto. * libc/sys/linux/include/netinet/tcp_seq.h: Ditto. * libc/sys/linux/include/netinet/tcp_timer.h: Ditto. * libc/sys/linux/include/netinet/tcp_var.h: Ditto. * libc/sys/linux/include/netinet/tcpip.h: Ditto. * libc/sys/linux/include/netinet/udp.h: Ditto. * libc/sys/linux/include/netinet/udp_var.h: Ditto. * libc/sys/linux/include/netinet6/ah.h: Ditto. * libc/sys/linux/include/netinet6/ah6.h: Ditto. * libc/sys/linux/include/netinet6/esp.h: Ditto. * libc/sys/linux/include/netinet6/esp6.h: Ditto. * libc/sys/linux/include/netinet6/esp_rijndael.h: Ditto. * libc/sys/linux/include/netinet6/icmp6.h: Ditto. * libc/sys/linux/include/netinet6/in6.h: Ditto. * libc/sys/linux/include/netinet6/in6_gif.h: Ditto. * libc/sys/linux/include/netinet6/in6_ifattach.h: Ditto. * libc/sys/linux/include/netinet6/in6_pcb.h: Ditto. * libc/sys/linux/include/netinet6/in6_prefix.h: Ditto. * libc/sys/linux/include/netinet6/in6_var.h: Ditto. * libc/sys/linux/include/netinet6/ip6.h: Ditto. * libc/sys/linux/include/netinet6/ip6_ecn.h: Ditto. * libc/sys/linux/include/netinet6/ip6_fw.h: Ditto. * libc/sys/linux/include/netinet6/ip6_mroute.h: Ditto. * libc/sys/linux/include/netinet6/ip6_var.h: Ditto. * libc/sys/linux/include/netinet6/ip6protosw.h: Ditto. * libc/sys/linux/include/netinet6/ipcomp.h: Ditto. * libc/sys/linux/include/netinet6/ipcomp6.h: Ditto. * libc/sys/linux/include/netinet6/ipsec.h: Ditto. * libc/sys/linux/include/netinet6/ipsec6.h: Ditto. * libc/sys/linux/include/netinet6/mld6_var.h: Ditto. * libc/sys/linux/include/netinet6/nd6.h: Ditto. * libc/sys/linux/include/netinet6/pim6.h: Ditto. * libc/sys/linux/include/netinet6/pim6_var.h: Ditto. * libc/sys/linux/include/netinet6/raw_ip6.h: Ditto. * libc/sys/linux/include/netinet6/scope6_var.h: Ditto. * libc/sys/linux/include/netinet6/tcp6_var.h: Ditto. * libc/sys/linux/include/netinet6/udp6_var.h: Ditto. * libc/sys/linux/include/netns/idp.h: Ditto. * libc/sys/linux/include/netns/idp_var.h: Ditto. * libc/sys/linux/include/netns/ns.h: Ditto. * libc/sys/linux/include/netns/ns_error.h: Ditto. * libc/sys/linux/include/netns/ns_if.h: Ditto. * libc/sys/linux/include/netns/ns_pcb.h: Ditto. * libc/sys/linux/include/netns/sp.h: Ditto. * libc/sys/linux/include/netns/spidp.h: Ditto. * libc/sys/linux/include/netns/spp_debug.h: Ditto. * libc/sys/linux/include/netns/spp_timer.h: Ditto. * libc/sys/linux/include/netns/spp_var.h: Ditto. * libc/sys/linux/include/rpc/Makefile: Ditto. * libc/sys/linux/include/rpc/auth.h: Ditto. * libc/sys/linux/include/rpc/auth_des.h: Ditto. * libc/sys/linux/include/rpc/auth_kerb.h: Ditto. * libc/sys/linux/include/rpc/auth_unix.h: Ditto. * libc/sys/linux/include/rpc/clnt.h: Ditto. * libc/sys/linux/include/rpc/clnt_soc.h: Ditto. * libc/sys/linux/include/rpc/clnt_stat.h: Ditto. * libc/sys/linux/include/rpc/des.h: Ditto. * libc/sys/linux/include/rpc/des_crypt.h: Ditto. * libc/sys/linux/include/rpc/nettype.h: Ditto. * libc/sys/linux/include/rpc/pmap_clnt.h: Ditto. * libc/sys/linux/include/rpc/pmap_prot.h: Ditto. * libc/sys/linux/include/rpc/pmap_rmt.h: Ditto. * libc/sys/linux/include/rpc/raw.h: Ditto. * libc/sys/linux/include/rpc/rpc.h: Ditto. * libc/sys/linux/include/rpc/rpc_com.h: Ditto. * libc/sys/linux/include/rpc/rpc_msg.h: Ditto. * libc/sys/linux/include/rpc/rpcb_clnt.h: Ditto. * libc/sys/linux/include/rpc/rpcb_prot.h: Ditto. * libc/sys/linux/include/rpc/rpcb_prot.x: Ditto. * libc/sys/linux/include/rpc/rpcent.h: Ditto. * libc/sys/linux/include/rpc/svc.h: Ditto. * libc/sys/linux/include/rpc/svc_auth.h: Ditto. * libc/sys/linux/include/rpc/svc_dg.h: Ditto. * libc/sys/linux/include/rpc/svc_soc.h: Ditto. * libc/sys/linux/include/rpc/types.h: Ditto. * libc/sys/linux/include/rpc/xdr.h: Ditto. * libc/sys/linux/intl/Makefile.am: Ditto. * libc/sys/linux/intl/Makefile.in: Ditto. * libc/sys/linux/intl/bindtextdom.c: Ditto. * libc/sys/linux/intl/catgets.c: Ditto. * libc/sys/linux/intl/catgetsinfo.h: Ditto. * libc/sys/linux/intl/config.h: Ditto. * libc/sys/linux/intl/dcgettext.c: Ditto. * libc/sys/linux/intl/dcigettext.c: Ditto. * libc/sys/linux/intl/dcngettext.c: Ditto. * libc/sys/linux/intl/dgettext.c: Ditto. * libc/sys/linux/intl/dngettext.c: Ditto. * libc/sys/linux/intl/explodename.c: Ditto. * libc/sys/linux/intl/finddomain.c: Ditto. * libc/sys/linux/intl/gettext.c: Ditto. * libc/sys/linux/intl/gettext.h: Ditto. * libc/sys/linux/intl/gettextP.h: Ditto. * libc/sys/linux/intl/hash-string.h: Ditto. * libc/sys/linux/intl/l10nflist.c: Ditto. * libc/sys/linux/intl/loadinfo.h: Ditto. * libc/sys/linux/intl/loadmsgcat.c: Ditto. * libc/sys/linux/intl/locale.alias: Ditto. * libc/sys/linux/intl/localealias.c: Ditto. * libc/sys/linux/intl/ngettext.c: Ditto. * libc/sys/linux/intl/open_catalog.c: Ditto. * libc/sys/linux/intl/plural.c: Ditto. * libc/sys/linux/intl/plural.y: Ditto. * libc/sys/linux/intl/stpcpy.c: Ditto. * libc/sys/linux/intl/textdomain.c: Ditto. * libc/sys/linux/linuxthreads/LICENSE: Ditto. * libc/sys/linux/linuxthreads/Makefile.am: Ditto. * libc/sys/linux/linuxthreads/Makefile.in: Ditto. * libc/sys/linux/linuxthreads/aclocal.m4: Ditto. * libc/sys/linux/linuxthreads/attr.c: Ditto. * libc/sys/linux/linuxthreads/barrier.c: Ditto. * libc/sys/linux/linuxthreads/bp-sym.h: Ditto. * libc/sys/linux/linuxthreads/cancel.c: Ditto. * libc/sys/linux/linuxthreads/condvar.c: Ditto. * libc/sys/linux/linuxthreads/config.h: Ditto. * libc/sys/linux/linuxthreads/configure: Ditto. * libc/sys/linux/linuxthreads/configure.in: Ditto. * libc/sys/linux/linuxthreads/defs.awk: Ditto. * libc/sys/linux/linuxthreads/ecmutex.c: Ditto. * libc/sys/linux/linuxthreads/events.c: Ditto. * libc/sys/linux/linuxthreads/getcpuclockid.c: Ditto. * libc/sys/linux/linuxthreads/getreent.c: Ditto. * libc/sys/linux/linuxthreads/internals.h: Ditto. * libc/sys/linux/linuxthreads/join.c: Ditto. * libc/sys/linux/linuxthreads/joinrace.c: Ditto. * libc/sys/linux/linuxthreads/kernel-features.h: Ditto. * libc/sys/linux/linuxthreads/libc-internal.h: Ditto. * libc/sys/linux/linuxthreads/libc-symbols.h: Ditto. * libc/sys/linux/linuxthreads/linuxthreads.texi: Ditto. * libc/sys/linux/linuxthreads/lockfile.c: Ditto. * libc/sys/linux/linuxthreads/manager.c: Ditto. * libc/sys/linux/linuxthreads/mq_notify.c: Ditto. * libc/sys/linux/linuxthreads/mutex.c: Ditto. * libc/sys/linux/linuxthreads/no-tsd.c: Ditto. * libc/sys/linux/linuxthreads/oldsemaphore.c: Ditto. * libc/sys/linux/linuxthreads/posix-timer.h: Ditto. * libc/sys/linux/linuxthreads/prio.c: Ditto. * libc/sys/linux/linuxthreads/proc_service.h: Ditto. * libc/sys/linux/linuxthreads/pt-machine.c: Ditto. * libc/sys/linux/linuxthreads/ptclock_gettime.c: Ditto. * libc/sys/linux/linuxthreads/ptclock_settime.c: Ditto. * libc/sys/linux/linuxthreads/ptfork.c: Ditto. * libc/sys/linux/linuxthreads/pthread.c: Ditto. * libc/sys/linux/linuxthreads/ptlongjmp.c: Ditto. * libc/sys/linux/linuxthreads/queue.h: Ditto. * libc/sys/linux/linuxthreads/reent.c: Ditto. * libc/sys/linux/linuxthreads/reqsyscalls.c: Ditto. * libc/sys/linux/linuxthreads/restart.h: Ditto. * libc/sys/linux/linuxthreads/rwlock.c: Ditto. * libc/sys/linux/linuxthreads/semaphore.c: Ditto. * libc/sys/linux/linuxthreads/semaphore.h: Ditto. * libc/sys/linux/linuxthreads/shlib-compat.h: Ditto. * libc/sys/linux/linuxthreads/signals.c: Ditto. * libc/sys/linux/linuxthreads/specific.c: Ditto. * libc/sys/linux/linuxthreads/spinlock.c: Ditto. * libc/sys/linux/linuxthreads/spinlock.h: Ditto. * libc/sys/linux/linuxthreads/sysctl.c: Ditto. * libc/sys/linux/linuxthreads/td_init.c: Ditto. * libc/sys/linux/linuxthreads/td_log.c: Ditto. * libc/sys/linux/linuxthreads/td_symbol_list.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_clear_event.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_delete.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_enable_stats.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_event_addr.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_event_getmsg.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_get_nthreads.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_get_ph.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_get_stats.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_map_id2thr.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_map_lwp2thr.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_new.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_reset_stats.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_set_event.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_setconcurrency.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_thr_iter.c: Ditto. * libc/sys/linux/linuxthreads/td_ta_tsd_iter.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_clear_event.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_dbresume.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_dbsuspend.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_event_enable.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_event_getmsg.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_get_info.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_getfpregs.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_getgregs.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_getxregs.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_getxregsize.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_set_event.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_setfpregs.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_setgregs.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_setprio.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_setsigpending.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_setxregs.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_sigsetmask.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_tsd.c: Ditto. * libc/sys/linux/linuxthreads/td_thr_validate.c: Ditto. * libc/sys/linux/linuxthreads/testrtsig.h: Ditto. * libc/sys/linux/linuxthreads/thread_db.h: Ditto. * libc/sys/linux/linuxthreads/thread_dbP.h: Ditto. * libc/sys/linux/linuxthreads/timer_create.c: Ditto. * libc/sys/linux/linuxthreads/timer_delete.c: Ditto. * libc/sys/linux/linuxthreads/timer_getoverr.c: Ditto. * libc/sys/linux/linuxthreads/timer_gettime.c: Ditto. * libc/sys/linux/linuxthreads/timer_routines.c: Ditto. * libc/sys/linux/linuxthreads/timer_settime.c: Ditto. * libc/sys/linux/linuxthreads/tst-cancel.c: Ditto. * libc/sys/linux/linuxthreads/tst-context.c: Ditto. * libc/sys/linux/linuxthreads/tststack.c: Ditto. * libc/sys/linux/linuxthreads/unload.c: Ditto. * libc/sys/linux/linuxthreads/weaks.c: Ditto. * libc/sys/linux/linuxthreads/wrapsyscall.c: Ditto. * libc/sys/linux/linuxthreads/bits/initspin.h: Ditto. * libc/sys/linux/linuxthreads/bits/libc-lock.h: Ditto. * libc/sys/linux/linuxthreads/bits/libc-tsd.h: Ditto. * libc/sys/linux/linuxthreads/bits/local_lim.h: Ditto. * libc/sys/linux/linuxthreads/bits/posix_opt.h: Ditto. * libc/sys/linux/linuxthreads/bits/pthreadtypes.h: Ditto. * libc/sys/linux/linuxthreads/bits/sigthread.h: Ditto. * libc/sys/linux/linuxthreads/machine/Makefile.am: Ditto. * libc/sys/linux/linuxthreads/machine/Makefile.in: Ditto. * libc/sys/linux/linuxthreads/machine/aclocal.m4: Ditto. * libc/sys/linux/linuxthreads/machine/configure: Ditto. * libc/sys/linux/linuxthreads/machine/configure.in: Ditto. * libc/sys/linux/linuxthreads/machine/generic/generic-sysd: Ditto.ep.h * libc/sys/linux/linuxthreads/machine/i386/Makefile.am: Ditto. * libc/sys/linux/linuxthreads/machine/i386/Makefile.in: Ditto. * libc/sys/linux/linuxthreads/machine/i386/aclocal.m4: Ditto. * libc/sys/linux/linuxthreads/machine/i386/bp-asm.h: Ditto. * libc/sys/linux/linuxthreads/machine/i386/clone.S: Ditto. * libc/sys/linux/linuxthreads/machine/i386/configure: Ditto. * libc/sys/linux/linuxthreads/machine/i386/configure.in: Ditto. * libc/sys/linux/linuxthreads/machine/i386/i386-sysdep.S: Ditto. * libc/sys/linux/linuxthreads/machine/i386/i386-sysdep.h: Ditto. * libc/sys/linux/linuxthreads/machine/i386/pspinlock.c: Ditto. * libc/sys/linux/linuxthreads/machine/i386/pt-machine.h: Ditto. * libc/sys/linux/linuxthreads/machine/i386/sigcontextinfo.h: Ditto. * libc/sys/linux/linuxthreads/machine/i386/stackinfo.h: Ditto. * libc/sys/linux/linuxthreads/machine/i386/sysdep.S: Ditto. * libc/sys/linux/linuxthreads/machine/i386/sysdep.h: Ditto. * libc/sys/linux/linuxthreads/machine/i386/useldt.h: Ditto. * libc/sys/linux/machine/i386/dl-machine.h: Ditto. * libc/sys/linux/net/Makefile.am: Ditto. * libc/sys/linux/net/Makefile.in: Ditto. * libc/sys/linux/net/addr2ascii.3: Ditto. * libc/sys/linux/net/addr2ascii.c: Ditto. * libc/sys/linux/net/ascii2addr.c: Ditto. * libc/sys/linux/net/base64.c: Ditto. * libc/sys/linux/net/bindresvport.c: Ditto. * libc/sys/linux/net/byteorder.3: Ditto. * libc/sys/linux/net/ether_addr.c: Ditto. * libc/sys/linux/net/ethers.3: Ditto. * libc/sys/linux/net/getaddrinfo.3: Ditto. * libc/sys/linux/net/getaddrinfo.c: Ditto. * libc/sys/linux/net/gethostbydns.c: Ditto. * libc/sys/linux/net/gethostbyht.c: Ditto. * libc/sys/linux/net/gethostbyname.3: Ditto. * libc/sys/linux/net/gethostbynis.c: Ditto. * libc/sys/linux/net/gethostnamadr.c: Ditto. * libc/sys/linux/net/getifaddrs.3: Ditto. * libc/sys/linux/net/getifaddrs.c: Ditto. * libc/sys/linux/net/getipnodebyname.3: Ditto. * libc/sys/linux/net/getnameinfo.3: Ditto. * libc/sys/linux/net/getnameinfo.c: Ditto. * libc/sys/linux/net/getnetbydns.c: Ditto. * libc/sys/linux/net/getnetbyht.c: Ditto. * libc/sys/linux/net/getnetbynis.c: Ditto. * libc/sys/linux/net/getnetent.3: Ditto. * libc/sys/linux/net/getnetnamadr.c: Ditto. * libc/sys/linux/net/getproto.c: Ditto. * libc/sys/linux/net/getprotoent.3: Ditto. * libc/sys/linux/net/getprotoent.c: Ditto. * libc/sys/linux/net/getprotoname.c: Ditto. * libc/sys/linux/net/getservbyname.c: Ditto. * libc/sys/linux/net/getservbyport.c: Ditto. * libc/sys/linux/net/getservent.3: Ditto. * libc/sys/linux/net/getservent.c: Ditto. * libc/sys/linux/net/herror.c: Ditto. * libc/sys/linux/net/hesiod.3: Ditto. * libc/sys/linux/net/hesiod.c: Ditto. * libc/sys/linux/net/if_indextoname.3: Ditto. * libc/sys/linux/net/ifname.c: Ditto. * libc/sys/linux/net/inet.3: Ditto. * libc/sys/linux/net/inet6_option_s: Ditto.pace.3 * libc/sys/linux/net/inet6_rthdr_space.3: Ditto. * libc/sys/linux/net/inet_addr.c: Ditto. * libc/sys/linux/net/inet_lnaof.c: Ditto. * libc/sys/linux/net/inet_makeaddr.c: Ditto. * libc/sys/linux/net/inet_net.3: Ditto. * libc/sys/linux/net/inet_net_ntop.c: Ditto. * libc/sys/linux/net/inet_net_pton.c: Ditto. * libc/sys/linux/net/inet_neta.c: Ditto. * libc/sys/linux/net/inet_netof.c: Ditto. * libc/sys/linux/net/inet_network.c: Ditto. * libc/sys/linux/net/inet_ntoa.c: Ditto. * libc/sys/linux/net/inet_ntop.c: Ditto. * libc/sys/linux/net/inet_pton.c: Ditto. * libc/sys/linux/net/innetgr-stub.c: Ditto. * libc/sys/linux/net/ip6opt.c: Ditto. * libc/sys/linux/net/iso_addr.3: Ditto. * libc/sys/linux/net/iso_addr.c: Ditto. * libc/sys/linux/net/issetugid-stub.c: Ditto. * libc/sys/linux/net/linkaddr.3: Ditto. * libc/sys/linux/net/linkaddr.c: Ditto. * libc/sys/linux/net/map_v4v6.c: Ditto. * libc/sys/linux/net/name6.c: Ditto. * libc/sys/linux/net/namespace.h: Ditto. * libc/sys/linux/net/ns.3: Ditto. * libc/sys/linux/net/ns_addr.c: Ditto. * libc/sys/linux/net/ns_name.c: Ditto. * libc/sys/linux/net/ns_netint.c: Ditto. * libc/sys/linux/net/ns_ntoa.c: Ditto. * libc/sys/linux/net/ns_parse.c: Ditto. * libc/sys/linux/net/ns_print.c: Ditto. * libc/sys/linux/net/ns_ttl.c: Ditto. * libc/sys/linux/net/nsap_addr.c: Ditto. * libc/sys/linux/net/nsdispatch.3: Ditto. * libc/sys/linux/net/nsdispatch.c: Ditto. * libc/sys/linux/net/nslexer.c: Ditto. * libc/sys/linux/net/nslexer.l: Ditto. * libc/sys/linux/net/nsparser.c: Ditto. * libc/sys/linux/net/nsparser.h: Ditto. * libc/sys/linux/net/nsparser.y: Ditto. * libc/sys/linux/net/rcmd.3: Ditto. * libc/sys/linux/net/rcmd.c: Ditto. * libc/sys/linux/net/rcmdsh.3: Ditto. * libc/sys/linux/net/rcmdsh.c: Ditto. * libc/sys/linux/net/recv.c: Ditto. * libc/sys/linux/net/res_comp.c: Ditto. * libc/sys/linux/net/res_config.h: Ditto. * libc/sys/linux/net/res_data.c: Ditto. * libc/sys/linux/net/res_debug.c: Ditto. * libc/sys/linux/net/res_init.c: Ditto. * libc/sys/linux/net/res_mkquery.c: Ditto. * libc/sys/linux/net/res_mkupdate.c: Ditto. * libc/sys/linux/net/res_query.c: Ditto. * libc/sys/linux/net/res_send.c: Ditto. * libc/sys/linux/net/res_update.c: Ditto. * libc/sys/linux/net/resolver.3: Ditto. * libc/sys/linux/net/rthdr.c: Ditto. * libc/sys/linux/net/send.c: Ditto. * libc/sys/linux/net/un-namespace.h: Ditto. * libc/sys/linux/net/vars.c: Ditto. * libc/sys/linux/stdlib/COPYRIGHT: Ditto. * libc/sys/linux/stdlib/Makefile.am: Ditto. * libc/sys/linux/stdlib/Makefile.in: Ditto. * libc/sys/linux/stdlib/cclass.h: Ditto. * libc/sys/linux/stdlib/cname.h: Ditto. * libc/sys/linux/stdlib/collate.c: Ditto. * libc/sys/linux/stdlib/collate.h: Ditto. * libc/sys/linux/stdlib/collcmp.c: Ditto. * libc/sys/linux/stdlib/engine.c: Ditto. * libc/sys/linux/stdlib/fnmatch.3: Ditto. * libc/sys/linux/stdlib/fnmatch.c: Ditto. * libc/sys/linux/stdlib/glob.3: Ditto. * libc/sys/linux/stdlib/glob.c: Ditto. * libc/sys/linux/stdlib/reallocf.c: Ditto. * libc/sys/linux/stdlib/regcomp.c: Ditto. * libc/sys/linux/stdlib/regerror.c: Ditto. * libc/sys/linux/stdlib/regex.3: Ditto. * libc/sys/linux/stdlib/regex2.h: Ditto. * libc/sys/linux/stdlib/regexec.c: Ditto. * libc/sys/linux/stdlib/regfree.c: Ditto. * libc/sys/linux/stdlib/utils.h: Ditto. * libc/sys/linux/stdlib/wordexp.c: Ditto. * libc/sys/linux/stdlib/wordfree.c: Ditto. * libc/sys/linux/sys/dlfcn.h: Ditto. * libc/sys/linux/sys/elfclass.h: Ditto. * libc/sys/linux/sys/event.h: Ditto. * libc/sys/linux/sys/ioccom.h: Ditto. * libc/sys/linux/sys/libc-tsd.h: Ditto. * libc/sys/linux/sys/link.h: Ditto. * libc/sys/linux/sys/lock.h: Ditto. * libc/sys/linux/sys/param.h: Ditto. * libc/sys/linux/sys/socket.h: Ditto. * libc/sys/linux/sys/sockio.h: Ditto.
This commit is contained in:
parent
4218d88897
commit
b359e82cea
568
newlib/ChangeLog
568
newlib/ChangeLog
@ -1,3 +1,571 @@
|
||||
2003-05-28 Jeff Johnston <jjohnstn@redhat.com>
|
||||
Tom Fitzsimmons <fitzsim@redhat.com>
|
||||
|
||||
* configure.in: Add iconvdata support for x86 linux.
|
||||
* configure: Regenerated.
|
||||
* libc/sys/linux/Makefile.am: Add EL/IX level 3 network, dynamic
|
||||
library, iconv, and linuxthreads support.
|
||||
* libc/sys/linux/configure.in: Ditto.
|
||||
* libc/sys/linux/Makefile.in: Regenerated.
|
||||
* libc/sys/linux/configure: Ditto.
|
||||
* iconvdata/EUC-JP.irreversible: New file.
|
||||
* iconvdata/Makefile.am: Ditto.
|
||||
* iconvdata/Makefile.in: Ditto.
|
||||
* iconvdata/SJIS.irreversible: Ditto.
|
||||
* iconvdata/aclocal.m4: Ditto.
|
||||
* iconvdata/configure: Ditto.
|
||||
* iconvdata/configure.in: Ditto.
|
||||
* iconvdata/dummy.c: Ditto.
|
||||
* iconvdata/euc-jp.c: Ditto.
|
||||
* iconvdata/gconv-modules: Ditto.
|
||||
* iconvdata/jis0201.c: Ditto.
|
||||
* iconvdata/jis0201.h: Ditto.
|
||||
* iconvdata/jis0208.c: Ditto.
|
||||
* iconvdata/jis0208.h: Ditto.
|
||||
* iconvdata/jis0212.c: Ditto.
|
||||
* iconvdata/jis0212.h: Ditto.
|
||||
* iconvdata/sjis.c: Ditto.
|
||||
* libc/include/errno.h: Protect definition of error_t.
|
||||
* libc/sys/linux/gethostid.c: New file.
|
||||
* libc/sys/linux/sethostid.c: Ditto.
|
||||
* libc/sys/linux/dl/Makefile.am: Ditto.
|
||||
* libc/sys/linux/dl/Makefile.in: Ditto.
|
||||
* libc/sys/linux/dl/abi-tag.h: Ditto.
|
||||
* libc/sys/linux/dl/atomicity.h: Ditto.
|
||||
* libc/sys/linux/dl/dl-addr.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-cache.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-cache.h: Ditto.
|
||||
* libc/sys/linux/dl/dl-close.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-debug.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-deps.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-dst.h: Ditto.
|
||||
* libc/sys/linux/dl/dl-error.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-fini.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-init.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-iteratephdr.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-libc.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-librecon.h: Ditto.
|
||||
* libc/sys/linux/dl/dl-load.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-lookup.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-lookupcfg.h: Ditto.
|
||||
* libc/sys/linux/dl/dl-minimal.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-misc.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-object.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-open.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-osinfo.h: Ditto.
|
||||
* libc/sys/linux/dl/dl-profile.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-profstub.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-reloc.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-runtime.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-support.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-sym.c: Ditto.
|
||||
* libc/sys/linux/dl/dl-version.c: Ditto.
|
||||
* libc/sys/linux/dl/dlfcn.h: Ditto.
|
||||
* libc/sys/linux/dl/do-lookup.h: Ditto.
|
||||
* libc/sys/linux/dl/do-rel.h: Ditto.
|
||||
* libc/sys/linux/dl/dynamic-link.h: Ditto.
|
||||
* libc/sys/linux/dl/kernel-features.h: Ditto.
|
||||
* libc/sys/linux/dl/ldsodefs.h: Ditto.
|
||||
* libc/sys/linux/dl/libintl.h: Ditto.
|
||||
* libc/sys/linux/dl/trusted-dirs.h: Ditto.
|
||||
* libc/sys/linux/dl/unsecvars.h: Ditto.
|
||||
* libc/sys/linux/iconv/Makefile.am: Ditto.
|
||||
* libc/sys/linux/iconv/Makefile.in: Ditto.
|
||||
* libc/sys/linux/iconv/categories.def: Ditto.
|
||||
* libc/sys/linux/iconv/dummy-repertoire.c: Ditto.
|
||||
* libc/sys/linux/iconv/gconv.c: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_builtin.c: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_builtin.h: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_cache.c: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_charset.h: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_close.c: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_conf.c: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_db.c: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_dl.c: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_int.h: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_open.c: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_simple.c: Ditto.
|
||||
* libc/sys/linux/iconv/gconv_trans.c: Ditto.
|
||||
* libc/sys/linux/iconv/hash-string.h: Ditto.
|
||||
* libc/sys/linux/iconv/iconv.c: Ditto.
|
||||
* libc/sys/linux/iconv/iconv.h: Ditto.
|
||||
* libc/sys/linux/iconv/iconv_charmap.c: Ditto.
|
||||
* libc/sys/linux/iconv/iconv_close.c: Ditto.
|
||||
* libc/sys/linux/iconv/iconv_open.c: Ditto.
|
||||
* libc/sys/linux/iconv/iconvconfig.c: Ditto.
|
||||
* libc/sys/linux/iconv/iconvconfig.h: Ditto.
|
||||
* libc/sys/linux/iconv/loadinfo.h: Ditto.
|
||||
* libc/sys/linux/iconv/localeinfo.h: Ditto.
|
||||
* libc/sys/linux/iconv/loop.c: Ditto.
|
||||
* libc/sys/linux/iconv/skeleton.c: Ditto.
|
||||
* libc/sys/linux/iconv/strtab.c: Ditto.
|
||||
* libc/sys/linux/include/dl-hash.h: Ditto.
|
||||
* libc/sys/linux/include/dlfcn.h: Ditto.
|
||||
* libc/sys/linux/include/fnmatch.h: Ditto.
|
||||
* libc/sys/linux/include/gconv.h: Ditto.
|
||||
* libc/sys/linux/include/glob.h: Ditto.
|
||||
* libc/sys/linux/include/hesiod.h: Ditto.
|
||||
* libc/sys/linux/include/ifaddrs.h: Ditto.
|
||||
* libc/sys/linux/include/libc_private.h: Ditto.
|
||||
* libc/sys/linux/include/link.h: Ditto.
|
||||
* libc/sys/linux/include/namespace.h: Ditto.
|
||||
* libc/sys/linux/include/netconfig.h: Ditto.
|
||||
* libc/sys/linux/include/netdb.h: Ditto.
|
||||
* libc/sys/linux/include/nsswitch.h: Ditto.
|
||||
* libc/sys/linux/include/regex.h: Ditto.
|
||||
* libc/sys/linux/include/resolv.h: Ditto.
|
||||
* libc/sys/linux/include/rune.h: Ditto.
|
||||
* libc/sys/linux/include/runetype.h: Ditto.
|
||||
* libc/sys/linux/include/semaphore.h: Ditto.
|
||||
* libc/sys/linux/include/setlocale.h: Ditto.
|
||||
* libc/sys/linux/include/un-namespace.h: Ditto.
|
||||
* libc/sys/linux/include/wordexp.h: Ditto.
|
||||
* libc/sys/linux/include/arpa/ftp.h: Ditto.
|
||||
* libc/sys/linux/include/arpa/inet.h: Ditto.
|
||||
* libc/sys/linux/include/arpa/nameser.h: Ditto.
|
||||
* libc/sys/linux/include/arpa/nameser_compat.h: Ditto.
|
||||
* libc/sys/linux/include/arpa/telnet.h: Ditto.
|
||||
* libc/sys/linux/include/arpa/tftp.h: Ditto.
|
||||
* libc/sys/linux/include/net/bpf.h: Ditto.
|
||||
* libc/sys/linux/include/net/bpf_compat.h: Ditto.
|
||||
* libc/sys/linux/include/net/bpfdesc.h: Ditto.
|
||||
* libc/sys/linux/include/net/bridge.h: Ditto.
|
||||
* libc/sys/linux/include/net/ethernet.h: Ditto.
|
||||
* libc/sys/linux/include/net/fddi.h: Ditto.
|
||||
* libc/sys/linux/include/net/if.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_arc.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_arp.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_atm.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_dl.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_gif.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_ieee80211.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_llc.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_media.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_mib.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_ppp.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_pppvar.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_slvar.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_sppp.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_stf.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_tap.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_tapvar.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_tun.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_tunvar.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_types.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_var.h: Ditto.
|
||||
* libc/sys/linux/include/net/if_vlan_var.h: Ditto.
|
||||
* libc/sys/linux/include/net/intrq.h: Ditto.
|
||||
* libc/sys/linux/include/net/iso88025.h: Ditto.
|
||||
* libc/sys/linux/include/net/net_osdep.h: Ditto.
|
||||
* libc/sys/linux/include/net/netisr.h: Ditto.
|
||||
* libc/sys/linux/include/net/pfil.h: Ditto.
|
||||
* libc/sys/linux/include/net/pfkeyv2.h: Ditto.
|
||||
* libc/sys/linux/include/net/ppp_comp.h: Ditto.
|
||||
* libc/sys/linux/include/net/ppp_defs.h: Ditto.
|
||||
* libc/sys/linux/include/net/radix.h: Ditto.
|
||||
* libc/sys/linux/include/net/raw_cb.h: Ditto.
|
||||
* libc/sys/linux/include/net/route.h: Ditto.
|
||||
* libc/sys/linux/include/net/slcompress.h: Ditto.
|
||||
* libc/sys/linux/include/net/slip.h: Ditto.
|
||||
* libc/sys/linux/include/net/zlib.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/icmp6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/icmp_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/if_atm.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/if_ether.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/igmp.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/igmp_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/in.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/in_gif.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/in_pcb.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/in_systm.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/in_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/ip.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/ip6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/ip_dummynet.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/ip_ecn.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/ip_encap.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/ip_flow.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/ip_fw.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/ip_icmp.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/ip_mroute.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/ip_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/ipprotosw.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/tcp.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/tcp_debug.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/tcp_fsm.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/tcp_seq.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/tcp_timer.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/tcp_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/tcpip.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/udp.h: Ditto.
|
||||
* libc/sys/linux/include/netinet/udp_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ah.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ah6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/esp.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/esp6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/esp_rijndael.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/icmp6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/in6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/in6_gif.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/in6_ifattach.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/in6_pcb.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/in6_prefix.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/in6_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ip6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ip6_ecn.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ip6_fw.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ip6_mroute.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ip6_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ip6protosw.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ipcomp.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ipcomp6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ipsec.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/ipsec6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/mld6_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/nd6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/pim6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/pim6_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/raw_ip6.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/scope6_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/tcp6_var.h: Ditto.
|
||||
* libc/sys/linux/include/netinet6/udp6_var.h: Ditto.
|
||||
* libc/sys/linux/include/netns/idp.h: Ditto.
|
||||
* libc/sys/linux/include/netns/idp_var.h: Ditto.
|
||||
* libc/sys/linux/include/netns/ns.h: Ditto.
|
||||
* libc/sys/linux/include/netns/ns_error.h: Ditto.
|
||||
* libc/sys/linux/include/netns/ns_if.h: Ditto.
|
||||
* libc/sys/linux/include/netns/ns_pcb.h: Ditto.
|
||||
* libc/sys/linux/include/netns/sp.h: Ditto.
|
||||
* libc/sys/linux/include/netns/spidp.h: Ditto.
|
||||
* libc/sys/linux/include/netns/spp_debug.h: Ditto.
|
||||
* libc/sys/linux/include/netns/spp_timer.h: Ditto.
|
||||
* libc/sys/linux/include/netns/spp_var.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/Makefile: Ditto.
|
||||
* libc/sys/linux/include/rpc/auth.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/auth_des.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/auth_kerb.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/auth_unix.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/clnt.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/clnt_soc.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/clnt_stat.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/des.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/des_crypt.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/nettype.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/pmap_clnt.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/pmap_prot.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/pmap_rmt.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/raw.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/rpc.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/rpc_com.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/rpc_msg.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/rpcb_clnt.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/rpcb_prot.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/rpcb_prot.x: Ditto.
|
||||
* libc/sys/linux/include/rpc/rpcent.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/svc.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/svc_auth.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/svc_dg.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/svc_soc.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/types.h: Ditto.
|
||||
* libc/sys/linux/include/rpc/xdr.h: Ditto.
|
||||
* libc/sys/linux/intl/Makefile.am: Ditto.
|
||||
* libc/sys/linux/intl/Makefile.in: Ditto.
|
||||
* libc/sys/linux/intl/bindtextdom.c: Ditto.
|
||||
* libc/sys/linux/intl/catgets.c: Ditto.
|
||||
* libc/sys/linux/intl/catgetsinfo.h: Ditto.
|
||||
* libc/sys/linux/intl/config.h: Ditto.
|
||||
* libc/sys/linux/intl/dcgettext.c: Ditto.
|
||||
* libc/sys/linux/intl/dcigettext.c: Ditto.
|
||||
* libc/sys/linux/intl/dcngettext.c: Ditto.
|
||||
* libc/sys/linux/intl/dgettext.c: Ditto.
|
||||
* libc/sys/linux/intl/dngettext.c: Ditto.
|
||||
* libc/sys/linux/intl/explodename.c: Ditto.
|
||||
* libc/sys/linux/intl/finddomain.c: Ditto.
|
||||
* libc/sys/linux/intl/gettext.c: Ditto.
|
||||
* libc/sys/linux/intl/gettext.h: Ditto.
|
||||
* libc/sys/linux/intl/gettextP.h: Ditto.
|
||||
* libc/sys/linux/intl/hash-string.h: Ditto.
|
||||
* libc/sys/linux/intl/l10nflist.c: Ditto.
|
||||
* libc/sys/linux/intl/loadinfo.h: Ditto.
|
||||
* libc/sys/linux/intl/loadmsgcat.c: Ditto.
|
||||
* libc/sys/linux/intl/locale.alias: Ditto.
|
||||
* libc/sys/linux/intl/localealias.c: Ditto.
|
||||
* libc/sys/linux/intl/ngettext.c: Ditto.
|
||||
* libc/sys/linux/intl/open_catalog.c: Ditto.
|
||||
* libc/sys/linux/intl/plural.c: Ditto.
|
||||
* libc/sys/linux/intl/plural.y: Ditto.
|
||||
* libc/sys/linux/intl/stpcpy.c: Ditto.
|
||||
* libc/sys/linux/intl/textdomain.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/LICENSE: Ditto.
|
||||
* libc/sys/linux/linuxthreads/Makefile.am: Ditto.
|
||||
* libc/sys/linux/linuxthreads/Makefile.in: Ditto.
|
||||
* libc/sys/linux/linuxthreads/aclocal.m4: Ditto.
|
||||
* libc/sys/linux/linuxthreads/attr.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/barrier.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/bp-sym.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/cancel.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/condvar.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/config.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/configure: Ditto.
|
||||
* libc/sys/linux/linuxthreads/configure.in: Ditto.
|
||||
* libc/sys/linux/linuxthreads/defs.awk: Ditto.
|
||||
* libc/sys/linux/linuxthreads/ecmutex.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/events.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/getcpuclockid.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/getreent.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/internals.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/join.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/joinrace.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/kernel-features.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/libc-internal.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/libc-symbols.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/linuxthreads.texi: Ditto.
|
||||
* libc/sys/linux/linuxthreads/lockfile.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/manager.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/mq_notify.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/mutex.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/no-tsd.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/oldsemaphore.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/posix-timer.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/prio.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/proc_service.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/pt-machine.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/ptclock_gettime.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/ptclock_settime.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/ptfork.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/pthread.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/ptlongjmp.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/queue.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/reent.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/reqsyscalls.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/restart.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/rwlock.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/semaphore.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/semaphore.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/shlib-compat.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/signals.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/specific.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/spinlock.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/spinlock.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/sysctl.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_init.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_log.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_symbol_list.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_clear_event.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_delete.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_enable_stats.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_event_addr.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_event_getmsg.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_get_nthreads.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_get_ph.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_get_stats.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_map_id2thr.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_map_lwp2thr.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_new.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_reset_stats.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_set_event.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_setconcurrency.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_thr_iter.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_ta_tsd_iter.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_clear_event.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_dbresume.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_dbsuspend.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_event_enable.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_event_getmsg.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_get_info.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_getfpregs.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_getgregs.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_getxregs.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_getxregsize.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_set_event.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_setfpregs.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_setgregs.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_setprio.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_setsigpending.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_setxregs.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_sigsetmask.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_tsd.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/td_thr_validate.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/testrtsig.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/thread_db.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/thread_dbP.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/timer_create.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/timer_delete.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/timer_getoverr.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/timer_gettime.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/timer_routines.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/timer_settime.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/tst-cancel.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/tst-context.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/tststack.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/unload.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/weaks.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/wrapsyscall.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/bits/initspin.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/bits/libc-lock.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/bits/libc-tsd.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/bits/local_lim.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/bits/posix_opt.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/bits/pthreadtypes.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/bits/sigthread.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/Makefile.am: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/Makefile.in: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/aclocal.m4: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/configure: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/configure.in: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/generic/generic-sysd: Ditto.ep.h
|
||||
* libc/sys/linux/linuxthreads/machine/i386/Makefile.am: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/Makefile.in: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/aclocal.m4: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/bp-asm.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/clone.S: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/configure: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/configure.in: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/i386-sysdep.S: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/i386-sysdep.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/pspinlock.c: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/pt-machine.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/sigcontextinfo.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/stackinfo.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/sysdep.S: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/sysdep.h: Ditto.
|
||||
* libc/sys/linux/linuxthreads/machine/i386/useldt.h: Ditto.
|
||||
* libc/sys/linux/machine/i386/dl-machine.h: Ditto.
|
||||
* libc/sys/linux/net/Makefile.am: Ditto.
|
||||
* libc/sys/linux/net/Makefile.in: Ditto.
|
||||
* libc/sys/linux/net/addr2ascii.3: Ditto.
|
||||
* libc/sys/linux/net/addr2ascii.c: Ditto.
|
||||
* libc/sys/linux/net/ascii2addr.c: Ditto.
|
||||
* libc/sys/linux/net/base64.c: Ditto.
|
||||
* libc/sys/linux/net/bindresvport.c: Ditto.
|
||||
* libc/sys/linux/net/byteorder.3: Ditto.
|
||||
* libc/sys/linux/net/ether_addr.c: Ditto.
|
||||
* libc/sys/linux/net/ethers.3: Ditto.
|
||||
* libc/sys/linux/net/getaddrinfo.3: Ditto.
|
||||
* libc/sys/linux/net/getaddrinfo.c: Ditto.
|
||||
* libc/sys/linux/net/gethostbydns.c: Ditto.
|
||||
* libc/sys/linux/net/gethostbyht.c: Ditto.
|
||||
* libc/sys/linux/net/gethostbyname.3: Ditto.
|
||||
* libc/sys/linux/net/gethostbynis.c: Ditto.
|
||||
* libc/sys/linux/net/gethostnamadr.c: Ditto.
|
||||
* libc/sys/linux/net/getifaddrs.3: Ditto.
|
||||
* libc/sys/linux/net/getifaddrs.c: Ditto.
|
||||
* libc/sys/linux/net/getipnodebyname.3: Ditto.
|
||||
* libc/sys/linux/net/getnameinfo.3: Ditto.
|
||||
* libc/sys/linux/net/getnameinfo.c: Ditto.
|
||||
* libc/sys/linux/net/getnetbydns.c: Ditto.
|
||||
* libc/sys/linux/net/getnetbyht.c: Ditto.
|
||||
* libc/sys/linux/net/getnetbynis.c: Ditto.
|
||||
* libc/sys/linux/net/getnetent.3: Ditto.
|
||||
* libc/sys/linux/net/getnetnamadr.c: Ditto.
|
||||
* libc/sys/linux/net/getproto.c: Ditto.
|
||||
* libc/sys/linux/net/getprotoent.3: Ditto.
|
||||
* libc/sys/linux/net/getprotoent.c: Ditto.
|
||||
* libc/sys/linux/net/getprotoname.c: Ditto.
|
||||
* libc/sys/linux/net/getservbyname.c: Ditto.
|
||||
* libc/sys/linux/net/getservbyport.c: Ditto.
|
||||
* libc/sys/linux/net/getservent.3: Ditto.
|
||||
* libc/sys/linux/net/getservent.c: Ditto.
|
||||
* libc/sys/linux/net/herror.c: Ditto.
|
||||
* libc/sys/linux/net/hesiod.3: Ditto.
|
||||
* libc/sys/linux/net/hesiod.c: Ditto.
|
||||
* libc/sys/linux/net/if_indextoname.3: Ditto.
|
||||
* libc/sys/linux/net/ifname.c: Ditto.
|
||||
* libc/sys/linux/net/inet.3: Ditto.
|
||||
* libc/sys/linux/net/inet6_option_s: Ditto.pace.3
|
||||
* libc/sys/linux/net/inet6_rthdr_space.3: Ditto.
|
||||
* libc/sys/linux/net/inet_addr.c: Ditto.
|
||||
* libc/sys/linux/net/inet_lnaof.c: Ditto.
|
||||
* libc/sys/linux/net/inet_makeaddr.c: Ditto.
|
||||
* libc/sys/linux/net/inet_net.3: Ditto.
|
||||
* libc/sys/linux/net/inet_net_ntop.c: Ditto.
|
||||
* libc/sys/linux/net/inet_net_pton.c: Ditto.
|
||||
* libc/sys/linux/net/inet_neta.c: Ditto.
|
||||
* libc/sys/linux/net/inet_netof.c: Ditto.
|
||||
* libc/sys/linux/net/inet_network.c: Ditto.
|
||||
* libc/sys/linux/net/inet_ntoa.c: Ditto.
|
||||
* libc/sys/linux/net/inet_ntop.c: Ditto.
|
||||
* libc/sys/linux/net/inet_pton.c: Ditto.
|
||||
* libc/sys/linux/net/innetgr-stub.c: Ditto.
|
||||
* libc/sys/linux/net/ip6opt.c: Ditto.
|
||||
* libc/sys/linux/net/iso_addr.3: Ditto.
|
||||
* libc/sys/linux/net/iso_addr.c: Ditto.
|
||||
* libc/sys/linux/net/issetugid-stub.c: Ditto.
|
||||
* libc/sys/linux/net/linkaddr.3: Ditto.
|
||||
* libc/sys/linux/net/linkaddr.c: Ditto.
|
||||
* libc/sys/linux/net/map_v4v6.c: Ditto.
|
||||
* libc/sys/linux/net/name6.c: Ditto.
|
||||
* libc/sys/linux/net/namespace.h: Ditto.
|
||||
* libc/sys/linux/net/ns.3: Ditto.
|
||||
* libc/sys/linux/net/ns_addr.c: Ditto.
|
||||
* libc/sys/linux/net/ns_name.c: Ditto.
|
||||
* libc/sys/linux/net/ns_netint.c: Ditto.
|
||||
* libc/sys/linux/net/ns_ntoa.c: Ditto.
|
||||
* libc/sys/linux/net/ns_parse.c: Ditto.
|
||||
* libc/sys/linux/net/ns_print.c: Ditto.
|
||||
* libc/sys/linux/net/ns_ttl.c: Ditto.
|
||||
* libc/sys/linux/net/nsap_addr.c: Ditto.
|
||||
* libc/sys/linux/net/nsdispatch.3: Ditto.
|
||||
* libc/sys/linux/net/nsdispatch.c: Ditto.
|
||||
* libc/sys/linux/net/nslexer.c: Ditto.
|
||||
* libc/sys/linux/net/nslexer.l: Ditto.
|
||||
* libc/sys/linux/net/nsparser.c: Ditto.
|
||||
* libc/sys/linux/net/nsparser.h: Ditto.
|
||||
* libc/sys/linux/net/nsparser.y: Ditto.
|
||||
* libc/sys/linux/net/rcmd.3: Ditto.
|
||||
* libc/sys/linux/net/rcmd.c: Ditto.
|
||||
* libc/sys/linux/net/rcmdsh.3: Ditto.
|
||||
* libc/sys/linux/net/rcmdsh.c: Ditto.
|
||||
* libc/sys/linux/net/recv.c: Ditto.
|
||||
* libc/sys/linux/net/res_comp.c: Ditto.
|
||||
* libc/sys/linux/net/res_config.h: Ditto.
|
||||
* libc/sys/linux/net/res_data.c: Ditto.
|
||||
* libc/sys/linux/net/res_debug.c: Ditto.
|
||||
* libc/sys/linux/net/res_init.c: Ditto.
|
||||
* libc/sys/linux/net/res_mkquery.c: Ditto.
|
||||
* libc/sys/linux/net/res_mkupdate.c: Ditto.
|
||||
* libc/sys/linux/net/res_query.c: Ditto.
|
||||
* libc/sys/linux/net/res_send.c: Ditto.
|
||||
* libc/sys/linux/net/res_update.c: Ditto.
|
||||
* libc/sys/linux/net/resolver.3: Ditto.
|
||||
* libc/sys/linux/net/rthdr.c: Ditto.
|
||||
* libc/sys/linux/net/send.c: Ditto.
|
||||
* libc/sys/linux/net/un-namespace.h: Ditto.
|
||||
* libc/sys/linux/net/vars.c: Ditto.
|
||||
* libc/sys/linux/stdlib/COPYRIGHT: Ditto.
|
||||
* libc/sys/linux/stdlib/Makefile.am: Ditto.
|
||||
* libc/sys/linux/stdlib/Makefile.in: Ditto.
|
||||
* libc/sys/linux/stdlib/cclass.h: Ditto.
|
||||
* libc/sys/linux/stdlib/cname.h: Ditto.
|
||||
* libc/sys/linux/stdlib/collate.c: Ditto.
|
||||
* libc/sys/linux/stdlib/collate.h: Ditto.
|
||||
* libc/sys/linux/stdlib/collcmp.c: Ditto.
|
||||
* libc/sys/linux/stdlib/engine.c: Ditto.
|
||||
* libc/sys/linux/stdlib/fnmatch.3: Ditto.
|
||||
* libc/sys/linux/stdlib/fnmatch.c: Ditto.
|
||||
* libc/sys/linux/stdlib/glob.3: Ditto.
|
||||
* libc/sys/linux/stdlib/glob.c: Ditto.
|
||||
* libc/sys/linux/stdlib/reallocf.c: Ditto.
|
||||
* libc/sys/linux/stdlib/regcomp.c: Ditto.
|
||||
* libc/sys/linux/stdlib/regerror.c: Ditto.
|
||||
* libc/sys/linux/stdlib/regex.3: Ditto.
|
||||
* libc/sys/linux/stdlib/regex2.h: Ditto.
|
||||
* libc/sys/linux/stdlib/regexec.c: Ditto.
|
||||
* libc/sys/linux/stdlib/regfree.c: Ditto.
|
||||
* libc/sys/linux/stdlib/utils.h: Ditto.
|
||||
* libc/sys/linux/stdlib/wordexp.c: Ditto.
|
||||
* libc/sys/linux/stdlib/wordfree.c: Ditto.
|
||||
* libc/sys/linux/sys/dlfcn.h: Ditto.
|
||||
* libc/sys/linux/sys/elfclass.h: Ditto.
|
||||
* libc/sys/linux/sys/event.h: Ditto.
|
||||
* libc/sys/linux/sys/ioccom.h: Ditto.
|
||||
* libc/sys/linux/sys/libc-tsd.h: Ditto.
|
||||
* libc/sys/linux/sys/link.h: Ditto.
|
||||
* libc/sys/linux/sys/lock.h: Ditto.
|
||||
* libc/sys/linux/sys/param.h: Ditto.
|
||||
* libc/sys/linux/sys/socket.h: Ditto.
|
||||
* libc/sys/linux/sys/sockio.h: Ditto.
|
||||
|
||||
2003-05-28 Dhananjay Deshpande <dhananjayd@kpitcummins.com>
|
||||
|
||||
* newlib/libc/machine/h8300/memcpy.S: Use .h8300hn and .h8300sn for
|
||||
|
6
newlib/configure
vendored
6
newlib/configure
vendored
@ -3090,6 +3090,12 @@ else
|
||||
fi
|
||||
|
||||
EXTRA_DIRS=
|
||||
case $host in
|
||||
i345686-pc-linux-*)
|
||||
configdirs="${configdirs} iconvdata"
|
||||
EXTRA_DIRS=iconvdata
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# These get added in the top-level configure.in, except in the case where
|
||||
|
@ -51,6 +51,12 @@ fi
|
||||
AM_CONDITIONAL(HAVE_DOC, test x$have_doc = xyes)
|
||||
|
||||
EXTRA_DIRS=
|
||||
case $host in
|
||||
i[3456]86-pc-linux-*)
|
||||
configdirs="${configdirs} iconvdata"
|
||||
EXTRA_DIRS=iconvdata
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(EXTRA_DIRS)
|
||||
|
||||
# These get added in the top-level configure.in, except in the case where
|
||||
|
2
newlib/iconvdata/EUC-JP.irreversible
Normal file
2
newlib/iconvdata/EUC-JP.irreversible
Normal file
@ -0,0 +1,2 @@
|
||||
0x5C 0x00A5
|
||||
0x7E 0x203E
|
25
newlib/iconvdata/Makefile.am
Normal file
25
newlib/iconvdata/Makefile.am
Normal file
@ -0,0 +1,25 @@
|
||||
## Process this file with automake to generate Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = cygnus
|
||||
|
||||
INCLUDES = -I$(srcdir) -I$(srcdir)/../libc/sys/linux $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
|
||||
|
||||
if ELIX_LEVEL_1
|
||||
LIB_OBJS =
|
||||
else
|
||||
LIB_OBJS = euc-jp.$(oext) jis0201.$(oext) jis0208.$(oext) jis0212.$(oext)
|
||||
endif
|
||||
|
||||
AM_CFLAGS = -DNDEBUG
|
||||
|
||||
all: Makefile
|
||||
|
||||
pkglib_LTLIBRARIES = EUC-JP.la
|
||||
EUC_JP_la_SOURCES = dummy.c
|
||||
EUC_JP_la_LIBADD = $(LIB_OBJS)
|
||||
EUC_JP_la_DEPENDENCIES = $(LIB_OBJS)
|
||||
EUC_JP_la_LDFLAGS = -module -no-undefined -Xcompiler -Wl,-rpath-link=.. -Xcompiler -nostdlib -L.. -lc
|
||||
|
||||
install-data-local: install-pkglibLTLIBRARIES $(srcdir)/gconv-modules
|
||||
$(INSTALL_DATA) $(srcdir)/gconv-modules $(DESTDIR)$(pkglibdir)/gconv-modules
|
||||
|
389
newlib/iconvdata/Makefile.in
Normal file
389
newlib/iconvdata/Makefile.in
Normal file
@ -0,0 +1,389 @@
|
||||
# Makefile.in generated automatically by automake 1.4 from Makefile.am
|
||||
|
||||
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DESTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = .
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_alias = @build_alias@
|
||||
build_triplet = @build@
|
||||
host_alias = @host_alias@
|
||||
host_triplet = @host@
|
||||
target_alias = @target_alias@
|
||||
target_triplet = @target@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
CC = @CC@
|
||||
CPP = @CPP@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
EXEEXT = @EXEEXT@
|
||||
GCJ = @GCJ@
|
||||
GCJFLAGS = @GCJFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LN_S = @LN_S@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
NEWLIB_CFLAGS = @NEWLIB_CFLAGS@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
RANLIB = @RANLIB@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
aext = @aext@
|
||||
libm_machine_dir = @libm_machine_dir@
|
||||
machine_dir = @machine_dir@
|
||||
newlib_basedir = @newlib_basedir@
|
||||
oext = @oext@
|
||||
sys_dir = @sys_dir@
|
||||
|
||||
AUTOMAKE_OPTIONS = cygnus
|
||||
|
||||
INCLUDES = -I$(srcdir) -I$(srcdir)/../libc/sys/linux $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
|
||||
@ELIX_LEVEL_1_TRUE@LIB_OBJS =
|
||||
@ELIX_LEVEL_1_FALSE@LIB_OBJS = @ELIX_LEVEL_1_FALSE@euc-jp.$(oext) jis0201.$(oext) jis0208.$(oext) jis0212.$(oext)
|
||||
|
||||
AM_CFLAGS = -DNDEBUG
|
||||
|
||||
pkglib_LTLIBRARIES = EUC-JP.la
|
||||
EUC_JP_la_SOURCES = dummy.c
|
||||
EUC_JP_la_LIBADD = $(LIB_OBJS)
|
||||
EUC_JP_la_DEPENDENCIES = $(LIB_OBJS)
|
||||
EUC_JP_la_LDFLAGS = -module -no-undefined -Xcompiler -Wl,-rpath-link=.. -Xcompiler -nostdlib -L.. -lc
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs
|
||||
CONFIG_CLEAN_FILES =
|
||||
LTLIBRARIES = $(pkglib_LTLIBRARIES)
|
||||
|
||||
|
||||
DEFS = @DEFS@ -I. -I$(srcdir)
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LIBS = @LIBS@
|
||||
EUC_JP_la_OBJECTS = dummy.lo
|
||||
CFLAGS = @CFLAGS@
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
DIST_COMMON = Makefile.am Makefile.in aclocal.m4 configure configure.in
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = gtar
|
||||
GZIP_ENV = --best
|
||||
SOURCES = $(EUC_JP_la_SOURCES)
|
||||
OBJECTS = $(EUC_JP_la_OBJECTS)
|
||||
|
||||
all: all-redirect
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .S .c .lo .o .obj .s
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in
|
||||
cd $(srcdir) && $(ACLOCAL)
|
||||
|
||||
config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
$(SHELL) ./config.status --recheck
|
||||
$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
|
||||
cd $(srcdir) && $(AUTOCONF)
|
||||
|
||||
mostlyclean-pkglibLTLIBRARIES:
|
||||
|
||||
clean-pkglibLTLIBRARIES:
|
||||
-test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
|
||||
|
||||
distclean-pkglibLTLIBRARIES:
|
||||
|
||||
maintainer-clean-pkglibLTLIBRARIES:
|
||||
|
||||
install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
|
||||
@$(NORMAL_INSTALL)
|
||||
$(mkinstalldirs) $(DESTDIR)$(pkglibdir)
|
||||
@list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(pkglibdir)/$$p; \
|
||||
else :; fi; \
|
||||
done
|
||||
|
||||
uninstall-pkglibLTLIBRARIES:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
|
||||
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(pkglibdir)/$$p; \
|
||||
done
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
# FIXME: We should only use cygpath when building on Windows,
|
||||
# and only if it is available.
|
||||
.c.obj:
|
||||
$(COMPILE) -c `cygpath -w $<`
|
||||
|
||||
.s.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.S.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.o core *.core
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
clean-compile:
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
maintainer-clean-compile:
|
||||
|
||||
.c.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
.s.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
.S.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
|
||||
maintainer-clean-libtool:
|
||||
|
||||
EUC-JP.la: $(EUC_JP_la_OBJECTS) $(EUC_JP_la_DEPENDENCIES)
|
||||
$(LINK) -rpath $(pkglibdir) $(EUC_JP_la_LDFLAGS) $(EUC_JP_la_OBJECTS) $(EUC_JP_la_LIBADD) $(LIBS)
|
||||
|
||||
tags: TAGS
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
here=`pwd` && cd $(srcdir) \
|
||||
&& mkid -f$$here/ID $$unique $(LISP)
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|
||||
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
|
||||
|
||||
mostlyclean-tags:
|
||||
|
||||
clean-tags:
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID
|
||||
|
||||
maintainer-clean-tags:
|
||||
|
||||
distdir = $(PACKAGE)-$(VERSION)
|
||||
top_distdir = $(distdir)
|
||||
|
||||
# This target untars the dist file and tries a VPATH configuration. Then
|
||||
# it guarantees that the distribution is self-contained by making another
|
||||
# tarfile.
|
||||
distcheck: dist
|
||||
-rm -rf $(distdir)
|
||||
GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
|
||||
mkdir $(distdir)/=build
|
||||
mkdir $(distdir)/=inst
|
||||
dc_install_base=`cd $(distdir)/=inst && pwd`; \
|
||||
cd $(distdir)/=build \
|
||||
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dist
|
||||
-rm -rf $(distdir)
|
||||
@banner="$(distdir).tar.gz is ready for distribution"; \
|
||||
dashes=`echo "$$banner" | sed s/./=/g`; \
|
||||
echo "$$dashes"; \
|
||||
echo "$$banner"; \
|
||||
echo "$$dashes"
|
||||
dist: distdir
|
||||
-chmod -R a+r $(distdir)
|
||||
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
|
||||
-rm -rf $(distdir)
|
||||
dist-all: distdir
|
||||
-chmod -R a+r $(distdir)
|
||||
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
|
||||
-rm -rf $(distdir)
|
||||
distdir: $(DISTFILES)
|
||||
-rm -rf $(distdir)
|
||||
mkdir $(distdir)
|
||||
-chmod 777 $(distdir)
|
||||
@for file in $(DISTFILES); do \
|
||||
if test -f $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||
fi; \
|
||||
done
|
||||
info-am:
|
||||
info: info-am
|
||||
dvi-am:
|
||||
dvi: dvi-am
|
||||
check-am:
|
||||
check: check-am
|
||||
installcheck-am:
|
||||
installcheck: installcheck-am
|
||||
install-info-am:
|
||||
install-info: install-info-am
|
||||
install-exec-am: install-pkglibLTLIBRARIES
|
||||
install-exec: install-exec-am
|
||||
|
||||
install-data-am: install-data-local
|
||||
install-data: install-data-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
install: install-am
|
||||
uninstall-am: uninstall-pkglibLTLIBRARIES
|
||||
uninstall: uninstall-am
|
||||
all-am: Makefile $(LTLIBRARIES)
|
||||
all-redirect: all-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||
installdirs:
|
||||
$(mkinstalldirs) $(DESTDIR)$(pkglibdir)
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
|
||||
maintainer-clean-generic:
|
||||
mostlyclean-am: mostlyclean-pkglibLTLIBRARIES mostlyclean-compile \
|
||||
mostlyclean-libtool mostlyclean-tags \
|
||||
mostlyclean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
clean-am: clean-pkglibLTLIBRARIES clean-compile clean-libtool \
|
||||
clean-tags clean-generic mostlyclean-am
|
||||
|
||||
clean: clean-am
|
||||
|
||||
distclean-am: distclean-pkglibLTLIBRARIES distclean-compile \
|
||||
distclean-libtool distclean-tags distclean-generic \
|
||||
clean-am
|
||||
-rm -f libtool
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f config.status
|
||||
|
||||
maintainer-clean-am: maintainer-clean-pkglibLTLIBRARIES \
|
||||
maintainer-clean-compile maintainer-clean-libtool \
|
||||
maintainer-clean-tags maintainer-clean-generic \
|
||||
distclean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f config.status
|
||||
|
||||
.PHONY: mostlyclean-pkglibLTLIBRARIES distclean-pkglibLTLIBRARIES \
|
||||
clean-pkglibLTLIBRARIES maintainer-clean-pkglibLTLIBRARIES \
|
||||
uninstall-pkglibLTLIBRARIES install-pkglibLTLIBRARIES \
|
||||
mostlyclean-compile distclean-compile clean-compile \
|
||||
maintainer-clean-compile mostlyclean-libtool distclean-libtool \
|
||||
clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
|
||||
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
|
||||
dvi-am dvi check check-am installcheck-am installcheck install-info-am \
|
||||
install-info install-exec-am install-exec install-data-local \
|
||||
install-data-am install-data install-am install uninstall-am uninstall \
|
||||
all-redirect all-am all installdirs mostlyclean-generic \
|
||||
distclean-generic clean-generic maintainer-clean-generic clean \
|
||||
mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
all: Makefile
|
||||
|
||||
install-data-local: install-pkglibLTLIBRARIES $(srcdir)/gconv-modules
|
||||
$(INSTALL_DATA) $(srcdir)/gconv-modules $(DESTDIR)$(pkglibdir)/gconv-modules
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
5
newlib/iconvdata/SJIS.irreversible
Normal file
5
newlib/iconvdata/SJIS.irreversible
Normal file
@ -0,0 +1,5 @@
|
||||
0x5C 0x005C
|
||||
0x7E 0x007E
|
||||
0x8191 0xFFE0
|
||||
0x8192 0xFFE1
|
||||
0x81CA 0xFFE2
|
1181
newlib/iconvdata/aclocal.m4
vendored
Normal file
1181
newlib/iconvdata/aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3291
newlib/iconvdata/configure
vendored
Executable file
3291
newlib/iconvdata/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
21
newlib/iconvdata/configure.in
Normal file
21
newlib/iconvdata/configure.in
Normal file
@ -0,0 +1,21 @@
|
||||
dnl This is the newlib/iconvdata configure.in file.
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.5)
|
||||
AC_INIT(jis0201.c)
|
||||
|
||||
dnl Can't be done in NEWLIB_CONFIGURE because that confuses automake.
|
||||
AC_CONFIG_AUX_DIR(../..)
|
||||
|
||||
NEWLIB_CONFIGURE(..)
|
||||
|
||||
dnl We have to enable libtool after NEWLIB_CONFIGURE because if we try and
|
||||
dnl add it into NEWLIB_CONFIGURE, executable tests are made before the first
|
||||
dnl line of the macro which fail because appropriate LDFLAGS are not set.
|
||||
|
||||
if test "${use_libtool}" = "yes"; then
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AM_PROG_LIBTOOL
|
||||
fi
|
||||
|
||||
AC_OUTPUT(Makefile)
|
1
newlib/iconvdata/dummy.c
Normal file
1
newlib/iconvdata/dummy.c
Normal file
@ -0,0 +1 @@
|
||||
/* empty file to force proper Makefile creation */
|
246
newlib/iconvdata/euc-jp.c
Normal file
246
newlib/iconvdata/euc-jp.c
Normal file
@ -0,0 +1,246 @@
|
||||
/* Mapping tables for EUC-JP handling.
|
||||
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <dlfcn.h>
|
||||
#include <stdint.h>
|
||||
#include <gconv.h>
|
||||
#include <jis0201.h>
|
||||
#include <jis0208.h>
|
||||
#include <jis0212.h>
|
||||
|
||||
/* Definitions used in the body of the `gconv' function. */
|
||||
#define CHARSET_NAME "EUC-JP//"
|
||||
#define FROM_LOOP from_euc_jp
|
||||
#define TO_LOOP to_euc_jp
|
||||
#define DEFINE_INIT 1
|
||||
#define DEFINE_FINI 1
|
||||
#define MIN_NEEDED_FROM 1
|
||||
#define MAX_NEEDED_FROM 3
|
||||
#define MIN_NEEDED_TO 4
|
||||
|
||||
|
||||
/* First define the conversion function from EUC-JP to UCS4. */
|
||||
#define MIN_NEEDED_INPUT MIN_NEEDED_FROM
|
||||
#define MAX_NEEDED_INPUT MAX_NEEDED_FROM
|
||||
#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO
|
||||
#define LOOPFCT FROM_LOOP
|
||||
#define BODY \
|
||||
{ \
|
||||
uint32_t ch = *inptr; \
|
||||
\
|
||||
if (ch < 0x8e || (ch >= 0x90 && ch <= 0x9f)) \
|
||||
++inptr; \
|
||||
else if (ch == 0xff) \
|
||||
{ \
|
||||
/* This is illegal. */ \
|
||||
if (! ignore_errors_p ()) \
|
||||
{ \
|
||||
result = __GCONV_ILLEGAL_INPUT; \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
++inptr; \
|
||||
++*irreversible; \
|
||||
continue; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* Two or more byte character. First test whether the next \
|
||||
character is also available. */ \
|
||||
int ch2; \
|
||||
\
|
||||
if (__builtin_expect (inptr + 1 >= inend, 0)) \
|
||||
{ \
|
||||
/* The second character is not available. Store the \
|
||||
intermediate result. */ \
|
||||
result = __GCONV_INCOMPLETE_INPUT; \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
ch2 = inptr[1]; \
|
||||
\
|
||||
/* All second bytes of a multibyte character must be >= 0xa1. */ \
|
||||
if (__builtin_expect (ch2 < 0xa1, 0)) \
|
||||
{ \
|
||||
/* This is an illegal character. */ \
|
||||
if (! ignore_errors_p ()) \
|
||||
{ \
|
||||
result = __GCONV_ILLEGAL_INPUT; \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
++inptr; \
|
||||
++*irreversible; \
|
||||
continue; \
|
||||
} \
|
||||
\
|
||||
if (ch == 0x8e) \
|
||||
{ \
|
||||
/* This is code set 2: half-width katakana. */ \
|
||||
ch = jisx0201_to_ucs4 (ch2); \
|
||||
if (__builtin_expect (ch, 0) == __UNKNOWN_10646_CHAR) \
|
||||
{ \
|
||||
/* Illegal character. */ \
|
||||
if (! ignore_errors_p ()) \
|
||||
{ \
|
||||
/* This is an illegal character. */ \
|
||||
result = __GCONV_ILLEGAL_INPUT; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
inptr += 2; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
const unsigned char *endp; \
|
||||
\
|
||||
if (ch == 0x8f) \
|
||||
{ \
|
||||
/* This is code set 3: JIS X 0212-1990. */ \
|
||||
endp = inptr + 1; \
|
||||
\
|
||||
ch = jisx0212_to_ucs4 (&endp, inend - endp, 0x80); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* This is code set 1: JIS X 0208. */ \
|
||||
endp = inptr; \
|
||||
\
|
||||
ch = jisx0208_to_ucs4 (&endp, inend - inptr, 0x80); \
|
||||
} \
|
||||
\
|
||||
if (__builtin_expect (ch, 1) == 0) \
|
||||
{ \
|
||||
/* Not enough input available. */ \
|
||||
result = __GCONV_INCOMPLETE_INPUT; \
|
||||
break; \
|
||||
} \
|
||||
if (__builtin_expect (ch, 0) == __UNKNOWN_10646_CHAR) \
|
||||
{ \
|
||||
/* Illegal character. */ \
|
||||
if (! ignore_errors_p ()) \
|
||||
{ \
|
||||
/* This is an illegal character. */ \
|
||||
result = __GCONV_ILLEGAL_INPUT; \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
inptr += 2; \
|
||||
++*irreversible; \
|
||||
continue; \
|
||||
} \
|
||||
inptr = endp; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
put32 (outptr, ch); \
|
||||
outptr += 4; \
|
||||
}
|
||||
#define LOOP_NEED_FLAGS
|
||||
#include <iconv/loop.c>
|
||||
|
||||
|
||||
/* Next, define the other direction. */
|
||||
#define MIN_NEEDED_INPUT MIN_NEEDED_TO
|
||||
#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM
|
||||
#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM
|
||||
#define LOOPFCT TO_LOOP
|
||||
#define BODY \
|
||||
{ \
|
||||
uint32_t ch = get32 (inptr); \
|
||||
\
|
||||
if (ch < 0x8e || (ch >= 0x90 && ch <= 0x9f)) \
|
||||
/* It's plain ASCII or C1. */ \
|
||||
*outptr++ = ch; \
|
||||
else if (ch == 0xa5) \
|
||||
/* YEN sign => backslash */ \
|
||||
*outptr++ = 0x5c; \
|
||||
else if (ch == 0x203e) \
|
||||
/* overscore => asciitilde */ \
|
||||
*outptr++ = 0x7e; \
|
||||
else \
|
||||
{ \
|
||||
/* Try the JIS character sets. */ \
|
||||
size_t found; \
|
||||
\
|
||||
/* See whether we have room for at least two characters. */ \
|
||||
if (__builtin_expect (outptr + 1 >= outend, 0)) \
|
||||
{ \
|
||||
result = __GCONV_FULL_OUTPUT; \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
found = ucs4_to_jisx0201 (ch, outptr + 1); \
|
||||
if (found != __UNKNOWN_10646_CHAR) \
|
||||
{ \
|
||||
/* Yes, it's a JIS 0201 character. Store the shift byte. */ \
|
||||
*outptr = 0x8e; \
|
||||
outptr += 2; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* No JIS 0201 character. */ \
|
||||
found = ucs4_to_jisx0208 (ch, outptr, 2); \
|
||||
/* Please note that we always have enough room for the output. */ \
|
||||
if (found != __UNKNOWN_10646_CHAR) \
|
||||
{ \
|
||||
/* It's a JIS 0208 character, adjust it for EUC-JP. */ \
|
||||
*outptr++ += 0x80; \
|
||||
*outptr++ += 0x80; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* No JIS 0208 character. */ \
|
||||
found = ucs4_to_jisx0212 (ch, outptr + 1, \
|
||||
outend - outptr - 1); \
|
||||
\
|
||||
if (__builtin_expect (found, 1) == 0) \
|
||||
{ \
|
||||
/* We ran out of space. */ \
|
||||
result = __GCONV_FULL_OUTPUT; \
|
||||
break; \
|
||||
} \
|
||||
else if (__builtin_expect (found, 0) != __UNKNOWN_10646_CHAR) \
|
||||
{ \
|
||||
/* It's a JIS 0212 character, adjust it for EUC-JP. */ \
|
||||
*outptr++ = 0x8f; \
|
||||
*outptr++ += 0x80; \
|
||||
*outptr++ += 0x80; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
UNICODE_TAG_HANDLER (ch, 4); \
|
||||
\
|
||||
/* Illegal character. */ \
|
||||
STANDARD_ERR_HANDLER (4); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
inptr += 4; \
|
||||
}
|
||||
#define LOOP_NEED_FLAGS
|
||||
#include <iconv/loop.c>
|
||||
|
||||
|
||||
/* Now define the toplevel functions. */
|
||||
#include <iconv/skeleton.c>
|
1511
newlib/iconvdata/gconv-modules
Normal file
1511
newlib/iconvdata/gconv-modules
Normal file
File diff suppressed because it is too large
Load Diff
58
newlib/iconvdata/jis0201.c
Normal file
58
newlib/iconvdata/jis0201.c
Normal file
@ -0,0 +1,58 @@
|
||||
/* Mapping tables for JIS0201 handling.
|
||||
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <stdint.h>
|
||||
|
||||
|
||||
const uint32_t __jisx0201_to_ucs4[256] =
|
||||
{
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x00a5, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x203e, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67,
|
||||
0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f,
|
||||
0xff70, 0xff71, 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77,
|
||||
0xff78, 0xff79, 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f,
|
||||
0xff80, 0xff81, 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87,
|
||||
0xff88, 0xff89, 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f,
|
||||
0xff90, 0xff91, 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97,
|
||||
0xff98, 0xff99, 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
|
||||
};
|
60
newlib/iconvdata/jis0201.h
Normal file
60
newlib/iconvdata/jis0201.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* Access functions for JISX0201 conversion.
|
||||
Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 _JIS0201_H
|
||||
#define _JIS0201_H 1
|
||||
|
||||
/* Conversion table. */
|
||||
extern const uint32_t __jisx0201_to_ucs4[];
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
jisx0201_to_ucs4 (char ch)
|
||||
{
|
||||
uint32_t val = __jisx0201_to_ucs4[(unsigned char) ch];
|
||||
|
||||
if (val == 0 && ch != '\0')
|
||||
val = __UNKNOWN_10646_CHAR;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static inline size_t
|
||||
ucs4_to_jisx0201 (uint32_t wch, char *s)
|
||||
{
|
||||
char ch;
|
||||
|
||||
if (wch == 0xa5)
|
||||
ch = '\x5c';
|
||||
else if (wch == 0x203e)
|
||||
ch = '\x7e';
|
||||
else if (wch < 0x7e && wch != 0x5c)
|
||||
ch = wch;
|
||||
else if (wch >= 0xff61 && wch <= 0xff9f)
|
||||
ch = wch - 0xfec0;
|
||||
else
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
|
||||
s[0] = ch;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* jis0201.h */
|
5012
newlib/iconvdata/jis0208.c
Normal file
5012
newlib/iconvdata/jis0208.c
Normal file
File diff suppressed because it is too large
Load Diff
108
newlib/iconvdata/jis0208.h
Normal file
108
newlib/iconvdata/jis0208.h
Normal file
@ -0,0 +1,108 @@
|
||||
/* Access functions for JISX0208 conversion.
|
||||
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 _JIS0208_H
|
||||
#define _JIS0208_H 1
|
||||
|
||||
#include <gconv.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Conversion table. */
|
||||
extern const uint16_t __jis0208_to_ucs[];
|
||||
|
||||
extern const char __jisx0208_from_ucs4_lat1[256][2];
|
||||
extern const char __jisx0208_from_ucs4_greek[0xc1][2];
|
||||
extern const struct jisx0208_ucs_idx __jisx0208_from_ucs_idx[];
|
||||
extern const char __jisx0208_from_ucs_tab[][2];
|
||||
|
||||
|
||||
/* Struct for table with indeces in UCS mapping table. */
|
||||
struct jisx0208_ucs_idx
|
||||
{
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
uint16_t idx;
|
||||
};
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
jisx0208_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset)
|
||||
{
|
||||
unsigned char ch = *(*s);
|
||||
unsigned char ch2;
|
||||
int idx;
|
||||
|
||||
if (ch < offset || (ch - offset) <= 0x20)
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
|
||||
if (avail < 2)
|
||||
return 0;
|
||||
|
||||
ch2 = (*s)[1];
|
||||
if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f)
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
|
||||
idx = (ch - 0x21 - offset) * 94 + (ch2 - 0x21 - offset);
|
||||
if (idx >= 0x1e80)
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
|
||||
(*s) += 2;
|
||||
|
||||
return __jis0208_to_ucs[idx] ?: ((*s) -= 2, __UNKNOWN_10646_CHAR);
|
||||
}
|
||||
|
||||
|
||||
static inline size_t
|
||||
ucs4_to_jisx0208 (uint32_t wch, char *s, size_t avail)
|
||||
{
|
||||
unsigned int ch = (unsigned int) wch;
|
||||
const char *cp;
|
||||
|
||||
if (avail < 2)
|
||||
return 0;
|
||||
|
||||
if (ch < 0x100)
|
||||
cp = __jisx0208_from_ucs4_lat1[ch];
|
||||
else if (ch >= 0x391 && ch <= 0x451)
|
||||
cp = __jisx0208_from_ucs4_greek[ch - 0x391];
|
||||
else
|
||||
{
|
||||
const struct jisx0208_ucs_idx *rp = __jisx0208_from_ucs_idx;
|
||||
|
||||
if (ch >= 0xffff)
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
while (ch > rp->end)
|
||||
++rp;
|
||||
if (ch >= rp->start)
|
||||
cp = __jisx0208_from_ucs_tab[rp->idx + ch - rp->start];
|
||||
else
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
}
|
||||
|
||||
if (cp[0] == '\0')
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
|
||||
s[0] = cp[0];
|
||||
s[1] = cp[1];
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
#endif /* jis0208.h */
|
3940
newlib/iconvdata/jis0212.c
Normal file
3940
newlib/iconvdata/jis0212.c
Normal file
File diff suppressed because it is too large
Load Diff
110
newlib/iconvdata/jis0212.h
Normal file
110
newlib/iconvdata/jis0212.h
Normal file
@ -0,0 +1,110 @@
|
||||
/* Access functions for JISX0212 conversion.
|
||||
Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 _JIS0212_H
|
||||
#define _JIS0212_H 1
|
||||
|
||||
#include <gconv.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/* Struct for table with indeces in mapping table. */
|
||||
struct jisx0212_idx
|
||||
{
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
uint16_t idx;
|
||||
};
|
||||
|
||||
/* Conversion table. */
|
||||
extern const struct jisx0212_idx __jisx0212_to_ucs_idx[];
|
||||
extern const uint16_t __jisx0212_to_ucs[];
|
||||
|
||||
extern const struct jisx0212_idx __jisx0212_from_ucs_idx[];
|
||||
extern const char __jisx0212_from_ucs[][2];
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
jisx0212_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset)
|
||||
{
|
||||
const struct jisx0212_idx *rp = __jisx0212_to_ucs_idx;
|
||||
unsigned char ch = *(*s);
|
||||
unsigned char ch2;
|
||||
uint32_t wch = 0;
|
||||
int idx;
|
||||
|
||||
if (ch < offset || (ch - offset) < 0x22 || (ch - offset) > 0x6d)
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
|
||||
if (avail < 2)
|
||||
return 0;
|
||||
|
||||
ch2 = (*s)[1];
|
||||
if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f)
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
|
||||
idx = (ch - offset - 0x21) * 94 + (ch2 - offset - 0x21);
|
||||
|
||||
while (idx > rp->end)
|
||||
++rp;
|
||||
if (idx >= rp->start)
|
||||
wch = __jisx0212_to_ucs[rp->idx + idx - rp->start];
|
||||
|
||||
if (wch != L'\0')
|
||||
(*s) += 2;
|
||||
else
|
||||
wch = __UNKNOWN_10646_CHAR;
|
||||
|
||||
return wch;
|
||||
}
|
||||
|
||||
|
||||
static inline size_t
|
||||
ucs4_to_jisx0212 (uint32_t wch, char *s, size_t avail)
|
||||
{
|
||||
const struct jisx0212_idx *rp = __jisx0212_from_ucs_idx;
|
||||
unsigned int ch = (unsigned int) wch;
|
||||
const char *cp;
|
||||
|
||||
if (ch >= 0xffff)
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
while (ch > rp->end)
|
||||
++rp;
|
||||
if (ch >= rp->start)
|
||||
cp = __jisx0212_from_ucs[rp->idx + ch - rp->start];
|
||||
else
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
|
||||
if (cp[0] == '\0')
|
||||
return __UNKNOWN_10646_CHAR;
|
||||
|
||||
s[0] = cp[0];
|
||||
if (cp[1] != '\0')
|
||||
{
|
||||
if (avail < 2)
|
||||
return 0;
|
||||
|
||||
s[1] = cp[1];
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
#endif /* jis0212.h */
|
4512
newlib/iconvdata/sjis.c
Normal file
4512
newlib/iconvdata/sjis.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,10 @@
|
||||
#ifndef __ERRNO_H__
|
||||
#define __ERRNO_H__
|
||||
|
||||
#ifndef __error_t_defined
|
||||
typedef int error_t;
|
||||
#define __error_t_defined 1
|
||||
#endif
|
||||
|
||||
#include <sys/errno.h>
|
||||
|
||||
|
@ -169,6 +169,8 @@ liblinux_la_LDFLAGS = -Xcompiler -nostdlib
|
||||
|
||||
ADD_OBJS = \
|
||||
malloc.$(oext) \
|
||||
gethostid.$(oext) \
|
||||
sethostid.$(oext) \
|
||||
$(LINUX_MACH_LIB)
|
||||
|
||||
if USE_LIBTOOL
|
||||
|
@ -257,6 +257,8 @@ liblinux_la_LDFLAGS = -Xcompiler -nostdlib
|
||||
|
||||
ADD_OBJS = \
|
||||
malloc.$(oext) \
|
||||
gethostid.$(oext) \
|
||||
sethostid.$(oext) \
|
||||
$(LINUX_MACH_LIB)
|
||||
|
||||
|
||||
|
15
newlib/libc/sys/linux/configure
vendored
15
newlib/libc/sys/linux/configure
vendored
@ -3043,6 +3043,17 @@ fi
|
||||
EXTRA_SUBDIRS=
|
||||
EXTRA_SUBLIBS=
|
||||
|
||||
if test "${newlib_multithread}" = "yes"; then
|
||||
EXTRA_CONFIG_DIRS=linuxthreads
|
||||
fi
|
||||
if test "x${newlib_elix_level}" = "x1"; then
|
||||
EXTRA_SUBDIRS=linuxthreads net
|
||||
else
|
||||
EXTRA_SUBDIRS="linuxthreads net intl stdlib iconv dl"
|
||||
EXTRA_SUBLIBS="net/libnet.la intl/libintl.la stdlib/libstdlib.la iconv/libiconv.la dl/libdl.la"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
subdirs="machine $EXTRA_CONFIG_DIRS"
|
||||
@ -3161,7 +3172,7 @@ done
|
||||
ac_given_srcdir=$srcdir
|
||||
ac_given_INSTALL="$INSTALL"
|
||||
|
||||
trap 'rm -fr `echo "Makefile cmath/Makefile argp/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
|
||||
trap 'rm -fr `echo "Makefile intl/Makefile net/Makefile stdlib/Makefile iconv/Makefile dl/Makefile cmath/Makefile argp/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
|
||||
EOF
|
||||
cat >> $CONFIG_STATUS <<EOF
|
||||
|
||||
@ -3300,7 +3311,7 @@ EOF
|
||||
|
||||
cat >> $CONFIG_STATUS <<EOF
|
||||
|
||||
CONFIG_FILES=\${CONFIG_FILES-"Makefile cmath/Makefile argp/Makefile"}
|
||||
CONFIG_FILES=\${CONFIG_FILES-"Makefile intl/Makefile net/Makefile stdlib/Makefile iconv/Makefile dl/Makefile cmath/Makefile argp/Makefile"}
|
||||
EOF
|
||||
cat >> $CONFIG_STATUS <<\EOF
|
||||
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
|
||||
|
@ -31,9 +31,20 @@ AC_SUBST(LINUX_MACH_LIB)
|
||||
|
||||
EXTRA_SUBDIRS=
|
||||
EXTRA_SUBLIBS=
|
||||
|
||||
if test "${newlib_multithread}" = "yes"; then
|
||||
EXTRA_CONFIG_DIRS=linuxthreads
|
||||
fi
|
||||
if test "x${newlib_elix_level}" = "x1"; then
|
||||
EXTRA_SUBDIRS=linuxthreads net
|
||||
else
|
||||
EXTRA_SUBDIRS="linuxthreads net intl stdlib iconv dl"
|
||||
EXTRA_SUBLIBS="net/libnet.la intl/libintl.la stdlib/libstdlib.la iconv/libiconv.la dl/libdl.la"
|
||||
fi
|
||||
|
||||
AC_SUBST(EXTRA_SUBDIRS)
|
||||
AC_SUBST(EXTRA_SUBLIBS)
|
||||
|
||||
AC_CONFIG_SUBDIRS(machine $EXTRA_CONFIG_DIRS)
|
||||
|
||||
AC_OUTPUT(Makefile cmath/Makefile argp/Makefile)
|
||||
AC_OUTPUT(Makefile intl/Makefile net/Makefile stdlib/Makefile iconv/Makefile dl/Makefile cmath/Makefile argp/Makefile)
|
||||
|
25
newlib/libc/sys/linux/dl/Makefile.am
Normal file
25
newlib/libc/sys/linux/dl/Makefile.am
Normal file
@ -0,0 +1,25 @@
|
||||
## Process this file with automake to generate Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = cygnus
|
||||
|
||||
INCLUDES = -DSHARED -D_GNU_SOURCE $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) -I$(srcdir)/..
|
||||
|
||||
LIB_SOURCES = \
|
||||
dl-addr.c dl-deps.c dl-init.c dl-load.c dl-misc.c dl-profile.c dl-runtime.c dl-version.c \
|
||||
dl-close.c dl-error.c dl-iteratephdr.c dl-lookup.c dl-object.c dl-profstub.c dl-support.c \
|
||||
dl-debug.c dl-fini.c dl-libc.c dl-open.c dl-reloc.c dl-sym.c dl-cache.c
|
||||
|
||||
AM_CFLAGS = -D_GNU_SOURCE -D__strerror_r=strerror_r
|
||||
libdl_la_LDFLAGS = -Xcompiler -nostdlib
|
||||
|
||||
if USE_LIBTOOL
|
||||
noinst_LTLIBRARIES = libdl.la
|
||||
libdl_la_SOURCES = $(LIB_SOURCES)
|
||||
noinst_DATA = objectlist.awk.in
|
||||
else
|
||||
noinst_LIBRARIES = lib.a
|
||||
lib_a_SOURCES = $(LIB_SOURCES)
|
||||
noinst_DATA =
|
||||
endif # USE_LIBTOOL
|
||||
|
||||
include $(srcdir)/../../../../Makefile.shared
|
379
newlib/libc/sys/linux/dl/Makefile.in
Normal file
379
newlib/libc/sys/linux/dl/Makefile.in
Normal file
@ -0,0 +1,379 @@
|
||||
# Makefile.in generated automatically by automake 1.4 from Makefile.am
|
||||
|
||||
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DESTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = ..
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_alias = @build_alias@
|
||||
build_triplet = @build@
|
||||
host_alias = @host_alias@
|
||||
host_triplet = @host@
|
||||
target_alias = @target_alias@
|
||||
target_triplet = @target@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CPP = @CPP@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
EXEEXT = @EXEEXT@
|
||||
GCJ = @GCJ@
|
||||
GCJFLAGS = @GCJFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LINUX_MACH_LIB = @LINUX_MACH_LIB@
|
||||
LN_S = @LN_S@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
NEWLIB_CFLAGS = @NEWLIB_CFLAGS@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
RANLIB = @RANLIB@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
aext = @aext@
|
||||
libm_machine_dir = @libm_machine_dir@
|
||||
machine_dir = @machine_dir@
|
||||
newlib_basedir = @newlib_basedir@
|
||||
oext = @oext@
|
||||
sys_dir = @sys_dir@
|
||||
|
||||
AUTOMAKE_OPTIONS = cygnus
|
||||
|
||||
INCLUDES = -DSHARED -D_GNU_SOURCE $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) -I$(srcdir)/..
|
||||
|
||||
LIB_SOURCES = \
|
||||
dl-addr.c dl-deps.c dl-init.c dl-load.c dl-misc.c dl-profile.c dl-runtime.c dl-version.c \
|
||||
dl-close.c dl-error.c dl-iteratephdr.c dl-lookup.c dl-object.c dl-profstub.c dl-support.c \
|
||||
dl-debug.c dl-fini.c dl-libc.c dl-open.c dl-reloc.c dl-sym.c dl-cache.c
|
||||
|
||||
|
||||
AM_CFLAGS = -D_GNU_SOURCE -D__strerror_r=strerror_r
|
||||
libdl_la_LDFLAGS = -Xcompiler -nostdlib
|
||||
|
||||
@USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = @USE_LIBTOOL_TRUE@libdl.la
|
||||
@USE_LIBTOOL_TRUE@libdl_la_SOURCES = @USE_LIBTOOL_TRUE@$(LIB_SOURCES)
|
||||
@USE_LIBTOOL_TRUE@noinst_DATA = @USE_LIBTOOL_TRUE@objectlist.awk.in
|
||||
@USE_LIBTOOL_FALSE@noinst_DATA =
|
||||
@USE_LIBTOOL_FALSE@noinst_LIBRARIES = @USE_LIBTOOL_FALSE@lib.a
|
||||
@USE_LIBTOOL_FALSE@lib_a_SOURCES = @USE_LIBTOOL_FALSE@$(LIB_SOURCES)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../mkinstalldirs
|
||||
CONFIG_CLEAN_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
|
||||
|
||||
DEFS = @DEFS@ -I. -I$(srcdir)
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LIBS = @LIBS@
|
||||
lib_a_LIBADD =
|
||||
@USE_LIBTOOL_FALSE@lib_a_OBJECTS = dl-addr.$(OBJEXT) dl-deps.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@dl-init.$(OBJEXT) dl-load.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@dl-misc.$(OBJEXT) dl-profile.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@dl-runtime.$(OBJEXT) dl-version.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@dl-close.$(OBJEXT) dl-error.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@dl-iteratephdr.$(OBJEXT) dl-lookup.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@dl-object.$(OBJEXT) dl-profstub.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@dl-support.$(OBJEXT) dl-debug.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@dl-fini.$(OBJEXT) dl-libc.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@dl-open.$(OBJEXT) dl-reloc.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@dl-sym.$(OBJEXT) dl-cache.$(OBJEXT)
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
|
||||
libdl_la_LIBADD =
|
||||
@USE_LIBTOOL_TRUE@libdl_la_OBJECTS = dl-addr.lo dl-deps.lo dl-init.lo \
|
||||
@USE_LIBTOOL_TRUE@dl-load.lo dl-misc.lo dl-profile.lo dl-runtime.lo \
|
||||
@USE_LIBTOOL_TRUE@dl-version.lo dl-close.lo dl-error.lo \
|
||||
@USE_LIBTOOL_TRUE@dl-iteratephdr.lo dl-lookup.lo dl-object.lo \
|
||||
@USE_LIBTOOL_TRUE@dl-profstub.lo dl-support.lo dl-debug.lo dl-fini.lo \
|
||||
@USE_LIBTOOL_TRUE@dl-libc.lo dl-open.lo dl-reloc.lo dl-sym.lo \
|
||||
@USE_LIBTOOL_TRUE@dl-cache.lo
|
||||
CFLAGS = @CFLAGS@
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
DATA = $(noinst_DATA)
|
||||
|
||||
DIST_COMMON = Makefile.am Makefile.in
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = gtar
|
||||
GZIP_ENV = --best
|
||||
SOURCES = $(lib_a_SOURCES) $(libdl_la_SOURCES)
|
||||
OBJECTS = $(lib_a_OBJECTS) $(libdl_la_OBJECTS)
|
||||
|
||||
all: all-redirect
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .S .c .lo .o .obj .s
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(srcdir)/../../../../Makefile.shared
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --cygnus dl/Makefile
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
|
||||
mostlyclean-noinstLIBRARIES:
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
|
||||
distclean-noinstLIBRARIES:
|
||||
|
||||
maintainer-clean-noinstLIBRARIES:
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
# FIXME: We should only use cygpath when building on Windows,
|
||||
# and only if it is available.
|
||||
.c.obj:
|
||||
$(COMPILE) -c `cygpath -w $<`
|
||||
|
||||
.s.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.S.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.o core *.core
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
clean-compile:
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
maintainer-clean-compile:
|
||||
|
||||
.c.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
.s.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
.S.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
|
||||
maintainer-clean-libtool:
|
||||
|
||||
lib.a: $(lib_a_OBJECTS) $(lib_a_DEPENDENCIES)
|
||||
-rm -f lib.a
|
||||
$(AR) cru lib.a $(lib_a_OBJECTS) $(lib_a_LIBADD)
|
||||
$(RANLIB) lib.a
|
||||
|
||||
mostlyclean-noinstLTLIBRARIES:
|
||||
|
||||
clean-noinstLTLIBRARIES:
|
||||
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
|
||||
|
||||
distclean-noinstLTLIBRARIES:
|
||||
|
||||
maintainer-clean-noinstLTLIBRARIES:
|
||||
|
||||
libdl.la: $(libdl_la_OBJECTS) $(libdl_la_DEPENDENCIES)
|
||||
$(LINK) $(libdl_la_LDFLAGS) $(libdl_la_OBJECTS) $(libdl_la_LIBADD) $(LIBS)
|
||||
|
||||
tags: TAGS
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
here=`pwd` && cd $(srcdir) \
|
||||
&& mkid -f$$here/ID $$unique $(LISP)
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|
||||
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
|
||||
|
||||
mostlyclean-tags:
|
||||
|
||||
clean-tags:
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID
|
||||
|
||||
maintainer-clean-tags:
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
|
||||
subdir = dl
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@for file in $(DISTFILES); do \
|
||||
if test -f $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||
fi; \
|
||||
done
|
||||
info-am:
|
||||
info: info-am
|
||||
dvi-am:
|
||||
dvi: dvi-am
|
||||
check-am:
|
||||
check: check-am
|
||||
installcheck-am:
|
||||
installcheck: installcheck-am
|
||||
install-info-am:
|
||||
install-info: install-info-am
|
||||
install-exec-am:
|
||||
install-exec: install-exec-am
|
||||
|
||||
install-data-am:
|
||||
install-data: install-data-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
install: install-am
|
||||
uninstall-am:
|
||||
uninstall: uninstall-am
|
||||
all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(DATA)
|
||||
all-redirect: all-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||
installdirs:
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
|
||||
maintainer-clean-generic:
|
||||
mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
|
||||
mostlyclean-libtool mostlyclean-noinstLTLIBRARIES \
|
||||
mostlyclean-tags mostlyclean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
clean-am: clean-noinstLIBRARIES clean-compile clean-libtool \
|
||||
clean-noinstLTLIBRARIES clean-tags clean-generic \
|
||||
mostlyclean-am
|
||||
|
||||
clean: clean-am
|
||||
|
||||
distclean-am: distclean-noinstLIBRARIES distclean-compile \
|
||||
distclean-libtool distclean-noinstLTLIBRARIES \
|
||||
distclean-tags distclean-generic clean-am
|
||||
-rm -f libtool
|
||||
|
||||
distclean: distclean-am
|
||||
|
||||
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
|
||||
maintainer-clean-compile maintainer-clean-libtool \
|
||||
maintainer-clean-noinstLTLIBRARIES \
|
||||
maintainer-clean-tags maintainer-clean-generic \
|
||||
distclean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
|
||||
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
|
||||
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
|
||||
mostlyclean-compile distclean-compile clean-compile \
|
||||
maintainer-clean-compile mostlyclean-libtool distclean-libtool \
|
||||
clean-libtool maintainer-clean-libtool mostlyclean-noinstLTLIBRARIES \
|
||||
distclean-noinstLTLIBRARIES clean-noinstLTLIBRARIES \
|
||||
maintainer-clean-noinstLTLIBRARIES tags mostlyclean-tags distclean-tags \
|
||||
clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
|
||||
check-am installcheck-am installcheck install-info-am install-info \
|
||||
install-exec-am install-exec install-data-am install-data install-am \
|
||||
install uninstall-am uninstall all-redirect all-am all installdirs \
|
||||
mostlyclean-generic distclean-generic clean-generic \
|
||||
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
objectlist.awk.in: $(noinst_LTLIBRARIES)
|
||||
-rm -f objectlist.awk.in
|
||||
for i in `ls *.lo` ; \
|
||||
do \
|
||||
echo $$i `pwd`/$$i >> objectlist.awk.in ; \
|
||||
done
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
4
newlib/libc/sys/linux/dl/abi-tag.h
Normal file
4
newlib/libc/sys/linux/dl/abi-tag.h
Normal file
@ -0,0 +1,4 @@
|
||||
#define __ABI_TAG_OS 0
|
||||
#ifndef __ABI_TAG_VERSION
|
||||
# define __ABI_TAG_VERSION 2,0,0
|
||||
#endif
|
56
newlib/libc/sys/linux/dl/atomicity.h
Normal file
56
newlib/libc/sys/linux/dl/atomicity.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* Low-level functions for atomic operations. ix86 version, x >= 4.
|
||||
Copyright (C) 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. */
|
||||
|
||||
#ifndef _ATOMICITY_H
|
||||
#define _ATOMICITY_H 1
|
||||
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
__attribute__ ((unused))
|
||||
exchange_and_add (volatile uint32_t *mem, uint32_t val)
|
||||
{
|
||||
register uint32_t result;
|
||||
__asm__ __volatile__ ("lock; xaddl %0,%1"
|
||||
: "=r" (result), "=m" (*mem) : "0" (val), "1" (*mem));
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__attribute__ ((unused))
|
||||
atomic_add (volatile uint32_t *mem, int val)
|
||||
{
|
||||
__asm__ __volatile__ ("lock; addl %1,%0"
|
||||
: "=m" (*mem) : "ir" (val), "0" (*mem));
|
||||
}
|
||||
|
||||
static inline char
|
||||
__attribute__ ((unused))
|
||||
compare_and_swap (volatile 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), "1" (*p), "a" (oldval));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* atomicity.h */
|
101
newlib/libc/sys/linux/dl/dl-addr.c
Normal file
101
newlib/libc/sys/linux/dl/dl-addr.c
Normal file
@ -0,0 +1,101 @@
|
||||
/* Locate the shared object symbol nearest a given address.
|
||||
Copyright (C) 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 <dlfcn.h>
|
||||
#include <stddef.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
int
|
||||
internal_function
|
||||
_dl_addr (const void *address, Dl_info *info)
|
||||
{
|
||||
const ElfW(Addr) addr = DL_LOOKUP_ADDRESS (address);
|
||||
struct link_map *l, *match;
|
||||
const ElfW(Sym) *symtab, *matchsym;
|
||||
const char *strtab;
|
||||
ElfW(Word) strtabsize;
|
||||
|
||||
/* Find the highest-addressed object that ADDRESS is not below. */
|
||||
match = NULL;
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
if (addr >= l->l_map_start && addr < l->l_map_end)
|
||||
{
|
||||
/* We know ADDRESS lies within L if in any shared object.
|
||||
Make sure it isn't past the end of L's segments. */
|
||||
size_t n = l->l_phnum;
|
||||
if (n > 0)
|
||||
{
|
||||
do
|
||||
--n;
|
||||
while (l->l_phdr[n].p_type != PT_LOAD);
|
||||
if (addr >= (l->l_addr +
|
||||
l->l_phdr[n].p_vaddr + l->l_phdr[n].p_memsz))
|
||||
/* Off the end of the highest-addressed shared object. */
|
||||
continue;
|
||||
}
|
||||
|
||||
match = l;
|
||||
break;
|
||||
}
|
||||
|
||||
if (match == NULL)
|
||||
return 0;
|
||||
|
||||
/* Now we know what object the address lies in. */
|
||||
info->dli_fname = match->l_name;
|
||||
info->dli_fbase = (void *) match->l_addr;
|
||||
|
||||
/* If this is the main program the information is incomplete. */
|
||||
if (__builtin_expect (info->dli_fbase == NULL, 0))
|
||||
{
|
||||
info->dli_fname = _dl_argv[0];
|
||||
info->dli_fbase = (void *) match->l_map_start;
|
||||
}
|
||||
|
||||
symtab = (const void *) D_PTR (match, l_info[DT_SYMTAB]);
|
||||
strtab = (const void *) D_PTR (match, l_info[DT_STRTAB]);
|
||||
strtabsize = match->l_info[DT_STRSZ]->d_un.d_val;
|
||||
|
||||
/* We assume that the string table follows the symbol table, because
|
||||
there is no way in ELF to know the size of the dynamic symbol table!! */
|
||||
for (matchsym = NULL; (void *) symtab < (void *) strtab; ++symtab)
|
||||
if (addr >= match->l_addr + symtab->st_value
|
||||
&& ((symtab->st_size == 0 && addr == match->l_addr + symtab->st_value)
|
||||
|| addr < match->l_addr + symtab->st_value + symtab->st_size)
|
||||
&& symtab->st_name < strtabsize
|
||||
&& (matchsym == NULL || matchsym->st_value < symtab->st_value)
|
||||
&& (ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
|
||||
|| ELFW(ST_BIND) (symtab->st_info) == STB_WEAK))
|
||||
matchsym = symtab;
|
||||
|
||||
if (matchsym)
|
||||
{
|
||||
/* We found a symbol close by. Fill in its name and exact address. */
|
||||
info->dli_sname = strtab + matchsym->st_name;
|
||||
info->dli_saddr = (void *) (match->l_addr + matchsym->st_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No symbol matches. We return only the containing object. */
|
||||
info->dli_sname = NULL;
|
||||
info->dli_saddr = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
271
newlib/libc/sys/linux/dl/dl-cache.c
Normal file
271
newlib/libc/sys/linux/dl/dl-cache.c
Normal file
@ -0,0 +1,271 @@
|
||||
/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
|
||||
Copyright (C) 1996,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. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <sys/mman.h>
|
||||
#include <dl-cache.h>
|
||||
#include <machine/dl-procinfo.h>
|
||||
#include <machine/weakalias.h>
|
||||
|
||||
extern const char *_dl_platform;
|
||||
|
||||
#ifndef _DL_PLATFORMS_COUNT
|
||||
# define _DL_PLATFORMS_COUNT 0
|
||||
#endif
|
||||
|
||||
/* This is the starting address and the size of the mmap()ed file. */
|
||||
static struct cache_file *cache;
|
||||
static struct cache_file_new *cache_new;
|
||||
static size_t cachesize;
|
||||
|
||||
/* 1 if cache_data + PTR points into the cache. */
|
||||
#define _dl_cache_verify_ptr(ptr) (ptr < cache_data_size)
|
||||
|
||||
/* This is the cache ID we expect. Normally it is 3 for glibc linked
|
||||
binaries. */
|
||||
int _dl_correct_cache_id = _DL_CACHE_DEFAULT_ID;
|
||||
|
||||
#define SEARCH_CACHE(cache) \
|
||||
/* We use binary search since the table is sorted in the cache file. \
|
||||
The first matching entry in the table is returned. \
|
||||
It is important to use the same algorithm as used while generating \
|
||||
the cache file. */ \
|
||||
do \
|
||||
{ \
|
||||
left = 0; \
|
||||
right = cache->nlibs - 1; \
|
||||
\
|
||||
while (left <= right) \
|
||||
{ \
|
||||
__typeof__ (cache->libs[0].key) key; \
|
||||
\
|
||||
middle = (left + right) / 2; \
|
||||
\
|
||||
key = cache->libs[middle].key; \
|
||||
\
|
||||
/* Make sure string table indices are not bogus before using \
|
||||
them. */ \
|
||||
if (! _dl_cache_verify_ptr (key)) \
|
||||
{ \
|
||||
cmpres = 1; \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
/* Actually compare the entry with the key. */ \
|
||||
cmpres = _dl_cache_libcmp (name, cache_data + key); \
|
||||
if (__builtin_expect (cmpres == 0, 0)) \
|
||||
{ \
|
||||
/* Found it. LEFT now marks the last entry for which we \
|
||||
know the name is correct. */ \
|
||||
left = middle; \
|
||||
\
|
||||
/* There might be entries with this name before the one we \
|
||||
found. So we have to find the beginning. */ \
|
||||
while (middle > 0) \
|
||||
{ \
|
||||
__typeof__ (cache->libs[0].key) key; \
|
||||
\
|
||||
key = cache->libs[middle - 1].key; \
|
||||
/* Make sure string table indices are not bogus before \
|
||||
using them. */ \
|
||||
if (! _dl_cache_verify_ptr (key) \
|
||||
/* Actually compare the entry. */ \
|
||||
|| _dl_cache_libcmp (name, cache_data + key) != 0) \
|
||||
break; \
|
||||
--middle; \
|
||||
} \
|
||||
\
|
||||
do \
|
||||
{ \
|
||||
int flags; \
|
||||
__typeof__ (cache->libs[0]) *lib = &cache->libs[middle]; \
|
||||
\
|
||||
/* Only perform the name test if necessary. */ \
|
||||
if (middle > left \
|
||||
/* We haven't seen this string so far. Test whether the \
|
||||
index is ok and whether the name matches. Otherwise \
|
||||
we are done. */ \
|
||||
&& (! _dl_cache_verify_ptr (lib->key) \
|
||||
|| (_dl_cache_libcmp (name, cache_data + lib->key) \
|
||||
!= 0))) \
|
||||
break; \
|
||||
\
|
||||
flags = lib->flags; \
|
||||
if (_dl_cache_check_flags (flags) \
|
||||
&& _dl_cache_verify_ptr (lib->value)) \
|
||||
{ \
|
||||
if (best == NULL || flags == _dl_correct_cache_id) \
|
||||
{ \
|
||||
HWCAP_CHECK; \
|
||||
best = cache_data + lib->value; \
|
||||
\
|
||||
if (flags == _dl_correct_cache_id) \
|
||||
/* We've found an exact match for the shared \
|
||||
object and no general `ELF' release. Stop \
|
||||
searching. */ \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
while (++middle <= right); \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
if (cmpres < 0) \
|
||||
left = middle + 1; \
|
||||
else \
|
||||
right = middle - 1; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
||||
|
||||
/* Look up NAME in ld.so.cache and return the file name stored there,
|
||||
or null if none is found. */
|
||||
|
||||
const char *
|
||||
internal_function
|
||||
_dl_load_cache_lookup (const char *name)
|
||||
{
|
||||
int left, right, middle;
|
||||
int cmpres;
|
||||
const char *cache_data;
|
||||
uint32_t cache_data_size;
|
||||
const char *best;
|
||||
|
||||
if (cache == NULL)
|
||||
{
|
||||
/* Read the contents of the file. */
|
||||
void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize,
|
||||
PROT_READ);
|
||||
|
||||
/* We can handle three different cache file formats here:
|
||||
- the old libc5/glibc2.0/2.1 format
|
||||
- the old format with the new format in it
|
||||
- only the new format
|
||||
The following checks if the cache contains any of these formats. */
|
||||
if (file != MAP_FAILED && cachesize > sizeof *cache
|
||||
&& memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0)
|
||||
{
|
||||
size_t offset;
|
||||
/* Looks ok. */
|
||||
cache = file;
|
||||
|
||||
/* Check for new version. */
|
||||
offset = ALIGN_CACHE (sizeof (struct cache_file)
|
||||
+ cache->nlibs * sizeof (struct file_entry));
|
||||
|
||||
cache_new = (struct cache_file_new *) ((void *) cache + offset);
|
||||
if (cachesize < (offset + sizeof (struct cache_file_new))
|
||||
|| memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW,
|
||||
sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
|
||||
cache_new = (void *) -1;
|
||||
}
|
||||
else if (file != MAP_FAILED && cachesize > sizeof *cache_new
|
||||
&& memcmp (file, CACHEMAGIC_VERSION_NEW,
|
||||
sizeof CACHEMAGIC_VERSION_NEW - 1) == 0)
|
||||
{
|
||||
cache_new = file;
|
||||
cache = file;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file != MAP_FAILED)
|
||||
munmap (file, cachesize);
|
||||
cache = (void *) -1;
|
||||
}
|
||||
|
||||
assert (cache != NULL);
|
||||
}
|
||||
|
||||
if (cache == (void *) -1)
|
||||
/* Previously looked for the cache file and didn't find it. */
|
||||
return NULL;
|
||||
|
||||
best = NULL;
|
||||
|
||||
if (cache_new != (void *) -1)
|
||||
{
|
||||
/* This file ends in static libraries where we don't have a hwcap. */
|
||||
unsigned long int *hwcap;
|
||||
uint64_t platform;
|
||||
weak_extern (_dl_hwcap);
|
||||
|
||||
/* This is where the strings start. */
|
||||
cache_data = (const char *) cache_new;
|
||||
|
||||
/* Now we can compute how large the string table is. */
|
||||
cache_data_size = (const char *) cache + cachesize - cache_data;
|
||||
|
||||
hwcap = &_dl_hwcap;
|
||||
platform = _dl_string_platform (_dl_platform);
|
||||
if (platform != -1)
|
||||
platform = 1ULL << platform;
|
||||
|
||||
/* Only accept hwcap if it's for the right platform. */
|
||||
#define HWCAP_CHECK \
|
||||
if (_dl_osversion && cache_new->libs[middle].osversion > _dl_osversion) \
|
||||
continue; \
|
||||
if (_DL_PLATFORMS_COUNT && platform != -1 \
|
||||
&& (lib->hwcap & _DL_HWCAP_PLATFORM) != 0 \
|
||||
&& (lib->hwcap & _DL_HWCAP_PLATFORM) != platform) \
|
||||
continue; \
|
||||
if (hwcap \
|
||||
&& ((lib->hwcap & *hwcap & ~_DL_HWCAP_PLATFORM) > *hwcap)) \
|
||||
continue
|
||||
SEARCH_CACHE (cache_new);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is where the strings start. */
|
||||
cache_data = (const char *) &cache->libs[cache->nlibs];
|
||||
|
||||
/* Now we can compute how large the string table is. */
|
||||
cache_data_size = (const char *) cache + cachesize - cache_data;
|
||||
|
||||
#undef HWCAP_CHECK
|
||||
#define HWCAP_CHECK do {} while (0)
|
||||
SEARCH_CACHE (cache);
|
||||
}
|
||||
|
||||
/* Print our result if wanted. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0) && best != NULL)
|
||||
_dl_debug_printf (" trying file=%s\n", best);
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
#ifndef MAP_COPY
|
||||
/* If the system does not support MAP_COPY we cannot leave the file open
|
||||
all the time since this would create problems when the file is replaced.
|
||||
Therefore we provide this function to close the file and open it again
|
||||
once needed. */
|
||||
void
|
||||
_dl_unload_cache (void)
|
||||
{
|
||||
if (cache != NULL && cache != (struct cache_file *) -1)
|
||||
{
|
||||
munmap (cache, cachesize);
|
||||
cache = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
140
newlib/libc/sys/linux/dl/dl-cache.h
Normal file
140
newlib/libc/sys/linux/dl/dl-cache.h
Normal file
@ -0,0 +1,140 @@
|
||||
/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
|
||||
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. */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef _DL_CACHE_DEFAULT_ID
|
||||
# define _DL_CACHE_DEFAULT_ID 3
|
||||
#endif
|
||||
|
||||
#ifndef _dl_cache_check_flags
|
||||
# define _dl_cache_check_flags(flags) \
|
||||
((flags) == 1 || (flags) == _DL_CACHE_DEFAULT_ID)
|
||||
#endif
|
||||
|
||||
#ifndef SYSCONFDIR
|
||||
# define SYSCONFDIR "/etc"
|
||||
#endif
|
||||
|
||||
#ifndef LD_SO_CACHE
|
||||
# define LD_SO_CACHE SYSCONFDIR "/ld.so.cache"
|
||||
#endif
|
||||
|
||||
#define CACHEMAGIC "ld.so-1.7.0"
|
||||
|
||||
/* libc5 and glibc 2.0/2.1 use the same format. For glibc 2.2 another
|
||||
format has been added in a compatible way:
|
||||
The beginning of the string table is used for the new table:
|
||||
old_magic
|
||||
nlibs
|
||||
libs[0]
|
||||
...
|
||||
libs[nlibs-1]
|
||||
pad, new magic needs to be aligned
|
||||
- this is string[0] for the old format
|
||||
new magic - this is string[0] for the new format
|
||||
newnlibs
|
||||
...
|
||||
newlibs[0]
|
||||
...
|
||||
newlibs[newnlibs-1]
|
||||
string 1
|
||||
string 2
|
||||
...
|
||||
*/
|
||||
struct file_entry
|
||||
{
|
||||
int flags; /* This is 1 for an ELF library. */
|
||||
unsigned int key, value; /* String table indices. */
|
||||
};
|
||||
|
||||
struct cache_file
|
||||
{
|
||||
char magic[sizeof CACHEMAGIC - 1];
|
||||
unsigned int nlibs;
|
||||
struct file_entry libs[0];
|
||||
};
|
||||
|
||||
#define CACHEMAGIC_NEW "glibc-ld.so.cache"
|
||||
#define CACHE_VERSION "1.1"
|
||||
#define CACHEMAGIC_VERSION_NEW CACHEMAGIC_NEW CACHE_VERSION
|
||||
|
||||
|
||||
struct file_entry_new
|
||||
{
|
||||
int32_t flags; /* This is 1 for an ELF library. */
|
||||
uint32_t key, value; /* String table indices. */
|
||||
uint32_t osversion; /* Required OS version. */
|
||||
uint64_t hwcap; /* Hwcap entry. */
|
||||
};
|
||||
|
||||
struct cache_file_new
|
||||
{
|
||||
char magic[sizeof CACHEMAGIC_NEW - 1];
|
||||
char version[sizeof CACHE_VERSION - 1];
|
||||
uint32_t nlibs; /* Number of entries. */
|
||||
uint32_t len_strings; /* Size of string table. */
|
||||
uint32_t unused[5]; /* Leave space for future extensions
|
||||
and align to 8 byte boundary. */
|
||||
struct file_entry_new libs[0]; /* Entries describing libraries. */
|
||||
/* After this the string table of size len_strings is found. */
|
||||
};
|
||||
|
||||
/* Used to align cache_file_new. */
|
||||
#define ALIGN_CACHE(addr) \
|
||||
(((addr) + __alignof__ (struct cache_file_new) -1) \
|
||||
& (~(__alignof__ (struct cache_file_new) - 1)))
|
||||
|
||||
static int
|
||||
_dl_cache_libcmp (const char *p1, const char *p2)
|
||||
{
|
||||
while (*p1 != '\0')
|
||||
{
|
||||
if (*p1 >= '0' && *p1 <= '9')
|
||||
{
|
||||
if (*p2 >= '0' && *p2 <= '9')
|
||||
{
|
||||
/* Must compare this numerically. */
|
||||
int val1;
|
||||
int val2;
|
||||
|
||||
val1 = *p1++ - '0';
|
||||
val2 = *p2++ - '0';
|
||||
while (*p1 >= '0' && *p1 <= '9')
|
||||
val1 = val1 * 10 + *p1++ - '0';
|
||||
while (*p2 >= '0' && *p2 <= '9')
|
||||
val2 = val2 * 10 + *p2++ - '0';
|
||||
if (val1 != val2)
|
||||
return val1 - val2;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
else if (*p2 >= '0' && *p2 <= '9')
|
||||
return -1;
|
||||
else if (*p1 != *p2)
|
||||
return *p1 - *p2;
|
||||
else
|
||||
{
|
||||
++p1;
|
||||
++p2;
|
||||
}
|
||||
}
|
||||
return *p1 - *p2;
|
||||
}
|
334
newlib/libc/sys/linux/dl/dl-close.c
Normal file
334
newlib/libc/sys/linux/dl/dl-close.c
Normal file
@ -0,0 +1,334 @@
|
||||
/* Close a shared object opened by `_dl_open'.
|
||||
Copyright (C) 1996,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. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <libintl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <bits/libc-lock.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
/* Type of the constructor functions. */
|
||||
typedef void (*fini_t) (void);
|
||||
|
||||
|
||||
void
|
||||
internal_function
|
||||
_dl_close (void *_map)
|
||||
{
|
||||
struct reldep_list
|
||||
{
|
||||
struct link_map **rellist;
|
||||
unsigned int nrellist;
|
||||
struct reldep_list *next;
|
||||
} *reldeps = NULL;
|
||||
struct link_map **list;
|
||||
struct link_map *map = _map;
|
||||
unsigned int i;
|
||||
unsigned int *new_opencount;
|
||||
|
||||
/* First see whether we can remove the object at all. */
|
||||
if (__builtin_expect (map->l_flags_1 & DF_1_NODELETE, 0)
|
||||
&& map->l_init_called)
|
||||
/* Nope. Do nothing. */
|
||||
return;
|
||||
|
||||
if (__builtin_expect (map->l_opencount, 1) == 0)
|
||||
_dl_signal_error (0, map->l_name, NULL, N_("shared object not open"));
|
||||
|
||||
/* Acquire the lock. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_acquire(_dl_load_lock);
|
||||
#endif
|
||||
|
||||
|
||||
/* Decrement the reference count. */
|
||||
if (map->l_opencount > 1 || map->l_type != lt_loaded)
|
||||
{
|
||||
/* There are still references to this object. Do nothing more. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
|
||||
_dl_debug_printf ("\nclosing file=%s; opencount == %u\n",
|
||||
map->l_name, map->l_opencount);
|
||||
|
||||
/* One decrement the object itself, not the dependencies. */
|
||||
--map->l_opencount;
|
||||
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release(_dl_load_lock);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
list = map->l_initfini;
|
||||
|
||||
/* Compute the new l_opencount values. */
|
||||
i = map->l_searchlist.r_nlist;
|
||||
if (__builtin_expect (i == 0, 0))
|
||||
/* This can happen if we handle relocation dependencies for an
|
||||
object which wasn't loaded directly. */
|
||||
for (i = 1; list[i] != NULL; ++i)
|
||||
;
|
||||
|
||||
new_opencount = (unsigned int *) alloca (i * sizeof (unsigned int));
|
||||
|
||||
for (i = 0; list[i] != NULL; ++i)
|
||||
{
|
||||
list[i]->l_idx = i;
|
||||
new_opencount[i] = list[i]->l_opencount;
|
||||
}
|
||||
--new_opencount[0];
|
||||
for (i = 1; list[i] != NULL; ++i)
|
||||
if ((! (list[i]->l_flags_1 & DF_1_NODELETE) || ! list[i]->l_init_called)
|
||||
/* Decrement counter. */
|
||||
&& --new_opencount[i] == 0
|
||||
/* Test whether this object was also loaded directly. */
|
||||
&& list[i]->l_searchlist.r_list != NULL)
|
||||
{
|
||||
/* In this case we have the decrement all the dependencies of
|
||||
this object. They are all in MAP's dependency list. */
|
||||
unsigned int j;
|
||||
struct link_map **dep_list = list[i]->l_searchlist.r_list;
|
||||
|
||||
for (j = 1; j < list[i]->l_searchlist.r_nlist; ++j)
|
||||
if (! (dep_list[j]->l_flags_1 & DF_1_NODELETE)
|
||||
|| ! dep_list[j]->l_init_called)
|
||||
{
|
||||
assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist);
|
||||
--new_opencount[dep_list[j]->l_idx];
|
||||
}
|
||||
}
|
||||
assert (new_opencount[0] == 0);
|
||||
|
||||
/* Call all termination functions at once. */
|
||||
for (i = 0; list[i] != NULL; ++i)
|
||||
{
|
||||
struct link_map *imap = list[i];
|
||||
if (new_opencount[i] == 0 && imap->l_type == lt_loaded
|
||||
&& (imap->l_info[DT_FINI] || imap->l_info[DT_FINI_ARRAY])
|
||||
&& (! (imap->l_flags_1 & DF_1_NODELETE) || ! imap->l_init_called)
|
||||
/* Skip any half-cooked objects that were never initialized. */
|
||||
&& imap->l_init_called)
|
||||
{
|
||||
/* When debugging print a message first. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0))
|
||||
_dl_debug_printf ("\ncalling fini: %s\n\n", imap->l_name);
|
||||
|
||||
/* Call its termination function. */
|
||||
if (imap->l_info[DT_FINI_ARRAY] != NULL)
|
||||
{
|
||||
ElfW(Addr) *array =
|
||||
(ElfW(Addr) *) (imap->l_addr
|
||||
+ imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
|
||||
unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
|
||||
/ sizeof (ElfW(Addr)));
|
||||
unsigned int cnt;
|
||||
|
||||
for (cnt = 0; cnt < sz; ++cnt)
|
||||
((fini_t) (imap->l_addr + array[cnt])) ();
|
||||
}
|
||||
|
||||
/* Next try the old-style destructor. */
|
||||
if (imap->l_info[DT_FINI] != NULL)
|
||||
(*(void (*) (void)) DL_DT_FINI_ADDRESS
|
||||
(imap, (void *) imap->l_addr
|
||||
+ imap->l_info[DT_FINI]->d_un.d_ptr)) ();
|
||||
}
|
||||
else if (new_opencount[i] != 0 && imap->l_type == lt_loaded)
|
||||
{
|
||||
/* The object is still used. But the object we are unloading
|
||||
right now is responsible for loading it and therefore we
|
||||
have the search list of the current object in its scope.
|
||||
Remove it. */
|
||||
struct r_scope_elem **runp = imap->l_scope;
|
||||
|
||||
while (*runp != NULL)
|
||||
if (*runp == &map->l_searchlist)
|
||||
{
|
||||
/* Copy all later elements. */
|
||||
while ((runp[0] = runp[1]) != NULL)
|
||||
++runp;
|
||||
break;
|
||||
}
|
||||
else
|
||||
++runp;
|
||||
}
|
||||
|
||||
/* Store the new l_opencount value. */
|
||||
imap->l_opencount = new_opencount[i];
|
||||
/* Just a sanity check. */
|
||||
assert (imap->l_type == lt_loaded || imap->l_opencount > 0);
|
||||
}
|
||||
|
||||
/* Notify the debugger we are about to remove some loaded objects. */
|
||||
_r_debug.r_state = RT_DELETE;
|
||||
_dl_debug_state ();
|
||||
|
||||
/* Check each element of the search list to see if all references to
|
||||
it are gone. */
|
||||
for (i = 0; list[i] != NULL; ++i)
|
||||
{
|
||||
struct link_map *imap = list[i];
|
||||
if (imap->l_opencount == 0 && imap->l_type == lt_loaded)
|
||||
{
|
||||
struct libname_list *lnp;
|
||||
|
||||
/* That was the last reference, and this was a dlopen-loaded
|
||||
object. We can unmap it. */
|
||||
if (__builtin_expect (imap->l_global, 0))
|
||||
{
|
||||
/* This object is in the global scope list. Remove it. */
|
||||
unsigned int cnt = _dl_main_searchlist->r_nlist;
|
||||
|
||||
do
|
||||
--cnt;
|
||||
while (_dl_main_searchlist->r_list[cnt] != imap);
|
||||
|
||||
/* The object was already correctly registered. */
|
||||
while (++cnt < _dl_main_searchlist->r_nlist)
|
||||
_dl_main_searchlist->r_list[cnt - 1]
|
||||
= _dl_main_searchlist->r_list[cnt];
|
||||
|
||||
--_dl_main_searchlist->r_nlist;
|
||||
}
|
||||
|
||||
/* We can unmap all the maps at once. We determined the
|
||||
start address and length when we loaded the object and
|
||||
the `munmap' call does the rest. */
|
||||
DL_UNMAP (imap);
|
||||
|
||||
/* Finally, unlink the data structure and free it. */
|
||||
#ifdef SHARED
|
||||
/* We will unlink the first object only if this is a statically
|
||||
linked program. */
|
||||
assert (imap->l_prev != NULL);
|
||||
imap->l_prev->l_next = imap->l_next;
|
||||
#else
|
||||
if (imap->l_prev != NULL)
|
||||
imap->l_prev->l_next = imap->l_next;
|
||||
else
|
||||
_dl_loaded = imap->l_next;
|
||||
#endif
|
||||
--_dl_nloaded;
|
||||
if (imap->l_next)
|
||||
imap->l_next->l_prev = imap->l_prev;
|
||||
|
||||
if (imap->l_versions != NULL)
|
||||
free (imap->l_versions);
|
||||
if (imap->l_origin != NULL && imap->l_origin != (char *) -1)
|
||||
free ((char *) imap->l_origin);
|
||||
|
||||
/* If the object has relocation dependencies save this
|
||||
information for latter. */
|
||||
if (__builtin_expect (imap->l_reldeps != NULL, 0))
|
||||
{
|
||||
struct reldep_list *newrel;
|
||||
|
||||
newrel = (struct reldep_list *) alloca (sizeof (*reldeps));
|
||||
newrel->rellist = imap->l_reldeps;
|
||||
newrel->nrellist = imap->l_reldepsact;
|
||||
newrel->next = reldeps;
|
||||
|
||||
reldeps = newrel;
|
||||
}
|
||||
|
||||
/* This name always is allocated. */
|
||||
free (imap->l_name);
|
||||
/* Remove the list with all the names of the shared object. */
|
||||
lnp = imap->l_libname;
|
||||
do
|
||||
{
|
||||
struct libname_list *this = lnp;
|
||||
lnp = lnp->next;
|
||||
if (!this->dont_free)
|
||||
free (this);
|
||||
}
|
||||
while (lnp != NULL);
|
||||
|
||||
/* Remove the searchlists. */
|
||||
if (imap != map)
|
||||
free (imap->l_initfini);
|
||||
|
||||
/* Remove the scope array if we allocated it. */
|
||||
if (imap->l_scope != imap->l_scope_mem)
|
||||
free (imap->l_scope);
|
||||
|
||||
if (imap->l_phdr_allocated)
|
||||
free ((void *) imap->l_phdr);
|
||||
|
||||
if (imap->l_rpath_dirs.dirs != (void *) -1)
|
||||
free (imap->l_rpath_dirs.dirs);
|
||||
if (imap->l_runpath_dirs.dirs != (void *) -1)
|
||||
free (imap->l_runpath_dirs.dirs);
|
||||
|
||||
free (imap);
|
||||
}
|
||||
}
|
||||
|
||||
/* Notify the debugger those objects are finalized and gone. */
|
||||
_r_debug.r_state = RT_CONSISTENT;
|
||||
_dl_debug_state ();
|
||||
|
||||
/* Now we can perhaps also remove the modules for which we had
|
||||
dependencies because of symbol lookup. */
|
||||
while (__builtin_expect (reldeps != NULL, 0))
|
||||
{
|
||||
while (reldeps->nrellist-- > 0)
|
||||
_dl_close (reldeps->rellist[reldeps->nrellist]);
|
||||
|
||||
free (reldeps->rellist);
|
||||
|
||||
reldeps = reldeps->next;
|
||||
}
|
||||
|
||||
free (list);
|
||||
|
||||
/* Release the lock. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release(_dl_load_lock);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
free_mem (void)
|
||||
{
|
||||
if (__builtin_expect (_dl_global_scope_alloc, 0) != 0
|
||||
&& _dl_main_searchlist->r_nlist == _dl_initial_searchlist.r_nlist)
|
||||
{
|
||||
/* All object dynamically loaded by the program are unloaded. Free
|
||||
the memory allocated for the global scope variable. */
|
||||
struct link_map **old = _dl_main_searchlist->r_list;
|
||||
|
||||
/* Put the old map in. */
|
||||
_dl_main_searchlist->r_list = _dl_initial_searchlist.r_list;
|
||||
/* Signal that the original map is used. */
|
||||
_dl_global_scope_alloc = 0;
|
||||
|
||||
/* Now free the old map. */
|
||||
free (old);
|
||||
}
|
||||
}
|
||||
text_set_element (__libc_subfreeres, free_mem);
|
57
newlib/libc/sys/linux/dl/dl-debug.c
Normal file
57
newlib/libc/sys/linux/dl/dl-debug.c
Normal file
@ -0,0 +1,57 @@
|
||||
/* Communicate dynamic linker state to the debugger at runtime.
|
||||
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; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <ldsodefs.h>
|
||||
|
||||
/* This structure communicates dl state to the debugger. The debugger
|
||||
normally finds it via the DT_DEBUG entry in the dynamic section, but in
|
||||
a statically-linked program there is no dynamic section for the debugger
|
||||
to examine and it looks for this particular symbol name. */
|
||||
struct r_debug _r_debug;
|
||||
|
||||
|
||||
/* Initialize _r_debug if it has not already been done. The argument is
|
||||
the run-time load address of the dynamic linker, to be put in
|
||||
_r_debug.r_ldbase. Returns the address of _r_debug. */
|
||||
|
||||
struct r_debug *
|
||||
internal_function
|
||||
_dl_debug_initialize (ElfW(Addr) ldbase)
|
||||
{
|
||||
if (_r_debug.r_brk == 0)
|
||||
{
|
||||
/* Tell the debugger where to find the map of loaded objects. */
|
||||
_r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */;
|
||||
_r_debug.r_ldbase = ldbase;
|
||||
_r_debug.r_map = _dl_loaded;
|
||||
_r_debug.r_brk = (ElfW(Addr)) &_dl_debug_state;
|
||||
}
|
||||
|
||||
return &_r_debug;
|
||||
}
|
||||
|
||||
|
||||
/* This function exists solely to have a breakpoint set on it by the
|
||||
debugger. The debugger is supposed to find this function's address by
|
||||
examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks
|
||||
for this particular symbol name in the PT_INTERP file. */
|
||||
void
|
||||
_dl_debug_state (void)
|
||||
{
|
||||
}
|
561
newlib/libc/sys/linux/dl/dl-deps.c
Normal file
561
newlib/libc/sys/linux/dl/dl-deps.c
Normal file
@ -0,0 +1,561 @@
|
||||
/* Load the dependencies of a mapped object.
|
||||
Copyright (C) 1996,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. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <libintl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
#include <dl-dst.h>
|
||||
|
||||
/* Whether an shared object references one or more auxiliary objects
|
||||
is signaled by the AUXTAG entry in l_info. */
|
||||
#define AUXTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
|
||||
+ DT_EXTRATAGIDX (DT_AUXILIARY))
|
||||
/* Whether an shared object references one or more auxiliary objects
|
||||
is signaled by the AUXTAG entry in l_info. */
|
||||
#define FILTERTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
|
||||
+ DT_EXTRATAGIDX (DT_FILTER))
|
||||
|
||||
/* This is zero at program start to signal that the global scope map is
|
||||
allocated by rtld. Later it keeps the size of the map. It might be
|
||||
reset if in _dl_close if the last global object is removed. */
|
||||
size_t _dl_global_scope_alloc;
|
||||
|
||||
extern size_t _dl_platformlen;
|
||||
|
||||
/* When loading auxiliary objects we must ignore errors. It's ok if
|
||||
an object is missing. */
|
||||
struct openaux_args
|
||||
{
|
||||
/* The arguments to openaux. */
|
||||
struct link_map *map;
|
||||
int trace_mode;
|
||||
const char *strtab;
|
||||
const char *name;
|
||||
|
||||
/* The return value of openaux. */
|
||||
struct link_map *aux;
|
||||
};
|
||||
|
||||
static void
|
||||
openaux (void *a)
|
||||
{
|
||||
struct openaux_args *args = (struct openaux_args *) a;
|
||||
|
||||
args->aux = _dl_map_object (args->map, args->name, 0,
|
||||
(args->map->l_type == lt_executable
|
||||
? lt_library : args->map->l_type),
|
||||
args->trace_mode, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* We use a very special kind of list to track the path
|
||||
through the list of loaded shared objects. We have to
|
||||
produce a flat list with unique members of all involved objects.
|
||||
*/
|
||||
struct list
|
||||
{
|
||||
int done; /* Nonzero if this map was processed. */
|
||||
struct link_map *map; /* The data. */
|
||||
struct list *next; /* Elements for normal list. */
|
||||
};
|
||||
|
||||
|
||||
/* Macro to expand DST. It is an macro since we use `alloca'. */
|
||||
#define expand_dst(l, str, fatal) \
|
||||
({ \
|
||||
const char *__str = (str); \
|
||||
const char *__result = __str; \
|
||||
size_t __cnt = DL_DST_COUNT(__str, 0); \
|
||||
\
|
||||
if (__cnt != 0) \
|
||||
{ \
|
||||
char *__newp; \
|
||||
\
|
||||
__newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str), \
|
||||
__cnt)); \
|
||||
\
|
||||
__result = DL_DST_SUBSTITUTE (l, __str, __newp, 0); \
|
||||
\
|
||||
if (*__result == '\0') \
|
||||
{ \
|
||||
/* The replacement for the DST is not known. We can't \
|
||||
processed. */ \
|
||||
if (fatal) \
|
||||
_dl_signal_error (0, __str, NULL, N_("\
|
||||
empty dynamics string token substitution")); \
|
||||
else \
|
||||
{ \
|
||||
/* This is for DT_AUXILIARY. */ \
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0)) \
|
||||
_dl_debug_printf ("cannot load auxiliary `%s' because of" \
|
||||
"empty dynamic string token " \
|
||||
"substitution\n", __str); \
|
||||
continue; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
__result; })
|
||||
|
||||
|
||||
void
|
||||
internal_function
|
||||
_dl_map_object_deps (struct link_map *map,
|
||||
struct link_map **preloads, unsigned int npreloads,
|
||||
int trace_mode)
|
||||
{
|
||||
struct list known[1 + npreloads + 1];
|
||||
struct list *runp, *tail;
|
||||
unsigned int nlist, i;
|
||||
/* Object name. */
|
||||
const char *name;
|
||||
int errno_saved;
|
||||
int errno_reason;
|
||||
const char *errstring;
|
||||
const char *objname;
|
||||
|
||||
auto inline void preload (struct link_map *map);
|
||||
|
||||
inline void preload (struct link_map *map)
|
||||
{
|
||||
known[nlist].done = 0;
|
||||
known[nlist].map = map;
|
||||
known[nlist].next = &known[nlist + 1];
|
||||
|
||||
++nlist;
|
||||
/* We use `l_reserved' as a mark bit to detect objects we have
|
||||
already put in the search list and avoid adding duplicate
|
||||
elements later in the list. */
|
||||
map->l_reserved = 1;
|
||||
}
|
||||
|
||||
/* No loaded object so far. */
|
||||
nlist = 0;
|
||||
|
||||
/* First load MAP itself. */
|
||||
preload (map);
|
||||
|
||||
/* Add the preloaded items after MAP but before any of its dependencies. */
|
||||
for (i = 0; i < npreloads; ++i)
|
||||
preload (preloads[i]);
|
||||
|
||||
/* Terminate the lists. */
|
||||
known[nlist - 1].next = NULL;
|
||||
|
||||
/* Pointer to last unique object. */
|
||||
tail = &known[nlist - 1];
|
||||
|
||||
/* Process each element of the search list, loading each of its
|
||||
auxiliary objects and immediate dependencies. Auxiliary objects
|
||||
will be added in the list before the object itself and
|
||||
dependencies will be appended to the list as we step through it.
|
||||
This produces a flat, ordered list that represents a
|
||||
breadth-first search of the dependency tree.
|
||||
|
||||
The whole process is complicated by the fact that we better
|
||||
should use alloca for the temporary list elements. But using
|
||||
alloca means we cannot use recursive function calls. */
|
||||
errno_saved = errno;
|
||||
errno_reason = 0;
|
||||
errstring = NULL;
|
||||
errno = 0;
|
||||
name = NULL;
|
||||
for (runp = known; runp; )
|
||||
{
|
||||
struct link_map *l = runp->map;
|
||||
struct link_map **needed = NULL;
|
||||
unsigned int nneeded = 0;
|
||||
|
||||
/* Unless otherwise stated, this object is handled. */
|
||||
runp->done = 1;
|
||||
|
||||
/* Allocate a temporary record to contain the references to the
|
||||
dependencies of this object. */
|
||||
if (l->l_searchlist.r_list == NULL && l->l_initfini == NULL
|
||||
&& l != map && l->l_ldnum > 0)
|
||||
needed = (struct link_map **) alloca (l->l_ldnum
|
||||
* sizeof (struct link_map *));
|
||||
|
||||
if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG])
|
||||
{
|
||||
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
|
||||
struct openaux_args args;
|
||||
struct list *orig;
|
||||
const ElfW(Dyn) *d;
|
||||
|
||||
args.strtab = strtab;
|
||||
args.map = l;
|
||||
args.trace_mode = trace_mode;
|
||||
orig = runp;
|
||||
|
||||
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
|
||||
if (__builtin_expect (d->d_tag, DT_NEEDED) == DT_NEEDED)
|
||||
{
|
||||
/* Map in the needed object. */
|
||||
struct link_map *dep;
|
||||
int err;
|
||||
|
||||
/* Recognize DSTs. */
|
||||
name = expand_dst (l, strtab + d->d_un.d_val, 0);
|
||||
/* Store the tag in the argument structure. */
|
||||
args.name = name;
|
||||
|
||||
err = _dl_catch_error (&objname, &errstring, openaux, &args);
|
||||
if (__builtin_expect (errstring != NULL, 0))
|
||||
{
|
||||
if (err)
|
||||
errno_reason = err;
|
||||
else
|
||||
errno_reason = -1;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
dep = args.aux;
|
||||
|
||||
if (! dep->l_reserved)
|
||||
{
|
||||
/* Allocate new entry. */
|
||||
struct list *newp;
|
||||
|
||||
newp = alloca (sizeof (struct list));
|
||||
|
||||
/* Append DEP to the list. */
|
||||
newp->map = dep;
|
||||
newp->done = 0;
|
||||
newp->next = NULL;
|
||||
tail->next = newp;
|
||||
tail = newp;
|
||||
++nlist;
|
||||
/* Set the mark bit that says it's already in the list. */
|
||||
dep->l_reserved = 1;
|
||||
}
|
||||
|
||||
/* Remember this dependency. */
|
||||
if (needed != NULL)
|
||||
needed[nneeded++] = dep;
|
||||
}
|
||||
else if (d->d_tag == DT_AUXILIARY || d->d_tag == DT_FILTER)
|
||||
{
|
||||
struct list *newp;
|
||||
|
||||
/* Recognize DSTs. */
|
||||
name = expand_dst (l, strtab + d->d_un.d_val,
|
||||
d->d_tag == DT_AUXILIARY);
|
||||
/* Store the tag in the argument structure. */
|
||||
args.name = name;
|
||||
|
||||
if (d->d_tag == DT_AUXILIARY)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Say that we are about to load an auxiliary library. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0))
|
||||
_dl_debug_printf ("load auxiliary object=%s"
|
||||
" requested by file=%s\n", name,
|
||||
l->l_name[0]
|
||||
? l->l_name : _dl_argv[0]);
|
||||
|
||||
/* We must be prepared that the addressed shared
|
||||
object is not available. */
|
||||
err = _dl_catch_error (&objname, &errstring, openaux,
|
||||
&args);
|
||||
if (__builtin_expect (errstring != NULL, 0))
|
||||
{
|
||||
/* We are not interested in the error message. */
|
||||
assert (errstring != NULL);
|
||||
if (errstring != _dl_out_of_memory)
|
||||
free ((char *) errstring);
|
||||
|
||||
/* Simply ignore this error and continue the work. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Say that we are about to load an auxiliary library. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0))
|
||||
_dl_debug_printf ("load filtered object=%s"
|
||||
" requested by file=%s\n", name,
|
||||
l->l_name[0]
|
||||
? l->l_name : _dl_argv[0]);
|
||||
|
||||
/* For filter objects the dependency must be available. */
|
||||
err = _dl_catch_error (&objname, &errstring, openaux,
|
||||
&args);
|
||||
if (__builtin_expect (errstring != NULL, 0))
|
||||
{
|
||||
if (err)
|
||||
errno_reason = err;
|
||||
else
|
||||
errno_reason = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* The auxiliary object is actually available.
|
||||
Incorporate the map in all the lists. */
|
||||
|
||||
/* Allocate new entry. This always has to be done. */
|
||||
newp = alloca (sizeof (struct list));
|
||||
|
||||
/* We want to insert the new map before the current one,
|
||||
but we have no back links. So we copy the contents of
|
||||
the current entry over. Note that ORIG and NEWP now
|
||||
have switched their meanings. */
|
||||
memcpy (newp, orig, sizeof (*newp));
|
||||
|
||||
/* Initialize new entry. */
|
||||
orig->done = 0;
|
||||
orig->map = args.aux;
|
||||
|
||||
/* Remember this dependency. */
|
||||
if (needed != NULL)
|
||||
needed[nneeded++] = args.aux;
|
||||
|
||||
/* We must handle two situations here: the map is new,
|
||||
so we must add it in all three lists. If the map
|
||||
is already known, we have two further possibilities:
|
||||
- if the object is before the current map in the
|
||||
search list, we do nothing. It is already found
|
||||
early
|
||||
- if the object is after the current one, we must
|
||||
move it just before the current map to make sure
|
||||
the symbols are found early enough
|
||||
*/
|
||||
if (args.aux->l_reserved)
|
||||
{
|
||||
/* The object is already somewhere in the list.
|
||||
Locate it first. */
|
||||
struct list *late;
|
||||
|
||||
/* This object is already in the search list we
|
||||
are building. Don't add a duplicate pointer.
|
||||
Just added by _dl_map_object. */
|
||||
for (late = newp; late->next != NULL; late = late->next)
|
||||
if (late->next->map == args.aux)
|
||||
break;
|
||||
|
||||
if (late->next != NULL)
|
||||
{
|
||||
/* The object is somewhere behind the current
|
||||
position in the search path. We have to
|
||||
move it to this earlier position. */
|
||||
orig->next = newp;
|
||||
|
||||
/* Now remove the later entry from the list
|
||||
and adjust the tail pointer. */
|
||||
if (tail == late->next)
|
||||
tail = late;
|
||||
late->next = late->next->next;
|
||||
|
||||
/* We must move the object earlier in the chain. */
|
||||
if (args.aux->l_prev != NULL)
|
||||
args.aux->l_prev->l_next = args.aux->l_next;
|
||||
if (args.aux->l_next != NULL)
|
||||
args.aux->l_next->l_prev = args.aux->l_prev;
|
||||
|
||||
args.aux->l_prev = newp->map->l_prev;
|
||||
newp->map->l_prev = args.aux;
|
||||
if (args.aux->l_prev != NULL)
|
||||
args.aux->l_prev->l_next = args.aux;
|
||||
args.aux->l_next = newp->map;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The object must be somewhere earlier in the
|
||||
list. Undo to the current list element what
|
||||
we did above. */
|
||||
memcpy (orig, newp, sizeof (*newp));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is easy. We just add the symbol right here. */
|
||||
orig->next = newp;
|
||||
++nlist;
|
||||
/* Set the mark bit that says it's already in the list. */
|
||||
args.aux->l_reserved = 1;
|
||||
|
||||
/* The only problem is that in the double linked
|
||||
list of all objects we don't have this new
|
||||
object at the correct place. Correct this here. */
|
||||
if (args.aux->l_prev)
|
||||
args.aux->l_prev->l_next = args.aux->l_next;
|
||||
if (args.aux->l_next)
|
||||
args.aux->l_next->l_prev = args.aux->l_prev;
|
||||
|
||||
args.aux->l_prev = newp->map->l_prev;
|
||||
newp->map->l_prev = args.aux;
|
||||
if (args.aux->l_prev != NULL)
|
||||
args.aux->l_prev->l_next = args.aux;
|
||||
args.aux->l_next = newp->map;
|
||||
}
|
||||
|
||||
/* Move the tail pointer if necessary. */
|
||||
if (orig == tail)
|
||||
tail = newp;
|
||||
|
||||
/* Move on the insert point. */
|
||||
orig = newp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the list of dependencies and store the array address. */
|
||||
if (needed != NULL)
|
||||
{
|
||||
needed[nneeded++] = NULL;
|
||||
|
||||
l->l_initfini = (struct link_map **)
|
||||
malloc ((nneeded + 1) * sizeof needed[0]);
|
||||
if (l->l_initfini == NULL)
|
||||
_dl_signal_error (ENOMEM, map->l_name, NULL,
|
||||
N_("cannot allocate dependency list"));
|
||||
l->l_initfini[0] = l;
|
||||
memcpy (&l->l_initfini[1], needed, nneeded * sizeof needed[0]);
|
||||
}
|
||||
|
||||
/* If we have no auxiliary objects just go on to the next map. */
|
||||
if (runp->done)
|
||||
do
|
||||
runp = runp->next;
|
||||
while (runp != NULL && runp->done);
|
||||
}
|
||||
|
||||
out:
|
||||
if (errno == 0 && errno_saved != 0)
|
||||
__set_errno (errno_saved);
|
||||
|
||||
if (map->l_initfini != NULL && map->l_type == lt_loaded)
|
||||
{
|
||||
/* This object was previously loaded as a dependency and we have
|
||||
a separate l_initfini list. We don't need it anymore. */
|
||||
assert (map->l_searchlist.r_list == NULL);
|
||||
free (map->l_initfini);
|
||||
}
|
||||
|
||||
/* Store the search list we built in the object. It will be used for
|
||||
searches in the scope of this object. */
|
||||
map->l_initfini =
|
||||
(struct link_map **) malloc ((2 * nlist + 1)
|
||||
* sizeof (struct link_map *));
|
||||
if (map->l_initfini == NULL)
|
||||
_dl_signal_error (ENOMEM, map->l_name, NULL,
|
||||
N_("cannot allocate symbol search list"));
|
||||
|
||||
|
||||
map->l_searchlist.r_list = &map->l_initfini[nlist + 1];
|
||||
map->l_searchlist.r_nlist = nlist;
|
||||
|
||||
for (nlist = 0, runp = known; runp; runp = runp->next)
|
||||
{
|
||||
if (__builtin_expect (trace_mode, 0) && runp->map->l_faked)
|
||||
/* This can happen when we trace the loading. */
|
||||
--map->l_searchlist.r_nlist;
|
||||
else
|
||||
map->l_searchlist.r_list[nlist++] = runp->map;
|
||||
|
||||
/* Now clear all the mark bits we set in the objects on the search list
|
||||
to avoid duplicates, so the next call starts fresh. */
|
||||
runp->map->l_reserved = 0;
|
||||
}
|
||||
|
||||
/* Maybe we can remove some relocation dependencies now. */
|
||||
assert (map->l_searchlist.r_list[0] == map);
|
||||
for (i = 0; i < map->l_reldepsact; ++i)
|
||||
{
|
||||
unsigned int j;
|
||||
|
||||
for (j = 1; j < nlist; ++j)
|
||||
if (map->l_searchlist.r_list[j] == map->l_reldeps[i])
|
||||
{
|
||||
/* A direct or transitive dependency is also on the list
|
||||
of relocation dependencies. Remove the latter. */
|
||||
--map->l_reldeps[i]->l_opencount;
|
||||
|
||||
for (j = i + 1; j < map->l_reldepsact; ++j)
|
||||
map->l_reldeps[j - 1] = map->l_reldeps[j];
|
||||
|
||||
--map->l_reldepsact;
|
||||
|
||||
/* Account for the '++i' performed by the 'for'. */
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now determine the order in which the initialization has to happen. */
|
||||
memcpy (map->l_initfini, map->l_searchlist.r_list,
|
||||
nlist * sizeof (struct link_map *));
|
||||
/* We can skip looking for the binary itself which is at the front
|
||||
of the search list. Look through the list backward so that circular
|
||||
dependencies are not changing the order. */
|
||||
for (i = 1; i < nlist; ++i)
|
||||
{
|
||||
struct link_map *l = map->l_searchlist.r_list[i];
|
||||
unsigned int j;
|
||||
unsigned int k;
|
||||
|
||||
/* Find the place in the initfini list where the map is currently
|
||||
located. */
|
||||
for (j = 1; map->l_initfini[j] != l; ++j)
|
||||
;
|
||||
|
||||
/* Find all object for which the current one is a dependency and
|
||||
move the found object (if necessary) in front. */
|
||||
for (k = j + 1; k < nlist; ++k)
|
||||
{
|
||||
struct link_map **runp;
|
||||
|
||||
runp = map->l_initfini[k]->l_initfini;
|
||||
if (runp != NULL)
|
||||
{
|
||||
while (*runp != NULL)
|
||||
if (__builtin_expect (*runp++ == l, 0))
|
||||
{
|
||||
struct link_map *here = map->l_initfini[k];
|
||||
|
||||
/* Move it now. */
|
||||
memmove (&map->l_initfini[j] + 1,
|
||||
&map->l_initfini[j],
|
||||
(k - j) * sizeof (struct link_map *));
|
||||
map->l_initfini[j] = here;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Terminate the list of dependencies. */
|
||||
map->l_initfini[nlist] = NULL;
|
||||
|
||||
if (errno_reason)
|
||||
_dl_signal_error (errno_reason == -1 ? 0 : errno_reason,
|
||||
objname, NULL, errstring);
|
||||
}
|
45
newlib/libc/sys/linux/dl/dl-dst.h
Normal file
45
newlib/libc/sys/linux/dl/dl-dst.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* Handling of dynamic sring tokens.
|
||||
Copyright (C) 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. */
|
||||
|
||||
/* Determine the number of DST elements in the name. Only if IS_PATH is
|
||||
nonzero paths are recognized (i.e., multiple, ':' separated filenames). */
|
||||
#define DL_DST_COUNT(name, is_path) \
|
||||
({ \
|
||||
size_t __cnt = 0; \
|
||||
const char *__sf = strchr (name, '$'); \
|
||||
\
|
||||
if (__builtin_expect (__sf != NULL, 0)) \
|
||||
__cnt = _dl_dst_count (__sf, is_path); \
|
||||
\
|
||||
__cnt; })
|
||||
|
||||
/* Prototype for used function. */
|
||||
extern size_t _dl_dst_count (const char *name, int is_path);
|
||||
|
||||
|
||||
/* Guess from the number of DSTs the length of the result string. */
|
||||
#define DL_DST_REQUIRED(l, name, len, cnt) 1024
|
||||
|
||||
/* Perform the DST substitution. */
|
||||
#define DL_DST_SUBSTITUTE(l, name, res, is_path) \
|
||||
_dl_dst_substitute (l, name, res, is_path)
|
||||
|
||||
/* Prototype for used function. */
|
||||
extern char *_dl_dst_substitute (struct link_map *l, const char *name,
|
||||
char *result, int is_path);
|
189
newlib/libc/sys/linux/dl/dl-error.c
Normal file
189
newlib/libc/sys/linux/dl/dl-error.c
Normal file
@ -0,0 +1,189 @@
|
||||
/* Error handling for runtime dynamic linker.
|
||||
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. */
|
||||
|
||||
#include <libintl.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <sys/libc-tsd.h>
|
||||
|
||||
/* This structure communicates state between _dl_catch_error and
|
||||
_dl_signal_error. */
|
||||
struct catch
|
||||
{
|
||||
const char *objname; /* Object/File name. */
|
||||
const char *errstring; /* Error detail filled in here. */
|
||||
jmp_buf env; /* longjmp here on error. */
|
||||
};
|
||||
|
||||
/* Multiple threads at once can use the `_dl_catch_error' function. The
|
||||
calls can come from `_dl_map_object_deps', `_dlerror_run', or from
|
||||
any of the libc functionality which loads dynamic objects (NSS, iconv).
|
||||
Therefore we have to be prepared to save the state in thread-local
|
||||
memory. */
|
||||
|
||||
__libc_tsd_define (static, DL_ERROR)
|
||||
#define tsd_getspecific() __libc_tsd_get (DL_ERROR)
|
||||
#define tsd_setspecific(data) __libc_tsd_set (DL_ERROR, (data))
|
||||
|
||||
|
||||
/* This message we return as a last resort. We define the string in a
|
||||
variable since we have to avoid freeing it and so have to enable
|
||||
a pointer comparison. See below and in dlfcn/dlerror.c. */
|
||||
const char _dl_out_of_memory[] = "out of memory";
|
||||
|
||||
|
||||
/* This points to a function which is called when an continuable error is
|
||||
received. Unlike the handling of `catch' this function may return.
|
||||
The arguments will be the `errstring' and `objname'.
|
||||
|
||||
Since this functionality is not used in normal programs (only in ld.so)
|
||||
we do not care about multi-threaded programs here. We keep this as a
|
||||
global variable. */
|
||||
static receiver_fct receiver;
|
||||
|
||||
|
||||
void
|
||||
internal_function
|
||||
_dl_signal_error (int errcode, const char *objname, const char *occation,
|
||||
const char *errstring)
|
||||
{
|
||||
struct catch *lcatch;
|
||||
|
||||
if (! errstring)
|
||||
errstring = N_("DYNAMIC LINKER BUG!!!");
|
||||
|
||||
lcatch = tsd_getspecific ();
|
||||
if (objname == NULL)
|
||||
objname = "";
|
||||
if (lcatch != NULL)
|
||||
{
|
||||
/* We are inside _dl_catch_error. Return to it. We have to
|
||||
duplicate the error string since it might be allocated on the
|
||||
stack. The object name is always a string constant. */
|
||||
size_t len_objname = strlen (objname) + 1;
|
||||
size_t len_errstring = strlen (errstring) + 1;
|
||||
|
||||
lcatch->errstring = (char *) malloc (len_objname + len_errstring);
|
||||
if (lcatch->errstring != NULL)
|
||||
{
|
||||
char *tmp;
|
||||
/* Make a copy of the object file name and the error string. */
|
||||
tmp = memcpy ((char *) lcatch->errstring,
|
||||
errstring, len_errstring);
|
||||
tmp += len_errstring;
|
||||
lcatch->objname = memcpy (tmp,
|
||||
objname, len_objname);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is better than nothing. */
|
||||
lcatch->objname = "";
|
||||
lcatch->errstring = _dl_out_of_memory;
|
||||
}
|
||||
longjmp (lcatch->env, errcode ?: -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Lossage while resolving the program's own symbols is always fatal. */
|
||||
char buffer[1024];
|
||||
_dl_fatal_printf ("%s: %s: %s%s%s%s%s\n",
|
||||
_dl_argv[0] ?: "<program name unknown>",
|
||||
occation ?: N_("error while loading shared libraries"),
|
||||
objname, *objname ? ": " : "",
|
||||
errstring, errcode ? ": " : "",
|
||||
(errcode
|
||||
? __strerror_r (errcode, buffer, sizeof buffer)
|
||||
: ""));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
internal_function
|
||||
_dl_signal_cerror (int errcode, const char *objname, const char *occation,
|
||||
const char *errstring)
|
||||
{
|
||||
if (receiver)
|
||||
{
|
||||
/* We are inside _dl_receive_error. Call the user supplied
|
||||
handler and resume the work. The receiver will still be
|
||||
installed. */
|
||||
(*receiver) (errcode, objname, errstring);
|
||||
}
|
||||
else
|
||||
_dl_signal_error (errcode, objname, occation, errstring);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
_dl_catch_error (const char **objname, const char **errstring,
|
||||
void (*operate) (void *), void *args)
|
||||
{
|
||||
int errcode;
|
||||
struct catch *volatile old;
|
||||
struct catch c;
|
||||
/* We need not handle `receiver' since setting a `catch' is handled
|
||||
before it. */
|
||||
|
||||
/* Some systems (e.g., SPARC) handle constructors to local variables
|
||||
inefficient. So we initialize `c' by hand. */
|
||||
c.errstring = NULL;
|
||||
|
||||
old = tsd_getspecific ();
|
||||
errcode = setjmp (c.env);
|
||||
if (__builtin_expect (errcode, 0) == 0)
|
||||
{
|
||||
tsd_setspecific (&c);
|
||||
(*operate) (args);
|
||||
tsd_setspecific (old);
|
||||
*objname = NULL;
|
||||
*errstring = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We get here only if we longjmp'd out of OPERATE. */
|
||||
tsd_setspecific (old);
|
||||
*objname = c.objname;
|
||||
*errstring = c.errstring;
|
||||
return errcode == -1 ? 0 : errcode;
|
||||
}
|
||||
|
||||
void
|
||||
internal_function
|
||||
_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
|
||||
{
|
||||
struct catch *old_catch;
|
||||
receiver_fct old_receiver;
|
||||
|
||||
old_catch = tsd_getspecific ();
|
||||
old_receiver = receiver;
|
||||
|
||||
/* Set the new values. */
|
||||
tsd_setspecific (NULL);
|
||||
receiver = fct;
|
||||
|
||||
(*operate) (args);
|
||||
|
||||
tsd_setspecific (old_catch);
|
||||
receiver = old_receiver;
|
||||
}
|
172
newlib/libc/sys/linux/dl/dl-fini.c
Normal file
172
newlib/libc/sys/linux/dl/dl-fini.c
Normal file
@ -0,0 +1,172 @@
|
||||
/* Call the termination functions of loaded shared objects.
|
||||
Copyright (C) 1995,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 <alloca.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
|
||||
/* Type of the constructor functions. */
|
||||
typedef void (*fini_t) (void);
|
||||
|
||||
|
||||
void
|
||||
internal_function
|
||||
_dl_fini (void)
|
||||
{
|
||||
/* Lots of fun ahead. We have to call the destructors for all still
|
||||
loaded objects. The problem is that the ELF specification now
|
||||
demands that dependencies between the modules are taken into account.
|
||||
I.e., the destructor for a module is called before the ones for any
|
||||
of its dependencies.
|
||||
|
||||
To make things more complicated, we cannot simply use the reverse
|
||||
order of the constructors. Since the user might have loaded objects
|
||||
using `dlopen' there are possibly several other modules with its
|
||||
dependencies to be taken into account. Therefore we have to start
|
||||
determining the order of the modules once again from the beginning. */
|
||||
unsigned int i;
|
||||
struct link_map *l;
|
||||
struct link_map **maps;
|
||||
|
||||
/* XXX Could it be (in static binaries) that there is no object loaded? */
|
||||
assert (_dl_nloaded > 0);
|
||||
|
||||
/* Now we can allocate an array to hold all the pointers and copy
|
||||
the pointers in. */
|
||||
maps = (struct link_map **) alloca (_dl_nloaded
|
||||
* sizeof (struct link_map *));
|
||||
for (l = _dl_loaded, i = 0; l != NULL; l = l->l_next)
|
||||
{
|
||||
assert (i < _dl_nloaded);
|
||||
|
||||
maps[i++] = l;
|
||||
|
||||
/* Bump l_opencount of all objects so that they are not dlclose()ed
|
||||
from underneath us. */
|
||||
++l->l_opencount;
|
||||
}
|
||||
assert (i == _dl_nloaded);
|
||||
|
||||
/* Now we have to do the sorting. */
|
||||
for (l = _dl_loaded->l_next; l != NULL; l = l->l_next)
|
||||
{
|
||||
unsigned int j;
|
||||
unsigned int k;
|
||||
|
||||
/* Find the place in the `maps' array. */
|
||||
for (j = 1; maps[j] != l; ++j)
|
||||
;
|
||||
|
||||
/* Find all object for which the current one is a dependency and
|
||||
move the found object (if necessary) in front. */
|
||||
for (k = j + 1; k < _dl_nloaded; ++k)
|
||||
{
|
||||
struct link_map **runp;
|
||||
|
||||
runp = maps[k]->l_initfini;
|
||||
if (runp != NULL)
|
||||
{
|
||||
while (*runp != NULL)
|
||||
if (*runp == l)
|
||||
{
|
||||
struct link_map *here = maps[k];
|
||||
|
||||
/* Move it now. */
|
||||
memmove (&maps[j] + 1,
|
||||
&maps[j],
|
||||
(k - j) * sizeof (struct link_map *));
|
||||
maps[j++] = here;
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
++runp;
|
||||
}
|
||||
|
||||
if (__builtin_expect (maps[k]->l_reldeps != NULL, 0))
|
||||
{
|
||||
unsigned int m = maps[k]->l_reldepsact;
|
||||
struct link_map **relmaps = maps[k]->l_reldeps;
|
||||
|
||||
while (m-- > 0)
|
||||
{
|
||||
if (relmaps[m] == l)
|
||||
{
|
||||
struct link_map *here = maps[k];
|
||||
|
||||
/* Move it now. */
|
||||
memmove (&maps[j] + 1,
|
||||
&maps[j],
|
||||
(k - j) * sizeof (struct link_map *));
|
||||
maps[j] = here;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* `maps' now contains the objects in the right order. Now call the
|
||||
destructors. We have to process this array from the front. */
|
||||
for (i = 0; i < _dl_nloaded; ++i)
|
||||
{
|
||||
l = maps[i];
|
||||
|
||||
if (l->l_init_called)
|
||||
{
|
||||
/* Make sure nothing happens if we are called twice. */
|
||||
l->l_init_called = 0;
|
||||
|
||||
/* Don't call the destructors for objects we are not supposed to. */
|
||||
if (l->l_name[0] == '\0' && l->l_type == lt_executable)
|
||||
continue;
|
||||
|
||||
/* Is there a destructor function? */
|
||||
if (l->l_info[DT_FINI_ARRAY] == NULL && l->l_info[DT_FINI] == NULL)
|
||||
continue;
|
||||
|
||||
/* When debugging print a message first. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0))
|
||||
_dl_debug_printf ("\ncalling fini: %s\n\n",
|
||||
l->l_name[0] ? l->l_name : _dl_argv[0]);
|
||||
|
||||
/* First see whether an array is given. */
|
||||
if (l->l_info[DT_FINI_ARRAY] != NULL)
|
||||
{
|
||||
ElfW(Addr) *array =
|
||||
(ElfW(Addr) *) (l->l_addr
|
||||
+ l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
|
||||
unsigned int sz = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
|
||||
/ sizeof (ElfW(Addr)));
|
||||
unsigned int cnt;
|
||||
|
||||
for (cnt = 0; cnt < sz; ++cnt)
|
||||
((fini_t) (l->l_addr + array[cnt])) ();
|
||||
}
|
||||
|
||||
/* Next try the old-style destructor. */
|
||||
if (l->l_info[DT_FINI] != NULL)
|
||||
((fini_t) DL_DT_FINI_ADDRESS (l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) ();
|
||||
}
|
||||
}
|
||||
}
|
149
newlib/libc/sys/linux/dl/dl-init.c
Normal file
149
newlib/libc/sys/linux/dl/dl-init.c
Normal file
@ -0,0 +1,149 @@
|
||||
/* Return the next shared object initializer function not yet run.
|
||||
Copyright (C) 1995,1996,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. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
|
||||
/* Type of the initializer. */
|
||||
typedef void (*init_t) (int, char **, char **);
|
||||
|
||||
/* Flag, nonzero during startup phase. */
|
||||
extern int _dl_starting_up;
|
||||
|
||||
/* The object to be initialized first. */
|
||||
extern struct link_map *_dl_initfirst;
|
||||
|
||||
|
||||
static void
|
||||
call_init (struct link_map *l, int argc, char **argv, char **env)
|
||||
{
|
||||
if (l->l_init_called)
|
||||
/* This object is all done. */
|
||||
return;
|
||||
|
||||
/* Avoid handling this constructor again in case we have a circular
|
||||
dependency. */
|
||||
l->l_init_called = 1;
|
||||
|
||||
/* Check for object which constructors we do not run here. */
|
||||
if (__builtin_expect (l->l_name[0], 'a') == '\0'
|
||||
&& l->l_type == lt_executable)
|
||||
return;
|
||||
|
||||
/* Are there any constructors? */
|
||||
if (l->l_info[DT_INIT] == NULL
|
||||
&& __builtin_expect (l->l_info[DT_INIT_ARRAY] == NULL, 1))
|
||||
return;
|
||||
|
||||
/* Print a debug message if wanted. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0))
|
||||
_dl_debug_printf ("\ncalling init: %s\n\n",
|
||||
l->l_name[0] ? l->l_name : _dl_argv[0]);
|
||||
|
||||
/* Now run the local constructors. There are two forms of them:
|
||||
- the one named by DT_INIT
|
||||
- the others in the DT_INIT_ARRAY.
|
||||
*/
|
||||
if (l->l_info[DT_INIT] != NULL)
|
||||
{
|
||||
init_t init = (init_t) DL_DT_INIT_ADDRESS
|
||||
(l, l->l_addr + l->l_info[DT_INIT]->d_un.d_ptr);
|
||||
|
||||
/* Call the function. */
|
||||
init (argc, argv, env);
|
||||
}
|
||||
|
||||
/* Next see whether there is an array with initialization functions. */
|
||||
if (l->l_info[DT_INIT_ARRAY] != NULL)
|
||||
{
|
||||
unsigned int j;
|
||||
unsigned int jm;
|
||||
ElfW(Addr) *addrs;
|
||||
|
||||
jm = l->l_info[DT_INIT_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr));
|
||||
|
||||
addrs = (ElfW(Addr) *) (l->l_info[DT_INIT_ARRAY]->d_un.d_ptr
|
||||
+ l->l_addr);
|
||||
for (j = 0; j < jm; ++j)
|
||||
((init_t) addrs[j]) (argc, argv, env);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
internal_function
|
||||
_dl_init (struct link_map *main_map, int argc, char **argv, char **env)
|
||||
{
|
||||
ElfW(Dyn) *preinit_array = main_map->l_info[DT_PREINIT_ARRAY];
|
||||
struct r_debug *r;
|
||||
unsigned int i;
|
||||
|
||||
if (__builtin_expect (_dl_initfirst != NULL, 0))
|
||||
{
|
||||
call_init (_dl_initfirst, argc, argv, env);
|
||||
_dl_initfirst = NULL;
|
||||
}
|
||||
|
||||
/* Don't do anything if there is no preinit array. */
|
||||
if (__builtin_expect (preinit_array != NULL, 0)
|
||||
&& (i = preinit_array->d_un.d_val / sizeof (ElfW(Addr))) > 0)
|
||||
{
|
||||
ElfW(Addr) *addrs;
|
||||
unsigned int cnt;
|
||||
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0))
|
||||
_dl_debug_printf ("\ncalling preinit: %s\n\n",
|
||||
main_map->l_name[0]
|
||||
? main_map->l_name : _dl_argv[0]);
|
||||
|
||||
addrs = (ElfW(Addr) *) (main_map->l_info[DT_PREINIT_ARRAY]->d_un.d_ptr
|
||||
+ main_map->l_addr);
|
||||
for (cnt = 0; cnt < i; ++cnt)
|
||||
((init_t) addrs[cnt]) (argc, argv, env);
|
||||
}
|
||||
|
||||
/* Notify the debugger we have added some objects. We need to call
|
||||
_dl_debug_initialize in a static program in case dynamic linking has
|
||||
not been used before. */
|
||||
r = _dl_debug_initialize (0);
|
||||
r->r_state = RT_ADD;
|
||||
_dl_debug_state ();
|
||||
|
||||
/* Stupid users forced the ELF specification to be changed. It now
|
||||
says that the dynamic loader is responsible for determining the
|
||||
order in which the constructors have to run. The constructors
|
||||
for all dependencies of an object must run before the constructor
|
||||
for the object itself. Circular dependencies are left unspecified.
|
||||
|
||||
This is highly questionable since it puts the burden on the dynamic
|
||||
loader which has to find the dependencies at runtime instead of
|
||||
letting the user do it right. Stupidity rules! */
|
||||
|
||||
i = main_map->l_searchlist.r_nlist;
|
||||
while (i-- > 0)
|
||||
call_init (main_map->l_initfini[i], argc, argv, env);
|
||||
|
||||
/* Notify the debugger all new objects are now ready to go. */
|
||||
r->r_state = RT_CONSISTENT;
|
||||
_dl_debug_state ();
|
||||
|
||||
/* Finished starting up. */
|
||||
_dl_starting_up = 0;
|
||||
}
|
65
newlib/libc/sys/linux/dl/dl-iteratephdr.c
Normal file
65
newlib/libc/sys/linux/dl/dl-iteratephdr.c
Normal file
@ -0,0 +1,65 @@
|
||||
/* Get loaded objects program headers.
|
||||
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
|
||||
|
||||
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 <errno.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <stddef.h>
|
||||
#include <bits/libc-lock.h>
|
||||
|
||||
int
|
||||
__dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
|
||||
size_t size, void *data), void *data)
|
||||
{
|
||||
struct link_map *l;
|
||||
struct dl_phdr_info info;
|
||||
int ret = 0;
|
||||
|
||||
/* Make sure we are alone. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_acquire(_dl_load_lock);
|
||||
#endif
|
||||
|
||||
|
||||
for (l = _dl_loaded; l != NULL; l = l->l_next)
|
||||
{
|
||||
/* Skip the dynamic linker. */
|
||||
if (l->l_phdr == NULL)
|
||||
continue;
|
||||
info.dlpi_addr = l->l_addr;
|
||||
info.dlpi_name = l->l_name;
|
||||
info.dlpi_phdr = l->l_phdr;
|
||||
info.dlpi_phnum = l->l_phnum;
|
||||
ret = callback (&info, sizeof (struct dl_phdr_info), data);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Release the lock. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release(_dl_load_lock);
|
||||
#endif
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef SHARED
|
||||
weak_alias (__dl_iterate_phdr, dl_iterate_phdr);
|
||||
#endif
|
156
newlib/libc/sys/linux/dl/dl-libc.c
Normal file
156
newlib/libc/sys/linux/dl/dl-libc.c
Normal file
@ -0,0 +1,156 @@
|
||||
/* Handle loading and unloading shared objects for internal libc purposes.
|
||||
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 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 <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
/* The purpose of this file is to provide wrappers around the dynamic
|
||||
linker error mechanism (similar to dlopen() et al in libdl) which
|
||||
are usable from within libc. Generally we want to throw away the
|
||||
string that dlerror() would return and just pass back a null pointer
|
||||
for errors. This also lets the rest of libc not know about the error
|
||||
handling mechanism.
|
||||
|
||||
Much of this code came from gconv_dl.c with slight modifications. */
|
||||
|
||||
static int
|
||||
internal_function
|
||||
dlerror_run (void (*operate) (void *), void *args)
|
||||
{
|
||||
const char *objname;
|
||||
const char *last_errstring = NULL;
|
||||
int result;
|
||||
|
||||
(void) _dl_catch_error (&objname, &last_errstring, operate, args);
|
||||
|
||||
result = last_errstring != NULL;
|
||||
if (result && last_errstring != _dl_out_of_memory)
|
||||
free ((char *) last_errstring);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* These functions are called by dlerror_run... */
|
||||
|
||||
struct do_dlopen_args
|
||||
{
|
||||
/* Argument to do_dlopen. */
|
||||
const char *name;
|
||||
|
||||
/* Return from do_dlopen. */
|
||||
struct link_map *map;
|
||||
};
|
||||
|
||||
struct do_dlsym_args
|
||||
{
|
||||
/* Arguments to do_dlsym. */
|
||||
struct link_map *map;
|
||||
const char *name;
|
||||
|
||||
/* Return values of do_dlsym. */
|
||||
lookup_t loadbase;
|
||||
const ElfW(Sym) *ref;
|
||||
};
|
||||
|
||||
static void
|
||||
do_dlopen (void *ptr)
|
||||
{
|
||||
struct do_dlopen_args *args = (struct do_dlopen_args *) ptr;
|
||||
/* Open and relocate the shared object. */
|
||||
args->map = _dl_open (args->name, RTLD_LAZY, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
do_dlsym (void *ptr)
|
||||
{
|
||||
struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
|
||||
args->ref = NULL;
|
||||
args->loadbase = _dl_lookup_symbol (args->name, args->map, &args->ref,
|
||||
args->map->l_local_scope, 0, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
do_dlclose (void *ptr)
|
||||
{
|
||||
_dl_close ((struct link_map *) ptr);
|
||||
}
|
||||
|
||||
/* ... and these functions call dlerror_run. */
|
||||
|
||||
void *
|
||||
__libc_dlopen (const char *__name)
|
||||
{
|
||||
struct do_dlopen_args args;
|
||||
args.name = __name;
|
||||
|
||||
return (dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map);
|
||||
}
|
||||
|
||||
void *
|
||||
__libc_dlsym (void *__map, const char *__name)
|
||||
{
|
||||
struct do_dlsym_args args;
|
||||
args.map = __map;
|
||||
args.name = __name;
|
||||
|
||||
return (dlerror_run (do_dlsym, &args) ? NULL
|
||||
: (void *) (DL_SYMBOL_ADDRESS (args.loadbase, args.ref)));
|
||||
}
|
||||
|
||||
int
|
||||
__libc_dlclose (void *__map)
|
||||
{
|
||||
return dlerror_run (do_dlclose, __map);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
free_mem (void)
|
||||
{
|
||||
struct link_map *l;
|
||||
struct r_search_path_elem *d;
|
||||
|
||||
/* Remove all search directories. */
|
||||
d = _dl_all_dirs;
|
||||
while (d != _dl_init_all_dirs)
|
||||
{
|
||||
struct r_search_path_elem *old = d;
|
||||
d = d->next;
|
||||
free (old);
|
||||
}
|
||||
|
||||
/* Remove all additional names added to the objects. */
|
||||
for (l = _dl_loaded; l != NULL; l = l->l_next)
|
||||
{
|
||||
struct libname_list *lnp = l->l_libname->next;
|
||||
|
||||
l->l_libname->next = NULL;
|
||||
|
||||
while (lnp != NULL)
|
||||
{
|
||||
struct libname_list *old = lnp;
|
||||
lnp = lnp->next;
|
||||
if (! old->dont_free)
|
||||
free (old);
|
||||
}
|
||||
}
|
||||
}
|
||||
text_set_element (__libc_subfreeres, free_mem);
|
87
newlib/libc/sys/linux/dl/dl-librecon.h
Normal file
87
newlib/libc/sys/linux/dl/dl-librecon.h
Normal file
@ -0,0 +1,87 @@
|
||||
/* Optional code to distinguish library flavours.
|
||||
Copyright (C) 1998, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 _DL_LIBRECON_H
|
||||
#define _DL_LIBRECON_H 1
|
||||
|
||||
#define DISTINGUISH_LIB_VERSIONS \
|
||||
do \
|
||||
{ \
|
||||
/* We have to find out whether the binary is linked against \
|
||||
libc 5 or glibc. We do this by looking at all the DT_NEEDED \
|
||||
entries. If one is libc.so.5 this is a libc 5 linked binary. */ \
|
||||
if (_dl_loaded->l_info[DT_NEEDED]) \
|
||||
{ \
|
||||
/* We have dependencies. */ \
|
||||
const ElfW(Dyn) *d; \
|
||||
const char *strtab; \
|
||||
\
|
||||
strtab = (const char *) D_PTR (_dl_loaded, l_info[DT_STRTAB]); \
|
||||
\
|
||||
for (d = _dl_loaded->l_ld; d->d_tag != DT_NULL; ++d) \
|
||||
if (d->d_tag == DT_NEEDED \
|
||||
&& strcmp (strtab + d->d_un.d_val, "libc.so.5") == 0) \
|
||||
break; \
|
||||
\
|
||||
/* We print a `5' or `6' depending on the outcome. */ \
|
||||
_dl_printf (d->d_tag != DT_NULL ? "5\n" : "6\n"); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Recognizing extra environment variables. */
|
||||
#define EXTRA_LD_ENVVARS \
|
||||
case 13: \
|
||||
if (memcmp (envline, "ASSUME_KERNEL", 13) == 0) \
|
||||
{ \
|
||||
unsigned long int i, j, osversion = 0; \
|
||||
char *p = &envline[14], *q; \
|
||||
\
|
||||
for (i = 0; i < 3; i++, p = q + 1) \
|
||||
{ \
|
||||
j = __strtoul_internal (p, &q, 0, 0); \
|
||||
if (j >= 255 || p == q || (i < 2 && *q && *q != '.')) \
|
||||
{ \
|
||||
osversion = 0; \
|
||||
break; \
|
||||
} \
|
||||
osversion |= j << (16 - 8 * i); \
|
||||
if (!*q) \
|
||||
break; \
|
||||
} \
|
||||
if (osversion) \
|
||||
_dl_osversion = osversion; \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
case 15: \
|
||||
if (memcmp (envline, "LIBRARY_VERSION", 15) == 0) \
|
||||
{ \
|
||||
_dl_correct_cache_id = envline[16] == '5' ? 2 : 3; \
|
||||
break; \
|
||||
}
|
||||
|
||||
/* Extra unsecure variables. The names are all stuffed in a single
|
||||
string which means they have to be terminated with a '\0' explicitly. */
|
||||
#define EXTRA_UNSECURE_ENVVARS \
|
||||
"LD_AOUT_LIBRARY_PATH\0" \
|
||||
"LD_AOUT_PRELOAD\0"
|
||||
|
||||
#endif /* dl-librecon.h */
|
1830
newlib/libc/sys/linux/dl/dl-load.c
Normal file
1830
newlib/libc/sys/linux/dl/dl-load.c
Normal file
File diff suppressed because it is too large
Load Diff
654
newlib/libc/sys/linux/dl/dl-lookup.c
Normal file
654
newlib/libc/sys/linux/dl/dl-lookup.c
Normal file
@ -0,0 +1,654 @@
|
||||
/* Look up a symbol in the loaded objects.
|
||||
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. */
|
||||
|
||||
#include <alloca.h>
|
||||
#include <libintl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
#include "dl-hash.h"
|
||||
#include <machine/dl-machine.h>
|
||||
#include <bits/libc-lock.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
|
||||
|
||||
/* We need this string more than once. */
|
||||
static const char undefined_msg[] = "undefined symbol: ";
|
||||
|
||||
|
||||
struct sym_val
|
||||
{
|
||||
const ElfW(Sym) *s;
|
||||
struct link_map *m;
|
||||
};
|
||||
|
||||
|
||||
#define make_string(string, rest...) \
|
||||
({ \
|
||||
const char *all[] = { string, ## rest }; \
|
||||
size_t len, cnt; \
|
||||
char *result, *cp; \
|
||||
\
|
||||
len = 1; \
|
||||
for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
|
||||
len += strlen (all[cnt]); \
|
||||
\
|
||||
cp = result = alloca (len); \
|
||||
for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
|
||||
{ \
|
||||
cp = strcpy (cp, all[cnt]); \
|
||||
cp += strlen(all[cnt]); \
|
||||
} \
|
||||
\
|
||||
result; \
|
||||
})
|
||||
|
||||
/* Statistics function. */
|
||||
unsigned long int _dl_num_relocations;
|
||||
|
||||
|
||||
/* We have two different situations when looking up a simple: with or
|
||||
without versioning. gcc is not able to optimize a single function
|
||||
definition serving for both purposes so we define two functions. */
|
||||
#define VERSIONED 0
|
||||
#include "do-lookup.h"
|
||||
|
||||
#define VERSIONED 1
|
||||
#include "do-lookup.h"
|
||||
|
||||
|
||||
/* Add extra dependency on MAP to UNDEF_MAP. */
|
||||
static int
|
||||
internal_function
|
||||
add_dependency (struct link_map *undef_map, struct link_map *map)
|
||||
{
|
||||
struct link_map **list;
|
||||
struct link_map *runp;
|
||||
unsigned int act;
|
||||
unsigned int i;
|
||||
int result = 0;
|
||||
|
||||
/* Avoid self-references. */
|
||||
if (undef_map == map)
|
||||
return 0;
|
||||
|
||||
/* Make sure nobody can unload the object while we are at it. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_acquire(_dl_load_lock);
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine whether UNDEF_MAP already has a reference to MAP. First
|
||||
look in the normal dependencies. */
|
||||
if (undef_map->l_searchlist.r_list != NULL)
|
||||
{
|
||||
list = undef_map->l_initfini;
|
||||
|
||||
for (i = 0; list[i] != NULL; ++i)
|
||||
if (list[i] == map)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* No normal dependency. See whether we already had to add it
|
||||
to the special list of dynamic dependencies. */
|
||||
list = undef_map->l_reldeps;
|
||||
act = undef_map->l_reldepsact;
|
||||
|
||||
for (i = 0; i < act; ++i)
|
||||
if (list[i] == map)
|
||||
goto out;
|
||||
|
||||
/* The object is not yet in the dependency list. Before we add
|
||||
it make sure just one more time the object we are about to
|
||||
reference is still available. There is a brief period in
|
||||
which the object could have been removed since we found the
|
||||
definition. */
|
||||
runp = _dl_loaded;
|
||||
while (runp != NULL && runp != map)
|
||||
runp = runp->l_next;
|
||||
|
||||
if (runp != NULL)
|
||||
{
|
||||
/* The object is still available. Add the reference now. */
|
||||
if (__builtin_expect (act >= undef_map->l_reldepsmax, 0))
|
||||
{
|
||||
/* Allocate more memory for the dependency list. Since this
|
||||
can never happen during the startup phase we can use
|
||||
`realloc'. */
|
||||
void *newp;
|
||||
|
||||
undef_map->l_reldepsmax += 5;
|
||||
newp = realloc (undef_map->l_reldeps,
|
||||
undef_map->l_reldepsmax
|
||||
* sizeof (struct link_map *));
|
||||
|
||||
if (__builtin_expect (newp != NULL, 1))
|
||||
undef_map->l_reldeps = (struct link_map **) newp;
|
||||
else
|
||||
/* Correct the addition. */
|
||||
undef_map->l_reldepsmax -= 5;
|
||||
}
|
||||
|
||||
/* If we didn't manage to allocate memory for the list this is
|
||||
no fatal mistake. We simply increment the use counter of the
|
||||
referenced object and don't record the dependencies. This
|
||||
means this increment can never be reverted and the object
|
||||
will never be unloaded. This is semantically the correct
|
||||
behaviour. */
|
||||
if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
|
||||
undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
|
||||
|
||||
if (map->l_searchlist.r_list != NULL)
|
||||
/* And increment the counter in the referenced object. */
|
||||
++map->l_opencount;
|
||||
else
|
||||
/* We have to bump the counts for all dependencies since so far
|
||||
this object was only a normal or transitive dependency.
|
||||
Now it might be closed with _dl_close() directly. */
|
||||
for (list = map->l_initfini; *list != NULL; ++list)
|
||||
++(*list)->l_opencount;
|
||||
|
||||
/* Display information if we are debugging. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
|
||||
_dl_debug_printf ("\
|
||||
\nfile=%s; needed by %s (relocation dependency)\n\n",
|
||||
map->l_name[0] ? map->l_name : _dl_argv[0],
|
||||
undef_map->l_name[0]
|
||||
? undef_map->l_name : _dl_argv[0]);
|
||||
}
|
||||
else
|
||||
/* Whoa, that was bad luck. We have to search again. */
|
||||
result = -1;
|
||||
|
||||
out:
|
||||
/* Release the lock. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release(_dl_load_lock);
|
||||
#endif
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
internal_function
|
||||
_dl_do_lookup (const char *undef_name, unsigned long int hash,
|
||||
const ElfW(Sym) *ref, struct sym_val *result,
|
||||
struct r_scope_elem *scope, size_t i,
|
||||
struct link_map *skip, int type_class);
|
||||
static int
|
||||
internal_function
|
||||
_dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
|
||||
const ElfW(Sym) *ref, struct sym_val *result,
|
||||
struct r_scope_elem *scope, size_t i,
|
||||
const struct r_found_version *const version,
|
||||
struct link_map *skip, int type_class);
|
||||
|
||||
|
||||
/* Search loaded objects' symbol tables for a definition of the symbol
|
||||
UNDEF_NAME. */
|
||||
|
||||
lookup_t
|
||||
internal_function
|
||||
_dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
|
||||
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
|
||||
int type_class, int explicit)
|
||||
{
|
||||
unsigned long int hash = _dl_elf_hash (undef_name);
|
||||
struct sym_val current_value = { NULL, NULL };
|
||||
struct r_scope_elem **scope;
|
||||
int protected;
|
||||
|
||||
++_dl_num_relocations;
|
||||
|
||||
/* Search the relevant loaded objects for a definition. */
|
||||
for (scope = symbol_scope; *scope; ++scope)
|
||||
if (do_lookup (undef_name, hash, *ref, ¤t_value, *scope, 0, NULL,
|
||||
type_class))
|
||||
{
|
||||
/* We have to check whether this would bind UNDEF_MAP to an object
|
||||
in the global scope which was dynamically loaded. In this case
|
||||
we have to prevent the latter from being unloaded unless the
|
||||
UNDEF_MAP object is also unloaded. */
|
||||
if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
|
||||
/* Don't do this for explicit lookups as opposed to implicit
|
||||
runtime lookups. */
|
||||
&& ! explicit
|
||||
/* Add UNDEF_MAP to the dependencies. */
|
||||
&& add_dependency (undef_map, current_value.m) < 0)
|
||||
/* Something went wrong. Perhaps the object we tried to reference
|
||||
was just removed. Try finding another definition. */
|
||||
return _dl_lookup_symbol (undef_name, undef_map, ref, symbol_scope,
|
||||
type_class, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (__builtin_expect (current_value.s == NULL, 0))
|
||||
{
|
||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||
|
||||
if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
|
||||
/* We could find no value for a strong reference. */
|
||||
/* XXX We cannot translate the messages. */
|
||||
_dl_signal_cerror (0, (reference_name && reference_name[0]
|
||||
? reference_name
|
||||
: (_dl_argv[0] ?: "<main program>")),
|
||||
N_("relocation error"),
|
||||
make_string (undefined_msg, undef_name));
|
||||
*ref = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
||||
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
|
||||
{
|
||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||
|
||||
_dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
|
||||
(reference_name && reference_name[0]
|
||||
? reference_name : (_dl_argv[0] ?: "<main program>")),
|
||||
current_value.m->l_name[0]
|
||||
? current_value.m->l_name : _dl_argv[0],
|
||||
protected ? "protected" : "normal", undef_name);
|
||||
}
|
||||
|
||||
if (__builtin_expect (protected == 0, 1))
|
||||
{
|
||||
*ref = current_value.s;
|
||||
return LOOKUP_VALUE (current_value.m);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It is very tricky. We need to figure out what value to
|
||||
return for the protected symbol */
|
||||
struct sym_val protected_value = { NULL, NULL };
|
||||
|
||||
for (scope = symbol_scope; *scope; ++scope)
|
||||
if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
|
||||
0, NULL, ELF_RTYPE_CLASS_PLT))
|
||||
break;
|
||||
|
||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
||||
{
|
||||
*ref = current_value.s;
|
||||
return LOOKUP_VALUE (current_value.m);
|
||||
}
|
||||
|
||||
return LOOKUP_VALUE (undef_map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This function is nearly the same as `_dl_lookup_symbol' but it
|
||||
skips in the first list all objects until SKIP_MAP is found. I.e.,
|
||||
it only considers objects which were loaded after the described
|
||||
object. If there are more search lists the object described by
|
||||
SKIP_MAP is only skipped. */
|
||||
lookup_t
|
||||
internal_function
|
||||
_dl_lookup_symbol_skip (const char *undef_name,
|
||||
struct link_map *undef_map, const ElfW(Sym) **ref,
|
||||
struct r_scope_elem *symbol_scope[],
|
||||
struct link_map *skip_map)
|
||||
{
|
||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||
struct sym_val current_value = { NULL, NULL };
|
||||
struct r_scope_elem **scope;
|
||||
size_t i;
|
||||
int protected;
|
||||
|
||||
++_dl_num_relocations;
|
||||
|
||||
/* Search the relevant loaded objects for a definition. */
|
||||
scope = symbol_scope;
|
||||
for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
|
||||
assert (i < (*scope)->r_nlist);
|
||||
|
||||
if (! _dl_do_lookup (undef_name, hash, *ref, ¤t_value, *scope, i,
|
||||
skip_map, 0))
|
||||
while (*++scope)
|
||||
if (_dl_do_lookup (undef_name, hash, *ref, ¤t_value, *scope, 0,
|
||||
skip_map, 0))
|
||||
break;
|
||||
|
||||
if (__builtin_expect (current_value.s == NULL, 0))
|
||||
{
|
||||
*ref = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
||||
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
|
||||
_dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
|
||||
(reference_name && reference_name[0]
|
||||
? reference_name : (_dl_argv[0] ?: "<main program>")),
|
||||
current_value.m->l_name[0]
|
||||
? current_value.m->l_name : _dl_argv[0],
|
||||
protected ? "protected" : "normal", undef_name);
|
||||
|
||||
if (__builtin_expect (protected == 0, 1))
|
||||
{
|
||||
*ref = current_value.s;
|
||||
return LOOKUP_VALUE (current_value.m);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It is very tricky. We need to figure out what value to
|
||||
return for the protected symbol. */
|
||||
struct sym_val protected_value = { NULL, NULL };
|
||||
|
||||
if (i >= (*scope)->r_nlist
|
||||
|| !_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
|
||||
i, skip_map, ELF_RTYPE_CLASS_PLT))
|
||||
while (*++scope)
|
||||
if (_dl_do_lookup (undef_name, hash, *ref, &protected_value, *scope,
|
||||
0, skip_map, ELF_RTYPE_CLASS_PLT))
|
||||
break;
|
||||
|
||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
||||
{
|
||||
*ref = current_value.s;
|
||||
return LOOKUP_VALUE (current_value.m);
|
||||
}
|
||||
|
||||
return LOOKUP_VALUE (undef_map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This function works like _dl_lookup_symbol but it takes an
|
||||
additional arguement with the version number of the requested
|
||||
symbol.
|
||||
|
||||
XXX We'll see whether we need this separate function. */
|
||||
lookup_t
|
||||
internal_function
|
||||
_dl_lookup_versioned_symbol (const char *undef_name,
|
||||
struct link_map *undef_map, const ElfW(Sym) **ref,
|
||||
struct r_scope_elem *symbol_scope[],
|
||||
const struct r_found_version *version,
|
||||
int type_class, int explicit)
|
||||
{
|
||||
unsigned long int hash = _dl_elf_hash (undef_name);
|
||||
struct sym_val current_value = { NULL, NULL };
|
||||
struct r_scope_elem **scope;
|
||||
int protected;
|
||||
|
||||
++_dl_num_relocations;
|
||||
|
||||
/* Search the relevant loaded objects for a definition. */
|
||||
for (scope = symbol_scope; *scope; ++scope)
|
||||
{
|
||||
int res = do_lookup_versioned (undef_name, hash, *ref, ¤t_value,
|
||||
*scope, 0, version, NULL, type_class);
|
||||
if (res > 0)
|
||||
{
|
||||
/* We have to check whether this would bind UNDEF_MAP to an object
|
||||
in the global scope which was dynamically loaded. In this case
|
||||
we have to prevent the latter from being unloaded unless the
|
||||
UNDEF_MAP object is also unloaded. */
|
||||
if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
|
||||
/* Don't do this for explicit lookups as opposed to implicit
|
||||
runtime lookups. */
|
||||
&& ! explicit
|
||||
/* Add UNDEF_MAP to the dependencies. */
|
||||
&& add_dependency (undef_map, current_value.m) < 0)
|
||||
/* Something went wrong. Perhaps the object we tried to reference
|
||||
was just removed. Try finding another definition. */
|
||||
return _dl_lookup_versioned_symbol (undef_name, undef_map, ref,
|
||||
symbol_scope, version,
|
||||
type_class, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (__builtin_expect (res, 0) < 0)
|
||||
{
|
||||
/* Oh, oh. The file named in the relocation entry does not
|
||||
contain the needed symbol. */
|
||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||
|
||||
/* XXX We cannot translate the message. */
|
||||
_dl_signal_cerror (0, (reference_name && reference_name[0]
|
||||
? reference_name
|
||||
: (_dl_argv[0] ?: "<main program>")),
|
||||
N_("relocation error"),
|
||||
make_string ("symbol ", undef_name, ", version ",
|
||||
version->name,
|
||||
" not defined in file ",
|
||||
version->filename,
|
||||
" with link time reference",
|
||||
res == -2
|
||||
? " (no version symbols)" : ""));
|
||||
*ref = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (__builtin_expect (current_value.s == NULL, 0))
|
||||
{
|
||||
if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
|
||||
{
|
||||
/* We could find no value for a strong reference. */
|
||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||
|
||||
/* XXX We cannot translate the message. */
|
||||
_dl_signal_cerror (0, (reference_name && reference_name[0]
|
||||
? reference_name
|
||||
: (_dl_argv[0] ?: "<main program>")), NULL,
|
||||
make_string (undefined_msg, undef_name,
|
||||
", version ",
|
||||
version->name ?: NULL));
|
||||
}
|
||||
*ref = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
||||
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
|
||||
{
|
||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||
|
||||
_dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
|
||||
(reference_name && reference_name[0]
|
||||
? reference_name : (_dl_argv[0] ?: "<main program>")),
|
||||
current_value.m->l_name[0]
|
||||
? current_value.m->l_name : _dl_argv[0],
|
||||
protected ? "protected" : "normal",
|
||||
undef_name, version->name);
|
||||
}
|
||||
|
||||
if (__builtin_expect (protected == 0, 1))
|
||||
{
|
||||
*ref = current_value.s;
|
||||
return LOOKUP_VALUE (current_value.m);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It is very tricky. We need to figure out what value to
|
||||
return for the protected symbol */
|
||||
struct sym_val protected_value = { NULL, NULL };
|
||||
|
||||
for (scope = symbol_scope; *scope; ++scope)
|
||||
if (_dl_do_lookup_versioned (undef_name, hash, *ref, &protected_value,
|
||||
*scope, 0, version, NULL,
|
||||
ELF_RTYPE_CLASS_PLT))
|
||||
break;
|
||||
|
||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
||||
{
|
||||
*ref = current_value.s;
|
||||
return LOOKUP_VALUE (current_value.m);
|
||||
}
|
||||
|
||||
return LOOKUP_VALUE (undef_map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Similar to _dl_lookup_symbol_skip but takes an additional argument
|
||||
with the version we are looking for. */
|
||||
lookup_t
|
||||
internal_function
|
||||
_dl_lookup_versioned_symbol_skip (const char *undef_name,
|
||||
struct link_map *undef_map,
|
||||
const ElfW(Sym) **ref,
|
||||
struct r_scope_elem *symbol_scope[],
|
||||
const struct r_found_version *version,
|
||||
struct link_map *skip_map)
|
||||
{
|
||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||
struct sym_val current_value = { NULL, NULL };
|
||||
struct r_scope_elem **scope;
|
||||
size_t i;
|
||||
int protected;
|
||||
|
||||
++_dl_num_relocations;
|
||||
|
||||
/* Search the relevant loaded objects for a definition. */
|
||||
scope = symbol_scope;
|
||||
for (i = 0; (*scope)->r_list[i] != skip_map; ++i)
|
||||
assert (i < (*scope)->r_nlist);
|
||||
|
||||
if (! _dl_do_lookup_versioned (undef_name, hash, *ref, ¤t_value,
|
||||
*scope, i, version, skip_map, 0))
|
||||
while (*++scope)
|
||||
if (_dl_do_lookup_versioned (undef_name, hash, *ref, ¤t_value,
|
||||
*scope, 0, version, skip_map, 0))
|
||||
break;
|
||||
|
||||
if (__builtin_expect (current_value.s == NULL, 0))
|
||||
{
|
||||
if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
|
||||
{
|
||||
/* We could find no value for a strong reference. */
|
||||
const size_t len = strlen (undef_name);
|
||||
char buf[sizeof undefined_msg + len];
|
||||
char *tmp;
|
||||
tmp = memcpy (buf, undefined_msg, sizeof undefined_msg - 1);
|
||||
tmp += (sizeof undefined_msg - 1);
|
||||
|
||||
memcpy (tmp, undef_name, len + 1);
|
||||
|
||||
/* XXX We cannot translate the messages. */
|
||||
_dl_signal_cerror (0, (reference_name && reference_name[0]
|
||||
? reference_name
|
||||
: (_dl_argv[0] ?: "<main program>")),
|
||||
NULL, buf);
|
||||
}
|
||||
*ref = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
||||
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
|
||||
_dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
|
||||
(reference_name && reference_name[0]
|
||||
? reference_name : (_dl_argv[0] ?: "<main program>")),
|
||||
current_value.m->l_name[0]
|
||||
? current_value.m->l_name : _dl_argv[0],
|
||||
protected ? "protected" : "normal",
|
||||
undef_name, version->name);
|
||||
|
||||
if (__builtin_expect (protected == 0, 1))
|
||||
{
|
||||
*ref = current_value.s;
|
||||
return LOOKUP_VALUE (current_value.m);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It is very tricky. We need to figure out what value to
|
||||
return for the protected symbol */
|
||||
struct sym_val protected_value = { NULL, NULL };
|
||||
|
||||
if (i >= (*scope)->r_nlist
|
||||
|| !_dl_do_lookup_versioned (undef_name, hash, *ref,
|
||||
&protected_value, *scope, i, version,
|
||||
skip_map, ELF_RTYPE_CLASS_PLT))
|
||||
while (*++scope)
|
||||
if (_dl_do_lookup_versioned (undef_name, hash, *ref,
|
||||
&protected_value, *scope, 0, version,
|
||||
skip_map, ELF_RTYPE_CLASS_PLT))
|
||||
break;
|
||||
|
||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
||||
{
|
||||
*ref = current_value.s;
|
||||
return LOOKUP_VALUE (current_value.m);
|
||||
}
|
||||
|
||||
return LOOKUP_VALUE (undef_map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Cache the location of MAP's hash table. */
|
||||
|
||||
void
|
||||
internal_function
|
||||
_dl_setup_hash (struct link_map *map)
|
||||
{
|
||||
Elf_Symndx *hash;
|
||||
Elf_Symndx nchain;
|
||||
|
||||
if (!map->l_info[DT_HASH])
|
||||
return;
|
||||
hash = (void *)(map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr);
|
||||
|
||||
map->l_nbuckets = *hash++;
|
||||
nchain = *hash++;
|
||||
map->l_buckets = hash;
|
||||
hash += map->l_nbuckets;
|
||||
map->l_chain = hash;
|
||||
}
|
||||
|
||||
/* These are here so that we only inline do_lookup{,_versioned} in the common
|
||||
case, not everywhere. */
|
||||
static int
|
||||
internal_function
|
||||
_dl_do_lookup (const char *undef_name, unsigned long int hash,
|
||||
const ElfW(Sym) *ref, struct sym_val *result,
|
||||
struct r_scope_elem *scope, size_t i,
|
||||
struct link_map *skip, int type_class)
|
||||
{
|
||||
return do_lookup (undef_name, hash, ref, result, scope, i, skip,
|
||||
type_class);
|
||||
}
|
||||
|
||||
static int
|
||||
internal_function
|
||||
_dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
|
||||
const ElfW(Sym) *ref, struct sym_val *result,
|
||||
struct r_scope_elem *scope, size_t i,
|
||||
const struct r_found_version *const version,
|
||||
struct link_map *skip, int type_class)
|
||||
{
|
||||
return do_lookup_versioned (undef_name, hash, ref, result, scope, i,
|
||||
version, skip, type_class);
|
||||
}
|
22
newlib/libc/sys/linux/dl/dl-lookupcfg.h
Normal file
22
newlib/libc/sys/linux/dl/dl-lookupcfg.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* Configuration of lookup functions.
|
||||
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. */
|
||||
|
||||
/* Some platforms need more information from the symbol lookup function
|
||||
than just the address. But this is not generally the case. */
|
||||
#undef DL_LOOKUP_RETURNS_MAP
|
250
newlib/libc/sys/linux/dl/dl-minimal.c
Normal file
250
newlib/libc/sys/linux/dl/dl-minimal.c
Normal file
@ -0,0 +1,250 @@
|
||||
/* Minimal replacements for basic facilities used in the dynamic linker.
|
||||
Copyright (C) 1995,96,97,98,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 <errno.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <machine/weakalias.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* Minimal `malloc' allocator for use while loading shared libraries.
|
||||
No block is ever freed. */
|
||||
|
||||
static void *alloc_ptr, *alloc_end, *alloc_last_block;
|
||||
|
||||
/* Declarations of global functions. */
|
||||
extern void weak_function free (void *ptr);
|
||||
extern void * weak_function realloc (void *ptr, size_t n);
|
||||
extern unsigned long int weak_function __strtoul_internal
|
||||
(const char *nptr, char **endptr, int base, int group);
|
||||
extern unsigned long int weak_function strtoul (const char *nptr,
|
||||
char **endptr, int base);
|
||||
|
||||
|
||||
void * weak_function
|
||||
malloc (size_t n)
|
||||
{
|
||||
#ifdef MAP_ANON
|
||||
#define _dl_zerofd (-1)
|
||||
#else
|
||||
extern int _dl_zerofd;
|
||||
|
||||
if (_dl_zerofd == -1)
|
||||
_dl_zerofd = _dl_sysdep_open_zero_fill ();
|
||||
#define MAP_ANON 0
|
||||
#endif
|
||||
|
||||
if (alloc_end == 0)
|
||||
{
|
||||
/* Consume any unused space in the last page of our data segment. */
|
||||
extern int _end;
|
||||
alloc_ptr = &_end;
|
||||
alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0) + _dl_pagesize - 1)
|
||||
& ~(_dl_pagesize - 1));
|
||||
}
|
||||
|
||||
/* Make sure the allocation pointer is ideally aligned. */
|
||||
alloc_ptr = (void *) 0 + (((alloc_ptr - (void *) 0) + sizeof (double) - 1)
|
||||
& ~(sizeof (double) - 1));
|
||||
|
||||
if (alloc_ptr + n >= alloc_end)
|
||||
{
|
||||
/* Insufficient space left; allocate another page. */
|
||||
caddr_t page;
|
||||
size_t nup = (n + _dl_pagesize - 1) & ~(_dl_pagesize - 1);
|
||||
page = __mmap (0, nup, PROT_READ|PROT_WRITE,
|
||||
MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
|
||||
assert (page != MAP_FAILED);
|
||||
if (page != alloc_end)
|
||||
alloc_ptr = page;
|
||||
alloc_end = page + nup;
|
||||
}
|
||||
|
||||
alloc_last_block = (void *) alloc_ptr;
|
||||
alloc_ptr += n;
|
||||
return alloc_last_block;
|
||||
}
|
||||
|
||||
/* We use this function occasionally since the real implementation may
|
||||
be optimized when it can assume the memory it returns already is
|
||||
set to NUL. */
|
||||
void * weak_function
|
||||
calloc (size_t nmemb, size_t size)
|
||||
{
|
||||
size_t total = nmemb * size;
|
||||
void *result = malloc (total);
|
||||
return memset (result, '\0', total);
|
||||
}
|
||||
|
||||
/* This will rarely be called. */
|
||||
void weak_function
|
||||
free (void *ptr)
|
||||
{
|
||||
/* We can free only the last block allocated. */
|
||||
if (ptr == alloc_last_block)
|
||||
alloc_ptr = alloc_last_block;
|
||||
}
|
||||
|
||||
/* This is only called with the most recent block returned by malloc. */
|
||||
void * weak_function
|
||||
realloc (void *ptr, size_t n)
|
||||
{
|
||||
void *new;
|
||||
if (ptr == NULL)
|
||||
return malloc (n);
|
||||
assert (ptr == alloc_last_block);
|
||||
alloc_ptr = alloc_last_block;
|
||||
new = malloc (n);
|
||||
assert (new == ptr);
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
/* Define our own version of the internal function used by strerror. We
|
||||
only provide the messages for some common errors. This avoids pulling
|
||||
in the whole error list. */
|
||||
|
||||
char * weak_function
|
||||
__strerror_r (int errnum, char *buf, size_t buflen)
|
||||
{
|
||||
char *msg;
|
||||
|
||||
switch (errnum)
|
||||
{
|
||||
case ENOMEM:
|
||||
msg = (char *) "Cannot allocate memory";
|
||||
break;
|
||||
case EINVAL:
|
||||
msg = (char *) "Invalid argument";
|
||||
break;
|
||||
case ENOENT:
|
||||
msg = (char *) "No such file or directory";
|
||||
break;
|
||||
case EPERM:
|
||||
msg = (char *) "Operation not permitted";
|
||||
break;
|
||||
case EIO:
|
||||
msg = (char *) "Input/output error";
|
||||
break;
|
||||
case EACCES:
|
||||
msg = (char *) "Permission denied";
|
||||
break;
|
||||
default:
|
||||
/* No need to check buffer size, all calls in the dynamic linker
|
||||
provide enough space. */
|
||||
msg = (char *) "Error";
|
||||
break;
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
/* Define (weakly) our own assert failure function which doesn't use stdio.
|
||||
If we are linked into the user program (-ldl), the normal __assert_fail
|
||||
defn can override this one. */
|
||||
|
||||
void weak_function
|
||||
__assert_fail (const char *assertion,
|
||||
const char *file, unsigned int line, const char *function)
|
||||
{
|
||||
_dl_fatal_printf ("\
|
||||
Inconsistency detected by ld.so: %s: %u: %s%sAssertion `%s' failed!\n",
|
||||
file, line, function ?: "", function ? ": " : "",
|
||||
assertion);
|
||||
|
||||
}
|
||||
|
||||
void weak_function
|
||||
__assert_perror_fail (int errnum,
|
||||
const char *file, unsigned int line,
|
||||
const char *function)
|
||||
{
|
||||
char errbuf[64];
|
||||
_dl_fatal_printf ("\
|
||||
Inconsistency detected by ld.so: %s: %u: %s%sUnexpected error: %s\n",
|
||||
file, line, function ?: "", function ? ": " : "",
|
||||
__strerror_r (errnum, errbuf, sizeof (errbuf)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
unsigned long int weak_function
|
||||
__strtoul_internal (const char *nptr, char **endptr, int base, int group)
|
||||
{
|
||||
unsigned long int result = 0;
|
||||
long int sign = 1;
|
||||
|
||||
while (*nptr == ' ' || *nptr == '\t')
|
||||
++nptr;
|
||||
|
||||
if (*nptr == '-')
|
||||
{
|
||||
sign = -1;
|
||||
++nptr;
|
||||
}
|
||||
else if (*nptr == '+')
|
||||
++nptr;
|
||||
|
||||
if (*nptr < '0' || *nptr > '9')
|
||||
{
|
||||
if (endptr != NULL)
|
||||
*endptr = (char *) nptr;
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
assert (base == 0);
|
||||
base = 10;
|
||||
if (*nptr == '0')
|
||||
{
|
||||
if (nptr[1] == 'x' || nptr[1] == 'X')
|
||||
{
|
||||
base = 16;
|
||||
nptr += 2;
|
||||
}
|
||||
else
|
||||
base = 8;
|
||||
}
|
||||
|
||||
while (*nptr >= '0' && *nptr <= '9')
|
||||
{
|
||||
unsigned long int digval = *nptr - '0';
|
||||
if (result > LONG_MAX / 10
|
||||
|| (result == ULONG_MAX / 10 && digval > ULONG_MAX % 10))
|
||||
{
|
||||
errno = ERANGE;
|
||||
if (endptr != NULL)
|
||||
*endptr = (char *) nptr;
|
||||
return ULONG_MAX;
|
||||
}
|
||||
result *= base;
|
||||
result += digval;
|
||||
++nptr;
|
||||
}
|
||||
|
||||
if (endptr != NULL)
|
||||
*endptr = (char *) nptr;
|
||||
return result * sign;
|
||||
}
|
277
newlib/libc/sys/linux/dl/dl-misc.c
Normal file
277
newlib/libc/sys/linux/dl/dl-misc.c
Normal file
@ -0,0 +1,277 @@
|
||||
/* Miscellaneous support functions for dynamic linker
|
||||
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. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <limits.h>
|
||||
#include <link.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#ifndef MAP_ANON
|
||||
/* This is the only dl-sysdep.c function that is actually needed at run-time
|
||||
by _dl_map_object. */
|
||||
|
||||
int
|
||||
_dl_sysdep_open_zero_fill (void)
|
||||
{
|
||||
return __open ("/dev/zero", O_RDONLY);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Read the whole contents of FILE into new mmap'd space with given
|
||||
protections. *SIZEP gets the size of the file. On error MAP_FAILED
|
||||
is returned. */
|
||||
|
||||
void *
|
||||
internal_function
|
||||
_dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
|
||||
{
|
||||
void *result = MAP_FAILED;
|
||||
struct stat64 st;
|
||||
int fd = __open (file, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
if (fstat64 (fd, &st) >= 0)
|
||||
{
|
||||
*sizep = st.st_size;
|
||||
|
||||
/* No need to map the file if it is empty. */
|
||||
if (*sizep != 0)
|
||||
/* Map a copy of the file contents. */
|
||||
result = mmap (NULL, *sizep, prot,
|
||||
#ifdef MAP_COPY
|
||||
MAP_COPY
|
||||
#else
|
||||
MAP_PRIVATE
|
||||
#endif
|
||||
#ifdef MAP_FILE
|
||||
| MAP_FILE
|
||||
#endif
|
||||
, fd, 0);
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Descriptor to write debug messages to. */
|
||||
int _dl_debug_fd = 2;
|
||||
|
||||
|
||||
/* Bare-bone printf implementation. This function only knows about
|
||||
the formats and flags needed and can handle only up to 64 stripes in
|
||||
the output. */
|
||||
static void
|
||||
_dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
|
||||
{
|
||||
const int niovmax = 64;
|
||||
struct iovec iov[niovmax];
|
||||
int niov = 0;
|
||||
pid_t pid = 0;
|
||||
char pidbuf[7];
|
||||
|
||||
while (*fmt != '\0')
|
||||
{
|
||||
const char *startp = fmt;
|
||||
|
||||
if (tag_p > 0)
|
||||
{
|
||||
/* Generate the tag line once. It consists of the PID and a
|
||||
colon followed by a tab. */
|
||||
if (pid == 0)
|
||||
{
|
||||
char *p = "0";
|
||||
pid = __getpid ();
|
||||
assert (pid >= 0 && pid < 100000);
|
||||
while (p > pidbuf)
|
||||
*--p = '0';
|
||||
pidbuf[5] = ':';
|
||||
pidbuf[6] = '\t';
|
||||
}
|
||||
|
||||
/* Append to the output. */
|
||||
assert (niov < niovmax);
|
||||
iov[niov].iov_len = 7;
|
||||
iov[niov++].iov_base = pidbuf;
|
||||
|
||||
/* No more tags until we see the next newline. */
|
||||
tag_p = -1;
|
||||
}
|
||||
|
||||
/* Skip everything except % and \n (if tags are needed). */
|
||||
while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
|
||||
++fmt;
|
||||
|
||||
/* Append constant string. */
|
||||
assert (niov < niovmax);
|
||||
if ((iov[niov].iov_len = fmt - startp) != 0)
|
||||
iov[niov++].iov_base = (char *) startp;
|
||||
|
||||
if (*fmt == '%')
|
||||
{
|
||||
/* It is a format specifier. */
|
||||
char fill = ' ';
|
||||
int width = -1;
|
||||
#if LONG_MAX != INT_MAX
|
||||
int long_mod = 0;
|
||||
#endif
|
||||
|
||||
/* Recognize zero-digit fill flag. */
|
||||
if (*++fmt == '0')
|
||||
{
|
||||
fill = '0';
|
||||
++fmt;
|
||||
}
|
||||
|
||||
/* See whether with comes from a parameter. Note that no other
|
||||
way to specify the width is implemented. */
|
||||
if (*fmt == '*')
|
||||
{
|
||||
width = va_arg (arg, int);
|
||||
++fmt;
|
||||
}
|
||||
|
||||
/* Recognize the l modifier. It is only important on some
|
||||
platforms where long and int have a different size. We
|
||||
can use the same code for size_t. */
|
||||
if (*fmt == 'l' || *fmt == 'Z')
|
||||
{
|
||||
#if LONG_MAX != INT_MAX
|
||||
long_mod = 1;
|
||||
#endif
|
||||
++fmt;
|
||||
}
|
||||
|
||||
switch (*fmt)
|
||||
{
|
||||
/* Integer formatting. */
|
||||
case 'u':
|
||||
case 'x':
|
||||
{
|
||||
/* We have to make a difference if long and int have a
|
||||
different size. */
|
||||
#if LONG_MAX != INT_MAX
|
||||
unsigned long int num = (long_mod
|
||||
? va_arg (arg, unsigned long int)
|
||||
: va_arg (arg, unsigned int));
|
||||
#else
|
||||
unsigned long int num = va_arg (arg, unsigned int);
|
||||
#endif
|
||||
/* We use alloca() to allocate the buffer with the most
|
||||
pessimistic guess for the size. Using alloca() allows
|
||||
having more than one integer formatting in a call. */
|
||||
char *buf = (char *) alloca (3 * sizeof (unsigned long int));
|
||||
char *endp = &buf[3 * sizeof (unsigned long int)];
|
||||
char *cp = "0";
|
||||
|
||||
/* Pad to the width the user specified. */
|
||||
if (width != -1)
|
||||
while (endp - cp < width)
|
||||
*--cp = fill;
|
||||
|
||||
iov[niov].iov_base = cp;
|
||||
iov[niov].iov_len = endp - cp;
|
||||
++niov;
|
||||
}
|
||||
break;
|
||||
|
||||
case 's':
|
||||
/* Get the string argument. */
|
||||
iov[niov].iov_base = va_arg (arg, char *);
|
||||
iov[niov].iov_len = strlen (iov[niov].iov_base);
|
||||
++niov;
|
||||
break;
|
||||
|
||||
case '%':
|
||||
iov[niov].iov_base = (void *) fmt;
|
||||
iov[niov].iov_len = 1;
|
||||
++niov;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert (! "invalid format specifier");
|
||||
}
|
||||
++fmt;
|
||||
}
|
||||
else if (*fmt == '\n')
|
||||
{
|
||||
/* See whether we have to print a single newline character. */
|
||||
if (fmt == startp)
|
||||
{
|
||||
iov[niov].iov_base = (char *) startp;
|
||||
iov[niov++].iov_len = 1;
|
||||
}
|
||||
else
|
||||
/* No, just add it to the rest of the string. */
|
||||
++iov[niov - 1].iov_len;
|
||||
|
||||
/* Next line, print a tag again. */
|
||||
tag_p = 1;
|
||||
++fmt;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally write the result. */
|
||||
writev (fd, iov, niov);
|
||||
}
|
||||
|
||||
|
||||
/* Write to debug file. */
|
||||
void
|
||||
_dl_debug_printf (const char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
|
||||
va_start (arg, fmt);
|
||||
_dl_debug_vdprintf (_dl_debug_fd, 1, fmt, arg);
|
||||
va_end (arg);
|
||||
}
|
||||
|
||||
|
||||
/* Write to debug file but don't start with a tag. */
|
||||
void
|
||||
_dl_debug_printf_c (const char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
|
||||
va_start (arg, fmt);
|
||||
_dl_debug_vdprintf (_dl_debug_fd, -1, fmt, arg);
|
||||
va_end (arg);
|
||||
}
|
||||
|
||||
|
||||
/* Write the given file descriptor. */
|
||||
void
|
||||
_dl_dprintf (int fd, const char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
|
||||
va_start (arg, fmt);
|
||||
_dl_debug_vdprintf (fd, 0, fmt, arg);
|
||||
va_end (arg);
|
||||
}
|
163
newlib/libc/sys/linux/dl/dl-object.c
Normal file
163
newlib/libc/sys/linux/dl/dl-object.c
Normal file
@ -0,0 +1,163 @@
|
||||
/* Storage management for the chain of loaded shared objects.
|
||||
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. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
/* Allocate a `struct link_map' for a new object being loaded,
|
||||
and enter it into the _dl_loaded list. */
|
||||
|
||||
struct link_map *
|
||||
internal_function
|
||||
_dl_new_object (char *realname, const char *libname, int type,
|
||||
struct link_map *loader)
|
||||
{
|
||||
struct link_map *l;
|
||||
int idx;
|
||||
size_t libname_len = strlen (libname) + 1;
|
||||
struct link_map *new;
|
||||
struct libname_list *newname;
|
||||
|
||||
new = (struct link_map *) calloc (sizeof (*new) + sizeof (*newname)
|
||||
+ libname_len, 1);
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
|
||||
new->l_libname = newname = (struct libname_list *) (new + 1);
|
||||
newname->name = (char *) memcpy (newname + 1, libname, libname_len);
|
||||
/* newname->next = NULL; We use calloc therefore not necessary. */
|
||||
newname->dont_free = 1;
|
||||
|
||||
new->l_name = realname;
|
||||
new->l_type = type;
|
||||
new->l_loader = loader;
|
||||
/* new->l_global = 0; We use calloc therefore not necessary. */
|
||||
|
||||
/* Use the 'l_scope_mem' array by default for the the 'l_scope'
|
||||
information. If we need more entries we will allocate a large
|
||||
array dynamically. */
|
||||
new->l_scope = new->l_scope_mem;
|
||||
new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
|
||||
|
||||
/* Counter for the scopes we have to handle. */
|
||||
idx = 0;
|
||||
|
||||
if (_dl_loaded != NULL)
|
||||
{
|
||||
l = _dl_loaded;
|
||||
while (l->l_next != NULL)
|
||||
l = l->l_next;
|
||||
new->l_prev = l;
|
||||
/* new->l_next = NULL; Would be necessary but we use calloc. */
|
||||
l->l_next = new;
|
||||
|
||||
/* Add the global scope. */
|
||||
new->l_scope[idx++] = &_dl_loaded->l_searchlist;
|
||||
}
|
||||
else
|
||||
_dl_loaded = new;
|
||||
++_dl_nloaded;
|
||||
|
||||
/* If we have no loader the new object acts as it. */
|
||||
if (loader == NULL)
|
||||
loader = new;
|
||||
else
|
||||
/* Determine the local scope. */
|
||||
while (loader->l_loader != NULL)
|
||||
loader = loader->l_loader;
|
||||
|
||||
/* Insert the scope if it isn't the global scope we already added. */
|
||||
if (idx == 0 || &loader->l_searchlist != new->l_scope[0])
|
||||
new->l_scope[idx] = &loader->l_searchlist;
|
||||
|
||||
new->l_local_scope[0] = &new->l_searchlist;
|
||||
|
||||
/* Don't try to find the origin for the main map which has the name "". */
|
||||
if (realname[0] != '\0')
|
||||
{
|
||||
size_t realname_len = strlen (realname) + 1;
|
||||
char *origin;
|
||||
char *cp;
|
||||
|
||||
if (realname[0] == '/')
|
||||
{
|
||||
/* It is an absolute path. Use it. But we have to make a
|
||||
copy since we strip out the trailing slash. */
|
||||
cp = origin = (char *) malloc (realname_len);
|
||||
if (origin == NULL)
|
||||
{
|
||||
origin = (char *) -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = realname_len;
|
||||
char *result = NULL;
|
||||
|
||||
/* Get the current directory name. */
|
||||
origin = NULL;
|
||||
do
|
||||
{
|
||||
len += 128;
|
||||
origin = (char *) realloc (origin, len);
|
||||
}
|
||||
while (origin != NULL
|
||||
&& (result = getcwd (origin, len - realname_len)) == NULL
|
||||
&& errno == ERANGE);
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
/* We were not able to determine the current directory.
|
||||
Note that free(origin) is OK if origin == NULL. */
|
||||
free (origin);
|
||||
origin = (char *) -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Find the end of the path and see whether we have to add
|
||||
a slash. */
|
||||
cp = memchr (origin, '\0', strlen(origin));
|
||||
if (cp[-1] != '/')
|
||||
*cp++ = '/';
|
||||
}
|
||||
|
||||
/* Add the real file name. */
|
||||
memcpy (cp, realname, realname_len);
|
||||
|
||||
/* Now remove the filename and the slash. Leave the slash if it
|
||||
the name is something like "/foo". */
|
||||
cp = strrchr (origin, '/');
|
||||
if (cp == origin)
|
||||
origin[1] = '\0';
|
||||
else
|
||||
*cp = '\0';
|
||||
|
||||
out:
|
||||
new->l_origin = origin;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
487
newlib/libc/sys/linux/dl/dl-open.c
Normal file
487
newlib/libc/sys/linux/dl/dl-open.c
Normal file
@ -0,0 +1,487 @@
|
||||
/* Load a shared object at runtime, relocate it, and run its initializer.
|
||||
Copyright (C) 1996,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. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <libintl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h> /* Check whether MAP_COPY is defined. */
|
||||
#include <sys/param.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <bp-sym.h>
|
||||
|
||||
#include <dl-dst.h>
|
||||
#include <machine/weakalias.h>
|
||||
|
||||
|
||||
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
|
||||
void (*dl_main) (const ElfW(Phdr) *phdr,
|
||||
ElfW(Word) phnum,
|
||||
ElfW(Addr) *user_entry));
|
||||
weak_extern (BP_SYM (_dl_sysdep_start))
|
||||
|
||||
/* This function is used to unload the cache file if necessary. */
|
||||
extern void _dl_unload_cache (void);
|
||||
|
||||
int __libc_argc = 0;
|
||||
char **__libc_argv = NULL;
|
||||
|
||||
extern char **environ;
|
||||
|
||||
extern int _dl_lazy; /* Do we do lazy relocations? */
|
||||
|
||||
/* Undefine the following for debugging. */
|
||||
/* #define SCOPE_DEBUG 1 */
|
||||
#ifdef SCOPE_DEBUG
|
||||
static void show_scope (struct link_map *new);
|
||||
#endif
|
||||
|
||||
extern size_t _dl_platformlen;
|
||||
|
||||
/* We must be carefull not to leave us in an inconsistent state. Thus we
|
||||
catch any error and re-raise it after cleaning up. */
|
||||
|
||||
struct dl_open_args
|
||||
{
|
||||
const char *file;
|
||||
int mode;
|
||||
const void *caller;
|
||||
struct link_map *map;
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
add_to_global (struct link_map *new)
|
||||
{
|
||||
struct link_map **new_global;
|
||||
unsigned int to_add = 0;
|
||||
unsigned int cnt;
|
||||
|
||||
/* Count the objects we have to put in the global scope. */
|
||||
for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
||||
if (new->l_searchlist.r_list[cnt]->l_global == 0)
|
||||
++to_add;
|
||||
|
||||
/* The symbols of the new objects and its dependencies are to be
|
||||
introduced into the global scope that will be used to resolve
|
||||
references from other dynamically-loaded objects.
|
||||
|
||||
The global scope is the searchlist in the main link map. We
|
||||
extend this list if necessary. There is one problem though:
|
||||
since this structure was allocated very early (before the libc
|
||||
is loaded) the memory it uses is allocated by the malloc()-stub
|
||||
in the ld.so. When we come here these functions are not used
|
||||
anymore. Instead the malloc() implementation of the libc is
|
||||
used. But this means the block from the main map cannot be used
|
||||
in an realloc() call. Therefore we allocate a completely new
|
||||
array the first time we have to add something to the locale scope. */
|
||||
|
||||
if (_dl_global_scope_alloc == 0)
|
||||
{
|
||||
/* This is the first dynamic object given global scope. */
|
||||
_dl_global_scope_alloc = _dl_main_searchlist->r_nlist + to_add + 8;
|
||||
new_global = (struct link_map **)
|
||||
malloc (_dl_global_scope_alloc * sizeof (struct link_map *));
|
||||
if (new_global == NULL)
|
||||
{
|
||||
_dl_global_scope_alloc = 0;
|
||||
nomem:
|
||||
_dl_signal_error (ENOMEM, new->l_libname->name, NULL,
|
||||
N_("cannot extend global scope"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy over the old entries. */
|
||||
memcpy (new_global, _dl_main_searchlist->r_list,
|
||||
(_dl_main_searchlist->r_nlist * sizeof (struct link_map *)));
|
||||
|
||||
_dl_main_searchlist->r_list = new_global;
|
||||
}
|
||||
else if (_dl_main_searchlist->r_nlist + to_add > _dl_global_scope_alloc)
|
||||
{
|
||||
/* We have to extend the existing array of link maps in the
|
||||
main map. */
|
||||
new_global = (struct link_map **)
|
||||
realloc (_dl_main_searchlist->r_list,
|
||||
((_dl_global_scope_alloc + to_add + 8)
|
||||
* sizeof (struct link_map *)));
|
||||
if (new_global == NULL)
|
||||
goto nomem;
|
||||
|
||||
_dl_global_scope_alloc += to_add + 8;
|
||||
_dl_main_searchlist->r_list = new_global;
|
||||
}
|
||||
|
||||
/* Now add the new entries. */
|
||||
for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt)
|
||||
{
|
||||
struct link_map *map = new->l_searchlist.r_list[cnt];
|
||||
|
||||
if (map->l_global == 0)
|
||||
{
|
||||
map->l_global = 1;
|
||||
_dl_main_searchlist->r_list[_dl_main_searchlist->r_nlist] = map;
|
||||
++_dl_main_searchlist->r_nlist;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dl_open_worker (void *a)
|
||||
{
|
||||
struct dl_open_args *args = a;
|
||||
const char *file = args->file;
|
||||
int mode = args->mode;
|
||||
struct link_map *new, *l;
|
||||
const char *dst;
|
||||
int lazy;
|
||||
unsigned int i;
|
||||
|
||||
/* Maybe we have to expand a DST. */
|
||||
dst = strchr (file, '$');
|
||||
if (dst != NULL)
|
||||
{
|
||||
const void *caller = args->caller;
|
||||
size_t len = strlen (file);
|
||||
size_t required;
|
||||
struct link_map *call_map;
|
||||
char *new_file;
|
||||
|
||||
/* We have to find out from which object the caller is calling. */
|
||||
call_map = NULL;
|
||||
for (l = _dl_loaded; l; l = l->l_next)
|
||||
if (caller >= (const void *) l->l_map_start
|
||||
&& caller < (const void *) l->l_map_end)
|
||||
{
|
||||
/* There must be exactly one DSO for the range of the virtual
|
||||
memory. Otherwise something is really broken. */
|
||||
call_map = l;
|
||||
break;
|
||||
}
|
||||
|
||||
if (call_map == NULL)
|
||||
/* In this case we assume this is the main application. */
|
||||
call_map = _dl_loaded;
|
||||
|
||||
/* Determine how much space we need. We have to allocate the
|
||||
memory locally. */
|
||||
required = DL_DST_REQUIRED (call_map, file, len, _dl_dst_count (dst, 0));
|
||||
|
||||
/* Get space for the new file name. */
|
||||
new_file = (char *) alloca (required + 1);
|
||||
|
||||
/* Generate the new file name. */
|
||||
DL_DST_SUBSTITUTE (call_map, file, new_file, 0);
|
||||
|
||||
/* If the substitution failed don't try to load. */
|
||||
if (*new_file == '\0')
|
||||
_dl_signal_error (0, "dlopen", NULL,
|
||||
N_("empty dynamic string token substitution"));
|
||||
|
||||
/* Now we have a new file name. */
|
||||
file = new_file;
|
||||
}
|
||||
|
||||
/* Load the named object. */
|
||||
args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0,
|
||||
mode);
|
||||
|
||||
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
|
||||
set and the object is not already loaded. */
|
||||
if (new == NULL)
|
||||
{
|
||||
assert (mode & RTLD_NOLOAD);
|
||||
return;
|
||||
}
|
||||
|
||||
/* It was already open. */
|
||||
if (new->l_searchlist.r_list != NULL)
|
||||
{
|
||||
/* Let the user know about the opencount. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
|
||||
_dl_debug_printf ("opening file=%s; opencount == %u\n\n",
|
||||
new->l_name, new->l_opencount);
|
||||
|
||||
/* If the user requested the object to be in the global namespace
|
||||
but it is not so far, add it now. */
|
||||
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
|
||||
(void) add_to_global (new);
|
||||
|
||||
/* Increment just the reference counter of the object. */
|
||||
++new->l_opencount;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Load that object's dependencies. */
|
||||
_dl_map_object_deps (new, NULL, 0, 0);
|
||||
|
||||
/* So far, so good. Now check the versions. */
|
||||
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
|
||||
if (new->l_searchlist.r_list[i]->l_versions == NULL)
|
||||
(void) _dl_check_map_versions (new->l_searchlist.r_list[i], 0, 0);
|
||||
|
||||
#ifdef SCOPE_DEBUG
|
||||
show_scope (new);
|
||||
#endif
|
||||
|
||||
/* Only do lazy relocation if `LD_BIND_NOW' is not set. */
|
||||
lazy = (mode & RTLD_BINDING_MASK) == RTLD_LAZY && _dl_lazy;
|
||||
|
||||
/* Relocate the objects loaded. We do this in reverse order so that copy
|
||||
relocs of earlier objects overwrite the data written by later objects. */
|
||||
|
||||
l = new;
|
||||
while (l->l_next)
|
||||
l = l->l_next;
|
||||
while (1)
|
||||
{
|
||||
if (! l->l_relocated)
|
||||
{
|
||||
#if 0
|
||||
#ifdef SHARED
|
||||
if (_dl_profile != NULL)
|
||||
{
|
||||
/* If this here is the shared object which we want to profile
|
||||
make sure the profile is started. We can find out whether
|
||||
this is necessary or not by observing the `_dl_profile_map'
|
||||
variable. If was NULL but is not NULL afterwars we must
|
||||
start the profiling. */
|
||||
struct link_map *old_profile_map = _dl_profile_map;
|
||||
|
||||
_dl_relocate_object (l, l->l_scope, 1, 1);
|
||||
|
||||
if (old_profile_map == NULL && _dl_profile_map != NULL)
|
||||
/* We must prepare the profiling. */
|
||||
_dl_start_profile (_dl_profile_map, _dl_profile_output);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
_dl_relocate_object (l, l->l_scope, lazy, 0);
|
||||
}
|
||||
|
||||
if (l == new)
|
||||
break;
|
||||
l = l->l_prev;
|
||||
}
|
||||
|
||||
/* Increment the open count for all dependencies. If the file is
|
||||
not loaded as a dependency here add the search list of the newly
|
||||
loaded object to the scope. */
|
||||
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
|
||||
if (++new->l_searchlist.r_list[i]->l_opencount > 1
|
||||
&& new->l_searchlist.r_list[i]->l_type == lt_loaded)
|
||||
{
|
||||
struct link_map *imap = new->l_searchlist.r_list[i];
|
||||
struct r_scope_elem **runp = imap->l_scope;
|
||||
size_t cnt = 0;
|
||||
|
||||
while (*runp != NULL)
|
||||
{
|
||||
/* This can happen if imap was just loaded, but during
|
||||
relocation had l_opencount bumped because of relocation
|
||||
dependency. Avoid duplicates in l_scope. */
|
||||
if (__builtin_expect (*runp == &new->l_searchlist, 0))
|
||||
break;
|
||||
|
||||
++cnt;
|
||||
++runp;
|
||||
}
|
||||
|
||||
if (*runp != NULL)
|
||||
/* Avoid duplicates. */
|
||||
continue;
|
||||
|
||||
if (__builtin_expect (cnt + 1 >= imap->l_scope_max, 0))
|
||||
{
|
||||
/* The 'r_scope' array is too small. Allocate a new one
|
||||
dynamically. */
|
||||
struct r_scope_elem **newp;
|
||||
size_t new_size = imap->l_scope_max * 2;
|
||||
|
||||
if (imap->l_scope == imap->l_scope_mem)
|
||||
{
|
||||
newp = (struct r_scope_elem **)
|
||||
malloc (new_size * sizeof (struct r_scope_elem *));
|
||||
if (newp == NULL)
|
||||
_dl_signal_error (ENOMEM, "dlopen", NULL,
|
||||
N_("cannot create scope list"));
|
||||
imap->l_scope = memcpy (newp, imap->l_scope,
|
||||
cnt * sizeof (imap->l_scope[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
newp = (struct r_scope_elem **)
|
||||
realloc (imap->l_scope,
|
||||
new_size * sizeof (struct r_scope_elem *));
|
||||
if (newp == NULL)
|
||||
_dl_signal_error (ENOMEM, "dlopen", NULL,
|
||||
N_("cannot create scope list"));
|
||||
imap->l_scope = newp;
|
||||
}
|
||||
|
||||
imap->l_scope_max = new_size;
|
||||
}
|
||||
|
||||
imap->l_scope[cnt++] = &new->l_searchlist;
|
||||
imap->l_scope[cnt] = NULL;
|
||||
}
|
||||
|
||||
/* Run the initializer functions of new objects. */
|
||||
_dl_init (new, __libc_argc, __libc_argv, environ);
|
||||
|
||||
/* Now we can make the new map available in the global scope. */
|
||||
if (mode & RTLD_GLOBAL)
|
||||
/* Move the object in the global namespace. */
|
||||
if (add_to_global (new) != 0)
|
||||
/* It failed. */
|
||||
return;
|
||||
|
||||
/* Mark the object as not deletable if the RTLD_NODELETE flags was
|
||||
passed. */
|
||||
if (__builtin_expect (mode & RTLD_NODELETE, 0))
|
||||
new->l_flags_1 |= DF_1_NODELETE;
|
||||
|
||||
/* Let the user know about the opencount. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
|
||||
_dl_debug_printf ("opening file=%s; opencount == %u\n\n",
|
||||
new->l_name, new->l_opencount);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
internal_function
|
||||
_dl_open (const char *file, int mode, const void *caller)
|
||||
{
|
||||
struct dl_open_args args;
|
||||
const char *objname;
|
||||
const char *errstring;
|
||||
int errcode;
|
||||
|
||||
if ((mode & RTLD_BINDING_MASK) == 0)
|
||||
/* One of the flags must be set. */
|
||||
_dl_signal_error (EINVAL, file, NULL, N_("invalid mode for dlopen()"));
|
||||
|
||||
/* Make sure we are alone. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_acquire_recursive(_dl_load_lock);
|
||||
#endif
|
||||
|
||||
args.file = file;
|
||||
args.mode = mode;
|
||||
args.caller = caller;
|
||||
args.map = NULL;
|
||||
errcode = _dl_catch_error (&objname, &errstring, dl_open_worker, &args);
|
||||
|
||||
#ifndef MAP_COPY
|
||||
/* We must munmap() the cache file. */
|
||||
_dl_unload_cache ();
|
||||
#endif
|
||||
|
||||
/* Release the lock. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release_recursive(_dl_load_lock);
|
||||
#endif
|
||||
|
||||
|
||||
if (errstring)
|
||||
{
|
||||
/* Some error occurred during loading. */
|
||||
char *local_errstring;
|
||||
size_t len_errstring;
|
||||
|
||||
/* Remove the object from memory. It may be in an inconsistent
|
||||
state if relocation failed, for example. */
|
||||
if (args.map)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* Increment open counters for all objects since this has
|
||||
not happened yet. */
|
||||
for (i = 0; i < args.map->l_searchlist.r_nlist; ++i)
|
||||
++args.map->l_searchlist.r_list[i]->l_opencount;
|
||||
|
||||
_dl_close (args.map);
|
||||
}
|
||||
|
||||
/* Make a local copy of the error string so that we can release the
|
||||
memory allocated for it. */
|
||||
len_errstring = strlen (errstring) + 1;
|
||||
if (objname == errstring + len_errstring)
|
||||
{
|
||||
size_t total_len = len_errstring + strlen (objname) + 1;
|
||||
local_errstring = alloca (total_len);
|
||||
memcpy (local_errstring, errstring, total_len);
|
||||
objname = local_errstring + len_errstring;
|
||||
}
|
||||
else
|
||||
{
|
||||
local_errstring = alloca (len_errstring);
|
||||
memcpy (local_errstring, errstring, len_errstring);
|
||||
}
|
||||
|
||||
if (errstring != _dl_out_of_memory)
|
||||
free ((char *) errstring);
|
||||
|
||||
/* Reraise the error. */
|
||||
_dl_signal_error (errcode, objname, NULL, local_errstring);
|
||||
}
|
||||
|
||||
#ifndef SHARED
|
||||
DL_STATIC_INIT (args.map);
|
||||
#endif
|
||||
|
||||
return args.map;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SCOPE_DEBUG
|
||||
#include <unistd.h>
|
||||
|
||||
static void
|
||||
show_scope (struct link_map *new)
|
||||
{
|
||||
int scope_cnt;
|
||||
|
||||
for (scope_cnt = 0; new->l_scope[scope_cnt] != NULL; ++scope_cnt)
|
||||
{
|
||||
char numbuf[2];
|
||||
unsigned int cnt;
|
||||
|
||||
numbuf[0] = '0' + scope_cnt;
|
||||
numbuf[1] = '\0';
|
||||
_dl_printf ("scope %s:", numbuf);
|
||||
|
||||
for (cnt = 0; cnt < new->l_scope[scope_cnt]->r_nlist; ++cnt)
|
||||
if (*new->l_scope[scope_cnt]->r_list[cnt]->l_name)
|
||||
_dl_printf (" %s", new->l_scope[scope_cnt]->r_list[cnt]->l_name);
|
||||
else
|
||||
_dl_printf (" <main>");
|
||||
|
||||
_dl_printf ("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
108
newlib/libc/sys/linux/dl/dl-osinfo.h
Normal file
108
newlib/libc/sys/linux/dl/dl-osinfo.h
Normal file
@ -0,0 +1,108 @@
|
||||
/* Operating system specific code for generic dynamic loader functions.
|
||||
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 <string.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include "kernel-features.h"
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifdef SHARED
|
||||
/* This is the function used in the dynamic linker to print the fatal error
|
||||
message. */
|
||||
static inline void
|
||||
__attribute__ ((__noreturn__))
|
||||
dl_fatal (const char *str)
|
||||
{
|
||||
_dl_dprintf (2, str);
|
||||
_exit (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define DL_SYSDEP_OSCHECK(FATAL) \
|
||||
do { \
|
||||
/* Test whether the kernel is new enough. This test is only \
|
||||
performed if the library is not compiled to run on all \
|
||||
kernels. */ \
|
||||
if (__LINUX_KERNEL_VERSION > 0) \
|
||||
{ \
|
||||
char bufmem[64]; \
|
||||
char *buf = bufmem; \
|
||||
unsigned int version; \
|
||||
int parts; \
|
||||
char *cp; \
|
||||
struct utsname uts; \
|
||||
\
|
||||
/* Try the uname syscall */ \
|
||||
if (__uname (&uts)) \
|
||||
{ \
|
||||
/* This was not successful. Now try reading the /proc \
|
||||
filesystem. */ \
|
||||
ssize_t reslen; \
|
||||
int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY); \
|
||||
if (fd == -1 \
|
||||
|| (reslen = __read (fd, bufmem, sizeof (bufmem))) <= 0) \
|
||||
/* This also didn't work. We give up since we cannot \
|
||||
make sure the library can actually work. */ \
|
||||
FATAL ("FATAL: cannot determine library version\n"); \
|
||||
__close (fd); \
|
||||
buf[MIN (reslen, (ssize_t) sizeof (bufmem) - 1)] = '\0'; \
|
||||
} \
|
||||
else \
|
||||
buf = uts.release; \
|
||||
\
|
||||
/* Now convert it into a number. The string consists of at most \
|
||||
three parts. */ \
|
||||
version = 0; \
|
||||
parts = 0; \
|
||||
cp = buf; \
|
||||
while ((*cp >= '0') && (*cp <= '9')) \
|
||||
{ \
|
||||
unsigned int here = *cp++ - '0'; \
|
||||
\
|
||||
while ((*cp >= '0') && (*cp <= '9')) \
|
||||
{ \
|
||||
here *= 10; \
|
||||
here += *cp++ - '0'; \
|
||||
} \
|
||||
\
|
||||
++parts; \
|
||||
version <<= 8; \
|
||||
version |= here; \
|
||||
\
|
||||
if (*cp++ != '.') \
|
||||
/* Another part following? */ \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
if (parts < 3) \
|
||||
version <<= 8 * (3 - parts); \
|
||||
\
|
||||
/* Now we can test with the required version. */ \
|
||||
if (version < __LINUX_KERNEL_VERSION) \
|
||||
/* Not sufficent. */ \
|
||||
FATAL ("FATAL: kernel too old\n"); \
|
||||
\
|
||||
_dl_osversion = version; \
|
||||
} \
|
||||
} while (0)
|
539
newlib/libc/sys/linux/dl/dl-profile.c
Normal file
539
newlib/libc/sys/linux/dl/dl-profile.c
Normal file
@ -0,0 +1,539 @@
|
||||
/* Profiling of shared libraries.
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
Based on the BSD mcount implementation.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <sys/gmon.h>
|
||||
#include <sys/gmon_out.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <atomicity.h>
|
||||
#include <config.h>
|
||||
|
||||
/* The LD_PROFILE feature has to be implemented different to the
|
||||
normal profiling using the gmon/ functions. The problem is that an
|
||||
arbitrary amount of processes simulataneously can be run using
|
||||
profiling and all write the results in the same file. To provide
|
||||
this mechanism one could implement a complicated mechanism to merge
|
||||
the content of two profiling runs or one could extend the file
|
||||
format to allow more than one data set. For the second solution we
|
||||
would have the problem that the file can grow in size beyond any
|
||||
limit and both solutions have the problem that the concurrency of
|
||||
writing the results is a big problem.
|
||||
|
||||
Another much simpler method is to use mmap to map the same file in
|
||||
all using programs and modify the data in the mmap'ed area and so
|
||||
also automatically on the disk. Using the MAP_SHARED option of
|
||||
mmap(2) this can be done without big problems in more than one
|
||||
file.
|
||||
|
||||
This approach is very different from the normal profiling. We have
|
||||
to use the profiling data in exactly the way they are expected to
|
||||
be written to disk. But the normal format used by gprof is not usable
|
||||
to do this. It is optimized for size. It writes the tags as single
|
||||
bytes but this means that the following 32/64 bit values are
|
||||
unaligned.
|
||||
|
||||
Therefore we use a new format. This will look like this
|
||||
|
||||
0 1 2 3 <- byte is 32 bit word
|
||||
0000 g m o n
|
||||
0004 *version* <- GMON_SHOBJ_VERSION
|
||||
0008 00 00 00 00
|
||||
000c 00 00 00 00
|
||||
0010 00 00 00 00
|
||||
|
||||
0014 *tag* <- GMON_TAG_TIME_HIST
|
||||
0018 ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- 32/64 bit LowPC
|
||||
0018+A ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- 32/64 bit HighPC
|
||||
0018+2*A *histsize*
|
||||
001c+2*A *profrate*
|
||||
0020+2*A s e c o
|
||||
0024+2*A n d s \0
|
||||
0028+2*A \0 \0 \0 \0
|
||||
002c+2*A \0 \0 \0
|
||||
002f+2*A s
|
||||
|
||||
0030+2*A ?? ?? ?? ?? <- Count data
|
||||
... ...
|
||||
0030+2*A+K ?? ?? ?? ??
|
||||
|
||||
0030+2*A+K *tag* <- GMON_TAG_CG_ARC
|
||||
0034+2*A+K *lastused*
|
||||
0038+2*A+K ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- FromPC#1
|
||||
0038+3*A+K ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- ToPC#1
|
||||
0038+4*A+K ?? ?? ?? ?? <- Count#1
|
||||
... ... ...
|
||||
0038+(2*(CN-1)+2)*A+(CN-1)*4+K ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- FromPC#CGN
|
||||
0038+(2*(CN-1)+3)*A+(CN-1)*4+K ?? ?? ?? ??
|
||||
?? ?? ?? ?? <- ToPC#CGN
|
||||
0038+(2*CN+2)*A+(CN-1)*4+K ?? ?? ?? ?? <- Count#CGN
|
||||
|
||||
We put (for now?) no basic block information in the file since this would
|
||||
introduce rase conditions among all the processes who want to write them.
|
||||
|
||||
`K' is the number of count entries which is computed as
|
||||
|
||||
textsize / HISTFRACTION
|
||||
|
||||
`CG' in the above table is the number of call graph arcs. Normally,
|
||||
the table is sparse and the profiling code writes out only the those
|
||||
entries which are really used in the program run. But since we must
|
||||
not extend this table (the profiling file) we'll keep them all here.
|
||||
So CN can be executed in advance as
|
||||
|
||||
MINARCS <= textsize*(ARCDENSITY/100) <= MAXARCS
|
||||
|
||||
Now the remaining question is: how to build the data structures we can
|
||||
work with from this data. We need the from set and must associate the
|
||||
froms with all the associated tos. We will do this by constructing this
|
||||
data structures at the program start. To do this we'll simply visit all
|
||||
entries in the call graph table and add it to the appropriate list. */
|
||||
|
||||
extern int __profile_frequency (void);
|
||||
|
||||
/* We define a special type to address the elements of the arc table.
|
||||
This is basically the `gmon_cg_arc_record' format but it includes
|
||||
the room for the tag and it uses real types. */
|
||||
struct here_cg_arc_record
|
||||
{
|
||||
uintptr_t from_pc;
|
||||
uintptr_t self_pc;
|
||||
uint32_t count;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static struct here_cg_arc_record *data;
|
||||
|
||||
/* Nonzero if profiling is under way. */
|
||||
static int running;
|
||||
|
||||
/* This is the number of entry which have been incorporated in the toset. */
|
||||
static uint32_t narcs;
|
||||
/* This is a pointer to the object representing the number of entries
|
||||
currently in the mmaped file. At no point of time this has to be the
|
||||
same as NARCS. If it is equal all entries from the file are in our
|
||||
lists. */
|
||||
static volatile uint32_t *narcsp;
|
||||
|
||||
static volatile uint16_t *kcount;
|
||||
static size_t kcountsize;
|
||||
|
||||
struct here_fromstruct
|
||||
{
|
||||
struct here_cg_arc_record volatile *here;
|
||||
uint16_t link;
|
||||
};
|
||||
|
||||
static volatile uint16_t *tos;
|
||||
|
||||
static struct here_fromstruct *froms;
|
||||
static uint32_t fromlimit;
|
||||
static volatile uint32_t fromidx;
|
||||
|
||||
static uintptr_t lowpc;
|
||||
static size_t textsize;
|
||||
static unsigned int hashfraction;
|
||||
static unsigned int log_hashfraction;
|
||||
|
||||
|
||||
|
||||
/* Set up profiling data to profile object desribed by MAP. The output
|
||||
file is found (or created) in OUTPUT_DIR. */
|
||||
void
|
||||
internal_function
|
||||
_dl_start_profile (struct link_map *map, const char *output_dir)
|
||||
{
|
||||
char *filename;
|
||||
int fd;
|
||||
struct stat64 st;
|
||||
const ElfW(Phdr) *ph;
|
||||
ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
|
||||
ElfW(Addr) mapend = 0;
|
||||
struct gmon_hdr gmon_hdr;
|
||||
struct gmon_hist_hdr hist_hdr;
|
||||
char *hist, *cp, *tmp;
|
||||
size_t idx;
|
||||
size_t tossize;
|
||||
size_t fromssize;
|
||||
uintptr_t highpc;
|
||||
struct gmon_hdr *addr = NULL;
|
||||
off_t expected_size;
|
||||
/* See profil(2) where this is described. */
|
||||
int s_scale;
|
||||
#define SCALE_1_TO_1 0x10000L
|
||||
|
||||
/* Compute the size of the sections which contain program code. */
|
||||
for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
|
||||
if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
|
||||
{
|
||||
ElfW(Addr) start = (ph->p_vaddr & ~(_dl_pagesize - 1));
|
||||
ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
|
||||
& ~(_dl_pagesize - 1));
|
||||
|
||||
if (start < mapstart)
|
||||
mapstart = start;
|
||||
if (end > mapend)
|
||||
mapend = end;
|
||||
}
|
||||
|
||||
/* Now we can compute the size of the profiling data. This is done
|
||||
with the same formulars as in `monstartup' (see gmon.c). */
|
||||
running = 0;
|
||||
lowpc = ROUNDDOWN (mapstart + map->l_addr,
|
||||
HISTFRACTION * sizeof (HISTCOUNTER));
|
||||
highpc = ROUNDUP (mapend + map->l_addr,
|
||||
HISTFRACTION * sizeof (HISTCOUNTER));
|
||||
textsize = highpc - lowpc;
|
||||
kcountsize = textsize / HISTFRACTION;
|
||||
hashfraction = HASHFRACTION;
|
||||
if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
|
||||
/* If HASHFRACTION is a power of two, mcount can use shifting
|
||||
instead of integer division. Precompute shift amount. */
|
||||
log_hashfraction = ffs (hashfraction * sizeof (*froms)) - 1;
|
||||
else
|
||||
log_hashfraction = -1;
|
||||
tossize = textsize / HASHFRACTION;
|
||||
fromlimit = textsize * ARCDENSITY / 100;
|
||||
if (fromlimit < MINARCS)
|
||||
fromlimit = MINARCS;
|
||||
if (fromlimit > MAXARCS)
|
||||
fromlimit = MAXARCS;
|
||||
fromssize = fromlimit * sizeof (struct here_fromstruct);
|
||||
|
||||
expected_size = (sizeof (struct gmon_hdr)
|
||||
+ 4 + sizeof (struct gmon_hist_hdr) + kcountsize
|
||||
+ 4 + 4 + fromssize * sizeof (struct here_cg_arc_record));
|
||||
|
||||
/* Create the gmon_hdr we expect or write. */
|
||||
memset (&gmon_hdr, '\0', sizeof (struct gmon_hdr));
|
||||
memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
|
||||
*(int32_t *) gmon_hdr.version = GMON_SHOBJ_VERSION;
|
||||
|
||||
/* Create the hist_hdr we expect or write. */
|
||||
*(char **) hist_hdr.low_pc = (char *) mapstart;
|
||||
*(char **) hist_hdr.high_pc = (char *) mapend;
|
||||
*(int32_t *) hist_hdr.hist_size = kcountsize / sizeof (HISTCOUNTER);
|
||||
*(int32_t *) hist_hdr.prof_rate = __profile_frequency ();
|
||||
strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
|
||||
hist_hdr.dimen_abbrev = 's';
|
||||
|
||||
/* First determine the output name. We write in the directory
|
||||
OUTPUT_DIR and the name is composed from the shared objects
|
||||
soname (or the file name) and the ending ".profile". */
|
||||
filename = (char *) alloca (strlen (output_dir) + 1 + strlen (_dl_profile)
|
||||
+ sizeof ".profile");
|
||||
cp = strcpy (filename, output_dir);
|
||||
cp += strlen (output_dir);
|
||||
*cp++ = '/';
|
||||
tmp = strcpy (cp, _dl_profile);
|
||||
tmp += strlen (_dl_profile);
|
||||
strcpy (tmp, ".profile");
|
||||
|
||||
#ifdef O_NOFOLLOW
|
||||
# define EXTRA_FLAGS | O_NOFOLLOW
|
||||
#else
|
||||
# define EXTRA_FLAGS
|
||||
#endif
|
||||
fd = __open (filename, O_RDWR | O_CREAT EXTRA_FLAGS);
|
||||
if (fd == -1)
|
||||
{
|
||||
/* We cannot write the profiling data so don't do anything. */
|
||||
char buf[400];
|
||||
_dl_error_printf ("%s: cannot open file: %s\n", filename,
|
||||
__strerror_r (errno, buf, sizeof buf));
|
||||
return;
|
||||
}
|
||||
|
||||
if (fstat64 (fd, &st) < 0 || !S_ISREG (st.st_mode))
|
||||
{
|
||||
/* Not stat'able or not a regular file => don't use it. */
|
||||
char buf[400];
|
||||
int errnum = errno;
|
||||
__close (fd);
|
||||
_dl_error_printf ("%s: cannot stat file: %s\n", filename,
|
||||
__strerror_r (errnum, buf, sizeof buf));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test the size. If it does not match what we expect from the size
|
||||
values in the map MAP we don't use it and warn the user. */
|
||||
if (st.st_size == 0)
|
||||
{
|
||||
/* We have to create the file. */
|
||||
char buf[_dl_pagesize];
|
||||
|
||||
memset (buf, '\0', _dl_pagesize);
|
||||
|
||||
if (__lseek (fd, expected_size & ~(_dl_pagesize - 1), SEEK_SET) == -1)
|
||||
{
|
||||
char buf[400];
|
||||
int errnum;
|
||||
cannot_create:
|
||||
errnum = errno;
|
||||
__close (fd);
|
||||
_dl_error_printf ("%s: cannot create file: %s\n", filename,
|
||||
__strerror_r (errnum, buf, sizeof buf));
|
||||
return;
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY (__libc_write (fd, buf, (expected_size
|
||||
& (_dl_pagesize - 1))))
|
||||
< 0)
|
||||
goto cannot_create;
|
||||
}
|
||||
else if (st.st_size != expected_size)
|
||||
{
|
||||
__close (fd);
|
||||
wrong_format:
|
||||
|
||||
if (addr != NULL)
|
||||
__munmap ((void *) addr, expected_size);
|
||||
|
||||
_dl_error_printf ("%s: file is no correct profile data file for `%s'\n",
|
||||
filename, _dl_profile);
|
||||
return;
|
||||
}
|
||||
|
||||
addr = (struct gmon_hdr *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED|MAP_FILE, fd, 0);
|
||||
if (addr == (struct gmon_hdr *) MAP_FAILED)
|
||||
{
|
||||
char buf[400];
|
||||
int errnum = errno;
|
||||
__close (fd);
|
||||
_dl_error_printf ("%s: cannot map file: %s\n", filename,
|
||||
__strerror_r (errnum, buf, sizeof buf));
|
||||
return;
|
||||
}
|
||||
|
||||
/* We don't need the file desriptor anymore. */
|
||||
__close (fd);
|
||||
|
||||
/* Pointer to data after the header. */
|
||||
hist = (char *) (addr + 1);
|
||||
kcount = (uint16_t *) ((char *) hist + sizeof (uint32_t)
|
||||
+ sizeof (struct gmon_hist_hdr));
|
||||
|
||||
/* Compute pointer to array of the arc information. */
|
||||
narcsp = (uint32_t *) ((char *) kcount + kcountsize + sizeof (uint32_t));
|
||||
data = (struct here_cg_arc_record *) ((char *) narcsp + sizeof (uint32_t));
|
||||
|
||||
if (st.st_size == 0)
|
||||
{
|
||||
/* Create the signature. */
|
||||
memcpy (addr, &gmon_hdr, sizeof (struct gmon_hdr));
|
||||
|
||||
*(uint32_t *) hist = GMON_TAG_TIME_HIST;
|
||||
memcpy (hist + sizeof (uint32_t), &hist_hdr,
|
||||
sizeof (struct gmon_hist_hdr));
|
||||
|
||||
narcsp[-1] = GMON_TAG_CG_ARC;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Test the signature in the file. */
|
||||
if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
|
||||
|| *(uint32_t *) hist != GMON_TAG_TIME_HIST
|
||||
|| memcmp (hist + sizeof (uint32_t), &hist_hdr,
|
||||
sizeof (struct gmon_hist_hdr)) != 0
|
||||
|| narcsp[-1] != GMON_TAG_CG_ARC)
|
||||
goto wrong_format;
|
||||
}
|
||||
|
||||
/* Allocate memory for the froms data and the pointer to the tos records. */
|
||||
tos = (uint16_t *) calloc (tossize + fromssize, 1);
|
||||
if (tos == NULL)
|
||||
{
|
||||
__munmap ((void *) addr, expected_size);
|
||||
_dl_fatal_printf ("Out of memory while initializing profiler\n");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
froms = (struct here_fromstruct *) ((char *) tos + tossize);
|
||||
fromidx = 0;
|
||||
|
||||
/* Now we have to process all the arc count entries. BTW: it is
|
||||
not critical whether the *NARCSP value changes meanwhile. Before
|
||||
we enter a new entry in to toset we will check that everything is
|
||||
available in TOS. This happens in _dl_mcount.
|
||||
|
||||
Loading the entries in reverse order should help to get the most
|
||||
frequently used entries at the front of the list. */
|
||||
for (idx = narcs = MIN (*narcsp, fromlimit); idx > 0; )
|
||||
{
|
||||
size_t to_index;
|
||||
size_t newfromidx;
|
||||
--idx;
|
||||
to_index = (data[idx].self_pc / (hashfraction * sizeof (*tos)));
|
||||
newfromidx = fromidx++;
|
||||
froms[newfromidx].here = &data[idx];
|
||||
froms[newfromidx].link = tos[to_index];
|
||||
tos[to_index] = newfromidx;
|
||||
}
|
||||
|
||||
/* Setup counting data. */
|
||||
if (kcountsize < highpc - lowpc)
|
||||
{
|
||||
#if 0
|
||||
s_scale = ((double) kcountsize / (highpc - lowpc)) * SCALE_1_TO_1;
|
||||
#else
|
||||
size_t range = highpc - lowpc;
|
||||
size_t quot = range / kcountsize;
|
||||
|
||||
if (quot >= SCALE_1_TO_1)
|
||||
s_scale = 1;
|
||||
else if (quot >= SCALE_1_TO_1 / 256)
|
||||
s_scale = SCALE_1_TO_1 / quot;
|
||||
else if (range > ULONG_MAX / 256)
|
||||
s_scale = (SCALE_1_TO_1 * 256) / (range / (kcountsize / 256));
|
||||
else
|
||||
s_scale = (SCALE_1_TO_1 * 256) / ((range * 256) / kcountsize);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
s_scale = SCALE_1_TO_1;
|
||||
|
||||
/* Start the profiler. */
|
||||
profil ((void *) kcount, kcountsize, lowpc, s_scale);
|
||||
|
||||
/* Turn on profiling. */
|
||||
running = 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc)
|
||||
{
|
||||
volatile uint16_t *topcindex;
|
||||
size_t i, fromindex;
|
||||
struct here_fromstruct *fromp;
|
||||
|
||||
if (! running)
|
||||
return;
|
||||
|
||||
/* Compute relative addresses. The shared object can be loaded at
|
||||
any address. The value of frompc could be anything. We cannot
|
||||
restrict it in any way, just set to a fixed value (0) in case it
|
||||
is outside the allowed range. These calls show up as calls from
|
||||
<external> in the gprof output. */
|
||||
frompc -= lowpc;
|
||||
if (frompc >= textsize)
|
||||
frompc = 0;
|
||||
selfpc -= lowpc;
|
||||
if (selfpc >= textsize)
|
||||
goto done;
|
||||
|
||||
/* Getting here we now have to find out whether the location was
|
||||
already used. If yes we are lucky and only have to increment a
|
||||
counter (this also has to be atomic). If the entry is new things
|
||||
are getting complicated... */
|
||||
|
||||
/* Avoid integer divide if possible. */
|
||||
if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
|
||||
i = selfpc >> log_hashfraction;
|
||||
else
|
||||
i = selfpc / (hashfraction * sizeof (*tos));
|
||||
|
||||
topcindex = &tos[i];
|
||||
fromindex = *topcindex;
|
||||
|
||||
if (fromindex == 0)
|
||||
goto check_new_or_add;
|
||||
|
||||
fromp = &froms[fromindex];
|
||||
|
||||
/* We have to look through the chain of arcs whether there is already
|
||||
an entry for our arc. */
|
||||
while (fromp->here->from_pc != frompc)
|
||||
{
|
||||
if (fromp->link != 0)
|
||||
do
|
||||
fromp = &froms[fromp->link];
|
||||
while (fromp->link != 0 && fromp->here->from_pc != frompc);
|
||||
|
||||
if (fromp->here->from_pc != frompc)
|
||||
{
|
||||
topcindex = &fromp->link;
|
||||
|
||||
check_new_or_add:
|
||||
/* Our entry is not among the entries we read so far from the
|
||||
data file. Now see whether we have to update the list. */
|
||||
while (narcs != *narcsp && narcs < fromlimit)
|
||||
{
|
||||
size_t to_index;
|
||||
size_t newfromidx;
|
||||
to_index = (data[narcs].self_pc
|
||||
/ (hashfraction * sizeof (*tos)));
|
||||
newfromidx = exchange_and_add (&fromidx, 1) + 1;
|
||||
froms[newfromidx].here = &data[narcs];
|
||||
froms[newfromidx].link = tos[to_index];
|
||||
tos[to_index] = newfromidx;
|
||||
atomic_add (&narcs, 1);
|
||||
}
|
||||
|
||||
/* If we still have no entry stop searching and insert. */
|
||||
if (*topcindex == 0)
|
||||
{
|
||||
uint32_t newarc = exchange_and_add (narcsp, 1);
|
||||
|
||||
/* In rare cases it could happen that all entries in FROMS are
|
||||
occupied. So we cannot count this anymore. */
|
||||
if (newarc >= fromlimit)
|
||||
goto done;
|
||||
|
||||
*topcindex = exchange_and_add (&fromidx, 1) + 1;
|
||||
fromp = &froms[*topcindex];
|
||||
|
||||
fromp->here = &data[newarc];
|
||||
data[newarc].from_pc = frompc;
|
||||
data[newarc].self_pc = selfpc;
|
||||
data[newarc].count = 0;
|
||||
fromp->link = 0;
|
||||
atomic_add (&narcs, 1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
fromp = &froms[*topcindex];
|
||||
}
|
||||
else
|
||||
/* Found in. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Increment the counter. */
|
||||
atomic_add (&fromp->here->count, 1);
|
||||
|
||||
done:
|
||||
;
|
||||
}
|
43
newlib/libc/sys/linux/dl/dl-profstub.c
Normal file
43
newlib/libc/sys/linux/dl/dl-profstub.c
Normal file
@ -0,0 +1,43 @@
|
||||
/* Helper definitions for profiling of shared libraries.
|
||||
Copyright (C) 1998, 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <dlfcn.h>
|
||||
#include <elf.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <libc-symbols.h>
|
||||
|
||||
/* This is the map for the shared object we profile. It is defined here
|
||||
only because we test for this value being NULL or not. */
|
||||
extern struct link_map *_dl_profile_map;
|
||||
|
||||
|
||||
void
|
||||
_dl_mcount_wrapper (void *selfpc)
|
||||
{
|
||||
_dl_mcount ((ElfW(Addr)) RETURN_ADDRESS (0), (ElfW(Addr)) selfpc);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_dl_mcount_wrapper_check (void *selfpc)
|
||||
{
|
||||
if (_dl_profile_map != NULL)
|
||||
_dl_mcount ((ElfW(Addr)) RETURN_ADDRESS (0), (ElfW(Addr)) selfpc);
|
||||
}
|
213
newlib/libc/sys/linux/dl/dl-reloc.c
Normal file
213
newlib/libc/sys/linux/dl/dl-reloc.c
Normal file
@ -0,0 +1,213 @@
|
||||
/* Relocate a shared object and resolve its references to other loaded objects.
|
||||
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. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <libintl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include "dynamic-link.h"
|
||||
|
||||
/* Statistics function. */
|
||||
unsigned long int _dl_num_cache_relocations;
|
||||
|
||||
|
||||
void
|
||||
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||
int lazy, int consider_profiling)
|
||||
{
|
||||
struct textrels
|
||||
{
|
||||
caddr_t start;
|
||||
size_t len;
|
||||
int prot;
|
||||
struct textrels *next;
|
||||
} *textrels = NULL;
|
||||
/* Initialize it to make the compiler happy. */
|
||||
const char *errstring = NULL;
|
||||
|
||||
if (l->l_relocated)
|
||||
return;
|
||||
|
||||
/* If DT_BIND_NOW is set relocate all references in this object. We
|
||||
do not do this if we are profiling, of course. */
|
||||
if (!consider_profiling
|
||||
&& __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
|
||||
lazy = 0;
|
||||
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_RELOC, 0))
|
||||
_dl_printf ("\nrelocation processing: %s%s\n",
|
||||
l->l_name[0] ? l->l_name : _dl_argv[0], lazy ? " (lazy)" : "");
|
||||
|
||||
/* DT_TEXTREL is now in level 2 and might phase out at some time.
|
||||
But we rewrite the DT_FLAGS entry to a DT_TEXTREL entry to make
|
||||
testing easier and therefore it will be available at all time. */
|
||||
if (__builtin_expect (l->l_info[DT_TEXTREL] != NULL, 0))
|
||||
{
|
||||
/* Bletch. We must make read-only segments writable
|
||||
long enough to relocate them. */
|
||||
const ElfW(Phdr) *ph;
|
||||
for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
|
||||
if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
|
||||
{
|
||||
struct textrels *newp;
|
||||
|
||||
newp = (struct textrels *) alloca (sizeof (*newp));
|
||||
newp->len = (((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
|
||||
& ~(_dl_pagesize - 1))
|
||||
- (ph->p_vaddr & ~(_dl_pagesize - 1)));
|
||||
newp->start = ((ph->p_vaddr & ~(_dl_pagesize - 1))
|
||||
+ (caddr_t) l->l_addr);
|
||||
|
||||
if (mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0)
|
||||
{
|
||||
errstring = N_("cannot make segment writable for relocation");
|
||||
call_error:
|
||||
_dl_signal_error (errno, l->l_name, NULL, errstring);
|
||||
}
|
||||
|
||||
#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
|
||||
newp->prot = (PF_TO_PROT
|
||||
>> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
|
||||
#else
|
||||
newp->prot = 0;
|
||||
if (ph->p_flags & PF_R)
|
||||
newp->prot |= PROT_READ;
|
||||
if (ph->p_flags & PF_W)
|
||||
newp->prot |= PROT_WRITE;
|
||||
if (ph->p_flags & PF_X)
|
||||
newp->prot |= PROT_EXEC;
|
||||
#endif
|
||||
newp->next = textrels;
|
||||
textrels = newp;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* Do the actual relocation of the object's GOT and other data. */
|
||||
|
||||
/* String table object symbols. */
|
||||
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
|
||||
|
||||
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||
#define RESOLVE_MAP(ref, version, r_type) \
|
||||
(ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
|
||||
? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
|
||||
&& elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \
|
||||
? (++_dl_num_cache_relocations, \
|
||||
(*ref) = l->l_lookup_cache.ret, \
|
||||
l->l_lookup_cache.value) \
|
||||
: ({ lookup_t _lr; \
|
||||
int _tc = elf_machine_type_class (r_type); \
|
||||
l->l_lookup_cache.type_class = _tc; \
|
||||
l->l_lookup_cache.sym = (*ref); \
|
||||
_lr = ((version) != NULL && (version)->hash != 0 \
|
||||
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \
|
||||
l, (ref), scope, \
|
||||
(version), _tc, 0) \
|
||||
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \
|
||||
scope, _tc, 0)); \
|
||||
l->l_lookup_cache.ret = (*ref); \
|
||||
l->l_lookup_cache.value = _lr; })) \
|
||||
: l)
|
||||
#define RESOLVE(ref, version, r_type) \
|
||||
(ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
|
||||
? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
|
||||
&& elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \
|
||||
? (++_dl_num_cache_relocations, \
|
||||
(*ref) = l->l_lookup_cache.ret, \
|
||||
l->l_lookup_cache.value) \
|
||||
: ({ lookup_t _lr; \
|
||||
int _tc = elf_machine_type_class (r_type); \
|
||||
l->l_lookup_cache.type_class = _tc; \
|
||||
l->l_lookup_cache.sym = (*ref); \
|
||||
_lr = ((version) != NULL && (version)->hash != 0 \
|
||||
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \
|
||||
l, (ref), scope, \
|
||||
(version), _tc, 0) \
|
||||
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \
|
||||
scope, _tc, 0)); \
|
||||
l->l_lookup_cache.ret = (*ref); \
|
||||
l->l_lookup_cache.value = _lr; })) \
|
||||
: l->l_addr)
|
||||
|
||||
#include "dynamic-link.h"
|
||||
|
||||
ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling);
|
||||
|
||||
if (__builtin_expect (consider_profiling, 0))
|
||||
{
|
||||
/* Allocate the array which will contain the already found
|
||||
relocations. If the shared object lacks a PLT (for example
|
||||
if it only contains lead function) the l_info[DT_PLTRELSZ]
|
||||
will be NULL. */
|
||||
if (l->l_info[DT_PLTRELSZ] == NULL)
|
||||
{
|
||||
errstring = N_("%s: profiler found no PLTREL in object %s\n");
|
||||
fatal:
|
||||
_dl_fatal_printf (errstring,
|
||||
_dl_argv[0] ?: "<program name unknown>",
|
||||
l->l_name);
|
||||
}
|
||||
|
||||
l->l_reloc_result =
|
||||
(ElfW(Addr) *) calloc (sizeof (ElfW(Addr)),
|
||||
l->l_info[DT_PLTRELSZ]->d_un.d_val);
|
||||
if (l->l_reloc_result == NULL)
|
||||
{
|
||||
errstring = N_("\
|
||||
%s: profiler out of memory shadowing PLTREL of %s\n");
|
||||
goto fatal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark the object so we know this work has been done. */
|
||||
l->l_relocated = 1;
|
||||
|
||||
/* Undo the segment protection changes. */
|
||||
while (__builtin_expect (textrels != NULL, 0))
|
||||
{
|
||||
if (mprotect (textrels->start, textrels->len, textrels->prot) < 0)
|
||||
{
|
||||
errstring = N_("cannot restore segment prot after reloc");
|
||||
goto call_error;
|
||||
}
|
||||
|
||||
textrels = textrels->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
internal_function
|
||||
_dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt)
|
||||
{
|
||||
/* XXX We cannot translate these messages. */
|
||||
static const char msg[2][32] = { "unexpected reloc type",
|
||||
"unexpected PLT reloc type" };
|
||||
char msgbuf[sizeof (msg[0])];
|
||||
|
||||
strcpy (msgbuf, msg[plt]);
|
||||
|
||||
_dl_signal_error (0, map->l_name, NULL, msgbuf);
|
||||
}
|
231
newlib/libc/sys/linux/dl/dl-runtime.c
Normal file
231
newlib/libc/sys/linux/dl/dl-runtime.c
Normal file
@ -0,0 +1,231 @@
|
||||
/* On-demand PLT fixup for shared objects.
|
||||
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. */
|
||||
|
||||
#include <alloca.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
#include "dynamic-link.h"
|
||||
|
||||
#define __attribute_used__
|
||||
|
||||
#if !defined ELF_MACHINE_NO_RELA || ELF_MACHINE_NO_REL
|
||||
# define PLTREL ElfW(Rela)
|
||||
#else
|
||||
# define PLTREL ElfW(Rel)
|
||||
#endif
|
||||
|
||||
#ifndef VERSYMIDX
|
||||
# define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
|
||||
#endif
|
||||
|
||||
|
||||
/* This function is called through a special trampoline from the PLT the
|
||||
first time each PLT entry is called. We must perform the relocation
|
||||
specified in the PLT of the given shared object, and return the resolved
|
||||
function address to the trampoline, which will restart the original call
|
||||
to that address. Future calls will bounce directly from the PLT to the
|
||||
function. */
|
||||
|
||||
#ifndef ELF_MACHINE_NO_PLT
|
||||
static ElfW(Addr) __attribute_used__
|
||||
fixup (
|
||||
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
|
||||
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
|
||||
# endif
|
||||
/* GKM FIXME: Fix trampoline to pass bounds so we can do
|
||||
without the `__unbounded' qualifier. */
|
||||
struct link_map *__unbounded l, ElfW(Word) reloc_offset)
|
||||
{
|
||||
const ElfW(Sym) *const symtab
|
||||
= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
|
||||
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
|
||||
|
||||
const PLTREL *const reloc
|
||||
= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
|
||||
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
|
||||
void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
|
||||
lookup_t result;
|
||||
ElfW(Addr) value;
|
||||
|
||||
/* The use of `alloca' here looks ridiculous but it helps. The goal is
|
||||
to prevent the function from being inlined and thus optimized out.
|
||||
There is no official way to do this so we use this trick. gcc never
|
||||
inlines functions which use `alloca'. */
|
||||
alloca (sizeof (int));
|
||||
|
||||
/* Sanity check that we're really looking at a PLT relocation. */
|
||||
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
|
||||
|
||||
/* Look up the target symbol. If the normal lookup rules are not
|
||||
used don't look in the global scope. */
|
||||
if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
|
||||
{
|
||||
switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||
{
|
||||
default:
|
||||
{
|
||||
const ElfW(Half) *vernum =
|
||||
(const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
|
||||
ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
|
||||
const struct r_found_version *version = &l->l_versions[ndx];
|
||||
|
||||
if (version->hash != 0)
|
||||
{
|
||||
result = _dl_lookup_versioned_symbol (strtab + sym->st_name,
|
||||
l, &sym, l->l_scope,
|
||||
version,
|
||||
ELF_RTYPE_CLASS_PLT, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 0:
|
||||
result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
|
||||
l->l_scope, ELF_RTYPE_CLASS_PLT, 0);
|
||||
}
|
||||
|
||||
/* Currently result contains the base load address (or link map)
|
||||
of the object that defines sym. Now add in the symbol
|
||||
offset. */
|
||||
value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We already found the symbol. The module (and therefore its load
|
||||
address) is also known. */
|
||||
value = l->l_addr + sym->st_value;
|
||||
#ifdef DL_LOOKUP_RETURNS_MAP
|
||||
result = l;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* And now perhaps the relocation addend. */
|
||||
value = elf_machine_plt_value (l, reloc, value);
|
||||
|
||||
/* Finally, fix up the plt itself. */
|
||||
if (__builtin_expect (_dl_bind_not, 0))
|
||||
return value;
|
||||
|
||||
return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined PROF && !defined ELF_MACHINE_NO_PLT && !__BOUNDED_POINTERS__
|
||||
|
||||
static ElfW(Addr) __attribute_used__
|
||||
profile_fixup (
|
||||
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
|
||||
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
|
||||
#endif
|
||||
struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
|
||||
{
|
||||
void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
|
||||
ElfW(Addr) *resultp;
|
||||
lookup_t result;
|
||||
ElfW(Addr) value;
|
||||
|
||||
/* The use of `alloca' here looks ridiculous but it helps. The goal is
|
||||
to prevent the function from being inlined, and thus optimized out.
|
||||
There is no official way to do this so we use this trick. gcc never
|
||||
inlines functions which use `alloca'. */
|
||||
alloca (sizeof (int));
|
||||
|
||||
/* This is the address in the array where we store the result of previous
|
||||
relocations. */
|
||||
resultp = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
|
||||
|
||||
value = *resultp;
|
||||
if (value == 0)
|
||||
{
|
||||
/* This is the first time we have to relocate this object. */
|
||||
const ElfW(Sym) *const symtab
|
||||
= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
|
||||
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
|
||||
|
||||
const PLTREL *const reloc
|
||||
= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
|
||||
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
|
||||
|
||||
/* Sanity check that we're really looking at a PLT relocation. */
|
||||
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
|
||||
|
||||
/* Look up the target symbol. If the symbol is marked STV_PROTECTED
|
||||
don't look in the global scope. */
|
||||
if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
|
||||
{
|
||||
switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||
{
|
||||
default:
|
||||
{
|
||||
const ElfW(Half) *vernum =
|
||||
(const void *) D_PTR (l,l_info[VERSYMIDX (DT_VERSYM)]);
|
||||
ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
|
||||
const struct r_found_version *version = &l->l_versions[ndx];
|
||||
|
||||
if (version->hash != 0)
|
||||
{
|
||||
result = _dl_lookup_versioned_symbol(strtab + sym->st_name,
|
||||
l, &sym, l->l_scope,
|
||||
version,
|
||||
ELF_RTYPE_CLASS_PLT,
|
||||
0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 0:
|
||||
result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
|
||||
l->l_scope, ELF_RTYPE_CLASS_PLT, 0);
|
||||
}
|
||||
|
||||
/* Currently result contains the base load address (or link map)
|
||||
of the object that defines sym. Now add in the symbol
|
||||
offset. */
|
||||
value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We already found the symbol. The module (and therefore its load
|
||||
address) is also known. */
|
||||
value = l->l_addr + sym->st_value;
|
||||
#ifdef DL_LOOKUP_RETURNS_MAP
|
||||
result = l;
|
||||
#endif
|
||||
}
|
||||
/* And now perhaps the relocation addend. */
|
||||
value = elf_machine_plt_value (l, reloc, value);
|
||||
|
||||
/* Store the result for later runs. */
|
||||
if (__builtin_expect (! _dl_bind_not, 1))
|
||||
*resultp = value;
|
||||
}
|
||||
|
||||
(*mcount_fct) (retaddr, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif /* PROF && ELF_MACHINE_NO_PLT */
|
||||
|
||||
|
||||
/* This macro is defined in dl-machine.h to define the entry point called
|
||||
by the PLT. The `fixup' function above does the real work, but a little
|
||||
more twiddling is needed to get the stack right and jump to the address
|
||||
finally resolved. */
|
||||
|
||||
ELF_MACHINE_RUNTIME_TRAMPOLINE
|
184
newlib/libc/sys/linux/dl/dl-support.c
Normal file
184
newlib/libc/sys/linux/dl/dl-support.c
Normal file
@ -0,0 +1,184 @@
|
||||
/* Support for dynamic linking code in static libc.
|
||||
Copyright (C) 1996, 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. */
|
||||
|
||||
/* This file defines some things that for the dynamic linker are defined in
|
||||
rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <libintl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <pthread.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <machine/dl-machine.h>
|
||||
#include <dl-librecon.h>
|
||||
#include <unsecvars.h>
|
||||
#include <machine/hp-timing.h>
|
||||
|
||||
char *__progname = "newlib";
|
||||
char **_dl_argv = &__progname; /* This is checked for some error messages. */
|
||||
|
||||
/* Name of the architecture. */
|
||||
const char *_dl_platform;
|
||||
size_t _dl_platformlen;
|
||||
|
||||
int _dl_debug_mask;
|
||||
int _dl_lazy;
|
||||
/* XXX I know about at least one case where we depend on the old weak
|
||||
behavior (it has to do with librt). Until we get DSO groups implemented
|
||||
we have to make this the default. Bummer. --drepper */
|
||||
#if 0
|
||||
int _dl_dynamic_weak;
|
||||
#else
|
||||
int _dl_dynamic_weak = 1;
|
||||
#endif
|
||||
|
||||
/* If nonzero print warnings about problematic situations. */
|
||||
int _dl_verbose;
|
||||
|
||||
/* Structure to store information about search paths. */
|
||||
struct r_search_path *_dl_search_paths;
|
||||
|
||||
/* We never do profiling. */
|
||||
const char *_dl_profile;
|
||||
|
||||
/* Names of shared object for which the RUNPATHs and RPATHs should be
|
||||
ignored. */
|
||||
const char *_dl_inhibit_rpath;
|
||||
|
||||
/* The map for the object we will profile. */
|
||||
struct link_map *_dl_profile_map;
|
||||
|
||||
/* This is the address of the last stack address ever used. */
|
||||
void *__libc_stack_end;
|
||||
|
||||
/* Path where the binary is found. */
|
||||
const char *_dl_origin_path;
|
||||
|
||||
/* Nonzero if runtime lookup should not update the .got/.plt. */
|
||||
int _dl_bind_not;
|
||||
|
||||
/* Initially empty list of loaded objects. */
|
||||
struct link_map *_dl_loaded;
|
||||
/* Number of object in the _dl_loaded list. */
|
||||
unsigned int _dl_nloaded;
|
||||
|
||||
/* Fake scope. In dynamically linked binaries this is the scope of the
|
||||
main application but here we don't have something like this. So
|
||||
create a fake scope containing nothing. */
|
||||
struct r_scope_elem _dl_initial_searchlist;
|
||||
/* Variable which can be used in lookup to process the global scope. */
|
||||
struct r_scope_elem *_dl_global_scope[2] = { &_dl_initial_searchlist, NULL };
|
||||
/* This is a global pointer to this structure which is public. It is
|
||||
used by dlopen/dlclose to add and remove objects from what is regarded
|
||||
to be the global scope. */
|
||||
struct r_scope_elem *_dl_main_searchlist = &_dl_initial_searchlist;
|
||||
|
||||
/* Nonzero during startup. */
|
||||
int _dl_starting_up = 1;
|
||||
|
||||
/* We expect less than a second for relocation. */
|
||||
#ifdef HP_SMALL_TIMING_AVAIL
|
||||
# undef HP_TIMING_AVAIL
|
||||
# define HP_TIMING_AVAIL HP_SMALL_TIMING_AVAIL
|
||||
#endif
|
||||
|
||||
/* Initial value of the CPU clock. */
|
||||
#ifndef HP_TIMING_NONAVAIL
|
||||
hp_timing_t _dl_cpuclock_offset;
|
||||
#endif
|
||||
|
||||
/* During the program run we must not modify the global data of
|
||||
loaded shared object simultanously in two threads. Therefore we
|
||||
protect `_dl_open' and `_dl_close' in dl-close.c.
|
||||
|
||||
This must be a recursive lock since the initializer function of
|
||||
the loaded object might as well require a call to this function.
|
||||
At this time it is not anymore a problem to modify the tables. */
|
||||
__LOCK_RECURSIVE_INIT (, _dl_load_lock)
|
||||
|
||||
|
||||
#ifdef HAVE_AUX_VECTOR
|
||||
extern int _dl_clktck;
|
||||
|
||||
void
|
||||
internal_function
|
||||
_dl_aux_init (ElfW(auxv_t) *av)
|
||||
{
|
||||
for (; av->a_type != AT_NULL; ++av)
|
||||
switch (av->a_type)
|
||||
{
|
||||
case AT_PAGESZ:
|
||||
_dl_pagesize = av->a_un.a_val;
|
||||
break;
|
||||
case AT_CLKTCK:
|
||||
_dl_clktck = av->a_un.a_val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void non_dynamic_init (void) __attribute__ ((unused));
|
||||
|
||||
void
|
||||
non_dynamic_init (void)
|
||||
{
|
||||
if (HP_TIMING_AVAIL)
|
||||
HP_TIMING_NOW (_dl_cpuclock_offset);
|
||||
|
||||
if (!_dl_pagesize)
|
||||
_dl_pagesize = __getpagesize ();
|
||||
|
||||
_dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;
|
||||
|
||||
/* Initialize the data structures for the search paths for shared
|
||||
objects. */
|
||||
_dl_init_paths (getenv ("LD_LIBRARY_PATH"));
|
||||
|
||||
_dl_lazy = *(getenv ("LD_BIND_NOW") ?: "") == '\0';
|
||||
|
||||
_dl_bind_not = *(getenv ("LD_BIND_NOT") ?: "") != '\0';
|
||||
|
||||
_dl_dynamic_weak = *(getenv ("LD_DYNAMIC_WEAK") ?: "") == '\0';
|
||||
|
||||
#ifdef DL_PLATFORM_INIT
|
||||
DL_PLATFORM_INIT;
|
||||
#endif
|
||||
|
||||
/* Now determine the length of the platform string. */
|
||||
if (_dl_platform != NULL)
|
||||
_dl_platformlen = strlen (_dl_platform);
|
||||
}
|
||||
text_set_element (__libc_subinit, non_dynamic_init);
|
||||
|
||||
const struct r_strlenpair *
|
||||
internal_function
|
||||
_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
||||
size_t *max_capstrlen)
|
||||
{
|
||||
static struct r_strlenpair result;
|
||||
static char buf[1];
|
||||
|
||||
result.str = buf; /* Does not really matter. */
|
||||
result.len = 0;
|
||||
|
||||
*sz = 1;
|
||||
return &result;
|
||||
}
|
158
newlib/libc/sys/linux/dl/dl-sym.c
Normal file
158
newlib/libc/sys/linux/dl/dl-sym.c
Normal file
@ -0,0 +1,158 @@
|
||||
/* Look up a symbol in a shared object loaded by `dlopen'.
|
||||
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. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <libintl.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <dl-hash.h>
|
||||
|
||||
void *
|
||||
internal_function
|
||||
_dl_sym (void *handle, const char *name, void *who)
|
||||
{
|
||||
const ElfW(Sym) *ref = NULL;
|
||||
lookup_t result;
|
||||
ElfW(Addr) caller = (ElfW(Addr)) who;
|
||||
struct link_map *match;
|
||||
struct link_map *l;
|
||||
|
||||
/* If the address is not recognized the call comes from the main
|
||||
program (we hope). */
|
||||
match = _dl_loaded;
|
||||
|
||||
/* Find the highest-addressed object that CALLER is not below. */
|
||||
for (l = _dl_loaded; l != NULL; l = l->l_next)
|
||||
if (caller >= l->l_map_start && caller < l->l_map_end)
|
||||
{
|
||||
/* There must be exactly one DSO for the range of the virtual
|
||||
memory. Otherwise something is really broken. */
|
||||
match = l;
|
||||
break;
|
||||
}
|
||||
|
||||
if (handle == RTLD_DEFAULT)
|
||||
/* Search the global scope as seen in the caller object. */
|
||||
result = _dl_lookup_symbol (name, match, &ref, match->l_scope, 0, 0);
|
||||
else
|
||||
{
|
||||
if (handle != RTLD_NEXT)
|
||||
{
|
||||
/* Search the scope of the given object. */
|
||||
struct link_map *map = handle;
|
||||
|
||||
result = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
|
||||
0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (__builtin_expect (match == _dl_loaded, 0))
|
||||
{
|
||||
if (! _dl_loaded
|
||||
|| caller < _dl_loaded->l_map_start
|
||||
|| caller >= _dl_loaded->l_map_end)
|
||||
_dl_signal_error (0, NULL, NULL, N_("\
|
||||
RTLD_NEXT used in code not dynamically loaded"));
|
||||
}
|
||||
|
||||
l = match;
|
||||
while (l->l_loader != NULL)
|
||||
l = l->l_loader;
|
||||
|
||||
result = _dl_lookup_symbol_skip (name, l, &ref, l->l_local_scope,
|
||||
match);
|
||||
}
|
||||
}
|
||||
|
||||
if (ref != NULL)
|
||||
return DL_SYMBOL_ADDRESS (result, ref);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
internal_function
|
||||
_dl_vsym (void *handle, const char *name, const char *version, void *who)
|
||||
{
|
||||
const ElfW(Sym) *ref = NULL;
|
||||
struct r_found_version vers;
|
||||
lookup_t result;
|
||||
ElfW(Addr) caller = (ElfW(Addr)) who;
|
||||
struct link_map *match;
|
||||
struct link_map *l;
|
||||
|
||||
/* Compute hash value to the version string. */
|
||||
vers.name = version;
|
||||
vers.hidden = 1;
|
||||
vers.hash = _dl_elf_hash (version);
|
||||
/* We don't have a specific file where the symbol can be found. */
|
||||
vers.filename = NULL;
|
||||
|
||||
/* If the address is not recognized the call comes from the main
|
||||
program (we hope). */
|
||||
match = _dl_loaded;
|
||||
|
||||
/* Find the highest-addressed object that CALLER is not below. */
|
||||
for (l = _dl_loaded; l != NULL; l = l->l_next)
|
||||
if (caller >= l->l_map_start && caller < l->l_map_end)
|
||||
{
|
||||
/* There must be exactly one DSO for the range of the virtual
|
||||
memory. Otherwise something is really broken. */
|
||||
match = l;
|
||||
break;
|
||||
}
|
||||
|
||||
if (handle == RTLD_DEFAULT)
|
||||
/* Search the global scope. */
|
||||
result = _dl_lookup_versioned_symbol (name, match, &ref, match->l_scope,
|
||||
&vers, 0, 0);
|
||||
else if (handle == RTLD_NEXT)
|
||||
{
|
||||
if (__builtin_expect (match == _dl_loaded, 0))
|
||||
{
|
||||
if (! _dl_loaded
|
||||
|| caller < _dl_loaded->l_map_start
|
||||
|| caller >= _dl_loaded->l_map_end)
|
||||
_dl_signal_error (0, NULL, NULL, N_("\
|
||||
RTLD_NEXT used in code not dynamically loaded"));
|
||||
}
|
||||
|
||||
l = match;
|
||||
while (l->l_loader != NULL)
|
||||
l = l->l_loader;
|
||||
|
||||
result = _dl_lookup_versioned_symbol_skip (name, l, &ref,
|
||||
l->l_local_scope,
|
||||
&vers, match);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Search the scope of the given object. */
|
||||
struct link_map *map = handle;
|
||||
result = _dl_lookup_versioned_symbol (name, map, &ref,
|
||||
map->l_local_scope, &vers, 0, 1);
|
||||
}
|
||||
|
||||
if (ref != NULL)
|
||||
return DL_SYMBOL_ADDRESS (result, ref);
|
||||
|
||||
return NULL;
|
||||
}
|
385
newlib/libc/sys/linux/dl/dl-version.c
Normal file
385
newlib/libc/sys/linux/dl/dl-version.c
Normal file
@ -0,0 +1,385 @@
|
||||
/* Handle symbol and library versioning.
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <elf.h>
|
||||
#include <errno.h>
|
||||
#include <libintl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
#ifndef VERSYMIDX
|
||||
# define VERSYMIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
|
||||
#endif
|
||||
|
||||
|
||||
#define make_string(string, rest...) \
|
||||
({ \
|
||||
const char *all[] = { string, ## rest }; \
|
||||
size_t len, cnt; \
|
||||
char *result, *cp; \
|
||||
\
|
||||
len = 1; \
|
||||
for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
|
||||
len += strlen (all[cnt]); \
|
||||
\
|
||||
cp = result = alloca (len); \
|
||||
for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt) \
|
||||
{ \
|
||||
cp = strcpy (cp, all[cnt]); \
|
||||
cp += strlen (all[cnt]); \
|
||||
} \
|
||||
\
|
||||
result; \
|
||||
})
|
||||
|
||||
|
||||
static inline struct link_map *
|
||||
find_needed (const char *name, struct link_map *map)
|
||||
{
|
||||
struct link_map *tmap;
|
||||
unsigned int n;
|
||||
|
||||
for (tmap = _dl_loaded; tmap != NULL; tmap = tmap->l_next)
|
||||
if (_dl_name_match_p (name, tmap))
|
||||
return tmap;
|
||||
|
||||
/* The required object is not in the global scope, look to see if it is
|
||||
a dependency of the current object. */
|
||||
for (n = 0; n < map->l_searchlist.r_nlist; n++)
|
||||
if (_dl_name_match_p (name, map->l_searchlist.r_list[n]))
|
||||
return map->l_searchlist.r_list[n];
|
||||
|
||||
/* Should never happen. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
internal_function
|
||||
match_symbol (const char *name, ElfW(Word) hash, const char *string,
|
||||
struct link_map *map, int verbose, int weak)
|
||||
{
|
||||
const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
|
||||
ElfW(Addr) def_offset;
|
||||
ElfW(Verdef) *def;
|
||||
/* Initialize to make the compiler happy. */
|
||||
const char *errstring = NULL;
|
||||
int result = 0;
|
||||
|
||||
/* Display information about what we are doing while debugging. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_VERSIONS, 0))
|
||||
_dl_debug_printf ("\
|
||||
checking for version `%s' in file %s required by file %s\n",
|
||||
string, map->l_name[0] ? map->l_name : _dl_argv[0],
|
||||
name);
|
||||
|
||||
if (__builtin_expect (map->l_info[VERSYMIDX (DT_VERDEF)] == NULL, 0))
|
||||
{
|
||||
/* The file has no symbol versioning. I.e., the dependent
|
||||
object was linked against another version of this file. We
|
||||
only print a message if verbose output is requested. */
|
||||
if (verbose)
|
||||
{
|
||||
/* XXX We cannot translate the messages. */
|
||||
errstring = make_string ("\
|
||||
no version information available (required by ", name, ")");
|
||||
goto call_cerror;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
def_offset = map->l_info[VERSYMIDX (DT_VERDEF)]->d_un.d_ptr;
|
||||
assert (def_offset != 0);
|
||||
|
||||
def = (ElfW(Verdef) *) ((char *) map->l_addr + def_offset);
|
||||
while (1)
|
||||
{
|
||||
/* Currently the version number of the definition entry is 1.
|
||||
Make sure all we see is this version. */
|
||||
if (__builtin_expect (def->vd_version, 1) != 1)
|
||||
{
|
||||
char buf[20];
|
||||
buf[sizeof (buf) - 1] = '\0';
|
||||
/* XXX We cannot translate the message. */
|
||||
errstring = make_string ("unsupported version of Verdef record");
|
||||
result = 1;
|
||||
goto call_cerror;
|
||||
}
|
||||
|
||||
/* Compare the hash values. */
|
||||
if (hash == def->vd_hash)
|
||||
{
|
||||
ElfW(Verdaux) *aux = (ElfW(Verdaux) *) ((char *) def + def->vd_aux);
|
||||
|
||||
/* To be safe, compare the string as well. */
|
||||
if (__builtin_expect (strcmp (string, strtab + aux->vda_name), 0)
|
||||
== 0)
|
||||
/* Bingo! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If no more definitions we failed to find what we want. */
|
||||
if (def->vd_next == 0)
|
||||
break;
|
||||
|
||||
/* Next definition. */
|
||||
def = (ElfW(Verdef) *) ((char *) def + def->vd_next);
|
||||
}
|
||||
|
||||
/* Symbol not found. If it was a weak reference it is not fatal. */
|
||||
if (__builtin_expect (weak, 1))
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
/* XXX We cannot translate the message. */
|
||||
errstring = make_string ("weak version `", string,
|
||||
"' not found (required by ", name, ")");
|
||||
goto call_cerror;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX We cannot translate the message. */
|
||||
errstring = make_string ("version `", string, "' not found (required by ",
|
||||
name, ")");
|
||||
result = 1;
|
||||
call_cerror:
|
||||
_dl_signal_cerror (0, map->l_name[0] ? map->l_name : _dl_argv[0], NULL,
|
||||
errstring);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
_dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
|
||||
{
|
||||
int result = 0;
|
||||
const char *strtab;
|
||||
/* Pointer to section with needed versions. */
|
||||
ElfW(Dyn) *dyn;
|
||||
/* Pointer to dynamic section with definitions. */
|
||||
ElfW(Dyn) *def;
|
||||
/* We need to find out which is the highest version index used
|
||||
in a dependecy. */
|
||||
unsigned int ndx_high = 0;
|
||||
/* Initialize to make the compiler happy. */
|
||||
const char *errstring = NULL;
|
||||
int errval = 0;
|
||||
|
||||
/* If we don't have a string table, we must be ok. */
|
||||
if (map->l_info[DT_STRTAB] == NULL)
|
||||
return 0;
|
||||
strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
|
||||
|
||||
dyn = map->l_info[VERSYMIDX (DT_VERNEED)];
|
||||
def = map->l_info[VERSYMIDX (DT_VERDEF)];
|
||||
|
||||
if (dyn != NULL)
|
||||
{
|
||||
/* This file requires special versions from its dependencies. */
|
||||
ElfW(Verneed) *ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr);
|
||||
|
||||
/* Currently the version number of the needed entry is 1.
|
||||
Make sure all we see is this version. */
|
||||
if (__builtin_expect (ent->vn_version, 1) != 1)
|
||||
{
|
||||
char buf[20];
|
||||
buf[sizeof (buf) - 1] = '\0';
|
||||
/* XXX We cannot translate the message. */
|
||||
errstring = make_string ("unsupported version of Verneed record\n");
|
||||
call_error:
|
||||
_dl_signal_error (errval, (*map->l_name ? map->l_name : _dl_argv[0]),
|
||||
NULL, errstring);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
ElfW(Vernaux) *aux;
|
||||
struct link_map *needed = find_needed (strtab + ent->vn_file, map);
|
||||
|
||||
/* If NEEDED is NULL this means a dependency was not found
|
||||
and no stub entry was created. This should never happen. */
|
||||
assert (needed != NULL);
|
||||
|
||||
/* Make sure this is no stub we created because of a missing
|
||||
dependency. */
|
||||
if (__builtin_expect (! trace_mode, 1)
|
||||
|| ! __builtin_expect (needed->l_faked, 0))
|
||||
{
|
||||
/* NEEDED is the map for the file we need. Now look for the
|
||||
dependency symbols. */
|
||||
aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux);
|
||||
while (1)
|
||||
{
|
||||
/* Match the symbol. */
|
||||
result |= match_symbol ((*map->l_name
|
||||
? map->l_name : _dl_argv[0]),
|
||||
aux->vna_hash,
|
||||
strtab + aux->vna_name,
|
||||
needed, verbose,
|
||||
aux->vna_flags & VER_FLG_WEAK);
|
||||
|
||||
/* Compare the version index. */
|
||||
if ((unsigned int) (aux->vna_other & 0x7fff) > ndx_high)
|
||||
ndx_high = aux->vna_other & 0x7fff;
|
||||
|
||||
if (aux->vna_next == 0)
|
||||
/* No more symbols. */
|
||||
break;
|
||||
|
||||
/* Next symbol. */
|
||||
aux = (ElfW(Vernaux) *) ((char *) aux + aux->vna_next);
|
||||
}
|
||||
}
|
||||
|
||||
if (ent->vn_next == 0)
|
||||
/* No more dependencies. */
|
||||
break;
|
||||
|
||||
/* Next dependency. */
|
||||
ent = (ElfW(Verneed) *) ((char *) ent + ent->vn_next);
|
||||
}
|
||||
}
|
||||
|
||||
/* We also must store the names of the defined versions. Determine
|
||||
the maximum index here as well.
|
||||
|
||||
XXX We could avoid the loop by just taking the number of definitions
|
||||
as an upper bound of new indeces. */
|
||||
if (def != NULL)
|
||||
{
|
||||
ElfW(Verdef) *ent;
|
||||
ent = (ElfW(Verdef) *) (map->l_addr + def->d_un.d_ptr);
|
||||
while (1)
|
||||
{
|
||||
if ((unsigned int) (ent->vd_ndx & 0x7fff) > ndx_high)
|
||||
ndx_high = ent->vd_ndx & 0x7fff;
|
||||
|
||||
if (ent->vd_next == 0)
|
||||
/* No more definitions. */
|
||||
break;
|
||||
|
||||
ent = (ElfW(Verdef) *) ((char *) ent + ent->vd_next);
|
||||
}
|
||||
}
|
||||
|
||||
if (ndx_high > 0)
|
||||
{
|
||||
/* Now we are ready to build the array with the version names
|
||||
which can be indexed by the version index in the VERSYM
|
||||
section. */
|
||||
map->l_versions = (struct r_found_version *)
|
||||
calloc (ndx_high + 1, sizeof (*map->l_versions));
|
||||
if (__builtin_expect (map->l_versions == NULL, 0))
|
||||
{
|
||||
errstring = N_("cannot allocate version reference table");
|
||||
errval = ENOMEM;
|
||||
goto call_error;
|
||||
}
|
||||
|
||||
/* Store the number of available symbols. */
|
||||
map->l_nversions = ndx_high + 1;
|
||||
|
||||
/* Compute the pointer to the version symbols. */
|
||||
map->l_versyms = (void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
|
||||
|
||||
if (dyn != NULL)
|
||||
{
|
||||
ElfW(Verneed) *ent;
|
||||
ent = (ElfW(Verneed) *) (map->l_addr + dyn->d_un.d_ptr);
|
||||
while (1)
|
||||
{
|
||||
ElfW(Vernaux) *aux;
|
||||
aux = (ElfW(Vernaux) *) ((char *) ent + ent->vn_aux);
|
||||
while (1)
|
||||
{
|
||||
ElfW(Half) ndx = aux->vna_other & 0x7fff;
|
||||
map->l_versions[ndx].hash = aux->vna_hash;
|
||||
map->l_versions[ndx].hidden = aux->vna_other & 0x8000;
|
||||
map->l_versions[ndx].name = &strtab[aux->vna_name];
|
||||
map->l_versions[ndx].filename = &strtab[ent->vn_file];
|
||||
|
||||
if (aux->vna_next == 0)
|
||||
/* No more symbols. */
|
||||
break;
|
||||
|
||||
/* Advance to next symbol. */
|
||||
aux = (ElfW(Vernaux) *) ((char *) aux + aux->vna_next);
|
||||
}
|
||||
|
||||
if (ent->vn_next == 0)
|
||||
/* No more dependencies. */
|
||||
break;
|
||||
|
||||
/* Advance to next dependency. */
|
||||
ent = (ElfW(Verneed) *) ((char *) ent + ent->vn_next);
|
||||
}
|
||||
}
|
||||
|
||||
/* And insert the defined versions. */
|
||||
if (def != NULL)
|
||||
{
|
||||
ElfW(Verdef) *ent;
|
||||
ent = (ElfW(Verdef) *) (map->l_addr + def->d_un.d_ptr);
|
||||
while (1)
|
||||
{
|
||||
ElfW(Verdaux) *aux;
|
||||
aux = (ElfW(Verdaux) *) ((char *) ent + ent->vd_aux);
|
||||
|
||||
if ((ent->vd_flags & VER_FLG_BASE) == 0)
|
||||
{
|
||||
/* The name of the base version should not be
|
||||
available for matching a versioned symbol. */
|
||||
ElfW(Half) ndx = ent->vd_ndx & 0x7fff;
|
||||
map->l_versions[ndx].hash = ent->vd_hash;
|
||||
map->l_versions[ndx].name = &strtab[aux->vda_name];
|
||||
map->l_versions[ndx].filename = NULL;
|
||||
}
|
||||
|
||||
if (ent->vd_next == 0)
|
||||
/* No more definitions. */
|
||||
break;
|
||||
|
||||
ent = (ElfW(Verdef) *) ((char *) ent + ent->vd_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
_dl_check_all_versions (struct link_map *map, int verbose, int trace_mode)
|
||||
{
|
||||
struct link_map *l;
|
||||
int result = 0;
|
||||
|
||||
for (l = map; l != NULL; l = l->l_next)
|
||||
result |= ! l->l_faked && _dl_check_map_versions (l, verbose, trace_mode);
|
||||
|
||||
return result;
|
||||
}
|
84
newlib/libc/sys/linux/dl/dlfcn.h
Normal file
84
newlib/libc/sys/linux/dl/dlfcn.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* User functions for run-time dynamic loading.
|
||||
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 _DLFCN_H
|
||||
#define _DLFCN_H 1
|
||||
|
||||
#include <features.h>
|
||||
|
||||
/* Collect various system dependent definitions and declarations. */
|
||||
#include <sys/dlfcn.h>
|
||||
|
||||
|
||||
/* 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)
|
||||
|
||||
|
||||
__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;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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;
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* dlfcn.h */
|
200
newlib/libc/sys/linux/dl/do-lookup.h
Normal file
200
newlib/libc/sys/linux/dl/do-lookup.h
Normal file
@ -0,0 +1,200 @@
|
||||
/* Look up a symbol in the loaded objects.
|
||||
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. */
|
||||
|
||||
#if VERSIONED
|
||||
# define FCT do_lookup_versioned
|
||||
# define ARG const struct r_found_version *const version,
|
||||
#else
|
||||
# define FCT do_lookup
|
||||
# define ARG
|
||||
#endif
|
||||
|
||||
/* Inner part of the lookup functions. We return a value > 0 if we
|
||||
found the symbol, the value 0 if nothing is found and < 0 if
|
||||
something bad happened. */
|
||||
static inline int
|
||||
FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref,
|
||||
struct sym_val *result, struct r_scope_elem *scope, size_t i, ARG
|
||||
struct link_map *skip, int type_class)
|
||||
{
|
||||
struct link_map **list = scope->r_list;
|
||||
size_t n = scope->r_nlist;
|
||||
struct link_map *map;
|
||||
|
||||
do
|
||||
{
|
||||
const ElfW(Sym) *symtab;
|
||||
const char *strtab;
|
||||
const ElfW(Half) *verstab;
|
||||
Elf_Symndx symidx;
|
||||
const ElfW(Sym) *sym;
|
||||
#if ! VERSIONED
|
||||
int num_versions = 0;
|
||||
const ElfW(Sym) *versioned_sym = NULL;
|
||||
#endif
|
||||
|
||||
map = list[i];
|
||||
|
||||
/* Here come the extra test needed for `_dl_lookup_symbol_skip'. */
|
||||
if (skip != NULL && map == skip)
|
||||
continue;
|
||||
|
||||
/* Don't search the executable when resolving a copy reloc. */
|
||||
if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
|
||||
continue;
|
||||
|
||||
/* Print some debugging info if wanted. */
|
||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_SYMBOLS, 0))
|
||||
_dl_debug_printf ("symbol=%s; lookup in file=%s\n", undef_name,
|
||||
map->l_name[0] ? map->l_name : _dl_argv[0]);
|
||||
|
||||
symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
|
||||
strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
|
||||
verstab = map->l_versyms;
|
||||
|
||||
/* Search the appropriate hash bucket in this object's symbol table
|
||||
for a definition for the same symbol name. */
|
||||
for (symidx = map->l_buckets[hash % map->l_nbuckets];
|
||||
symidx != STN_UNDEF;
|
||||
symidx = map->l_chain[symidx])
|
||||
{
|
||||
sym = &symtab[symidx];
|
||||
|
||||
assert (ELF_RTYPE_CLASS_PLT == 1);
|
||||
if (sym->st_value == 0 || /* No value. */
|
||||
/* ((type_class & ELF_RTYPE_CLASS_PLT)
|
||||
&& (sym->st_shndx == SHN_UNDEF)) */
|
||||
(type_class & (sym->st_shndx == SHN_UNDEF)))
|
||||
continue;
|
||||
|
||||
if (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC)
|
||||
/* Ignore all but STT_NOTYPE, STT_OBJECT and STT_FUNC entries
|
||||
since these are no code/data definitions. */
|
||||
continue;
|
||||
|
||||
if (sym != ref && strcmp (strtab + sym->st_name, undef_name))
|
||||
/* Not the symbol we are looking for. */
|
||||
continue;
|
||||
|
||||
#if VERSIONED
|
||||
if (__builtin_expect (verstab == NULL, 0))
|
||||
{
|
||||
/* We need a versioned symbol but haven't found any. If
|
||||
this is the object which is referenced in the verneed
|
||||
entry it is a bug in the library since a symbol must
|
||||
not simply disappear.
|
||||
|
||||
It would also be a bug in the object since it means that
|
||||
the list of required versions is incomplete and so the
|
||||
tests in dl-version.c haven't found a problem.*/
|
||||
assert (version->filename == NULL
|
||||
|| ! _dl_name_match_p (version->filename, map));
|
||||
|
||||
/* Otherwise we accept the symbol. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We can match the version information or use the
|
||||
default one if it is not hidden. */
|
||||
ElfW(Half) ndx = verstab[symidx] & 0x7fff;
|
||||
if ((map->l_versions[ndx].hash != version->hash
|
||||
|| strcmp (map->l_versions[ndx].name, version->name))
|
||||
&& (version->hidden || map->l_versions[ndx].hash
|
||||
|| (verstab[symidx] & 0x8000)))
|
||||
/* It's not the version we want. */
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
/* No specific version is selected. When the object file
|
||||
also does not define a version we have a match.
|
||||
Otherwise we accept the default version, or in case there
|
||||
is only one version defined, this one version. */
|
||||
if (verstab != NULL)
|
||||
{
|
||||
ElfW(Half) ndx = verstab[symidx] & 0x7fff;
|
||||
if (ndx > 2) /* map->l_versions[ndx].hash != 0) */
|
||||
{
|
||||
/* Don't accept hidden symbols. */
|
||||
if ((verstab[symidx] & 0x8000) == 0 && num_versions++ == 0)
|
||||
/* No version so far. */
|
||||
versioned_sym = sym;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* There cannot be another entry for this symbol so stop here. */
|
||||
goto found_it;
|
||||
}
|
||||
|
||||
/* If we have seen exactly one versioned symbol while we are
|
||||
looking for an unversioned symbol and the version is not the
|
||||
default version we still accept this symbol since there are
|
||||
no possible ambiguities. */
|
||||
#if VERSIONED
|
||||
sym = NULL;
|
||||
#else
|
||||
sym = num_versions == 1 ? versioned_sym : NULL;
|
||||
#endif
|
||||
|
||||
if (sym != NULL)
|
||||
{
|
||||
found_it:
|
||||
switch (ELFW(ST_BIND) (sym->st_info))
|
||||
{
|
||||
case STB_WEAK:
|
||||
/* Weak definition. Use this value if we don't find another. */
|
||||
if (__builtin_expect (_dl_dynamic_weak, 0))
|
||||
{
|
||||
if (! result->s)
|
||||
{
|
||||
result->s = sym;
|
||||
result->m = map;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case STB_GLOBAL:
|
||||
/* Global definition. Just what we need. */
|
||||
result->s = sym;
|
||||
result->m = map;
|
||||
return 1;
|
||||
default:
|
||||
/* Local symbols are ignored. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if VERSIONED
|
||||
/* If this current map is the one mentioned in the verneed entry
|
||||
and we have not found a weak entry, it is a bug. */
|
||||
if (symidx == STN_UNDEF && version->filename != NULL
|
||||
&& __builtin_expect (_dl_name_match_p (version->filename, map), 0))
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
while (++i < n);
|
||||
|
||||
/* We have not found anything until now. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef FCT
|
||||
#undef ARG
|
||||
#undef VERSIONED
|
118
newlib/libc/sys/linux/dl/do-rel.h
Normal file
118
newlib/libc/sys/linux/dl/do-rel.h
Normal file
@ -0,0 +1,118 @@
|
||||
/* Do relocations for ELF dynamic linking.
|
||||
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. */
|
||||
|
||||
/* This file may be included twice, to define both
|
||||
`elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */
|
||||
|
||||
#include <machine/weakalias.h>
|
||||
|
||||
#ifdef DO_RELA
|
||||
# define elf_dynamic_do_rel elf_dynamic_do_rela
|
||||
# define RELCOUNT_IDX VERSYMIDX (DT_RELACOUNT)
|
||||
# define Rel Rela
|
||||
# define elf_machine_rel elf_machine_rela
|
||||
# define elf_machine_rel_relative elf_machine_rela_relative
|
||||
#else
|
||||
# define RELCOUNT_IDX VERSYMIDX (DT_RELCOUNT)
|
||||
#endif
|
||||
|
||||
#ifndef VERSYMIDX
|
||||
# define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
|
||||
#endif
|
||||
|
||||
/* Perform the relocations in MAP on the running program image as specified
|
||||
by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT
|
||||
relocations; they should be set up to call _dl_runtime_resolve, rather
|
||||
than fully resolved now. */
|
||||
|
||||
static inline void
|
||||
elf_dynamic_do_rel (struct link_map *map,
|
||||
ElfW(Addr) reladdr, ElfW(Addr) relsize,
|
||||
int lazy)
|
||||
{
|
||||
const ElfW(Rel) *r = (const void *) reladdr;
|
||||
const ElfW(Rel) *end = (const void *) (reladdr + relsize);
|
||||
ElfW(Addr) l_addr = map->l_addr;
|
||||
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
/* We never bind lazily during ld.so bootstrap. Unfortunately gcc is
|
||||
not clever enough to see through all the function calls to realize
|
||||
that. */
|
||||
if (lazy)
|
||||
{
|
||||
/* Doing lazy PLT relocations; they need very little info. */
|
||||
for (; r < end; ++r)
|
||||
elf_machine_lazy_rel (map, l_addr, r);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
const ElfW(Sym) *const symtab =
|
||||
(const void *) D_PTR (map, l_info[DT_SYMTAB]);
|
||||
ElfW(Word) nrelative = (map->l_info[RELCOUNT_IDX] == NULL
|
||||
? 0 : map->l_info[RELCOUNT_IDX]->d_un.d_val);
|
||||
const ElfW(Rel) *relative = r;
|
||||
r = MIN (r + nrelative, end);
|
||||
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
/* This is defined in rtld.c, but nowhere in the static libc.a; make
|
||||
the reference weak so static programs can still link. This
|
||||
declaration cannot be done when compiling rtld.c (i.e. #ifdef
|
||||
RTLD_BOOTSTRAP) because rtld.c contains the common defn for
|
||||
_dl_rtld_map, which is incompatible with a weak decl in the same
|
||||
file. */
|
||||
weak_extern (_dl_rtld_map);
|
||||
if (map != &_dl_rtld_map) /* Already done in rtld itself. */
|
||||
# ifndef DO_RELA
|
||||
/* Rela platforms get the offset from r_addend and this must
|
||||
be copied in the relocation address. Therefore we can skip
|
||||
the relative relocations only if this is for rel
|
||||
relocations. */
|
||||
if (l_addr != 0)
|
||||
# endif
|
||||
#endif
|
||||
for (; relative < r; ++relative)
|
||||
elf_machine_rel_relative (l_addr, relative,
|
||||
(void *) (l_addr + relative->r_offset));
|
||||
|
||||
if (map->l_info[VERSYMIDX (DT_VERSYM)])
|
||||
{
|
||||
const ElfW(Half) *const version =
|
||||
(const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
|
||||
|
||||
for (; r < end; ++r)
|
||||
{
|
||||
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)];
|
||||
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
|
||||
&map->l_versions[ndx],
|
||||
(void *) (l_addr + r->r_offset));
|
||||
}
|
||||
}
|
||||
else
|
||||
for (; r < end; ++r)
|
||||
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
|
||||
(void *) (l_addr + r->r_offset));
|
||||
}
|
||||
}
|
||||
|
||||
#undef elf_dynamic_do_rel
|
||||
#undef Rel
|
||||
#undef elf_machine_rel
|
||||
#undef elf_machine_rel_relative
|
||||
#undef RELCOUNT_IDX
|
244
newlib/libc/sys/linux/dl/dynamic-link.h
Normal file
244
newlib/libc/sys/linux/dl/dynamic-link.h
Normal file
@ -0,0 +1,244 @@
|
||||
/* Inline functions for dynamic linking.
|
||||
Copyright (C) 1995,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 <elf.h>
|
||||
#include <machine/dl-machine.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef VERSYMIDX
|
||||
# define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
|
||||
#endif
|
||||
|
||||
|
||||
/* Global read-only variable defined in rtld.c which is nonzero if we
|
||||
shall give more warning messages. */
|
||||
extern int _dl_verbose __attribute__ ((unused));
|
||||
|
||||
|
||||
/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */
|
||||
|
||||
static inline void __attribute__ ((unused))
|
||||
elf_get_dynamic_info (struct link_map *l)
|
||||
{
|
||||
ElfW(Dyn) *dyn = l->l_ld;
|
||||
ElfW(Addr) l_addr;
|
||||
ElfW(Dyn) **info;
|
||||
|
||||
if (! dyn)
|
||||
return;
|
||||
|
||||
l_addr = l->l_addr;
|
||||
info = l->l_info;
|
||||
|
||||
while (dyn->d_tag != DT_NULL)
|
||||
{
|
||||
if (dyn->d_tag < DT_NUM)
|
||||
info[dyn->d_tag] = dyn;
|
||||
else if (dyn->d_tag >= DT_LOPROC &&
|
||||
dyn->d_tag < DT_LOPROC + DT_THISPROCNUM)
|
||||
info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn;
|
||||
else if ((Elf32_Word) DT_VERSIONTAGIDX (dyn->d_tag) < DT_VERSIONTAGNUM)
|
||||
info[VERSYMIDX (dyn->d_tag)] = dyn;
|
||||
else if ((Elf32_Word) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
|
||||
info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
|
||||
+ DT_VERSIONTAGNUM] = dyn;
|
||||
else
|
||||
assert (! "bad dynamic tag");
|
||||
++dyn;
|
||||
}
|
||||
#ifndef DL_RO_DYN_SECTION
|
||||
if (info[DT_PLTGOT] != NULL)
|
||||
info[DT_PLTGOT]->d_un.d_ptr += l_addr;
|
||||
if (info[DT_STRTAB] != NULL)
|
||||
info[DT_STRTAB]->d_un.d_ptr += l_addr;
|
||||
if (info[DT_SYMTAB] != NULL)
|
||||
info[DT_SYMTAB]->d_un.d_ptr += l_addr;
|
||||
# if ! ELF_MACHINE_NO_RELA
|
||||
if (info[DT_RELA] != NULL)
|
||||
{
|
||||
assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
|
||||
info[DT_RELA]->d_un.d_ptr += l_addr;
|
||||
}
|
||||
# endif
|
||||
# if ! ELF_MACHINE_NO_REL
|
||||
if (info[DT_REL] != NULL)
|
||||
{
|
||||
assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
|
||||
info[DT_REL]->d_un.d_ptr += l_addr;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
if (info[DT_PLTREL] != NULL)
|
||||
{
|
||||
# if ELF_MACHINE_NO_RELA
|
||||
assert (info[DT_PLTREL]->d_un.d_val == DT_REL);
|
||||
# elif ELF_MACHINE_NO_REL
|
||||
assert (info[DT_PLTREL]->d_un.d_val == DT_RELA);
|
||||
# else
|
||||
assert (info[DT_PLTREL]->d_un.d_val == DT_REL
|
||||
|| info[DT_PLTREL]->d_un.d_val == DT_RELA);
|
||||
# endif
|
||||
}
|
||||
#ifndef DL_RO_DYN_SECTION
|
||||
if (info[DT_JMPREL] != NULL)
|
||||
info[DT_JMPREL]->d_un.d_ptr += l_addr;
|
||||
if (info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||
info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr += l_addr;
|
||||
#endif
|
||||
if (info[DT_FLAGS] != NULL)
|
||||
{
|
||||
/* Flags are used. Translate to the old form where available.
|
||||
Since these l_info entries are only tested for NULL pointers it
|
||||
is ok if they point to the DT_FLAGS entry. */
|
||||
ElfW(Word) flags = info[DT_FLAGS]->d_un.d_val;
|
||||
if (flags & DF_SYMBOLIC)
|
||||
info[DT_SYMBOLIC] = info[DT_FLAGS];
|
||||
if (flags & DF_TEXTREL)
|
||||
info[DT_TEXTREL] = info[DT_FLAGS];
|
||||
if (flags & DF_BIND_NOW)
|
||||
info[DT_BIND_NOW] = info[DT_FLAGS];
|
||||
}
|
||||
if (info[VERSYMIDX (DT_FLAGS_1)] != NULL)
|
||||
l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
|
||||
if (info[DT_RUNPATH] != NULL)
|
||||
/* If both RUNPATH and RPATH are given, the latter is ignored. */
|
||||
info[DT_RPATH] = NULL;
|
||||
}
|
||||
|
||||
#ifdef RESOLVE
|
||||
|
||||
/* Get the definitions of `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.
|
||||
These functions are almost identical, so we use cpp magic to avoid
|
||||
duplicating their code. It cannot be done in a more general function
|
||||
because we must be able to completely inline. */
|
||||
|
||||
/* On some machines, notably SPARC, DT_REL* includes DT_JMPREL in its
|
||||
range. Note that according to the ELF spec, this is completely legal!
|
||||
But conditionally define things so that on machines we know this will
|
||||
not happen we do something more optimal. */
|
||||
|
||||
# ifdef ELF_MACHINE_PLTREL_OVERLAP
|
||||
# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
|
||||
do { \
|
||||
struct { ElfW(Addr) start, size; int lazy; } ranges[3]; \
|
||||
int ranges_index; \
|
||||
\
|
||||
ranges[0].lazy = ranges[2].lazy = 0; \
|
||||
ranges[1].lazy = 1; \
|
||||
ranges[0].size = ranges[1].size = ranges[2].size = 0; \
|
||||
\
|
||||
if ((map)->l_info[DT_##RELOC]) \
|
||||
{ \
|
||||
ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
|
||||
ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
|
||||
} \
|
||||
\
|
||||
if ((do_lazy) \
|
||||
&& (map)->l_info[DT_PLTREL] \
|
||||
&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
|
||||
{ \
|
||||
ranges[1].start = D_PTR ((map), l_info[DT_JMPREL]); \
|
||||
ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
|
||||
ranges[2].start = ranges[1].start + ranges[1].size; \
|
||||
ranges[2].size = ranges[0].start + ranges[0].size - ranges[2].start; \
|
||||
ranges[0].size = ranges[1].start - ranges[0].start; \
|
||||
} \
|
||||
\
|
||||
for (ranges_index = 0; ranges_index < 3; ++ranges_index) \
|
||||
elf_dynamic_do_##reloc ((map), \
|
||||
ranges[ranges_index].start, \
|
||||
ranges[ranges_index].size, \
|
||||
ranges[ranges_index].lazy); \
|
||||
} while (0)
|
||||
# else
|
||||
# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
|
||||
do { \
|
||||
struct { ElfW(Addr) start, size; int lazy; } ranges[2]; \
|
||||
int ranges_index; \
|
||||
ranges[0].lazy = 0; \
|
||||
ranges[0].size = ranges[1].size = 0; \
|
||||
ranges[0].start = 0; \
|
||||
\
|
||||
if ((map)->l_info[DT_##RELOC]) \
|
||||
{ \
|
||||
ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
|
||||
ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
|
||||
} \
|
||||
if ((map)->l_info[DT_PLTREL] \
|
||||
&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
|
||||
{ \
|
||||
ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \
|
||||
\
|
||||
if ((do_lazy) \
|
||||
/* This test does not only detect whether the relocation \
|
||||
sections are in the right order, it also checks whether \
|
||||
there is a DT_REL/DT_RELA section. */ \
|
||||
|| ranges[0].start + ranges[0].size != start) \
|
||||
{ \
|
||||
ranges[1].start = start; \
|
||||
ranges[1].size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
|
||||
ranges[1].lazy = (do_lazy); \
|
||||
} \
|
||||
else \
|
||||
/* Combine processing the sections. */ \
|
||||
ranges[0].size += (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
|
||||
} \
|
||||
\
|
||||
for (ranges_index = 0; ranges_index < 2; ++ranges_index) \
|
||||
elf_dynamic_do_##reloc ((map), \
|
||||
ranges[ranges_index].start, \
|
||||
ranges[ranges_index].size, \
|
||||
ranges[ranges_index].lazy); \
|
||||
} while (0)
|
||||
# endif
|
||||
|
||||
# if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
|
||||
# define _ELF_CHECK_REL 0
|
||||
# else
|
||||
# define _ELF_CHECK_REL 1
|
||||
# endif
|
||||
|
||||
# if ! ELF_MACHINE_NO_REL
|
||||
# include "do-rel.h"
|
||||
# define ELF_DYNAMIC_DO_REL(map, lazy) \
|
||||
_ELF_DYNAMIC_DO_RELOC (REL, rel, map, lazy, _ELF_CHECK_REL)
|
||||
# else
|
||||
# define ELF_DYNAMIC_DO_REL(map, lazy) /* Nothing to do. */
|
||||
# endif
|
||||
|
||||
# if ! ELF_MACHINE_NO_RELA
|
||||
# define DO_RELA
|
||||
# include "do-rel.h"
|
||||
# define ELF_DYNAMIC_DO_RELA(map, lazy) \
|
||||
_ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy, _ELF_CHECK_REL)
|
||||
# else
|
||||
# define ELF_DYNAMIC_DO_RELA(map, lazy) /* Nothing to do. */
|
||||
# endif
|
||||
|
||||
/* This can't just be an inline function because GCC is too dumb
|
||||
to inline functions containing inlines themselves. */
|
||||
# define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) \
|
||||
do { \
|
||||
int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \
|
||||
(consider_profile)); \
|
||||
ELF_DYNAMIC_DO_REL ((map), edr_lazy); \
|
||||
ELF_DYNAMIC_DO_RELA ((map), edr_lazy); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
193
newlib/libc/sys/linux/dl/kernel-features.h
Normal file
193
newlib/libc/sys/linux/dl/kernel-features.h
Normal file
@ -0,0 +1,193 @@
|
||||
/* Set flags signalling availability of kernel features based on given
|
||||
kernel version number.
|
||||
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. */
|
||||
|
||||
/* This file must not contain any C code. At least it must be protected
|
||||
to allow using the file also in assembler files. */
|
||||
|
||||
#ifndef __LINUX_KERNEL_VERSION
|
||||
/* We assume the worst; all kernels should be supported. */
|
||||
# define __LINUX_KERNEL_VERSION 0
|
||||
#endif
|
||||
|
||||
/* We assume for __LINUX_KERNEL_VERSION the same encoding used in
|
||||
linux/version.h. I.e., the major, minor, and subminor all get a
|
||||
byte with the major number being in the highest byte. This means
|
||||
we can do numeric comparisons.
|
||||
|
||||
In the following we will define certain symbols depending on
|
||||
whether the describes kernel feature is available in the kernel
|
||||
version given by __LINUX_KERNEL_VERSION. We are not always exactly
|
||||
recording the correct versions in which the features were
|
||||
introduced. If somebody cares these values can afterwards be
|
||||
corrected. Most of the numbers here are set corresponding to
|
||||
2.2.0. */
|
||||
|
||||
/* `getcwd' system call. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131584
|
||||
# define __ASSUME_GETCWD_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* Real-time signal became usable in 2.1.70. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131398
|
||||
# define __ASSUME_REALTIME_SIGNALS 1
|
||||
#endif
|
||||
|
||||
/* When were the `pread'/`pwrite' syscalls introduced? */
|
||||
#if __LINUX_KERNEL_VERSION >= 131584
|
||||
# define __ASSUME_PREAD_SYSCALL 1
|
||||
# define __ASSUME_PWRITE_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* When was `poll' introduced? */
|
||||
#if __LINUX_KERNEL_VERSION >= 131584
|
||||
# define __ASSUME_POLL_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* The `lchown' syscall was introduced in 2.1.80. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131408
|
||||
# define __ASSUME_LCHOWN_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* When did the `setresuid' sysall became available? */
|
||||
#if __LINUX_KERNEL_VERSION >= 131584 && !defined __sparc__
|
||||
# define __ASSUME_SETRESUID_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* The SIOCGIFNAME ioctl is available starting with 2.1.50. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131408
|
||||
# define __ASSUME_SIOCGIFNAME 1
|
||||
#endif
|
||||
|
||||
/* On x86 another `getrlimit' syscall was added in 2.3.25. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131865 && defined __i386__
|
||||
# define __ASSUME_NEW_GETRLIMIT_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* On x86 the truncate64/ftruncate64 syscalls were introduced in 2.3.31. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131871 && defined __i386__
|
||||
# define __ASSUME_TRUNCATE64_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* On x86 the mmap2 syscall was introduced in 2.3.31. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131871 && defined __i386__
|
||||
# define __ASSUME_MMAP2_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* On x86 the stat64/lstat64/fstat64 syscalls were introduced in 2.3.34. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131874 && defined __i386__
|
||||
# define __ASSUME_STAT64_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* On sparc and ARM the truncate64/ftruncate64/mmap2/stat64/lstat64/fstat64
|
||||
syscalls were introduced in 2.3.35. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131875 && (defined __sparc__ || defined __arm__)
|
||||
# define __ASSUME_TRUNCATE64_SYSCALL 1
|
||||
# define __ASSUME_MMAP2_SYSCALL 1
|
||||
# define __ASSUME_STAT64_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* I know for sure that these are in 2.3.35 on powerpc. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131875 && defined __powerpc__
|
||||
# define __ASSUME_TRUNCATE64_SYSCALL 1
|
||||
# define __ASSUME_STAT64_SYSCALL 1
|
||||
# define __ASSUME_NEW_GETRLIMIT_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* Linux 2.3.39 introduced 32bit UID/GIDs and IPC64. Some platforms had 32
|
||||
bit type all along. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131879 || defined __powerpc__ || defined __mips__
|
||||
# define __ASSUME_32BITUIDS 1
|
||||
# ifndef __powerpc__
|
||||
# define __ASSUME_IPC64 1
|
||||
# endif
|
||||
# ifdef __sparc__
|
||||
# define __ASSUME_SETRESUID_SYSCALL 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Linux 2.4.0 on PPC introduced a correct IPC64. */
|
||||
#if __LINUX_KERNEL_VERSION >= 132096 && defined __powerpc__
|
||||
# define __ASSUME_IPC64 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
|
||||
|
||||
/* The changed st_ino field appeared in 2.4.0-test6. But we cannot
|
||||
distinguish this version from other 2.4.0 releases. Therefore play
|
||||
save and assume it available is for 2.4.1 and up. */
|
||||
#if __LINUX_KERNEL_VERSION >= 132097
|
||||
# define __ASSUME_ST_INO_64_BIT 1
|
||||
#endif
|
||||
|
||||
/* To support locking of large files a new fcntl() syscall was introduced
|
||||
in 2.4.0-test7. We test for 2.4.1 for the earliest version we know
|
||||
the syscall is available. */
|
||||
#if __LINUX_KERNEL_VERSION >= 132097 && (defined __i386__ || defined __sparc__)
|
||||
# define __ASSUME_FCNTL64 1
|
||||
#endif
|
||||
|
||||
/* Arm got fcntl64 in 2.4.4, PowerPC and SH have it also in 2.4.4 (I
|
||||
don't know when it got introduced). */
|
||||
#if __LINUX_KERNEL_VERSION >= 132100 \
|
||||
&& (defined __arm__ || defined __powerpc__ || defined __sh__)
|
||||
# define __ASSUME_FCNTL64 1
|
||||
#endif
|
||||
|
||||
/* The getdents64 syscall was introduced in 2.4.0-test7. We test for
|
||||
2.4.1 for the earliest version we know the syscall is available. */
|
||||
#if __LINUX_KERNEL_VERSION >= 132097
|
||||
# define __ASSUME_GETDENTS64_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* When did O_DIRECTORY became available? Early in 2.3 but when?
|
||||
Be safe, use 2.3.99. */
|
||||
#if __LINUX_KERNEL_VERSION >= 131939
|
||||
# define __ASSUME_O_DIRECTORY 1
|
||||
#endif
|
||||
|
||||
/* Starting with one of the 2.4.0 pre-releases the Linux kernel passes
|
||||
up the page size information. */
|
||||
#if __LINUX_KERNEL_VERSION >= 132097
|
||||
# define __ASSUME_AT_PAGESIZE 1
|
||||
#endif
|
||||
|
||||
/* Starting with 2.4.5 kernels PPC passes the AUXV in the standard way
|
||||
and the mmap2 syscall made it into the official kernel. */
|
||||
#if __LINUX_KERNEL_VERSION >= (132096+5) && defined __powerpc__
|
||||
# define __ASSUME_STD_AUXV 1
|
||||
# define __ASSUME_MMAP2_SYSCALL 1
|
||||
#endif
|
||||
|
||||
/* There are an infinite number of PA-RISC kernel versions numbered
|
||||
2.4.0. But they've not really been released as such. We require
|
||||
and expect the final version here. */
|
||||
#ifdef __hppa__
|
||||
# define __ASSUME_32BITUIDS 1
|
||||
# define __ASSUME_TRUNCATE64_SYSCALL 1
|
||||
# define __ASSUME_MMAP2_SYSCALL 1
|
||||
# define __ASSUME_STAT64_SYSCALL 1
|
||||
# define __ASSUME_IPC64 1
|
||||
# define __ASSUME_ST_INO_64_BIT 1
|
||||
# define __ASSUME_FCNTL64 1
|
||||
# define __ASSUME_GETDENTS64_SYSCALL 1
|
||||
#endif
|
535
newlib/libc/sys/linux/dl/ldsodefs.h
Normal file
535
newlib/libc/sys/linux/dl/ldsodefs.h
Normal file
@ -0,0 +1,535 @@
|
||||
/* Run-time dynamic linker data structures for loaded ELF shared objects.
|
||||
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 _LDSODEFS_H
|
||||
#define _LDSODEFS_H 1
|
||||
|
||||
#include <features.h>
|
||||
|
||||
#define __need_size_t
|
||||
#define __need_NULL
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <elf.h>
|
||||
#include <dlfcn.h>
|
||||
#include <link.h>
|
||||
#include <dl-lookupcfg.h>
|
||||
#include <bits/libc-lock.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* 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 internal_function
|
||||
/* All references to the value of l_info[DT_PLTGOT],
|
||||
l_info[DT_STRTAB], l_info[DT_SYMTAB], l_info[DT_RELA],
|
||||
l_info[DT_REL], l_info[DT_JMPREL], and l_info[VERSYMIDX (DT_VERSYM)]
|
||||
have to be accessed via the D_PTR macro. The macro is needed since for
|
||||
most architectures the entry is already relocated - but for some not
|
||||
and we need to relocate at access time. */
|
||||
#ifdef DL_RO_DYN_SECTION
|
||||
# define D_PTR(map,i) (map->i->d_un.d_ptr + map->l_addr)
|
||||
#else
|
||||
# define D_PTR(map,i) map->i->d_un.d_ptr
|
||||
#endif
|
||||
|
||||
/* On some platforms more information than just the address of the symbol
|
||||
is needed from the lookup functions. In this case we return the whole
|
||||
link map. */
|
||||
#ifdef DL_LOOKUP_RETURNS_MAP
|
||||
typedef struct link_map *lookup_t;
|
||||
# define LOOKUP_VALUE(map) map
|
||||
# define LOOKUP_VALUE_ADDRESS(map) (map ? map->l_addr : 0)
|
||||
#else
|
||||
typedef ElfW(Addr) lookup_t;
|
||||
# define LOOKUP_VALUE(map) map->l_addr
|
||||
# define LOOKUP_VALUE_ADDRESS(address) address
|
||||
#endif
|
||||
|
||||
/* on some architectures a pointer to a function is not just a pointer
|
||||
to the actual code of the function but rather an architecture
|
||||
specific descriptor. */
|
||||
#ifndef ELF_FUNCTION_PTR_IS_SPECIAL
|
||||
# define DL_SYMBOL_ADDRESS(map, ref) \
|
||||
(void *) (LOOKUP_VALUE_ADDRESS (map) + ref->st_value)
|
||||
# define DL_LOOKUP_ADDRESS(addr) ((ElfW(Addr)) (addr))
|
||||
# define DL_DT_INIT_ADDRESS(map, start) (start)
|
||||
# define DL_DT_FINI_ADDRESS(map, start) (start)
|
||||
#endif
|
||||
|
||||
/* Unmap a loaded object, called by _dl_close (). */
|
||||
#ifndef DL_UNMAP_IS_SPECIAL
|
||||
# define DL_UNMAP(map) \
|
||||
__munmap ((void *) (map)->l_map_start, \
|
||||
(map)->l_map_end - (map)->l_map_start)
|
||||
#endif
|
||||
|
||||
/* By default we do not need special support to initialize DSOs loaded
|
||||
by statically linked binaries. */
|
||||
#ifndef DL_STATIC_INIT
|
||||
# define DL_STATIC_INIT(map)
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
#define ELF_RTYPE_CLASS_PLT 1
|
||||
#define ELF_RTYPE_CLASS_COPY 2
|
||||
|
||||
/* ELF uses the PF_x macros to specify the segment permissions, mmap
|
||||
uses PROT_xxx. In most cases the three macros have the values 1, 2,
|
||||
and 3 but not in a matching order. The following macros allows
|
||||
converting from the PF_x values to PROT_xxx values. */
|
||||
#define PF_TO_PROT \
|
||||
((PROT_READ << (PF_R * 4)) \
|
||||
| (PROT_WRITE << (PF_W * 4)) \
|
||||
| (PROT_EXEC << (PF_X * 4)) \
|
||||
| ((PROT_READ | PROT_WRITE) << ((PF_R | PF_W) * 4)) \
|
||||
| ((PROT_READ | PROT_EXEC) << ((PF_R | PF_X) * 4)) \
|
||||
| ((PROT_WRITE | PROT_EXEC) << (PF_W | PF_X) * 4) \
|
||||
| ((PROT_READ | PROT_WRITE | PROT_EXEC) << ((PF_R | PF_W | PF_X) * 4)))
|
||||
|
||||
|
||||
/* For the version handling we need an array with only names and their
|
||||
hash values. */
|
||||
struct r_found_version
|
||||
{
|
||||
const char *name;
|
||||
ElfW(Word) hash;
|
||||
|
||||
int hidden;
|
||||
const char *filename;
|
||||
};
|
||||
|
||||
/* We want to cache information about the searches for shared objects. */
|
||||
|
||||
enum r_dir_status { unknown, nonexisting, existing };
|
||||
|
||||
struct r_search_path_elem
|
||||
{
|
||||
/* This link is only used in the `all_dirs' member of `r_search_path'. */
|
||||
struct r_search_path_elem *next;
|
||||
|
||||
/* Strings saying where the definition came from. */
|
||||
const char *what;
|
||||
const char *where;
|
||||
|
||||
/* Basename for this search path element. The string must end with
|
||||
a slash character. */
|
||||
const char *dirname;
|
||||
size_t dirnamelen;
|
||||
|
||||
enum r_dir_status status[0];
|
||||
};
|
||||
|
||||
struct r_strlenpair
|
||||
{
|
||||
const char *str;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
|
||||
/* A data structure for a simple single linked list of strings. */
|
||||
struct libname_list
|
||||
{
|
||||
const char *name; /* Name requested (before search). */
|
||||
struct libname_list *next; /* Link to next name for this object. */
|
||||
int dont_free; /* Flag whether this element should be freed
|
||||
if the object is not entirely unloaded. */
|
||||
};
|
||||
|
||||
|
||||
/* Test whether given NAME matches any of the names of the given object. */
|
||||
static __inline int
|
||||
__attribute__ ((unused))
|
||||
_dl_name_match_p (const char *__name, struct link_map *__map)
|
||||
{
|
||||
int __found = strcmp (__name, __map->l_name) == 0;
|
||||
struct libname_list *__runp = __map->l_libname;
|
||||
|
||||
while (! __found && __runp != NULL)
|
||||
if (strcmp (__name, __runp->name) == 0)
|
||||
__found = 1;
|
||||
else
|
||||
__runp = __runp->next;
|
||||
|
||||
return __found;
|
||||
}
|
||||
|
||||
/* Function used as argument for `_dl_receive_error' function. The
|
||||
arguments are the error code, error string, and the objname the
|
||||
error occurred in. */
|
||||
typedef void (*receiver_fct) (int, const char *, const char *);
|
||||
|
||||
/* Internal functions of the run-time dynamic linker.
|
||||
These can be accessed if you link again the dynamic linker
|
||||
as a shared library, as in `-lld' or `/lib/ld.so' explicitly;
|
||||
but are not normally of interest to user programs.
|
||||
|
||||
The `-ldl' library functions in <dlfcn.h> provide a simple
|
||||
user interface to run-time dynamic linking. */
|
||||
|
||||
|
||||
/* Parameters passed to the dynamic linker. */
|
||||
extern char **_dl_argv;
|
||||
|
||||
/* Cached value of `getpagesize ()'. */
|
||||
extern size_t _dl_pagesize;
|
||||
|
||||
/* OS version. */
|
||||
extern unsigned int _dl_osversion;
|
||||
|
||||
/* File descriptor referring to the zero-fill device. */
|
||||
extern int _dl_zerofd;
|
||||
|
||||
/* Name of the shared object to be profiled (if any). */
|
||||
extern const char *_dl_profile;
|
||||
/* Map of shared object to be profiled. */
|
||||
extern struct link_map *_dl_profile_map;
|
||||
/* Filename of the output file. */
|
||||
extern const char *_dl_profile_output;
|
||||
|
||||
/* If nonzero the appropriate debug information is printed. */
|
||||
extern int _dl_debug_mask;
|
||||
#define DL_DEBUG_LIBS (1 << 0)
|
||||
#define DL_DEBUG_IMPCALLS (1 << 1)
|
||||
#define DL_DEBUG_BINDINGS (1 << 2)
|
||||
#define DL_DEBUG_SYMBOLS (1 << 3)
|
||||
#define DL_DEBUG_VERSIONS (1 << 4)
|
||||
#define DL_DEBUG_RELOC (1 << 5)
|
||||
#define DL_DEBUG_FILES (1 << 6)
|
||||
#define DL_DEBUG_STATISTICS (1 << 7)
|
||||
/* This one is used only internally. */
|
||||
#define DL_DEBUG_HELP (1 << 8)
|
||||
|
||||
/* Expect cache ID. */
|
||||
extern int _dl_correct_cache_id;
|
||||
|
||||
/* Mask for hardware capabilities that are available. */
|
||||
extern unsigned long int _dl_hwcap;
|
||||
|
||||
/* Mask for important hardware capabilities we honour. */
|
||||
extern unsigned long int _dl_hwcap_mask;
|
||||
|
||||
/* File descriptor to write debug messages to. */
|
||||
extern int _dl_debug_fd;
|
||||
|
||||
/* Names of shared object for which the RPATH should be ignored. */
|
||||
extern const char *_dl_inhibit_rpath;
|
||||
|
||||
/* Nonzero if references should be treated as weak during runtime linking. */
|
||||
extern int _dl_dynamic_weak;
|
||||
|
||||
/* The array with message we print as a last resort. */
|
||||
extern const char _dl_out_of_memory[];
|
||||
|
||||
/* Nonzero if runtime lookups should not update the .got/.plt. */
|
||||
extern int _dl_bind_not;
|
||||
|
||||
/* List of search directories. */
|
||||
extern struct r_search_path_elem *_dl_all_dirs;
|
||||
extern struct r_search_path_elem *_dl_init_all_dirs;
|
||||
|
||||
/* OS-dependent function to open the zero-fill device. */
|
||||
extern int _dl_sysdep_open_zero_fill (void); /* dl-sysdep.c */
|
||||
|
||||
|
||||
/* During the program run we must not modify the global data of
|
||||
loaded shared object simultanously in two threads. Therefore we
|
||||
protect `_dl_open' and `_dl_close' in dl-close.c.
|
||||
|
||||
This must be a recursive lock since the initializer function of
|
||||
the loaded object might as well require a call to this function.
|
||||
At this time it is not anymore a problem to modify the tables. */
|
||||
__libc_lock_define_recursive (extern, _dl_load_lock)
|
||||
|
||||
|
||||
/* Write message on the debug file descriptor. The parameters are
|
||||
interpreted as for a `printf' call. All the lines start with a
|
||||
tag showing the PID. */
|
||||
extern void _dl_debug_printf (const char *fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
|
||||
/* Write message on the debug file descriptor. The parameters are
|
||||
interpreted as for a `printf' call. All the lines buf the first
|
||||
start with a tag showing the PID. */
|
||||
extern void _dl_debug_printf_c (const char *fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
|
||||
|
||||
/* Write a message on the specified descriptor FD. The parameters are
|
||||
interpreted as for a `printf' call. */
|
||||
extern void _dl_dprintf (int fd, const char *fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
|
||||
/* Write a message on the specified descriptor standard output. The
|
||||
parameters are interpreted as for a `printf' call. */
|
||||
#define _dl_printf(fmt, args...) \
|
||||
_dl_dprintf (STDOUT_FILENO, fmt, ##args)
|
||||
|
||||
/* Write a message on the specified descriptor standard error. The
|
||||
parameters are interpreted as for a `printf' call. */
|
||||
#define _dl_error_printf(fmt, args...) \
|
||||
_dl_dprintf (STDERR_FILENO, fmt, ##args)
|
||||
|
||||
/* Write a message on the specified descriptor standard error and exit
|
||||
the program. The parameters are interpreted as for a `printf' call. */
|
||||
#define _dl_fatal_printf(fmt, args...) \
|
||||
do \
|
||||
{ \
|
||||
_dl_dprintf (STDERR_FILENO, fmt, ##args); \
|
||||
_exit (127); \
|
||||
} \
|
||||
while (1)
|
||||
|
||||
|
||||
/* This function is called by all the internal dynamic linker functions
|
||||
when they encounter an error. ERRCODE is either an `errno' code or
|
||||
zero; OBJECT is the name of the problematical shared object, or null if
|
||||
it is a general problem; ERRSTRING is a string describing the specific
|
||||
problem. */
|
||||
extern void _dl_signal_error (int errcode, const char *object,
|
||||
const char *occurred, const char *errstring)
|
||||
internal_function
|
||||
__attribute__ ((__noreturn__));
|
||||
|
||||
/* Like _dl_signal_error, but may return when called in the context of
|
||||
_dl_receive_error. */
|
||||
extern void _dl_signal_cerror (int errcode, const char *object,
|
||||
const char *occation, const char *errstring)
|
||||
internal_function;
|
||||
|
||||
/* Call OPERATE, receiving errors from `dl_signal_cerror'. Unlike
|
||||
`_dl_catch_error' the operation is resumed after the OPERATE
|
||||
function returns.
|
||||
ARGS is passed as argument to OPERATE. */
|
||||
extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
|
||||
void *args)
|
||||
internal_function;
|
||||
|
||||
|
||||
/* Open the shared object NAME and map in its segments.
|
||||
LOADER's DT_RPATH is used in searching for NAME.
|
||||
If the object is already opened, returns its existing map.
|
||||
For preloaded shared objects PRELOADED is set to a non-zero
|
||||
value to allow additional security checks. */
|
||||
extern struct link_map *_dl_map_object (struct link_map *loader,
|
||||
const char *name, int preloaded,
|
||||
int type, int trace_mode, int mode)
|
||||
internal_function;
|
||||
|
||||
/* Call _dl_map_object on the dependencies of MAP, and set up
|
||||
MAP->l_searchlist. PRELOADS points to a vector of NPRELOADS previously
|
||||
loaded objects that will be inserted into MAP->l_searchlist after MAP
|
||||
but before its dependencies. */
|
||||
extern void _dl_map_object_deps (struct link_map *map,
|
||||
struct link_map **preloads,
|
||||
unsigned int npreloads, int trace_mode)
|
||||
internal_function;
|
||||
|
||||
/* Cache the locations of MAP's hash table. */
|
||||
extern void _dl_setup_hash (struct link_map *map) internal_function;
|
||||
|
||||
|
||||
/* Search loaded objects' symbol tables for a definition of the symbol
|
||||
referred to by UNDEF. *SYM is the symbol table entry containing the
|
||||
reference; it is replaced with the defining symbol, and the base load
|
||||
address of the defining object is returned. SYMBOL_SCOPE is a
|
||||
null-terminated list of object scopes to search; each object's
|
||||
l_searchlist (i.e. the segment of the dependency tree starting at that
|
||||
object) is searched in turn. REFERENCE_NAME should name the object
|
||||
containing the reference; it is used in error messages.
|
||||
TYPE_CLASS describes the type of symbol we are looking for. */
|
||||
extern lookup_t _dl_lookup_symbol (const char *undef,
|
||||
struct link_map *undef_map,
|
||||
const ElfW(Sym) **sym,
|
||||
struct r_scope_elem *symbol_scope[],
|
||||
int type_class, int explicit)
|
||||
internal_function;
|
||||
|
||||
/* Lookup versioned symbol. */
|
||||
extern lookup_t _dl_lookup_versioned_symbol (const char *undef,
|
||||
struct link_map *undef_map,
|
||||
const ElfW(Sym) **sym,
|
||||
struct r_scope_elem *symbol_scope[],
|
||||
const struct r_found_version *version,
|
||||
int type_class, int explicit)
|
||||
internal_function;
|
||||
|
||||
/* For handling RTLD_NEXT we must be able to skip shared objects. */
|
||||
extern lookup_t _dl_lookup_symbol_skip (const char *undef,
|
||||
struct link_map *undef_map,
|
||||
const ElfW(Sym) **sym,
|
||||
struct r_scope_elem *symbol_scope[],
|
||||
struct link_map *skip_this)
|
||||
internal_function;
|
||||
|
||||
/* For handling RTLD_NEXT with versioned symbols we must be able to
|
||||
skip shared objects. */
|
||||
extern lookup_t _dl_lookup_versioned_symbol_skip (const char *undef,
|
||||
struct link_map *undef_map,
|
||||
const ElfW(Sym) **sym,
|
||||
struct r_scope_elem *symbol_scope[],
|
||||
const struct r_found_version *version,
|
||||
struct link_map *skip_this)
|
||||
internal_function;
|
||||
|
||||
/* Look up symbol NAME in MAP's scope and return its run-time address. */
|
||||
extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name)
|
||||
internal_function;
|
||||
|
||||
|
||||
/* Structure describing the dynamic linker itself. */
|
||||
extern struct link_map _dl_rtld_map;
|
||||
/* And a pointer to the map for the main map. */
|
||||
extern struct link_map *_dl_loaded;
|
||||
/* Number of object in the _dl_loaded list. */
|
||||
extern unsigned int _dl_nloaded;
|
||||
/* Array representing global scope. */
|
||||
extern struct r_scope_elem *_dl_global_scope[2];
|
||||
/* Direct pointer to the searchlist of the main object. */
|
||||
extern struct r_scope_elem *_dl_main_searchlist;
|
||||
/* Copy of the content of `_dl_main_searchlist'. */
|
||||
extern struct r_scope_elem _dl_initial_searchlist;
|
||||
/* This is zero at program start to signal that the global scope map is
|
||||
allocated by rtld. Later it keeps the size of the map. It might be
|
||||
reset if in _dl_close if the last global object is removed. */
|
||||
extern size_t _dl_global_scope_alloc;
|
||||
|
||||
/* Allocate a `struct link_map' for a new object being loaded,
|
||||
and enter it into the _dl_main_map list. */
|
||||
extern struct link_map *_dl_new_object (char *realname, const char *libname,
|
||||
int type, struct link_map *loader)
|
||||
internal_function;
|
||||
|
||||
/* Relocate the given object (if it hasn't already been).
|
||||
SCOPE is passed to _dl_lookup_symbol in symbol lookups.
|
||||
If LAZY is nonzero, don't relocate its PLT. */
|
||||
extern void _dl_relocate_object (struct link_map *map,
|
||||
struct r_scope_elem *scope[],
|
||||
int lazy, int consider_profiling);
|
||||
|
||||
/* Call _dl_signal_error with a message about an unhandled reloc type.
|
||||
TYPE is the result of ELFW(R_TYPE) (r_info), i.e. an R_<CPU>_* value.
|
||||
PLT is nonzero if this was a PLT reloc; it just affects the message. */
|
||||
extern void _dl_reloc_bad_type (struct link_map *map,
|
||||
unsigned int type, int plt)
|
||||
internal_function __attribute__ ((__noreturn__));
|
||||
|
||||
/* Check the version dependencies of all objects available through
|
||||
MAP. If VERBOSE print some more diagnostics. */
|
||||
extern int _dl_check_all_versions (struct link_map *map, int verbose,
|
||||
int trace_mode)
|
||||
internal_function;
|
||||
|
||||
/* Check the version dependencies for MAP. If VERBOSE print some more
|
||||
diagnostics. */
|
||||
extern int _dl_check_map_versions (struct link_map *map, int verbose,
|
||||
int trace_mode)
|
||||
internal_function;
|
||||
|
||||
/* Initialize the object in SCOPE by calling the constructors with
|
||||
ARGC, ARGV, and ENV as the parameters. */
|
||||
extern void _dl_init (struct link_map *main_map, int argc, char **argv,
|
||||
char **env) internal_function;
|
||||
|
||||
/* Call the finalizer functions of all shared objects whose
|
||||
initializer functions have completed. */
|
||||
extern void _dl_fini (void) internal_function;
|
||||
|
||||
/* The dynamic linker calls this function before and having changing
|
||||
any shared object mappings. The `r_state' member of `struct r_debug'
|
||||
says what change is taking place. This function's address is
|
||||
the value of the `r_brk' member. */
|
||||
extern void _dl_debug_state (void);
|
||||
|
||||
/* Initialize `struct r_debug' if it has not already been done. The
|
||||
argument is the run-time load address of the dynamic linker, to be put
|
||||
in the `r_ldbase' member. Returns the address of the structure. */
|
||||
extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase)
|
||||
internal_function;
|
||||
|
||||
/* Initialize the basic data structure for the search paths. */
|
||||
extern void _dl_init_paths (const char *library_path) internal_function;
|
||||
|
||||
/* Gather the information needed to install the profiling tables and start
|
||||
the timers. */
|
||||
extern void _dl_start_profile (struct link_map *map, const char *output_dir)
|
||||
internal_function;
|
||||
|
||||
/* The actual functions used to keep book on the calls. */
|
||||
extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc);
|
||||
|
||||
/* This function is simply a wrapper around the _dl_mcount function
|
||||
which does not require a FROMPC parameter since this is the
|
||||
calling function. */
|
||||
extern void _dl_mcount_wrapper (void *selfpc);
|
||||
|
||||
/* Show the members of the auxiliary array passed up from the kernel. */
|
||||
extern void _dl_show_auxv (void) internal_function;
|
||||
|
||||
/* Return all environment variables starting with `LD_', one after the
|
||||
other. */
|
||||
extern char *_dl_next_ld_env_entry (char ***position) internal_function;
|
||||
|
||||
/* Return an array with the names of the important hardware capabilities. */
|
||||
extern const struct r_strlenpair *_dl_important_hwcaps (const char *platform,
|
||||
size_t paltform_len,
|
||||
size_t *sz,
|
||||
size_t *max_capstrlen)
|
||||
internal_function;
|
||||
|
||||
/* Look up NAME in ld.so.cache and return the file name stored there,
|
||||
or null if none is found. */
|
||||
extern const char *_dl_load_cache_lookup (const char *name)
|
||||
internal_function;
|
||||
|
||||
/* If the system does not support MAP_COPY we cannot leave the file open
|
||||
all the time since this would create problems when the file is replaced.
|
||||
Therefore we provide this function to close the file and open it again
|
||||
once needed. */
|
||||
extern void _dl_unload_cache (void);
|
||||
|
||||
/* System-dependent function to read a file's whole contents in the
|
||||
most convenient manner available. *SIZEP gets the size of the
|
||||
file. On error MAP_FAILED is returned. */
|
||||
extern void *_dl_sysdep_read_whole_file (const char *file, size_t *sizep,
|
||||
int prot)
|
||||
internal_function;
|
||||
|
||||
/* System-specific function to do initial startup for the dynamic linker.
|
||||
After this, file access calls and getenv must work. This is responsible
|
||||
for setting __libc_enable_secure if we need to be secure (e.g. setuid),
|
||||
and for setting _dl_argc and _dl_argv, and then calling _dl_main. */
|
||||
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
|
||||
void (*dl_main) (const ElfW(Phdr) *phdr,
|
||||
ElfW(Word) phnum,
|
||||
ElfW(Addr) *user_entry));
|
||||
|
||||
extern void _dl_sysdep_start_cleanup (void)
|
||||
internal_function;
|
||||
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* ldsodefs.h */
|
2
newlib/libc/sys/linux/dl/libintl.h
Normal file
2
newlib/libc/sys/linux/dl/libintl.h
Normal file
@ -0,0 +1,2 @@
|
||||
#define N_(x) x
|
||||
|
7
newlib/libc/sys/linux/dl/trusted-dirs.h
Normal file
7
newlib/libc/sys/linux/dl/trusted-dirs.h
Normal file
@ -0,0 +1,7 @@
|
||||
#define SYSTEM_DIRS \
|
||||
"/usr/local/lib/"
|
||||
|
||||
#define SYSTEM_DIRS_LEN \
|
||||
15
|
||||
|
||||
#define SYSTEM_DIRS_MAX_LEN 15
|
19
newlib/libc/sys/linux/dl/unsecvars.h
Normal file
19
newlib/libc/sys/linux/dl/unsecvars.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* 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_ORIGIN_PATH\0" \
|
||||
"LD_DEBUG_OUTPUT\0" \
|
||||
"LD_PROFILE\0" \
|
||||
"GCONV_PATH\0" \
|
||||
"HOSTALIASES\0" \
|
||||
"LOCALDOMAIN\0" \
|
||||
"LOCPATH\0" \
|
||||
"MALLOC_TRACE\0" \
|
||||
"NLSPATH\0" \
|
||||
"RESOLV_HOST_CONF\0" \
|
||||
"RES_OPTIONS\0" \
|
||||
"TMPDIR\0" \
|
||||
"TZDIR\0"
|
114
newlib/libc/sys/linux/gethostid.c
Normal file
114
newlib/libc/sys/linux/gethostid.c
Normal file
@ -0,0 +1,114 @@
|
||||
/* Copyright (C) 1995,1996,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. */
|
||||
|
||||
#include <alloca.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#define HOSTIDFILE "/etc/hostid"
|
||||
#define OLD_HOSTIDFILE "/etc/hostid"
|
||||
|
||||
#if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
|
||||
# define OPEN __open64
|
||||
#else
|
||||
# define OPEN __open
|
||||
#endif
|
||||
|
||||
#ifdef SET_PROCEDURE
|
||||
int
|
||||
sethostid (id)
|
||||
long int id;
|
||||
{
|
||||
int fd;
|
||||
ssize_t written;
|
||||
|
||||
/* Open file for writing. Everybody is allowed to read this file. */
|
||||
fd = OPEN (HOSTIDFILE, O_CREAT|O_WRONLY|O_TRUNC, 0644);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
written = __write (fd, &id, sizeof (id));
|
||||
|
||||
__close (fd);
|
||||
|
||||
return written != sizeof (id) ? -1 : 0;
|
||||
}
|
||||
|
||||
#else
|
||||
# include <string.h>
|
||||
# include <sys/param.h>
|
||||
# include <netdb.h>
|
||||
# include <netinet/in.h>
|
||||
|
||||
long int
|
||||
gethostid ()
|
||||
{
|
||||
char hostname[MAXHOSTNAMELEN + 1];
|
||||
size_t buflen;
|
||||
char *buffer;
|
||||
struct hostent hostbuf, *hp;
|
||||
unsigned long int id;
|
||||
struct in_addr in;
|
||||
int herr;
|
||||
int fd;
|
||||
|
||||
/* First try to get the ID from a former invocation of sethostid. */
|
||||
fd = OPEN (HOSTIDFILE, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
ssize_t n = __read (fd, &id, sizeof (id));
|
||||
|
||||
__close (fd);
|
||||
|
||||
if (n == sizeof (id))
|
||||
return id;
|
||||
}
|
||||
|
||||
/* Getting from the file was not successful. An intelligent guess for
|
||||
a unique number of a host is its IP address. Return this. */
|
||||
if (__gethostname (hostname, MAXHOSTNAMELEN) < 0 || hostname[0] == '\0')
|
||||
/* This also fails. Return and arbitrary value. */
|
||||
return 0;
|
||||
|
||||
buflen = 1024;
|
||||
buffer = alloca (buflen);
|
||||
|
||||
/* To get the IP address we need to know the host name. */
|
||||
while (__gethostbyname_r (hostname, &hostbuf, buffer, buflen, &hp, &herr)
|
||||
!= 0
|
||||
|| hp == NULL)
|
||||
if (herr != NETDB_INTERNAL || errno != ERANGE)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
/* Enlarge buffer. */
|
||||
buflen *= 2;
|
||||
buffer = alloca (buflen);
|
||||
}
|
||||
|
||||
in.s_addr = 0;
|
||||
memcpy (&in, hp->h_addr,
|
||||
(int) sizeof (in) < hp->h_length ? sizeof (in) : hp->h_length);
|
||||
|
||||
/* For the return value to be not exactly the IP address we do some
|
||||
bit fiddling. */
|
||||
return in.s_addr << 16 | in.s_addr >> 16;
|
||||
}
|
||||
#endif
|
27
newlib/libc/sys/linux/iconv/Makefile.am
Normal file
27
newlib/libc/sys/linux/iconv/Makefile.am
Normal file
@ -0,0 +1,27 @@
|
||||
## Process this file with automake to generate Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = cygnus
|
||||
|
||||
INCLUDES = -DGCONV_DIR='"$(pkglibdir)"' -DGCONV_PATH='"$(pkglibdir)"' -I$(srcdir) -I$(srcdir)/.. $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
|
||||
|
||||
LIB_SOURCES = \
|
||||
iconv.h gconv.h \
|
||||
iconv_open.c iconv.c iconv_close.c \
|
||||
gconv_open.c gconv.c gconv_close.c \
|
||||
gconv_db.c gconv_dl.c gconv_conf.c gconv_builtin.c \
|
||||
gconv_simple.c gconv_trans.c gconv_cache.c
|
||||
|
||||
libiconv_la_CFLAGS =
|
||||
libiconv_la_LDFLAGS = -Xcompiler -nostdlib
|
||||
|
||||
if USE_LIBTOOL
|
||||
noinst_LTLIBRARIES = libiconv.la
|
||||
libiconv_la_SOURCES = $(LIB_SOURCES)
|
||||
noinst_DATA = objectlist.awk.in
|
||||
else
|
||||
noinst_LIBRARIES = lib.a
|
||||
lib_a_SOURCES = $(LIB_SOURCES)
|
||||
noinst_DATA =
|
||||
endif # USE_LIBTOOL
|
||||
|
||||
include $(srcdir)/../../../../Makefile.shared
|
375
newlib/libc/sys/linux/iconv/Makefile.in
Normal file
375
newlib/libc/sys/linux/iconv/Makefile.in
Normal file
@ -0,0 +1,375 @@
|
||||
# Makefile.in generated automatically by automake 1.4 from Makefile.am
|
||||
|
||||
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DESTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = ..
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_alias = @build_alias@
|
||||
build_triplet = @build@
|
||||
host_alias = @host_alias@
|
||||
host_triplet = @host@
|
||||
target_alias = @target_alias@
|
||||
target_triplet = @target@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CPP = @CPP@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
EXEEXT = @EXEEXT@
|
||||
GCJ = @GCJ@
|
||||
GCJFLAGS = @GCJFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LINUX_MACH_LIB = @LINUX_MACH_LIB@
|
||||
LN_S = @LN_S@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
NEWLIB_CFLAGS = @NEWLIB_CFLAGS@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
RANLIB = @RANLIB@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
aext = @aext@
|
||||
libm_machine_dir = @libm_machine_dir@
|
||||
machine_dir = @machine_dir@
|
||||
newlib_basedir = @newlib_basedir@
|
||||
oext = @oext@
|
||||
sys_dir = @sys_dir@
|
||||
|
||||
AUTOMAKE_OPTIONS = cygnus
|
||||
|
||||
INCLUDES = -DGCONV_DIR='"$(pkglibdir)"' -DGCONV_PATH='"$(pkglibdir)"' -I$(srcdir) -I$(srcdir)/.. $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
|
||||
|
||||
LIB_SOURCES = \
|
||||
iconv.h gconv.h \
|
||||
iconv_open.c iconv.c iconv_close.c \
|
||||
gconv_open.c gconv.c gconv_close.c \
|
||||
gconv_db.c gconv_dl.c gconv_conf.c gconv_builtin.c \
|
||||
gconv_simple.c gconv_trans.c gconv_cache.c
|
||||
|
||||
|
||||
libiconv_la_CFLAGS =
|
||||
libiconv_la_LDFLAGS = -Xcompiler -nostdlib
|
||||
|
||||
@USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = @USE_LIBTOOL_TRUE@libiconv.la
|
||||
@USE_LIBTOOL_TRUE@libiconv_la_SOURCES = @USE_LIBTOOL_TRUE@$(LIB_SOURCES)
|
||||
@USE_LIBTOOL_TRUE@noinst_DATA = @USE_LIBTOOL_TRUE@objectlist.awk.in
|
||||
@USE_LIBTOOL_FALSE@noinst_DATA =
|
||||
@USE_LIBTOOL_FALSE@noinst_LIBRARIES = @USE_LIBTOOL_FALSE@lib.a
|
||||
@USE_LIBTOOL_FALSE@lib_a_SOURCES = @USE_LIBTOOL_FALSE@$(LIB_SOURCES)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../mkinstalldirs
|
||||
CONFIG_CLEAN_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
|
||||
|
||||
DEFS = @DEFS@ -I. -I$(srcdir)
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LIBS = @LIBS@
|
||||
lib_a_LIBADD =
|
||||
@USE_LIBTOOL_FALSE@lib_a_OBJECTS = iconv_open.$(OBJEXT) iconv.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@iconv_close.$(OBJEXT) gconv_open.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@gconv.$(OBJEXT) gconv_close.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@gconv_db.$(OBJEXT) gconv_dl.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@gconv_conf.$(OBJEXT) gconv_builtin.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@gconv_simple.$(OBJEXT) gconv_trans.$(OBJEXT) \
|
||||
@USE_LIBTOOL_FALSE@gconv_cache.$(OBJEXT)
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
|
||||
libiconv_la_LIBADD =
|
||||
@USE_LIBTOOL_TRUE@libiconv_la_OBJECTS = iconv_open.lo iconv.lo \
|
||||
@USE_LIBTOOL_TRUE@iconv_close.lo gconv_open.lo gconv.lo gconv_close.lo \
|
||||
@USE_LIBTOOL_TRUE@gconv_db.lo gconv_dl.lo gconv_conf.lo \
|
||||
@USE_LIBTOOL_TRUE@gconv_builtin.lo gconv_simple.lo gconv_trans.lo \
|
||||
@USE_LIBTOOL_TRUE@gconv_cache.lo
|
||||
CFLAGS = @CFLAGS@
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
DATA = $(noinst_DATA)
|
||||
|
||||
DIST_COMMON = Makefile.am Makefile.in
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = gtar
|
||||
GZIP_ENV = --best
|
||||
SOURCES = $(lib_a_SOURCES) $(libiconv_la_SOURCES)
|
||||
OBJECTS = $(lib_a_OBJECTS) $(libiconv_la_OBJECTS)
|
||||
|
||||
all: all-redirect
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .S .c .lo .o .obj .s
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(srcdir)/../../../../Makefile.shared
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --cygnus iconv/Makefile
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
|
||||
mostlyclean-noinstLIBRARIES:
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
|
||||
distclean-noinstLIBRARIES:
|
||||
|
||||
maintainer-clean-noinstLIBRARIES:
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
# FIXME: We should only use cygpath when building on Windows,
|
||||
# and only if it is available.
|
||||
.c.obj:
|
||||
$(COMPILE) -c `cygpath -w $<`
|
||||
|
||||
.s.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.S.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.o core *.core
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
clean-compile:
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
maintainer-clean-compile:
|
||||
|
||||
.c.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
.s.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
.S.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
|
||||
maintainer-clean-libtool:
|
||||
|
||||
lib.a: $(lib_a_OBJECTS) $(lib_a_DEPENDENCIES)
|
||||
-rm -f lib.a
|
||||
$(AR) cru lib.a $(lib_a_OBJECTS) $(lib_a_LIBADD)
|
||||
$(RANLIB) lib.a
|
||||
|
||||
mostlyclean-noinstLTLIBRARIES:
|
||||
|
||||
clean-noinstLTLIBRARIES:
|
||||
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
|
||||
|
||||
distclean-noinstLTLIBRARIES:
|
||||
|
||||
maintainer-clean-noinstLTLIBRARIES:
|
||||
|
||||
libiconv.la: $(libiconv_la_OBJECTS) $(libiconv_la_DEPENDENCIES)
|
||||
$(LINK) $(libiconv_la_LDFLAGS) $(libiconv_la_OBJECTS) $(libiconv_la_LIBADD) $(LIBS)
|
||||
|
||||
tags: TAGS
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
here=`pwd` && cd $(srcdir) \
|
||||
&& mkid -f$$here/ID $$unique $(LISP)
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|
||||
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
|
||||
|
||||
mostlyclean-tags:
|
||||
|
||||
clean-tags:
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID
|
||||
|
||||
maintainer-clean-tags:
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
|
||||
subdir = iconv
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@for file in $(DISTFILES); do \
|
||||
if test -f $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||
fi; \
|
||||
done
|
||||
info-am:
|
||||
info: info-am
|
||||
dvi-am:
|
||||
dvi: dvi-am
|
||||
check-am:
|
||||
check: check-am
|
||||
installcheck-am:
|
||||
installcheck: installcheck-am
|
||||
install-info-am:
|
||||
install-info: install-info-am
|
||||
install-exec-am:
|
||||
install-exec: install-exec-am
|
||||
|
||||
install-data-am:
|
||||
install-data: install-data-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
install: install-am
|
||||
uninstall-am:
|
||||
uninstall: uninstall-am
|
||||
all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(DATA)
|
||||
all-redirect: all-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||
installdirs:
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
|
||||
maintainer-clean-generic:
|
||||
mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
|
||||
mostlyclean-libtool mostlyclean-noinstLTLIBRARIES \
|
||||
mostlyclean-tags mostlyclean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
clean-am: clean-noinstLIBRARIES clean-compile clean-libtool \
|
||||
clean-noinstLTLIBRARIES clean-tags clean-generic \
|
||||
mostlyclean-am
|
||||
|
||||
clean: clean-am
|
||||
|
||||
distclean-am: distclean-noinstLIBRARIES distclean-compile \
|
||||
distclean-libtool distclean-noinstLTLIBRARIES \
|
||||
distclean-tags distclean-generic clean-am
|
||||
-rm -f libtool
|
||||
|
||||
distclean: distclean-am
|
||||
|
||||
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
|
||||
maintainer-clean-compile maintainer-clean-libtool \
|
||||
maintainer-clean-noinstLTLIBRARIES \
|
||||
maintainer-clean-tags maintainer-clean-generic \
|
||||
distclean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
|
||||
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
|
||||
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
|
||||
mostlyclean-compile distclean-compile clean-compile \
|
||||
maintainer-clean-compile mostlyclean-libtool distclean-libtool \
|
||||
clean-libtool maintainer-clean-libtool mostlyclean-noinstLTLIBRARIES \
|
||||
distclean-noinstLTLIBRARIES clean-noinstLTLIBRARIES \
|
||||
maintainer-clean-noinstLTLIBRARIES tags mostlyclean-tags distclean-tags \
|
||||
clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
|
||||
check-am installcheck-am installcheck install-info-am install-info \
|
||||
install-exec-am install-exec install-data-am install-data install-am \
|
||||
install uninstall-am uninstall all-redirect all-am all installdirs \
|
||||
mostlyclean-generic distclean-generic clean-generic \
|
||||
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
objectlist.awk.in: $(noinst_LTLIBRARIES)
|
||||
-rm -f objectlist.awk.in
|
||||
for i in `ls *.lo` ; \
|
||||
do \
|
||||
echo $$i `pwd`/$$i >> objectlist.awk.in ; \
|
||||
done
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
344
newlib/libc/sys/linux/iconv/categories.def
Normal file
344
newlib/libc/sys/linux/iconv/categories.def
Normal file
@ -0,0 +1,344 @@
|
||||
/* Definition of all available locale categories and their items. -*- C -*-
|
||||
Copyright (C) 1995-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. */
|
||||
|
||||
/* These definitions are used by the locale-related files in the C library
|
||||
and the programs `localedef' and `locale'.
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
|
||||
/* 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",
|
||||
(
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
), _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)
|
||||
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)
|
||||
), 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)
|
||||
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)
|
||||
|
||||
), 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)
|
||||
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)
|
||||
), _nl_postload_time)
|
||||
|
||||
|
||||
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)
|
||||
DEFINE_ELEMENT (_NL_MESSAGES_CODESET, "messages-codeset", std, string)
|
||||
), NO_POSTLOAD)
|
||||
|
||||
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, "applcation", 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)
|
37
newlib/libc/sys/linux/iconv/dummy-repertoire.c
Normal file
37
newlib/libc/sys/linux/iconv/dummy-repertoire.c
Normal file
@ -0,0 +1,37 @@
|
||||
/* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 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. */
|
||||
|
||||
/* For iconv we don't have to handle repertoire maps. Provide dummy
|
||||
definitions to allow the use of linereader.c unchanged. */
|
||||
#include <repertoire.h>
|
||||
|
||||
|
||||
uint32_t
|
||||
repertoire_find_value (const struct repertoire_t *repertoire, const char *name,
|
||||
size_t len)
|
||||
{
|
||||
return ILLEGAL_CHAR_VALUE;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
repertoire_find_symbol (const struct repertoire_t *repertoire, uint32_t ucs)
|
||||
{
|
||||
return NULL;
|
||||
}
|
73
newlib/libc/sys/linux/iconv/gconv.c
Normal file
73
newlib/libc/sys/linux/iconv/gconv.c
Normal file
@ -0,0 +1,73 @@
|
||||
/* Convert characters in input buffer using conversion descriptor to
|
||||
output buffer.
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <assert.h>
|
||||
#include <gconv_int.h>
|
||||
#include <sys/param.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int
|
||||
internal_function
|
||||
__gconv (__gconv_t cd, const unsigned char **inbuf,
|
||||
const unsigned char *inbufend, unsigned char **outbuf,
|
||||
unsigned char *outbufend, size_t *irreversible)
|
||||
{
|
||||
size_t last_step;
|
||||
int result;
|
||||
|
||||
if (cd == (__gconv_t) -1L)
|
||||
return __GCONV_ILLEGAL_DESCRIPTOR;
|
||||
|
||||
last_step = cd->__nsteps - 1;
|
||||
|
||||
assert (irreversible != NULL);
|
||||
*irreversible = 0;
|
||||
|
||||
cd->__data[last_step].__outbuf = outbuf != NULL ? *outbuf : NULL;
|
||||
cd->__data[last_step].__outbufend = outbufend;
|
||||
|
||||
if (inbuf == NULL || *inbuf == NULL)
|
||||
/* We just flush. */
|
||||
result = cd->__steps->__fct (cd->__steps, cd->__data, NULL, NULL, NULL,
|
||||
irreversible,
|
||||
cd->__data[last_step].__outbuf == NULL ? 2 : 1, 0);
|
||||
else
|
||||
{
|
||||
const unsigned char *last_start;
|
||||
|
||||
assert (outbuf != NULL && *outbuf != NULL);
|
||||
|
||||
do
|
||||
{
|
||||
last_start = *inbuf;
|
||||
result = cd->__steps->__fct (cd->__steps, cd->__data, inbuf, inbufend,
|
||||
NULL, irreversible, 0, 0);
|
||||
}
|
||||
while (result == __GCONV_EMPTY_INPUT && last_start != *inbuf
|
||||
&& *inbuf + cd->__steps->__min_needed_from <= inbufend);
|
||||
}
|
||||
|
||||
if (outbuf != NULL && *outbuf != NULL)
|
||||
*outbuf = cd->__data[last_step].__outbuf;
|
||||
|
||||
return result;
|
||||
}
|
84
newlib/libc/sys/linux/iconv/gconv_builtin.c
Normal file
84
newlib/libc/sys/linux/iconv/gconv_builtin.c
Normal file
@ -0,0 +1,84 @@
|
||||
/* Table for builtin transformation mapping.
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <endian.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gconv_int.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
static struct builtin_map
|
||||
{
|
||||
const char *name;
|
||||
__gconv_fct fct;
|
||||
|
||||
int min_needed_from;
|
||||
int max_needed_from;
|
||||
int min_needed_to;
|
||||
int max_needed_to;
|
||||
|
||||
} map[] =
|
||||
{
|
||||
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \
|
||||
MinT, MaxT) \
|
||||
{ \
|
||||
.name = Name, \
|
||||
.fct = Fct, \
|
||||
\
|
||||
.min_needed_from = MinF, \
|
||||
.max_needed_from = MaxF, \
|
||||
.min_needed_to = MinT, \
|
||||
.max_needed_to = MaxT \
|
||||
},
|
||||
#define BUILTIN_ALIAS(From, To)
|
||||
|
||||
#include <gconv_builtin.h>
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
internal_function
|
||||
__gconv_get_builtin_trans (const char *name, struct __gconv_step *step)
|
||||
{
|
||||
size_t cnt;
|
||||
|
||||
for (cnt = 0; cnt < sizeof (map) / sizeof (map[0]); ++cnt)
|
||||
if (strcmp (name, map[cnt].name) == 0)
|
||||
break;
|
||||
|
||||
assert (cnt < sizeof (map) / sizeof (map[0]));
|
||||
|
||||
step->__fct = map[cnt].fct;
|
||||
step->__init_fct = NULL;
|
||||
step->__end_fct = NULL;
|
||||
step->__shlib_handle = NULL;
|
||||
step->__modname = NULL;
|
||||
|
||||
step->__min_needed_from = map[cnt].min_needed_from;
|
||||
step->__max_needed_from = map[cnt].max_needed_from;
|
||||
step->__min_needed_to = map[cnt].min_needed_to;
|
||||
step->__max_needed_to = map[cnt].max_needed_to;
|
||||
|
||||
/* None of the builtin converters handles stateful encoding. */
|
||||
step->__stateful = 0;
|
||||
}
|
115
newlib/libc/sys/linux/iconv/gconv_builtin.h
Normal file
115
newlib/libc/sys/linux/iconv/gconv_builtin.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* Builtin transformations.
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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. */
|
||||
|
||||
BUILTIN_ALIAS ("UCS4//", "ISO-10646/UCS4/")
|
||||
BUILTIN_ALIAS ("UCS-4//", "ISO-10646/UCS4/")
|
||||
BUILTIN_ALIAS ("UCS-4BE//", "ISO-10646/UCS4/")
|
||||
BUILTIN_ALIAS ("CSUCS4//", "ISO-10646/UCS4/")
|
||||
BUILTIN_ALIAS ("ISO-10646//", "ISO-10646/UCS4/")
|
||||
BUILTIN_ALIAS ("10646-1:1993//", "ISO-10646/UCS4/")
|
||||
BUILTIN_ALIAS ("10646-1:1993/UCS4/", "ISO-10646/UCS4/")
|
||||
BUILTIN_ALIAS ("OSF00010104//", "ISO-10646/UCS4/") /* level 1 */
|
||||
BUILTIN_ALIAS ("OSF00010105//", "ISO-10646/UCS4/") /* level 2 */
|
||||
BUILTIN_ALIAS ("OSF00010106//", "ISO-10646/UCS4/") /* level 3 */
|
||||
|
||||
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS4/", 1, "=INTERNAL->ucs4",
|
||||
__gconv_transform_internal_ucs4, 4, 4, 4, 4)
|
||||
BUILTIN_TRANSFORMATION ("ISO-10646/UCS4/", "INTERNAL", 1, "=ucs4->INTERNAL",
|
||||
__gconv_transform_ucs4_internal, 4, 4, 4, 4)
|
||||
|
||||
BUILTIN_TRANSFORMATION ("INTERNAL", "UCS-4LE//", 1, "=INTERNAL->ucs4le",
|
||||
__gconv_transform_internal_ucs4le, 4, 4, 4, 4)
|
||||
BUILTIN_TRANSFORMATION ("UCS-4LE//", "INTERNAL", 1, "=ucs4le->INTERNAL",
|
||||
__gconv_transform_ucs4le_internal, 4, 4, 4, 4)
|
||||
|
||||
BUILTIN_ALIAS ("WCHAR_T//", "INTERNAL")
|
||||
|
||||
BUILTIN_ALIAS ("UTF8//", "ISO-10646/UTF8/")
|
||||
BUILTIN_ALIAS ("UTF-8//", "ISO-10646/UTF8/")
|
||||
BUILTIN_ALIAS ("ISO-IR-193//", "ISO-10646/UTF8/")
|
||||
BUILTIN_ALIAS ("OSF05010001//", "ISO-10646/UTF8/")
|
||||
BUILTIN_ALIAS ("ISO-10646/UTF-8/", "ISO-10646/UTF8/")
|
||||
|
||||
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UTF8/", 1, "=INTERNAL->utf8",
|
||||
__gconv_transform_internal_utf8, 4, 4, 1, 6)
|
||||
|
||||
BUILTIN_TRANSFORMATION ("ISO-10646/UTF8/", "INTERNAL", 1, "=utf8->INTERNAL",
|
||||
__gconv_transform_utf8_internal, 1, 6, 4, 4)
|
||||
|
||||
BUILTIN_ALIAS ("UCS2//", "ISO-10646/UCS2/")
|
||||
BUILTIN_ALIAS ("UCS-2//", "ISO-10646/UCS2/")
|
||||
BUILTIN_ALIAS ("OSF00010100//", "ISO-10646/UCS2/") /* level 1 */
|
||||
BUILTIN_ALIAS ("OSF00010101//", "ISO-10646/UCS2/") /* level 2 */
|
||||
BUILTIN_ALIAS ("OSF00010102//", "ISO-10646/UCS2/") /* level 3 */
|
||||
|
||||
BUILTIN_TRANSFORMATION ("ISO-10646/UCS2/", "INTERNAL", 1, "=ucs2->INTERNAL",
|
||||
__gconv_transform_ucs2_internal, 2, 2, 4, 4)
|
||||
|
||||
BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS2/", 1, "=INTERNAL->ucs2",
|
||||
__gconv_transform_internal_ucs2, 4, 4, 2, 2)
|
||||
|
||||
|
||||
BUILTIN_ALIAS ("ANSI_X3.4//", "ANSI_X3.4-1968//")
|
||||
BUILTIN_ALIAS ("ISO-IR-6//", "ANSI_X3.4-1968//")
|
||||
BUILTIN_ALIAS ("ANSI_X3.4-1986//", "ANSI_X3.4-1968//")
|
||||
BUILTIN_ALIAS ("ISO_646.IRV:1991//", "ANSI_X3.4-1968//")
|
||||
BUILTIN_ALIAS ("ASCII//", "ANSI_X3.4-1968//")
|
||||
BUILTIN_ALIAS ("ISO646-US//", "ANSI_X3.4-1968//")
|
||||
BUILTIN_ALIAS ("US-ASCII//", "ANSI_X3.4-1968//")
|
||||
BUILTIN_ALIAS ("US//", "ANSI_X3.4-1968//")
|
||||
BUILTIN_ALIAS ("IBM367//", "ANSI_X3.4-1968//")
|
||||
BUILTIN_ALIAS ("CP367//", "ANSI_X3.4-1968//")
|
||||
BUILTIN_ALIAS ("CSASCII//", "ANSI_X3.4-1968//")
|
||||
BUILTIN_ALIAS ("OSF00010020//", "ANSI_X3.4-1968//")
|
||||
|
||||
BUILTIN_TRANSFORMATION ("ANSI_X3.4-1968//", "INTERNAL", 1, "=ascii->INTERNAL",
|
||||
__gconv_transform_ascii_internal, 4, 4, 1, 1)
|
||||
|
||||
BUILTIN_TRANSFORMATION ("INTERNAL", "ANSI_X3.4-1968//", 1, "=INTERNAL->ascii",
|
||||
__gconv_transform_internal_ascii, 4, 4, 1, 1)
|
||||
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
BUILTIN_ALIAS ("UNICODEBIG//", "ISO-10646/UCS2/")
|
||||
BUILTIN_ALIAS ("UCS-2BE//", "ISO-10646/UCS2/")
|
||||
|
||||
BUILTIN_ALIAS ("UCS-2LE//", "UNICODELITTLE//")
|
||||
|
||||
BUILTIN_TRANSFORMATION ("UNICODELITTLE//", "INTERNAL", 1,
|
||||
"=ucs2reverse->INTERNAL",
|
||||
__gconv_transform_ucs2reverse_internal, 2, 2, 4, 4)
|
||||
|
||||
BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODELITTLE//", 1,
|
||||
"=INTERNAL->ucs2reverse",
|
||||
__gconv_transform_internal_ucs2reverse, 4, 4, 2, 2)
|
||||
#else
|
||||
BUILTIN_ALIAS ("UNICODELITTLE//", "ISO-10646/UCS2/")
|
||||
BUILTIN_ALIAS ("UCS-2LE//", "ISO-10646/UCS2/")
|
||||
|
||||
BUILTIN_ALIAS ("UCS-2BE//", "UNICODEBIG//")
|
||||
|
||||
BUILTIN_TRANSFORMATION ("UNICODEBIG//", "INTERNAL", 1,
|
||||
"=ucs2reverse->INTERNAL",
|
||||
__gconv_transform_ucs2reverse_internal, 2, 2, 4, 4)
|
||||
|
||||
BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODEBIG//", 1,
|
||||
"=INTERNAL->ucs2reverse",
|
||||
__gconv_transform_internal_ucs2reverse, 4, 4, 2, 2)
|
||||
#endif
|
459
newlib/libc/sys/linux/iconv/gconv_cache.c
Normal file
459
newlib/libc/sys/linux/iconv/gconv_cache.c
Normal file
@ -0,0 +1,459 @@
|
||||
/* Cache handling for iconv modules.
|
||||
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <gconv_int.h>
|
||||
#include <iconvconfig.h>
|
||||
|
||||
#include "hash-string.h"
|
||||
|
||||
void *__gconv_cache;
|
||||
static size_t cache_size;
|
||||
static int cache_malloced;
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
__gconv_load_cache (void)
|
||||
{
|
||||
int fd;
|
||||
struct stat64 st;
|
||||
struct gconvcache_header *header;
|
||||
|
||||
/* We cannot use the cache if the GCONV_PATH environment variable is
|
||||
set. */
|
||||
__gconv_path_envvar = getenv ("GCONV_PATH");
|
||||
if (__gconv_path_envvar != NULL)
|
||||
return -1;
|
||||
|
||||
/* See whether the cache file exists. */
|
||||
fd = open (GCONV_MODULES_CACHE, O_RDONLY);
|
||||
if (__builtin_expect (fd, 0) == -1)
|
||||
/* Not available. */
|
||||
return -1;
|
||||
|
||||
#ifdef _POSIX_ASYNC_IO
|
||||
/* Get information about the file. */
|
||||
if (__builtin_expect (fstat64 (fd, &st), 0) < 0
|
||||
/* We do not have to start looking at the file if it cannot contain
|
||||
at least the cache header. */
|
||||
|| st.st_size < sizeof (struct gconvcache_header))
|
||||
{
|
||||
#endif
|
||||
close_and_exit:
|
||||
close (fd);
|
||||
return -1;
|
||||
#ifdef _POSIX_ASYNC_IO
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make the file content available. */
|
||||
cache_size = st.st_size;
|
||||
#ifdef _POSIX_MAPPED_FILES
|
||||
__gconv_cache = mmap (NULL, cache_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (__builtin_expect (__gconv_cache == MAP_FAILED, 0))
|
||||
#endif
|
||||
{
|
||||
size_t already_read;
|
||||
|
||||
__gconv_cache = malloc (cache_size);
|
||||
if (__gconv_cache == NULL)
|
||||
goto close_and_exit;
|
||||
|
||||
already_read = 0;
|
||||
do
|
||||
{
|
||||
ssize_t n = read (fd, (char *) __gconv_cache + already_read,
|
||||
cache_size - already_read);
|
||||
if (__builtin_expect (n, 0) == -1)
|
||||
{
|
||||
free (__gconv_cache);
|
||||
__gconv_cache = NULL;
|
||||
goto close_and_exit;
|
||||
}
|
||||
|
||||
already_read += n;
|
||||
}
|
||||
while (already_read < cache_size);
|
||||
|
||||
cache_malloced = 1;
|
||||
}
|
||||
|
||||
/* We don't need the file descriptor anymore. */
|
||||
close (fd);
|
||||
|
||||
/* Check the consistency. */
|
||||
header = (struct gconvcache_header *) __gconv_cache;
|
||||
if (__builtin_expect (header->magic, GCONVCACHE_MAGIC) != GCONVCACHE_MAGIC
|
||||
|| __builtin_expect (header->string_offset >= cache_size, 0)
|
||||
|| __builtin_expect (header->hash_offset >= cache_size, 0)
|
||||
|| __builtin_expect (header->hash_size == 0, 0)
|
||||
|| __builtin_expect ((header->hash_offset
|
||||
+ header->hash_size * sizeof (struct hash_entry))
|
||||
> cache_size, 0)
|
||||
|| __builtin_expect (header->module_offset >= cache_size, 0)
|
||||
|| __builtin_expect (header->otherconv_offset > cache_size, 0))
|
||||
{
|
||||
if (cache_malloced)
|
||||
{
|
||||
free (__gconv_cache);
|
||||
cache_malloced = 0;
|
||||
}
|
||||
#ifdef _POSIX_MAPPED_FILES
|
||||
else
|
||||
__munmap (__gconv_cache, cache_size);
|
||||
#endif
|
||||
__gconv_cache = NULL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* That worked. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
internal_function
|
||||
find_module_idx (const char *str, size_t *idxp)
|
||||
{
|
||||
unsigned int idx;
|
||||
unsigned int hval;
|
||||
unsigned int hval2;
|
||||
const struct gconvcache_header *header;
|
||||
const char *strtab;
|
||||
const struct hash_entry *hashtab;
|
||||
unsigned int limit;
|
||||
|
||||
header = (const struct gconvcache_header *) __gconv_cache;
|
||||
strtab = (char *) __gconv_cache + header->string_offset;
|
||||
hashtab = (struct hash_entry *) ((char *) __gconv_cache
|
||||
+ header->hash_offset);
|
||||
|
||||
hval = hash_string (str);
|
||||
idx = hval % header->hash_size;
|
||||
hval2 = 1 + hval % (header->hash_size - 2);
|
||||
|
||||
limit = cache_size - header->string_offset;
|
||||
while (hashtab[idx].string_offset != 0)
|
||||
if (hashtab[idx].string_offset < limit
|
||||
&& strcmp (str, strtab + hashtab[idx].string_offset) == 0)
|
||||
{
|
||||
*idxp = hashtab[idx].module_idx;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
if ((idx += hval2) >= header->hash_size)
|
||||
idx -= header->hash_size;
|
||||
|
||||
/* Nothing found. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
static int
|
||||
internal_function
|
||||
find_module (const char *directory, const char *filename,
|
||||
struct __gconv_step *result)
|
||||
{
|
||||
size_t dirlen = strlen (directory);
|
||||
size_t fnamelen = strlen (filename) + 1;
|
||||
char fullname[dirlen + fnamelen];
|
||||
int status = __GCONV_NOCONV;
|
||||
char *tmp;
|
||||
|
||||
tmp = mempcpy (fullname, directory, dirlen);
|
||||
tmp += dirlen;
|
||||
memcpy (tmp, filename, fnamelen);
|
||||
|
||||
result->__shlib_handle = __gconv_find_shlib (fullname);
|
||||
if (result->__shlib_handle != NULL)
|
||||
{
|
||||
status = __GCONV_OK;
|
||||
|
||||
result->__modname = NULL;
|
||||
result->__fct = result->__shlib_handle->fct;
|
||||
result->__init_fct = result->__shlib_handle->init_fct;
|
||||
result->__end_fct = result->__shlib_handle->end_fct;
|
||||
|
||||
result->__data = NULL;
|
||||
if (result->__init_fct != NULL)
|
||||
status = result->__init_fct (result);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
__gconv_compare_alias_cache (const char *name1, const char *name2, int *result)
|
||||
{
|
||||
size_t name1_idx;
|
||||
size_t name2_idx;
|
||||
|
||||
if (__gconv_cache == NULL)
|
||||
return -1;
|
||||
|
||||
if (find_module_idx (name1, &name1_idx) != 0
|
||||
|| find_module_idx (name2, &name2_idx) != 0)
|
||||
*result = strcmp (name1, name2);
|
||||
else
|
||||
*result = (int) (name1_idx - name2_idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
__gconv_lookup_cache (const char *toset, const char *fromset,
|
||||
struct __gconv_step **handle, size_t *nsteps, int flags)
|
||||
{
|
||||
const struct gconvcache_header *header;
|
||||
const char *strtab;
|
||||
size_t fromidx;
|
||||
size_t toidx;
|
||||
const struct module_entry *modtab;
|
||||
const struct module_entry *from_module;
|
||||
const struct module_entry *to_module;
|
||||
struct __gconv_step *result;
|
||||
|
||||
if (__gconv_cache == NULL)
|
||||
/* We have no cache available. */
|
||||
return __GCONV_NODB;
|
||||
|
||||
header = (const struct gconvcache_header *) __gconv_cache;
|
||||
strtab = (char *) __gconv_cache + header->string_offset;
|
||||
modtab = (const struct module_entry *) ((char *) __gconv_cache
|
||||
+ header->module_offset);
|
||||
|
||||
if (find_module_idx (fromset, &fromidx) != 0
|
||||
|| (header->module_offset + (fromidx + 1) * sizeof (struct module_entry)
|
||||
> cache_size))
|
||||
return __GCONV_NOCONV;
|
||||
from_module = &modtab[fromidx];
|
||||
|
||||
if (find_module_idx (toset, &toidx) != 0
|
||||
|| (header->module_offset + (toidx + 1) * sizeof (struct module_entry)
|
||||
> cache_size))
|
||||
return __GCONV_NOCONV;
|
||||
to_module = &modtab[toidx];
|
||||
|
||||
/* Avoid copy-only transformations if the user requests. */
|
||||
if (__builtin_expect (flags & GCONV_AVOID_NOCONV, 0) && fromidx == toidx)
|
||||
return __GCONV_NOCONV;
|
||||
|
||||
/* If there are special conversions available examine them first. */
|
||||
if (fromidx != 0 && toidx != 0
|
||||
&& __builtin_expect (from_module->extra_offset, 0) != 0)
|
||||
{
|
||||
/* Search through the list to see whether there is a module
|
||||
matching the destination character set. */
|
||||
const struct extra_entry *extra;
|
||||
|
||||
/* Note the -1. This is due to the offset added in iconvconfig.
|
||||
See there for more explanations. */
|
||||
extra = (const struct extra_entry *) ((char *) __gconv_cache
|
||||
+ header->otherconv_offset
|
||||
+ from_module->extra_offset - 1);
|
||||
while (extra->module_cnt != 0
|
||||
&& extra->module[extra->module_cnt - 1].outname_offset != toidx)
|
||||
extra = (const struct extra_entry *) ((char *) extra
|
||||
+ sizeof (struct extra_entry)
|
||||
+ (extra->module_cnt
|
||||
* sizeof (struct extra_entry_module)));
|
||||
|
||||
if (extra->module_cnt != 0)
|
||||
{
|
||||
/* Use the extra module. First determine how many steps. */
|
||||
char *fromname;
|
||||
int idx;
|
||||
|
||||
*nsteps = extra->module_cnt;
|
||||
*handle = result =
|
||||
(struct __gconv_step *) malloc (extra->module_cnt
|
||||
* sizeof (struct __gconv_step));
|
||||
if (result == NULL)
|
||||
return __GCONV_NOMEM;
|
||||
|
||||
fromname = (char *) strtab + from_module->canonname_offset;
|
||||
idx = 0;
|
||||
do
|
||||
{
|
||||
result[idx].__from_name = fromname;
|
||||
fromname = result[idx].__to_name =
|
||||
(char *) strtab + modtab[extra->module[idx].outname_offset].canonname_offset;
|
||||
|
||||
result[idx].__counter = 1;
|
||||
result[idx].__data = NULL;
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
if (strtab[extra->module[idx].dir_offset] != '\0')
|
||||
{
|
||||
/* Load the module, return handle for it. */
|
||||
int res;
|
||||
|
||||
res = find_module (strtab + extra->module[idx].dir_offset,
|
||||
strtab + extra->module[idx].name_offset,
|
||||
&result[idx]);
|
||||
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
|
||||
{
|
||||
/* Something went wrong. */
|
||||
free (result);
|
||||
goto try_internal;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* It's a builtin transformation. */
|
||||
__gconv_get_builtin_trans (strtab
|
||||
+ extra->module[idx].name_offset,
|
||||
&result[idx]);
|
||||
|
||||
}
|
||||
while (++idx < extra->module_cnt);
|
||||
|
||||
return __GCONV_OK;
|
||||
}
|
||||
}
|
||||
|
||||
try_internal:
|
||||
/* See whether we can convert via the INTERNAL charset. */
|
||||
if ((fromidx != 0 && __builtin_expect (from_module->fromname_offset, 1) == 0)
|
||||
|| (toidx != 0 && __builtin_expect (to_module->toname_offset, 1) == 0)
|
||||
|| (fromidx == 0 && toidx == 0))
|
||||
/* Not possible. Nothing we can do. */
|
||||
return __GCONV_NOCONV;
|
||||
|
||||
/* We will use up to two modules. Always allocate room for two. */
|
||||
result = (struct __gconv_step *) malloc (2 * sizeof (struct __gconv_step));
|
||||
if (result == NULL)
|
||||
return __GCONV_NOMEM;
|
||||
|
||||
*handle = result;
|
||||
*nsteps = 0;
|
||||
|
||||
/* Generate data structure for conversion to INTERNAL. */
|
||||
if (fromidx != 0)
|
||||
{
|
||||
result[0].__from_name = (char *) strtab + from_module->canonname_offset;
|
||||
result[0].__to_name = (char *) "INTERNAL";
|
||||
|
||||
result[0].__counter = 1;
|
||||
result[0].__data = NULL;
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
if (strtab[from_module->todir_offset] != '\0')
|
||||
{
|
||||
/* Load the module, return handle for it. */
|
||||
int res = find_module (strtab + from_module->todir_offset,
|
||||
strtab + from_module->toname_offset,
|
||||
&result[0]);
|
||||
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
|
||||
{
|
||||
/* Something went wrong. */
|
||||
free (result);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* It's a builtin transformation. */
|
||||
__gconv_get_builtin_trans (strtab + from_module->toname_offset,
|
||||
&result[0]);
|
||||
|
||||
++*nsteps;
|
||||
}
|
||||
|
||||
/* Generate data structure for conversion from INTERNAL. */
|
||||
if (toidx != 0)
|
||||
{
|
||||
int idx = *nsteps;
|
||||
|
||||
result[idx].__from_name = (char *) "INTERNAL";
|
||||
result[idx].__to_name = (char *) strtab + to_module->canonname_offset;
|
||||
|
||||
result[idx].__counter = 1;
|
||||
result[idx].__data = NULL;
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
if (strtab[to_module->fromdir_offset] != '\0')
|
||||
{
|
||||
/* Load the module, return handle for it. */
|
||||
int res = find_module (strtab + to_module->fromdir_offset,
|
||||
strtab + to_module->fromname_offset,
|
||||
&result[idx]);
|
||||
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
|
||||
{
|
||||
/* Something went wrong. */
|
||||
if (idx != 0)
|
||||
__gconv_release_step (&result[0]);
|
||||
free (result);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* It's a builtin transformation. */
|
||||
__gconv_get_builtin_trans (strtab + to_module->fromname_offset,
|
||||
&result[idx]);
|
||||
|
||||
++*nsteps;
|
||||
}
|
||||
|
||||
return __GCONV_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Free memory allocated for the transformation record. */
|
||||
void
|
||||
internal_function
|
||||
__gconv_release_cache (struct __gconv_step *steps, size_t nsteps)
|
||||
{
|
||||
if (__gconv_cache != NULL)
|
||||
/* The only thing we have to deallocate is the record with the
|
||||
steps. */
|
||||
free (steps);
|
||||
}
|
||||
|
||||
|
||||
/* Free all resources if necessary. */
|
||||
static void __attribute__ ((unused))
|
||||
free_mem (void)
|
||||
{
|
||||
if (cache_malloced)
|
||||
free (__gconv_cache);
|
||||
#ifdef _POSIX_MAPPED_FILES
|
||||
else
|
||||
__munmap (__gconv_cache, cache_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
text_set_element (__libc_subfreeres, free_mem);
|
73
newlib/libc/sys/linux/iconv/gconv_charset.h
Normal file
73
newlib/libc/sys/linux/iconv/gconv_charset.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* Charset name normalization.
|
||||
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <ctype.h>
|
||||
#include <locale.h>
|
||||
|
||||
|
||||
static inline void
|
||||
strip (char *wp, const char *s)
|
||||
{
|
||||
int slash_count = 0;
|
||||
char old_locale[20], *old_locale_p;
|
||||
|
||||
/* Set locale to default C locale. */
|
||||
old_locale_p = setlocale(LC_ALL, "C");
|
||||
strncpy(old_locale, old_locale_p, 20);
|
||||
while (*s != '\0')
|
||||
{
|
||||
if (isalnum (*s)
|
||||
|| *s == '_' || *s == '-' || *s == '.')
|
||||
*wp++ = toupper (*s);
|
||||
else if (*s == '/')
|
||||
{
|
||||
if (++slash_count == 3)
|
||||
break;
|
||||
*wp++ = '/';
|
||||
}
|
||||
++s;
|
||||
}
|
||||
|
||||
while (slash_count++ < 2)
|
||||
*wp++ = '/';
|
||||
|
||||
*wp = '\0';
|
||||
setlocale(LC_ALL, old_locale);
|
||||
}
|
||||
|
||||
|
||||
static char * __attribute__ ((unused))
|
||||
upstr (char *dst, const char *str)
|
||||
{
|
||||
char *cp = dst;
|
||||
char old_locale[20], *old_locale_p;
|
||||
/* Set locale to default C locale. */
|
||||
old_locale_p = setlocale(LC_ALL, "C");
|
||||
strncpy(old_locale, old_locale_p, 20);
|
||||
while ((*cp++ = toupper (*str++)) != '\0')
|
||||
/* nothing */;
|
||||
setlocale(LC_ALL, old_locale);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
/* If NAME is an codeset alias expand it. */
|
||||
extern int __gconv_compare_alias (const char *name1, const char *name2)
|
||||
internal_function;
|
65
newlib/libc/sys/linux/iconv/gconv_close.c
Normal file
65
newlib/libc/sys/linux/iconv/gconv_close.c
Normal file
@ -0,0 +1,65 @@
|
||||
/* Release any resource associated with given conversion descriptor.
|
||||
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <stdlib.h>
|
||||
|
||||
#include <gconv_int.h>
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
__gconv_close (__gconv_t cd)
|
||||
{
|
||||
struct __gconv_step *srunp;
|
||||
struct __gconv_step_data *drunp;
|
||||
size_t nsteps;
|
||||
|
||||
/* Free all resources by calling destructor functions and release
|
||||
the implementations. */
|
||||
srunp = cd->__steps;
|
||||
nsteps = cd->__nsteps;
|
||||
drunp = cd->__data;
|
||||
do
|
||||
{
|
||||
struct __gconv_trans_data *transp;
|
||||
|
||||
transp = drunp->__trans;
|
||||
while (transp != NULL)
|
||||
{
|
||||
struct __gconv_trans_data *curp = transp;
|
||||
transp = transp->__next;
|
||||
|
||||
if (__builtin_expect (curp->__trans_end_fct != NULL, 0))
|
||||
curp->__trans_end_fct (curp->__data);
|
||||
|
||||
free (curp);
|
||||
}
|
||||
|
||||
if (!(drunp->__flags & __GCONV_IS_LAST) && drunp->__outbuf != NULL)
|
||||
free (drunp->__outbuf);
|
||||
}
|
||||
while (!((drunp++)->__flags & __GCONV_IS_LAST));
|
||||
|
||||
/* Free the data allocated for the descriptor. */
|
||||
free (cd);
|
||||
|
||||
/* Close the participating modules. */
|
||||
return __gconv_close_transform (srunp, nsteps);
|
||||
}
|
680
newlib/libc/sys/linux/iconv/gconv_conf.c
Normal file
680
newlib/libc/sys/linux/iconv/gconv_conf.c
Normal file
@ -0,0 +1,680 @@
|
||||
/* Handle configuration data.
|
||||
Copyright (C) 1997,98,99,2000,2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <search.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <gconv_int.h>
|
||||
|
||||
/* This is the default path where we look for module lists. */
|
||||
static const char default_gconv_path[] = GCONV_PATH;
|
||||
|
||||
/* The path elements, as determined by the __gconv_get_path function.
|
||||
All path elements end in a slash. */
|
||||
struct path_elem *__gconv_path_elem;
|
||||
/* Maximum length of a single path element in __gconv_path_elem. */
|
||||
size_t __gconv_max_path_elem_len;
|
||||
|
||||
/* We use the following struct if we couldn't allocate memory. */
|
||||
static const struct path_elem empty_path_elem;
|
||||
|
||||
/* Name of the file containing the module information in the directories
|
||||
along the path. */
|
||||
static const char gconv_conf_filename[] = "gconv-modules";
|
||||
|
||||
/* Filename extension for the modules. */
|
||||
#ifndef MODULE_EXT
|
||||
# define MODULE_EXT ".so"
|
||||
#endif
|
||||
static const char gconv_module_ext[] = MODULE_EXT;
|
||||
|
||||
/* We have a few builtin transformations. */
|
||||
static struct gconv_module builtin_modules[] =
|
||||
{
|
||||
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \
|
||||
MinT, MaxT) \
|
||||
{ \
|
||||
from_string: From, \
|
||||
to_string: To, \
|
||||
cost_hi: Cost, \
|
||||
cost_lo: INT_MAX, \
|
||||
module_name: Name \
|
||||
},
|
||||
#define BUILTIN_ALIAS(From, To)
|
||||
|
||||
#include "gconv_builtin.h"
|
||||
};
|
||||
|
||||
#undef BUILTIN_TRANSFORMATION
|
||||
#undef BUILTIN_ALIAS
|
||||
|
||||
static const char *builtin_aliases[] =
|
||||
{
|
||||
#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \
|
||||
MinT, MaxT)
|
||||
#define BUILTIN_ALIAS(From, To) From " " To,
|
||||
|
||||
#include "gconv_builtin.h"
|
||||
};
|
||||
|
||||
#ifdef USE_IN_LIBIO
|
||||
# include <libio/libioP.h>
|
||||
# define __getdelim(line, len, c, fp) _IO_getdelim (line, len, c, fp)
|
||||
#endif
|
||||
|
||||
|
||||
/* Value of the GCONV_PATH environment variable. */
|
||||
const char *__gconv_path_envvar;
|
||||
|
||||
|
||||
/* Test whether there is already a matching module known. */
|
||||
static int
|
||||
internal_function
|
||||
detect_conflict (const char *alias)
|
||||
{
|
||||
struct gconv_module *node = __gconv_modules_db;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
int cmpres = strcmp (alias, node->from_string);
|
||||
|
||||
if (cmpres == 0)
|
||||
/* We have a conflict. */
|
||||
return 1;
|
||||
else if (cmpres < 0)
|
||||
node = node->left;
|
||||
else
|
||||
node = node->right;
|
||||
}
|
||||
|
||||
return node != NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Add new alias. */
|
||||
static inline void
|
||||
add_alias (char *rp, void *modules)
|
||||
{
|
||||
/* We now expect two more string. The strings are normalized
|
||||
(converted to UPPER case) and strored in the alias database. */
|
||||
struct gconv_alias *new_alias;
|
||||
char *from, *to, *wp;
|
||||
char old_locale[20], *old_locale_p;
|
||||
|
||||
/* Set locale to default C locale. */
|
||||
old_locale_p = setlocale(LC_ALL, "C");
|
||||
strncpy(old_locale, old_locale_p, 20);
|
||||
|
||||
while (isspace (*rp))
|
||||
++rp;
|
||||
from = wp = rp;
|
||||
while (*rp != '\0' && !isspace (*rp))
|
||||
*wp++ = toupper (*rp++);
|
||||
if (*rp == '\0')
|
||||
{
|
||||
setlocale(LC_ALL, old_locale);
|
||||
/* There is no `to' string on the line. Ignore it. */
|
||||
return;
|
||||
}
|
||||
*wp++ = '\0';
|
||||
to = ++rp;
|
||||
while (isspace (*rp))
|
||||
++rp;
|
||||
while (*rp != '\0' && !isspace (*rp))
|
||||
*wp++ = toupper (*rp++);
|
||||
if (to == wp)
|
||||
{
|
||||
setlocale(LC_ALL, old_locale);
|
||||
/* No `to' string, ignore the line. */
|
||||
return;
|
||||
}
|
||||
*wp++ = '\0';
|
||||
|
||||
/* Test whether this alias conflicts with any available module. */
|
||||
if (detect_conflict (from))
|
||||
{
|
||||
setlocale(LC_ALL, old_locale);
|
||||
/* It does conflict, don't add the alias. */
|
||||
return;
|
||||
}
|
||||
|
||||
new_alias = (struct gconv_alias *) malloc (sizeof (struct gconv_alias) + (wp - from));
|
||||
if (new_alias != NULL)
|
||||
{
|
||||
void **inserted;
|
||||
|
||||
new_alias->fromname = memcpy ((char *) new_alias
|
||||
+ sizeof (struct gconv_alias),
|
||||
from, wp - from);
|
||||
new_alias->toname = new_alias->fromname + (to - from);
|
||||
|
||||
inserted = (void **) tsearch (new_alias, &__gconv_alias_db,
|
||||
__gconv_alias_compare);
|
||||
if (inserted == NULL || *inserted != new_alias)
|
||||
/* Something went wrong, free this entry. */
|
||||
free (new_alias);
|
||||
}
|
||||
setlocale(LC_ALL, old_locale);
|
||||
}
|
||||
|
||||
|
||||
/* Insert a data structure for a new module in the search tree. */
|
||||
static inline void
|
||||
internal_function
|
||||
insert_module (struct gconv_module *newp, int tobefreed)
|
||||
{
|
||||
struct gconv_module **rootp = &__gconv_modules_db;
|
||||
|
||||
while (*rootp != NULL)
|
||||
{
|
||||
struct gconv_module *root = *rootp;
|
||||
int cmpres;
|
||||
|
||||
cmpres = strcmp (newp->from_string, root->from_string);
|
||||
if (cmpres == 0)
|
||||
{
|
||||
/* Both strings are identical. Insert the string at the
|
||||
end of the `same' list if it is not already there. */
|
||||
while (strcmp (newp->from_string, root->from_string) != 0
|
||||
|| strcmp (newp->to_string, root->to_string) != 0)
|
||||
{
|
||||
rootp = &root->same;
|
||||
root = *rootp;
|
||||
if (root == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (root != NULL)
|
||||
{
|
||||
/* This is a no new conversion. But maybe the cost is
|
||||
better. */
|
||||
if (newp->cost_hi < root->cost_hi
|
||||
|| (newp->cost_hi == root->cost_hi
|
||||
&& newp->cost_lo < root->cost_lo))
|
||||
{
|
||||
newp->left = root->left;
|
||||
newp->right = root->right;
|
||||
newp->same = root->same;
|
||||
*rootp = newp;
|
||||
|
||||
free (root);
|
||||
}
|
||||
else if (tobefreed)
|
||||
free (newp);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (cmpres < 0)
|
||||
rootp = &root->left;
|
||||
else
|
||||
rootp = &root->right;
|
||||
}
|
||||
|
||||
/* Plug in the new node here. */
|
||||
*rootp = newp;
|
||||
}
|
||||
|
||||
|
||||
/* Add new module. */
|
||||
static void
|
||||
internal_function
|
||||
add_module (char *rp, const char *directory, size_t dir_len, void **modules,
|
||||
size_t *nmodules, int modcounter)
|
||||
{
|
||||
/* We expect now
|
||||
1. `from' name
|
||||
2. `to' name
|
||||
3. filename of the module
|
||||
4. an optional cost value
|
||||
*/
|
||||
struct gconv_alias fake_alias;
|
||||
struct gconv_module *new_module;
|
||||
char *from, *to, *module, *wp;
|
||||
int need_ext;
|
||||
int cost_hi;
|
||||
char old_locale[20], *old_locale_p;
|
||||
char *old;
|
||||
size_t len;
|
||||
char *new;
|
||||
|
||||
/* Set locale to default C locale. */
|
||||
old_locale_p = setlocale(LC_ALL, "C");
|
||||
strncpy(old_locale, old_locale_p, 20);
|
||||
|
||||
while (isspace (*rp))
|
||||
++rp;
|
||||
from = rp;
|
||||
while (*rp != '\0' && !isspace (*rp))
|
||||
{
|
||||
*rp = toupper (*rp);
|
||||
++rp;
|
||||
}
|
||||
if (*rp == '\0')
|
||||
{
|
||||
setlocale(LC_ALL, old_locale);
|
||||
return;
|
||||
}
|
||||
*rp++ = '\0';
|
||||
to = wp = rp;
|
||||
while (isspace (*rp))
|
||||
{
|
||||
setlocale(LC_ALL, old_locale);
|
||||
++rp;
|
||||
}
|
||||
while (*rp != '\0' && !isspace (*rp))
|
||||
*wp++ = toupper (*rp++);
|
||||
if (*rp == '\0')
|
||||
{
|
||||
setlocale(LC_ALL, old_locale);
|
||||
return;
|
||||
}
|
||||
*wp++ = '\0';
|
||||
do
|
||||
++rp;
|
||||
while (isspace (*rp));
|
||||
module = wp;
|
||||
while (*rp != '\0' && !isspace (*rp))
|
||||
*wp++ = *rp++;
|
||||
if (*rp == '\0')
|
||||
{
|
||||
/* There is no cost, use one by default. */
|
||||
*wp++ = '\0';
|
||||
cost_hi = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There might be a cost value. */
|
||||
char *endp;
|
||||
|
||||
*wp++ = '\0';
|
||||
cost_hi = strtol (rp, &endp, 10);
|
||||
if (rp == endp || cost_hi < 1)
|
||||
/* No useful information. */
|
||||
cost_hi = 1;
|
||||
}
|
||||
|
||||
if (module[0] == '\0')
|
||||
{
|
||||
setlocale(LC_ALL, old_locale);
|
||||
/* No module name given. */
|
||||
return;
|
||||
}
|
||||
if (module[0] == '/')
|
||||
dir_len = 0;
|
||||
|
||||
/* See whether we must add the ending. */
|
||||
need_ext = 0;
|
||||
if (wp - module < (ptrdiff_t) sizeof (gconv_module_ext)
|
||||
|| memcmp (wp - sizeof (gconv_module_ext), gconv_module_ext,
|
||||
sizeof (gconv_module_ext)) != 0)
|
||||
/* We must add the module extension. */
|
||||
need_ext = sizeof (gconv_module_ext) - 1;
|
||||
|
||||
/* See whether we have already an alias with this name defined. */
|
||||
old = from;
|
||||
len = strnlen (old, to - from);
|
||||
new = (char *) alloca (len + 1);
|
||||
new[len] = '\0';
|
||||
fake_alias.fromname = (char *) memcpy (new, old, len);
|
||||
|
||||
if (tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare) != NULL)
|
||||
{
|
||||
setlocale(LC_ALL, old_locale);
|
||||
/* This module duplicates an alias. */
|
||||
return;
|
||||
}
|
||||
|
||||
new_module = (struct gconv_module *) calloc (1,
|
||||
sizeof (struct gconv_module)
|
||||
+ (wp - from)
|
||||
+ dir_len + need_ext);
|
||||
if (new_module != NULL)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
new_module->from_string = tmp = (char *) (new_module + 1);
|
||||
tmp = memcpy (tmp, from, to - from);
|
||||
tmp += (to - from);
|
||||
|
||||
new_module->to_string = tmp;
|
||||
tmp = memcpy (tmp, to, module - to);
|
||||
tmp += (module - to);
|
||||
|
||||
new_module->cost_hi = cost_hi;
|
||||
new_module->cost_lo = modcounter;
|
||||
|
||||
new_module->module_name = tmp;
|
||||
|
||||
if (dir_len != 0)
|
||||
{
|
||||
tmp = memcpy (tmp, directory, dir_len);
|
||||
tmp += dir_len;
|
||||
}
|
||||
|
||||
tmp = memcpy (tmp, module, wp - module);
|
||||
tmp += (wp - module);
|
||||
|
||||
if (need_ext)
|
||||
memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_ext));
|
||||
|
||||
/* Now insert the new module data structure in our search tree. */
|
||||
insert_module (new_module, 1);
|
||||
}
|
||||
setlocale(LC_ALL, old_locale);
|
||||
}
|
||||
|
||||
|
||||
/* Read the next configuration file. */
|
||||
static void
|
||||
internal_function
|
||||
read_conf_file (const char *filename, const char *directory, size_t dir_len,
|
||||
void **modules, size_t *nmodules)
|
||||
{
|
||||
FILE *fp = fopen (filename, "r");
|
||||
char *line = NULL;
|
||||
size_t line_len = 0;
|
||||
static int modcounter;
|
||||
char old_locale[20], *old_locale_p;
|
||||
|
||||
/* Don't complain if a file is not present or readable, simply silently
|
||||
ignore it. */
|
||||
if (fp == NULL)
|
||||
return;
|
||||
|
||||
/* Set locale to default C locale. */
|
||||
old_locale_p = setlocale(LC_ALL, "C");
|
||||
strncpy(old_locale, old_locale_p, 20);
|
||||
|
||||
/* Process the known entries of the file. Comments start with `#' and
|
||||
end with the end of the line. Empty lines are ignored. */
|
||||
while (!feof (fp))
|
||||
{
|
||||
char *rp, *endp, *word;
|
||||
ssize_t n = __getdelim (&line, &line_len, '\n', fp);
|
||||
if (n < 0)
|
||||
/* An error occurred. */
|
||||
break;
|
||||
|
||||
rp = line;
|
||||
/* Terminate the line (excluding comments or newline) by an NUL byte
|
||||
to simplify the following code. */
|
||||
endp = strchr (rp, '#');
|
||||
if (endp != NULL)
|
||||
*endp = '\0';
|
||||
else
|
||||
if (rp[n - 1] == '\n')
|
||||
rp[n - 1] = '\0';
|
||||
|
||||
while (isspace (*rp))
|
||||
++rp;
|
||||
|
||||
/* If this is an empty line go on with the next one. */
|
||||
if (rp == endp)
|
||||
continue;
|
||||
|
||||
word = rp;
|
||||
while (*rp != '\0' && !isspace (*rp))
|
||||
++rp;
|
||||
|
||||
if (rp - word == sizeof ("alias") - 1
|
||||
&& memcmp (word, "alias", sizeof ("alias") - 1) == 0)
|
||||
add_alias (rp, *modules);
|
||||
else if (rp - word == sizeof ("module") - 1
|
||||
&& memcmp (word, "module", sizeof ("module") - 1) == 0)
|
||||
add_module (rp, directory, dir_len, modules, nmodules, modcounter++);
|
||||
/* else */
|
||||
/* Otherwise ignore the line. */
|
||||
}
|
||||
|
||||
free (line);
|
||||
|
||||
fclose (fp);
|
||||
|
||||
setlocale(LC_ALL, old_locale);
|
||||
}
|
||||
|
||||
|
||||
/* Determine the directories we are looking for data in. */
|
||||
void
|
||||
__gconv_get_path (void)
|
||||
{
|
||||
struct path_elem *result;
|
||||
__LOCK_INIT(static, path_lock);
|
||||
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_acquire(path_lock);
|
||||
#endif
|
||||
|
||||
/* Make sure there wasn't a second thread doing it already. */
|
||||
result = (struct path_elem *) __gconv_path_elem;
|
||||
if (result == NULL)
|
||||
{
|
||||
/* Determine the complete path first. */
|
||||
char *gconv_path;
|
||||
size_t gconv_path_len;
|
||||
char *elem;
|
||||
char *oldp;
|
||||
char *cp;
|
||||
int nelems;
|
||||
char *cwd;
|
||||
size_t cwdlen;
|
||||
|
||||
if (__gconv_path_envvar == NULL)
|
||||
{
|
||||
char * old = default_gconv_path;
|
||||
size_t len = strlen (old) + 1;
|
||||
char *new = (char *) alloca (len);
|
||||
|
||||
/* No user-defined path. Make a modifiable copy of the
|
||||
default path. */
|
||||
gconv_path = (char *) memcpy (new, old, len);
|
||||
gconv_path_len = sizeof (default_gconv_path);
|
||||
cwd = NULL;
|
||||
cwdlen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Append the default path to the user-defined path. */
|
||||
size_t user_len = strlen (__gconv_path_envvar);
|
||||
char *tmp;
|
||||
|
||||
gconv_path_len = user_len + 1 + sizeof (default_gconv_path);
|
||||
gconv_path = alloca (gconv_path_len);
|
||||
tmp = memcpy (gconv_path, __gconv_path_envvar,
|
||||
user_len);
|
||||
tmp += user_len;
|
||||
memcpy (tmp, ":", 1);
|
||||
tmp += 1;
|
||||
memcpy (tmp,
|
||||
default_gconv_path, sizeof (default_gconv_path));
|
||||
|
||||
cwd = getcwd (NULL, 0);
|
||||
cwdlen = strlen (cwd);
|
||||
}
|
||||
assert (default_gconv_path[0] == '/');
|
||||
|
||||
/* In a first pass we calculate the number of elements. */
|
||||
oldp = NULL;
|
||||
cp = strchr (gconv_path, ':');
|
||||
nelems = 1;
|
||||
while (cp != NULL)
|
||||
{
|
||||
if (cp != oldp + 1)
|
||||
++nelems;
|
||||
oldp = cp;
|
||||
cp = strchr (cp + 1, ':');
|
||||
}
|
||||
|
||||
/* Allocate the memory for the result. */
|
||||
result = (struct path_elem *) malloc ((nelems + 1)
|
||||
* sizeof (struct path_elem)
|
||||
+ gconv_path_len + nelems
|
||||
+ (nelems - 1) * (cwdlen + 1));
|
||||
if (result != NULL)
|
||||
{
|
||||
char *strspace = (char *) &result[nelems + 1];
|
||||
int n = 0;
|
||||
|
||||
/* Separate the individual parts. */
|
||||
__gconv_max_path_elem_len = 0;
|
||||
elem = strtok_r (gconv_path, ":", &gconv_path);
|
||||
assert (elem != NULL);
|
||||
do
|
||||
{
|
||||
result[n].name = strspace;
|
||||
if (elem[0] != '/')
|
||||
{
|
||||
assert (cwd != NULL);
|
||||
strspace = memcpy (strspace, cwd, cwdlen);
|
||||
strspace += cwdlen;
|
||||
*strspace++ = '/';
|
||||
}
|
||||
strspace = strcpy (strspace, elem);
|
||||
while(*strspace != '\0') strspace++;
|
||||
|
||||
if (strspace[-1] != '/')
|
||||
*strspace++ = '/';
|
||||
|
||||
result[n].len = strspace - result[n].name;
|
||||
if (result[n].len > __gconv_max_path_elem_len)
|
||||
__gconv_max_path_elem_len = result[n].len;
|
||||
|
||||
*strspace++ = '\0';
|
||||
++n;
|
||||
}
|
||||
while ((elem = strtok_r (NULL, ":", &gconv_path)) != NULL);
|
||||
|
||||
result[n].name = NULL;
|
||||
result[n].len = 0;
|
||||
}
|
||||
|
||||
__gconv_path_elem = result ?: (struct path_elem *) &empty_path_elem;
|
||||
|
||||
if (cwd != NULL)
|
||||
free (cwd);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release(path_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Read all configuration files found in the user-specified and the default
|
||||
path. */
|
||||
void
|
||||
__gconv_read_conf (void)
|
||||
{
|
||||
void *modules = NULL;
|
||||
size_t nmodules = 0;
|
||||
int save_errno = errno;
|
||||
size_t cnt;
|
||||
char *filename;
|
||||
char *tmp;
|
||||
const char *elem;
|
||||
size_t elem_len;
|
||||
|
||||
/* First see whether we should use the cache. */
|
||||
if (__gconv_load_cache () == 0)
|
||||
{
|
||||
/* Yes, we are done. */
|
||||
__set_errno (save_errno);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
/* Find out where we have to look. */
|
||||
if (__gconv_path_elem == NULL)
|
||||
__gconv_get_path ();
|
||||
|
||||
for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt)
|
||||
{
|
||||
elem = __gconv_path_elem[cnt].name;
|
||||
elem_len = __gconv_path_elem[cnt].len;
|
||||
|
||||
/* No slash needs to be inserted between elem and gconv_conf_filename;
|
||||
elem already ends in a slash. */
|
||||
filename = alloca (elem_len + sizeof (gconv_conf_filename));
|
||||
tmp = memcpy (filename, elem, elem_len);
|
||||
tmp += elem_len;
|
||||
memcpy (tmp, gconv_conf_filename, sizeof (gconv_conf_filename));
|
||||
|
||||
/* Read the next configuration file. */
|
||||
read_conf_file (filename, elem, elem_len, &modules, &nmodules);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Add the internal modules. */
|
||||
for (cnt = 0; cnt < sizeof (builtin_modules) / sizeof (builtin_modules[0]);
|
||||
++cnt)
|
||||
{
|
||||
struct gconv_alias fake_alias;
|
||||
|
||||
fake_alias.fromname = (char *) builtin_modules[cnt].from_string;
|
||||
|
||||
if (tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare)
|
||||
!= NULL)
|
||||
/* It'll conflict so don't add it. */
|
||||
continue;
|
||||
|
||||
insert_module (&builtin_modules[cnt], 0);
|
||||
}
|
||||
|
||||
/* Add aliases for builtin conversions. */
|
||||
cnt = sizeof (builtin_aliases) / sizeof (builtin_aliases[0]);
|
||||
while (cnt > 0)
|
||||
{
|
||||
char * old = builtin_aliases[--cnt];
|
||||
size_t len = strlen (old) + 1;
|
||||
char *new = (char *) alloca (len);
|
||||
char *copy = (char *) memcpy (new, old, len);
|
||||
|
||||
add_alias (copy, modules);
|
||||
}
|
||||
|
||||
/* Restore the error number. */
|
||||
__set_errno (save_errno);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Free all resources if necessary. */
|
||||
static void __attribute__ ((unused))
|
||||
free_mem (void)
|
||||
{
|
||||
if (__gconv_path_elem != NULL && __gconv_path_elem != &empty_path_elem)
|
||||
free ((void *) __gconv_path_elem);
|
||||
}
|
||||
|
||||
text_set_element (__libc_subfreeres, free_mem);
|
803
newlib/libc/sys/linux/iconv/gconv_db.c
Normal file
803
newlib/libc/sys/linux/iconv/gconv_db.c
Normal file
@ -0,0 +1,803 @@
|
||||
/* Provide access to the collection of available transformation modules.
|
||||
Copyright (C) 1997,98,99,2000,2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <limits.h>
|
||||
#include <search.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <gconv_int.h>
|
||||
#include <gconv_charset.h>
|
||||
|
||||
|
||||
/* Simple data structure for alias mapping. We have two names, `from'
|
||||
and `to'. */
|
||||
void *__gconv_alias_db;
|
||||
|
||||
/* Array with available modules. */
|
||||
struct gconv_module *__gconv_modules_db;
|
||||
|
||||
/* We modify global data. */
|
||||
__LOCK_INIT(static, lock);
|
||||
|
||||
|
||||
/* Function for searching alias. */
|
||||
int
|
||||
__gconv_alias_compare (const void *p1, const void *p2)
|
||||
{
|
||||
const struct gconv_alias *s1 = (const struct gconv_alias *) p1;
|
||||
const struct gconv_alias *s2 = (const struct gconv_alias *) p2;
|
||||
return strcmp (s1->fromname, s2->fromname);
|
||||
}
|
||||
|
||||
|
||||
/* To search for a derivation we create a list of intermediate steps.
|
||||
Each element contains a pointer to the element which precedes it
|
||||
in the derivation order. */
|
||||
struct derivation_step
|
||||
{
|
||||
const char *result_set;
|
||||
size_t result_set_len;
|
||||
int cost_lo;
|
||||
int cost_hi;
|
||||
struct gconv_module *code;
|
||||
struct derivation_step *last;
|
||||
struct derivation_step *next;
|
||||
};
|
||||
|
||||
#define NEW_STEP(result, hi, lo, module, last_mod) \
|
||||
({ struct derivation_step *newp = alloca (sizeof (struct derivation_step)); \
|
||||
newp->result_set = result; \
|
||||
newp->result_set_len = strlen (result); \
|
||||
newp->cost_hi = hi; \
|
||||
newp->cost_lo = lo; \
|
||||
newp->code = module; \
|
||||
newp->last = last_mod; \
|
||||
newp->next = NULL; \
|
||||
newp; })
|
||||
|
||||
|
||||
/* If a specific transformation is used more than once we should not need
|
||||
to start looking for it again. Instead cache each successful result. */
|
||||
struct known_derivation
|
||||
{
|
||||
const char *from;
|
||||
const char *to;
|
||||
struct __gconv_step *steps;
|
||||
size_t nsteps;
|
||||
};
|
||||
|
||||
/* Compare function for database of found derivations. */
|
||||
static int
|
||||
derivation_compare (const void *p1, const void *p2)
|
||||
{
|
||||
const struct known_derivation *s1 = (const struct known_derivation *) p1;
|
||||
const struct known_derivation *s2 = (const struct known_derivation *) p2;
|
||||
int result;
|
||||
|
||||
result = strcmp (s1->from, s2->from);
|
||||
if (result == 0)
|
||||
result = strcmp (s1->to, s2->to);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* The search tree for known derivations. */
|
||||
static void *known_derivations;
|
||||
|
||||
/* Look up whether given transformation was already requested before. */
|
||||
static int
|
||||
internal_function
|
||||
derivation_lookup (const char *fromset, const char *toset,
|
||||
struct __gconv_step **handle, size_t *nsteps)
|
||||
{
|
||||
struct known_derivation key = { fromset, toset, NULL, 0 };
|
||||
struct known_derivation **result;
|
||||
|
||||
result = tfind (&key, &known_derivations, derivation_compare);
|
||||
|
||||
if (result == NULL)
|
||||
return __GCONV_NOCONV;
|
||||
|
||||
*handle = (*result)->steps;
|
||||
*nsteps = (*result)->nsteps;
|
||||
|
||||
/* Please note that we return GCONV_OK even if the last search for
|
||||
this transformation was unsuccessful. */
|
||||
return __GCONV_OK;
|
||||
}
|
||||
|
||||
/* Add new derivation to list of known ones. */
|
||||
static void
|
||||
internal_function
|
||||
add_derivation (const char *fromset, const char *toset,
|
||||
struct __gconv_step *handle, size_t nsteps)
|
||||
{
|
||||
struct known_derivation *new_deriv;
|
||||
size_t fromset_len = strlen (fromset) + 1;
|
||||
size_t toset_len = strlen (toset) + 1;
|
||||
|
||||
new_deriv = (struct known_derivation *)
|
||||
malloc (sizeof (struct known_derivation) + fromset_len + toset_len);
|
||||
if (new_deriv != NULL)
|
||||
{
|
||||
char *tmp;
|
||||
new_deriv->from = (char *) (new_deriv + 1);
|
||||
tmp = memcpy (new_deriv + 1, fromset, fromset_len);
|
||||
tmp += fromset_len;
|
||||
|
||||
new_deriv->to = memcpy (tmp,
|
||||
toset, toset_len);
|
||||
|
||||
new_deriv->steps = handle;
|
||||
new_deriv->nsteps = nsteps;
|
||||
|
||||
if (tsearch (new_deriv, &known_derivations, derivation_compare)
|
||||
== NULL)
|
||||
/* There is some kind of memory allocation problem. */
|
||||
free (new_deriv);
|
||||
}
|
||||
/* Please note that we don't complain if the allocation failed. This
|
||||
is not tragically but in case we use the memory debugging facilities
|
||||
not all memory will be freed. */
|
||||
}
|
||||
|
||||
static void
|
||||
free_derivation (void *p)
|
||||
{
|
||||
struct known_derivation *deriv = (struct known_derivation *) p;
|
||||
size_t cnt;
|
||||
|
||||
for (cnt = 0; cnt < deriv->nsteps; ++cnt)
|
||||
if (deriv->steps[cnt].__counter > 0
|
||||
&& deriv->steps[cnt].__end_fct != NULL)
|
||||
deriv->steps[cnt].__end_fct (&deriv->steps[cnt]);
|
||||
|
||||
/* Free the name strings. */
|
||||
free ((char *) deriv->steps[0].__from_name);
|
||||
free ((char *) deriv->steps[deriv->nsteps - 1].__to_name);
|
||||
|
||||
free ((struct __gconv_step *) deriv->steps);
|
||||
free (deriv);
|
||||
}
|
||||
|
||||
|
||||
/* Decrement the reference count for a single step in a steps array. */
|
||||
void
|
||||
internal_function
|
||||
__gconv_release_step (struct __gconv_step *step)
|
||||
{
|
||||
if (--step->__counter == 0)
|
||||
{
|
||||
/* Call the destructor. */
|
||||
if (step->__end_fct != NULL)
|
||||
step->__end_fct (step);
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
/* Skip builtin modules; they are not reference counted. */
|
||||
if (step->__shlib_handle != NULL)
|
||||
{
|
||||
/* Release the loaded module. */
|
||||
__gconv_release_shlib (step->__shlib_handle);
|
||||
step->__shlib_handle = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
internal_function
|
||||
gen_steps (struct derivation_step *best, const char *toset,
|
||||
const char *fromset, struct __gconv_step **handle, size_t *nsteps)
|
||||
{
|
||||
size_t step_cnt = 0;
|
||||
struct __gconv_step *result;
|
||||
struct derivation_step *current;
|
||||
int status = __GCONV_NOMEM;
|
||||
|
||||
/* First determine number of steps. */
|
||||
for (current = best; current->last != NULL; current = current->last)
|
||||
++step_cnt;
|
||||
|
||||
result = (struct __gconv_step *) malloc (sizeof (struct __gconv_step)
|
||||
* step_cnt);
|
||||
if (result != NULL)
|
||||
{
|
||||
int failed = 0;
|
||||
|
||||
status = __GCONV_OK;
|
||||
*nsteps = step_cnt;
|
||||
current = best;
|
||||
while (step_cnt-- > 0)
|
||||
{
|
||||
result[step_cnt].__from_name = (step_cnt == 0
|
||||
? strdup (fromset)
|
||||
: (char *)current->last->result_set);
|
||||
result[step_cnt].__to_name = (step_cnt + 1 == *nsteps
|
||||
? strdup (current->result_set)
|
||||
: result[step_cnt + 1].__from_name);
|
||||
|
||||
result[step_cnt].__counter = 1;
|
||||
result[step_cnt].__data = NULL;
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
if (current->code->module_name[0] == '/')
|
||||
{
|
||||
/* Load the module, return handle for it. */
|
||||
struct __gconv_loaded_object *shlib_handle =
|
||||
__gconv_find_shlib (current->code->module_name);
|
||||
|
||||
if (shlib_handle == NULL)
|
||||
{
|
||||
failed = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
result[step_cnt].__shlib_handle = shlib_handle;
|
||||
result[step_cnt].__modname = shlib_handle->name;
|
||||
result[step_cnt].__fct = shlib_handle->fct;
|
||||
result[step_cnt].__init_fct = shlib_handle->init_fct;
|
||||
result[step_cnt].__end_fct = shlib_handle->end_fct;
|
||||
|
||||
/* Call the init function. */
|
||||
if (result[step_cnt].__init_fct != NULL)
|
||||
{
|
||||
status = result[step_cnt].__init_fct (&result[step_cnt]);
|
||||
|
||||
if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
|
||||
{
|
||||
failed = 1;
|
||||
/* Make sure we unload this modules. */
|
||||
--step_cnt;
|
||||
result[step_cnt].__end_fct = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* It's a builtin transformation. */
|
||||
__gconv_get_builtin_trans (current->code->module_name,
|
||||
&result[step_cnt]);
|
||||
|
||||
current = current->last;
|
||||
}
|
||||
|
||||
if (__builtin_expect (failed, 0) != 0)
|
||||
{
|
||||
/* Something went wrong while initializing the modules. */
|
||||
while (++step_cnt < *nsteps)
|
||||
__gconv_release_step (&result[step_cnt]);
|
||||
free (result);
|
||||
*nsteps = 0;
|
||||
*handle = NULL;
|
||||
if (status == __GCONV_OK)
|
||||
status = __GCONV_NOCONV;
|
||||
}
|
||||
else
|
||||
*handle = result;
|
||||
}
|
||||
else
|
||||
{
|
||||
*nsteps = 0;
|
||||
*handle = NULL;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
static int
|
||||
internal_function
|
||||
increment_counter (struct __gconv_step *steps, size_t nsteps)
|
||||
{
|
||||
/* Increment the user counter. */
|
||||
size_t cnt = nsteps;
|
||||
int result = __GCONV_OK;
|
||||
|
||||
while (cnt-- > 0)
|
||||
{
|
||||
struct __gconv_step *step = &steps[cnt];
|
||||
|
||||
if (step->__counter++ == 0)
|
||||
{
|
||||
/* Skip builtin modules. */
|
||||
if (step->__modname != NULL)
|
||||
{
|
||||
/* Reopen a previously used module. */
|
||||
step->__shlib_handle = __gconv_find_shlib (step->__modname);
|
||||
if (step->__shlib_handle == NULL)
|
||||
{
|
||||
/* Oops, this is the second time we use this module
|
||||
(after unloading) and this time loading failed!? */
|
||||
--step->__counter;
|
||||
while (++cnt < nsteps)
|
||||
__gconv_release_step (&steps[cnt]);
|
||||
result = __GCONV_NOCONV;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The function addresses defined by the module may
|
||||
have changed. */
|
||||
step->__fct = step->__shlib_handle->fct;
|
||||
step->__init_fct = step->__shlib_handle->init_fct;
|
||||
step->__end_fct = step->__shlib_handle->end_fct;
|
||||
}
|
||||
|
||||
if (step->__init_fct != NULL)
|
||||
step->__init_fct (step);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* The main function: find a possible derivation from the `fromset' (either
|
||||
the given name or the alias) to the `toset' (again with alias). */
|
||||
static int
|
||||
internal_function
|
||||
find_derivation (const char *toset, const char *toset_expand,
|
||||
const char *fromset, const char *fromset_expand,
|
||||
struct __gconv_step **handle, size_t *nsteps)
|
||||
{
|
||||
struct derivation_step *first, *current, **lastp, *solution = NULL;
|
||||
int best_cost_hi = INT_MAX;
|
||||
int best_cost_lo = INT_MAX;
|
||||
int result;
|
||||
|
||||
/* Look whether an earlier call to `find_derivation' has already
|
||||
computed a possible derivation. If so, return it immediately. */
|
||||
result = derivation_lookup (fromset_expand ?: fromset, toset_expand ?: toset,
|
||||
handle, nsteps);
|
||||
if (result == __GCONV_OK)
|
||||
{
|
||||
#ifndef STATIC_GCONV
|
||||
result = increment_counter (*handle, *nsteps);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/* The task is to find a sequence of transformations, backed by the
|
||||
existing modules - whether builtin or dynamically loadable -,
|
||||
starting at `fromset' (or `fromset_expand') and ending at `toset'
|
||||
(or `toset_expand'), and with minimal cost.
|
||||
|
||||
For computer scientists, this is a shortest path search in the
|
||||
graph where the nodes are all possible charsets and the edges are
|
||||
the transformations listed in __gconv_modules_db.
|
||||
|
||||
For now we use a simple algorithm with quadratic runtime behaviour.
|
||||
A breadth-first search, starting at `fromset' and `fromset_expand'.
|
||||
The list starting at `first' contains all nodes that have been
|
||||
visited up to now, in the order in which they have been visited --
|
||||
excluding the goal nodes `toset' and `toset_expand' which get
|
||||
managed in the list starting at `solution'.
|
||||
`current' walks through the list starting at `first' and looks
|
||||
which nodes are reachable from the current node, adding them to
|
||||
the end of the list [`first' or `solution' respectively] (if
|
||||
they are visited the first time) or updating them in place (if
|
||||
they have have already been visited).
|
||||
In each node of either list, cost_lo and cost_hi contain the
|
||||
minimum cost over any paths found up to now, starting at `fromset'
|
||||
or `fromset_expand', ending at that node. best_cost_lo and
|
||||
best_cost_hi represent the minimum over the elements of the
|
||||
`solution' list. */
|
||||
|
||||
if (fromset_expand != NULL)
|
||||
{
|
||||
first = NEW_STEP (fromset_expand, 0, 0, NULL, NULL);
|
||||
first->next = NEW_STEP (fromset, 0, 0, NULL, NULL);
|
||||
lastp = &first->next->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
first = NEW_STEP (fromset, 0, 0, NULL, NULL);
|
||||
lastp = &first->next;
|
||||
}
|
||||
|
||||
for (current = first; current != NULL; current = current->next)
|
||||
{
|
||||
/* Now match all the available module specifications against the
|
||||
current charset name. If any of them matches check whether
|
||||
we already have a derivation for this charset. If yes, use the
|
||||
one with the lower costs. Otherwise add the new charset at the
|
||||
end.
|
||||
|
||||
The module database is organized in a tree form which allows
|
||||
searching for prefixes. So we search for the first entry with a
|
||||
matching prefix and any other matching entry can be found from
|
||||
this place. */
|
||||
struct gconv_module *node;
|
||||
|
||||
/* Maybe it is not necessary anymore to look for a solution for
|
||||
this entry since the cost is already as high (or higher) as
|
||||
the cost for the best solution so far. */
|
||||
if (current->cost_hi > best_cost_hi
|
||||
|| (current->cost_hi == best_cost_hi
|
||||
&& current->cost_lo >= best_cost_lo))
|
||||
continue;
|
||||
|
||||
node = __gconv_modules_db;
|
||||
while (node != NULL)
|
||||
{
|
||||
int cmpres = strcmp (current->result_set, node->from_string);
|
||||
if (cmpres == 0)
|
||||
{
|
||||
/* Walk through the list of modules with this prefix and
|
||||
try to match the name. */
|
||||
struct gconv_module *runp;
|
||||
|
||||
/* Check all the modules with this prefix. */
|
||||
runp = node;
|
||||
do
|
||||
{
|
||||
const char *result_set = (strcmp (runp->to_string, "-") == 0
|
||||
? (toset_expand ?: toset)
|
||||
: runp->to_string);
|
||||
int cost_hi = runp->cost_hi + current->cost_hi;
|
||||
int cost_lo = runp->cost_lo + current->cost_lo;
|
||||
struct derivation_step *step;
|
||||
|
||||
/* We managed to find a derivation. First see whether
|
||||
we have reached one of the goal nodes. */
|
||||
if (strcmp (result_set, toset) == 0
|
||||
|| (toset_expand != NULL
|
||||
&& strcmp (result_set, toset_expand) == 0))
|
||||
{
|
||||
/* Append to the `solution' list if there
|
||||
is no entry with this name. */
|
||||
for (step = solution; step != NULL; step = step->next)
|
||||
if (strcmp (result_set, step->result_set) == 0)
|
||||
break;
|
||||
|
||||
if (step == NULL)
|
||||
{
|
||||
step = NEW_STEP (result_set,
|
||||
cost_hi, cost_lo,
|
||||
runp, current);
|
||||
step->next = solution;
|
||||
solution = step;
|
||||
}
|
||||
else if (step->cost_hi > cost_hi
|
||||
|| (step->cost_hi == cost_hi
|
||||
&& step->cost_lo > cost_lo))
|
||||
{
|
||||
/* A better path was found for the node,
|
||||
on the `solution' list. */
|
||||
step->code = runp;
|
||||
step->last = current;
|
||||
step->cost_hi = cost_hi;
|
||||
step->cost_lo = cost_lo;
|
||||
}
|
||||
|
||||
/* Update best_cost accordingly. */
|
||||
if (cost_hi < best_cost_hi
|
||||
|| (cost_hi == best_cost_hi
|
||||
&& cost_lo < best_cost_lo))
|
||||
{
|
||||
best_cost_hi = cost_hi;
|
||||
best_cost_lo = cost_lo;
|
||||
}
|
||||
}
|
||||
else if (cost_hi < best_cost_hi
|
||||
|| (cost_hi == best_cost_hi
|
||||
&& cost_lo < best_cost_lo))
|
||||
{
|
||||
/* Append at the end of the `first' list if there
|
||||
is no entry with this name. */
|
||||
for (step = first; step != NULL; step = step->next)
|
||||
if (strcmp (result_set, step->result_set) == 0)
|
||||
break;
|
||||
|
||||
if (step == NULL)
|
||||
{
|
||||
*lastp = NEW_STEP (result_set,
|
||||
cost_hi, cost_lo,
|
||||
runp, current);
|
||||
lastp = &(*lastp)->next;
|
||||
}
|
||||
else if (step->cost_hi > cost_hi
|
||||
|| (step->cost_hi == cost_hi
|
||||
&& step->cost_lo > cost_lo))
|
||||
{
|
||||
/* A better path was found for the node,
|
||||
on the `first' list. */
|
||||
step->code = runp;
|
||||
step->last = current;
|
||||
|
||||
/* Update the cost for all steps. */
|
||||
for (step = first; step != NULL;
|
||||
step = step->next)
|
||||
/* But don't update the start nodes. */
|
||||
if (step->code != NULL)
|
||||
{
|
||||
struct derivation_step *back;
|
||||
int hi, lo;
|
||||
|
||||
hi = step->code->cost_hi;
|
||||
lo = step->code->cost_lo;
|
||||
|
||||
for (back = step->last; back->code != NULL;
|
||||
back = back->last)
|
||||
{
|
||||
hi += back->code->cost_hi;
|
||||
lo += back->code->cost_lo;
|
||||
}
|
||||
|
||||
step->cost_hi = hi;
|
||||
step->cost_lo = lo;
|
||||
}
|
||||
|
||||
/* Likewise for the nodes on the solution list.
|
||||
Also update best_cost accordingly. */
|
||||
for (step = solution; step != NULL;
|
||||
step = step->next)
|
||||
{
|
||||
step->cost_hi = (step->code->cost_hi
|
||||
+ step->last->cost_hi);
|
||||
step->cost_lo = (step->code->cost_lo
|
||||
+ step->last->cost_lo);
|
||||
|
||||
if (step->cost_hi < best_cost_hi
|
||||
|| (step->cost_hi == best_cost_hi
|
||||
&& step->cost_lo < best_cost_lo))
|
||||
{
|
||||
best_cost_hi = step->cost_hi;
|
||||
best_cost_lo = step->cost_lo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runp = runp->same;
|
||||
}
|
||||
while (runp != NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
else if (cmpres < 0)
|
||||
node = node->left;
|
||||
else
|
||||
node = node->right;
|
||||
}
|
||||
}
|
||||
|
||||
if (solution != NULL)
|
||||
{
|
||||
/* We really found a way to do the transformation. */
|
||||
|
||||
/* Choose the best solution. This is easy because we know that
|
||||
the solution list has at most length 2 (one for every possible
|
||||
goal node). */
|
||||
if (solution->next != NULL)
|
||||
{
|
||||
struct derivation_step *solution2 = solution->next;
|
||||
|
||||
if (solution2->cost_hi < solution->cost_hi
|
||||
|| (solution2->cost_hi == solution->cost_hi
|
||||
&& solution2->cost_lo < solution->cost_lo))
|
||||
solution = solution2;
|
||||
}
|
||||
|
||||
/* Now build a data structure describing the transformation steps. */
|
||||
result = gen_steps (solution, toset_expand ?: toset,
|
||||
fromset_expand ?: fromset, handle, nsteps);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We haven't found a transformation. Clear the result values. */
|
||||
*handle = NULL;
|
||||
*nsteps = 0;
|
||||
}
|
||||
|
||||
/* Add result in any case to list of known derivations. */
|
||||
add_derivation (fromset_expand ?: fromset, toset_expand ?: toset,
|
||||
*handle, *nsteps);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Control of initialization. */
|
||||
__libc_once_define (static, once);
|
||||
|
||||
|
||||
static const char *
|
||||
do_lookup_alias (const char *name)
|
||||
{
|
||||
struct gconv_alias key;
|
||||
struct gconv_alias **found;
|
||||
|
||||
key.fromname = (char *) name;
|
||||
found = tfind (&key, &__gconv_alias_db, __gconv_alias_compare);
|
||||
return found != NULL ? (*found)->toname : NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
__gconv_compare_alias (const char *name1, const char *name2)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* Ensure that the configuration data is read. */
|
||||
__libc_once (once, __gconv_read_conf);
|
||||
|
||||
if (__gconv_compare_alias_cache (name1, name2, &result) != 0)
|
||||
result = strcmp (do_lookup_alias (name1) ?: name1,
|
||||
do_lookup_alias (name2) ?: name2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
__gconv_find_transform (const char *toset, const char *fromset,
|
||||
struct __gconv_step **handle, size_t *nsteps,
|
||||
int flags)
|
||||
{
|
||||
const char *fromset_expand;
|
||||
const char *toset_expand;
|
||||
int result;
|
||||
|
||||
/* Ensure that the configuration data is read. */
|
||||
__libc_once (once, __gconv_read_conf);
|
||||
|
||||
/* Acquire the lock. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_acquire(lock);
|
||||
#endif
|
||||
|
||||
result = __gconv_lookup_cache (toset, fromset, handle, nsteps, flags);
|
||||
if (result != __GCONV_NODB)
|
||||
{
|
||||
/* We have a cache and could resolve the request, successful or not. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release(lock);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* If we don't have a module database return with an error. */
|
||||
if (__gconv_modules_db == NULL)
|
||||
{
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release(lock);
|
||||
#endif
|
||||
|
||||
return __GCONV_NOCONV;
|
||||
}
|
||||
|
||||
/* See whether the names are aliases. */
|
||||
fromset_expand = do_lookup_alias (fromset);
|
||||
toset_expand = do_lookup_alias (toset);
|
||||
|
||||
if (__builtin_expect (flags & GCONV_AVOID_NOCONV, 0)
|
||||
/* We are not supposed to create a pseudo transformation (means
|
||||
copying) when the input and output character set are the same. */
|
||||
&& (strcmp (toset, fromset) == 0
|
||||
|| (toset_expand != NULL && strcmp (toset_expand, fromset) == 0)
|
||||
|| (fromset_expand != NULL
|
||||
&& (strcmp (toset, fromset_expand) == 0
|
||||
|| (toset_expand != NULL
|
||||
&& strcmp (toset_expand, fromset_expand) == 0)))))
|
||||
{
|
||||
/* Both character sets are the same. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release(lock);
|
||||
#endif
|
||||
|
||||
return __GCONV_NOCONV;
|
||||
}
|
||||
|
||||
result = find_derivation (toset, toset_expand, fromset, fromset_expand,
|
||||
handle, nsteps);
|
||||
|
||||
/* Release the lock. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release(lock);
|
||||
#endif
|
||||
|
||||
|
||||
/* The following code is necessary since `find_derivation' will return
|
||||
GCONV_OK even when no derivation was found but the same request
|
||||
was processed before. I.e., negative results will also be cached. */
|
||||
return (result == __GCONV_OK
|
||||
? (*handle == NULL ? __GCONV_NOCONV : __GCONV_OK)
|
||||
: result);
|
||||
}
|
||||
|
||||
|
||||
/* Release the entries of the modules list. */
|
||||
int
|
||||
internal_function
|
||||
__gconv_close_transform (struct __gconv_step *steps, size_t nsteps)
|
||||
{
|
||||
int result = __GCONV_OK;
|
||||
size_t cnt;
|
||||
|
||||
/* Acquire the lock. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_acquire(lock);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
cnt = nsteps;
|
||||
while (cnt-- > 0)
|
||||
__gconv_release_step (&steps[cnt]);
|
||||
#endif
|
||||
|
||||
/* If we use the cache we free a bit more since we don't keep any
|
||||
transformation records around, they are cheap enough to
|
||||
recreate. */
|
||||
__gconv_release_cache (steps, nsteps);
|
||||
|
||||
/* Release the lock. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release(lock);
|
||||
#endif
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Free the modules mentioned. */
|
||||
static void
|
||||
internal_function
|
||||
free_modules_db (struct gconv_module *node)
|
||||
{
|
||||
if (node->left != NULL)
|
||||
free_modules_db (node->left);
|
||||
if (node->right != NULL)
|
||||
free_modules_db (node->right);
|
||||
do
|
||||
{
|
||||
struct gconv_module *act = node;
|
||||
node = node->same;
|
||||
if (act->module_name[0] == '/')
|
||||
free (act);
|
||||
}
|
||||
while (node != NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Free all resources if necessary. */
|
||||
static void __attribute__ ((unused))
|
||||
free_mem (void)
|
||||
{
|
||||
if (__gconv_alias_db != NULL)
|
||||
tdestroy (__gconv_alias_db, free);
|
||||
|
||||
if (__gconv_modules_db != NULL)
|
||||
free_modules_db (__gconv_modules_db);
|
||||
|
||||
if (known_derivations != NULL)
|
||||
tdestroy (known_derivations, free_derivation);
|
||||
}
|
||||
|
||||
text_set_element (__libc_subfreeres, free_mem);
|
237
newlib/libc/sys/linux/iconv/gconv_dl.c
Normal file
237
newlib/libc/sys/linux/iconv/gconv_dl.c
Normal file
@ -0,0 +1,237 @@
|
||||
/* Handle loading/unloading of shared object for transformation.
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <search.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <bits/libc-lock.h>
|
||||
#include <sys/param.h>
|
||||
#include <ltdl.h>
|
||||
|
||||
#include <gconv_int.h>
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
/* For debugging purposes. */
|
||||
static void print_all (void);
|
||||
#endif
|
||||
|
||||
|
||||
/* This is a tuning parameter. If a transformation module is not used
|
||||
anymore it gets not immediately unloaded. Instead we wait a certain
|
||||
number of load attempts for further modules. If none of the
|
||||
subsequent load attempts name the same object it finally gets unloaded.
|
||||
Otherwise it is still available which hopefully is the frequent case.
|
||||
The following number is the number of unloading attempts we wait
|
||||
before unloading. */
|
||||
#define TRIES_BEFORE_UNLOAD 2
|
||||
|
||||
/* Array of loaded objects. This is shared by all threads so we have
|
||||
to use semaphores to access it. */
|
||||
static void *loaded;
|
||||
|
||||
/* Comparison function for searching `loaded_object' tree. */
|
||||
static int
|
||||
known_compare (const void *p1, const void *p2)
|
||||
{
|
||||
const struct __gconv_loaded_object *s1 =
|
||||
(const struct __gconv_loaded_object *) p1;
|
||||
const struct __gconv_loaded_object *s2 =
|
||||
(const struct __gconv_loaded_object *) p2;
|
||||
|
||||
return strcmp (s1->name, s2->name);
|
||||
}
|
||||
|
||||
/* Open the gconv database if necessary. A non-negative return value
|
||||
means success. */
|
||||
struct __gconv_loaded_object *
|
||||
internal_function
|
||||
__gconv_find_shlib (const char *name)
|
||||
{
|
||||
struct __gconv_loaded_object *found;
|
||||
void *keyp;
|
||||
|
||||
|
||||
|
||||
/* Search the tree of shared objects previously requested. Data in
|
||||
the tree are `loaded_object' structures, whose first member is a
|
||||
`const char *', the lookup key. The search returns a pointer to
|
||||
the tree node structure; the first member of the is a pointer to
|
||||
our structure (i.e. what will be a `loaded_object'); since the
|
||||
first member of that is the lookup key string, &FCT_NAME is close
|
||||
enough to a pointer to our structure to use as a lookup key that
|
||||
will be passed to `known_compare' (above). */
|
||||
|
||||
keyp = tfind (&name, &loaded, known_compare);
|
||||
if (keyp == NULL)
|
||||
{
|
||||
/* This name was not known before. */
|
||||
size_t namelen = strlen (name) + 1;
|
||||
|
||||
found = malloc (sizeof (struct __gconv_loaded_object) + namelen);
|
||||
if (found != NULL)
|
||||
{
|
||||
/* Point the tree node at this new structure. */
|
||||
found->name = (char *) memcpy (found + 1, name, namelen);
|
||||
found->counter = -TRIES_BEFORE_UNLOAD - 1;
|
||||
found->handle = NULL;
|
||||
|
||||
if (__builtin_expect (tsearch (found, &loaded, known_compare)
|
||||
== NULL, 0))
|
||||
{
|
||||
/* Something went wrong while inserting the entry. */
|
||||
free (found);
|
||||
found = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
found = *(struct __gconv_loaded_object **) keyp;
|
||||
|
||||
/* Try to load the shared object if the usage count is 0. This
|
||||
implies that if the shared object is not loadable, the handle is
|
||||
NULL and the usage count > 0. */
|
||||
if (found != NULL)
|
||||
{
|
||||
if (found->counter < -TRIES_BEFORE_UNLOAD)
|
||||
{
|
||||
assert (found->handle == NULL);
|
||||
found->handle = __libc_dlopen (found->name);
|
||||
if (found->handle != NULL)
|
||||
{
|
||||
found->fct = __libc_dlsym (found->handle, "gconv");
|
||||
if (found->fct == NULL)
|
||||
{
|
||||
/* Argh, no conversion function. There is something
|
||||
wrong here. */
|
||||
__gconv_release_shlib (found);
|
||||
found = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
found->init_fct = __libc_dlsym (found->handle, "gconv_init");
|
||||
found->end_fct = __libc_dlsym (found->handle, "gconv_end");
|
||||
|
||||
/* We have succeeded in loading the shared object. */
|
||||
found->counter = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Error while loading the shared object. */
|
||||
found = NULL;
|
||||
}
|
||||
else if (found->handle != NULL)
|
||||
found->counter = MAX (found->counter + 1, 1);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/* This is very ugly but the tsearch functions provide no way to pass
|
||||
information to the walker function. So we use a global variable.
|
||||
It is MT safe since we use a lock. */
|
||||
static struct __gconv_loaded_object *release_handle;
|
||||
|
||||
static void
|
||||
do_release_shlib (void *nodep, VISIT value, int level)
|
||||
{
|
||||
struct __gconv_loaded_object *obj = *(struct __gconv_loaded_object **) nodep;
|
||||
|
||||
|
||||
|
||||
if (value != preorder && value != leaf)
|
||||
return;
|
||||
|
||||
if (obj == release_handle)
|
||||
{
|
||||
/* This is the object we want to unload. Now decrement the
|
||||
reference counter. */
|
||||
assert (obj->counter > 0);
|
||||
--obj->counter;
|
||||
}
|
||||
else if (obj->counter <= 0 && obj->counter >= -TRIES_BEFORE_UNLOAD
|
||||
&& --obj->counter < -TRIES_BEFORE_UNLOAD && obj->handle != NULL)
|
||||
{
|
||||
/* Unload the shared object. */
|
||||
__libc_dlclose (obj->handle);
|
||||
obj->handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Notify system that a shared object is not longer needed. */
|
||||
void
|
||||
internal_function
|
||||
__gconv_release_shlib (struct __gconv_loaded_object *handle)
|
||||
{
|
||||
/* Urgh, this is ugly but we have no other possibility. */
|
||||
release_handle = handle;
|
||||
|
||||
/* Process all entries. Please note that we also visit entries
|
||||
with release counts <= 0. This way we can finally unload them
|
||||
if necessary. */
|
||||
twalk (loaded, (void *) do_release_shlib);
|
||||
}
|
||||
|
||||
|
||||
/* We run this if we debug the memory allocation. */
|
||||
static void
|
||||
do_release_all (void *nodep)
|
||||
{
|
||||
struct __gconv_loaded_object *obj = (struct __gconv_loaded_object *) nodep;
|
||||
|
||||
|
||||
/* Unload the shared object. */
|
||||
if (obj->handle != NULL)
|
||||
__libc_dlclose (obj->handle);
|
||||
|
||||
free (obj);
|
||||
}
|
||||
|
||||
static void __attribute__ ((unused))
|
||||
free_mem (void)
|
||||
{
|
||||
tdestroy (loaded, do_release_all);
|
||||
}
|
||||
text_set_element (__libc_subfreeres, free_mem);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
do_print (const void *nodep, VISIT value, int level)
|
||||
{
|
||||
struct __gconv_loaded_object *obj = *(struct __gconv_loaded_object **) nodep;
|
||||
|
||||
printf ("%10s: \"%s\", %d\n",
|
||||
value == leaf ? "leaf" :
|
||||
value == preorder ? "preorder" :
|
||||
value == postorder ? "postorder" : "endorder",
|
||||
obj->name, obj->counter);
|
||||
}
|
||||
|
||||
static void
|
||||
print_all (void)
|
||||
{
|
||||
__twalk (loaded, do_print);
|
||||
}
|
||||
#endif
|
288
newlib/libc/sys/linux/iconv/gconv_int.h
Normal file
288
newlib/libc/sys/linux/iconv/gconv_int.h
Normal file
@ -0,0 +1,288 @@
|
||||
/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 _GCONV_INT_H
|
||||
#define _GCONV_INT_H 1
|
||||
|
||||
#include "gconv.h"
|
||||
#include <libc-symbols.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
|
||||
/* Type to represent search path. */
|
||||
struct path_elem
|
||||
{
|
||||
const char *name;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/* Variable with search path for `gconv' implementation. */
|
||||
extern struct path_elem *__gconv_path_elem;
|
||||
/* Maximum length of a single path element. */
|
||||
extern size_t __gconv_max_path_elem_len;
|
||||
|
||||
|
||||
/* Structure for alias definition. Simply two strings. */
|
||||
struct gconv_alias
|
||||
{
|
||||
char *fromname;
|
||||
char *toname;
|
||||
};
|
||||
|
||||
|
||||
/* How many character should be conveted in one call? */
|
||||
#define GCONV_NCHAR_GOAL 8160
|
||||
|
||||
|
||||
/* Structure describing one loaded shared object. This normally are
|
||||
objects to perform conversation but as a special case the db shared
|
||||
object is also handled. */
|
||||
struct __gconv_loaded_object
|
||||
{
|
||||
/* Name of the object. It must be the first structure element. */
|
||||
const char *name;
|
||||
|
||||
/* Reference counter for the db functionality. If no conversion is
|
||||
needed we unload the db library. */
|
||||
int counter;
|
||||
|
||||
/* The handle for the shared object. */
|
||||
void *handle;
|
||||
|
||||
/* Pointer to the functions the module defines. */
|
||||
__gconv_fct fct;
|
||||
__gconv_init_fct init_fct;
|
||||
__gconv_end_fct end_fct;
|
||||
};
|
||||
|
||||
|
||||
/* Description for an available conversion module. */
|
||||
struct gconv_module
|
||||
{
|
||||
const char *from_string;
|
||||
const char *to_string;
|
||||
|
||||
int cost_hi;
|
||||
int cost_lo;
|
||||
|
||||
const char *module_name;
|
||||
|
||||
struct gconv_module *left; /* Prefix smaller. */
|
||||
struct gconv_module *same; /* List of entries with identical prefix. */
|
||||
struct gconv_module *right; /* Prefix larger. */
|
||||
};
|
||||
|
||||
|
||||
/* Internal data structure to represent transliteration module. */
|
||||
struct trans_struct
|
||||
{
|
||||
const char *name;
|
||||
struct trans_struct *next;
|
||||
|
||||
const char **csnames;
|
||||
size_t ncsnames;
|
||||
__gconv_trans_fct trans_fct;
|
||||
__gconv_trans_context_fct trans_context_fct;
|
||||
__gconv_trans_init_fct trans_init_fct;
|
||||
__gconv_trans_end_fct trans_end_fct;
|
||||
};
|
||||
|
||||
|
||||
/* Flags for `gconv_open'. */
|
||||
enum
|
||||
{
|
||||
GCONV_AVOID_NOCONV = 1 << 0
|
||||
};
|
||||
|
||||
|
||||
/* Global variables. */
|
||||
|
||||
/* Database of alias names. */
|
||||
extern void *__gconv_alias_db;
|
||||
|
||||
/* Array with available modules. */
|
||||
extern size_t __gconv_nmodules;
|
||||
extern struct gconv_module *__gconv_modules_db;
|
||||
|
||||
/* Value of the GCONV_PATH environment variable. */
|
||||
extern const char *__gconv_path_envvar;
|
||||
|
||||
|
||||
/* The gconv functions expects the name to be in upper case and complete,
|
||||
including the trailing slashes if necessary. */
|
||||
#define norm_add_slashes(str,suffix) \
|
||||
({ \
|
||||
const char *cp = (str); \
|
||||
char *result; \
|
||||
char *tmp; \
|
||||
size_t cnt = 0; \
|
||||
size_t suffix_len = (suffix) == NULL ? 0 : strlen (suffix); \
|
||||
\
|
||||
while (*cp != '\0') \
|
||||
if (*cp++ == '/') \
|
||||
++cnt; \
|
||||
\
|
||||
tmp = result = alloca (cp - (str) + 3 + suffix_len); \
|
||||
cp = (str); \
|
||||
while (*cp != '\0') \
|
||||
*tmp++ = __toupper_l (*cp++, &_nl_C_locobj); \
|
||||
if (cnt < 2) \
|
||||
{ \
|
||||
*tmp++ = '/'; \
|
||||
if (cnt < 1) \
|
||||
{ \
|
||||
*tmp++ = '/'; \
|
||||
if (suffix != NULL) \
|
||||
{ \
|
||||
tmp = memcpy (tmp, suffix, suffix_len); \
|
||||
tmp += suffix_len; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
*tmp = '\0'; \
|
||||
result; \
|
||||
})
|
||||
|
||||
|
||||
/* Return in *HANDLE decriptor for transformation from FROMSET to TOSET. */
|
||||
extern int __gconv_open (const char *toset, const char *fromset,
|
||||
__gconv_t *handle, int flags)
|
||||
internal_function;
|
||||
|
||||
/* Free resources associated with transformation descriptor CD. */
|
||||
extern int __gconv_close (__gconv_t cd)
|
||||
internal_function;
|
||||
|
||||
/* Transform at most *INBYTESLEFT bytes from buffer starting at *INBUF
|
||||
according to rules described by CD and place up to *OUTBYTESLEFT
|
||||
bytes in buffer starting at *OUTBUF. Return number of non-identical
|
||||
conversions in *IRREVERSIBLE if this pointer is not null. */
|
||||
extern int __gconv (__gconv_t cd, const unsigned char **inbuf,
|
||||
const unsigned char *inbufend, unsigned char **outbuf,
|
||||
unsigned char *outbufend, size_t *irreversible)
|
||||
internal_function;
|
||||
|
||||
/* Return in *HANDLE a pointer to an array with *NSTEPS elements describing
|
||||
the single steps necessary for transformation from FROMSET to TOSET. */
|
||||
extern int __gconv_find_transform (const char *toset, const char *fromset,
|
||||
struct __gconv_step **handle,
|
||||
size_t *nsteps, int flags)
|
||||
internal_function;
|
||||
|
||||
/* Search for transformation in cache data. */
|
||||
extern int __gconv_lookup_cache (const char *toset, const char *fromset,
|
||||
struct __gconv_step **handle, size_t *nsteps,
|
||||
int flags)
|
||||
internal_function;
|
||||
|
||||
/* Compare the two name for whether they are after alias expansion the
|
||||
same. This function uses the cache and fails if none is
|
||||
loaded. */
|
||||
extern int __gconv_compare_alias_cache (const char *name1, const char *name2,
|
||||
int *result) internal_function;
|
||||
|
||||
/* Free data associated with a step's structure. */
|
||||
extern void __gconv_release_step (struct __gconv_step *step)
|
||||
internal_function;
|
||||
|
||||
/* Read all the configuration data and cache it. */
|
||||
extern void __gconv_read_conf (void);
|
||||
|
||||
/* Try to read module cache file. */
|
||||
extern int __gconv_load_cache (void) internal_function;
|
||||
|
||||
/* Determine the directories we are looking in. */
|
||||
extern void __gconv_get_path (void);
|
||||
|
||||
/* Comparison function to search alias. */
|
||||
extern int __gconv_alias_compare (const void *p1, const void *p2);
|
||||
|
||||
/* Clear reference to transformation step implementations which might
|
||||
cause the code to be unloaded. */
|
||||
extern int __gconv_close_transform (struct __gconv_step *steps,
|
||||
size_t nsteps)
|
||||
internal_function;
|
||||
|
||||
/* Free all resources allocated for the transformation record when
|
||||
using the cache. */
|
||||
extern void __gconv_release_cache (struct __gconv_step *steps, size_t nsteps)
|
||||
internal_function;
|
||||
|
||||
/* Load shared object named by NAME. If already loaded increment reference
|
||||
count. */
|
||||
extern struct __gconv_loaded_object *__gconv_find_shlib (const char *name)
|
||||
internal_function;
|
||||
|
||||
/* Release shared object. If no further reference is available unload
|
||||
the object. */
|
||||
extern void __gconv_release_shlib (struct __gconv_loaded_object *handle)
|
||||
internal_function;
|
||||
|
||||
/* Fill STEP with information about builtin module with NAME. */
|
||||
extern void __gconv_get_builtin_trans (const char *name,
|
||||
struct __gconv_step *step)
|
||||
internal_function;
|
||||
|
||||
/* Try to load transliteration step module. */
|
||||
extern int __gconv_translit_find (struct trans_struct *trans)
|
||||
internal_function;
|
||||
|
||||
/* Transliteration using the locale's data. */
|
||||
extern int __gconv_transliterate (struct __gconv_step *step,
|
||||
struct __gconv_step_data *step_data,
|
||||
void *trans_data,
|
||||
__const unsigned char *inbufstart,
|
||||
__const unsigned char **inbufp,
|
||||
__const unsigned char *inbufend,
|
||||
unsigned char **outbufstart,
|
||||
size_t *irreversible);
|
||||
|
||||
|
||||
/* Builtin transformations. */
|
||||
#ifdef _LIBC
|
||||
# define __BUILTIN_TRANS(Name) \
|
||||
extern int Name (struct __gconv_step *step, \
|
||||
struct __gconv_step_data *data, \
|
||||
const unsigned char **inbuf, \
|
||||
const unsigned char *inbufend, \
|
||||
unsigned char **outbufstart, size_t *irreversible, \
|
||||
int do_flush, int consume_incomplete)
|
||||
|
||||
__BUILTIN_TRANS (__gconv_transform_ascii_internal);
|
||||
__BUILTIN_TRANS (__gconv_transform_internal_ascii);
|
||||
__BUILTIN_TRANS (__gconv_transform_utf8_internal);
|
||||
__BUILTIN_TRANS (__gconv_transform_internal_utf8);
|
||||
__BUILTIN_TRANS (__gconv_transform_ucs2_internal);
|
||||
__BUILTIN_TRANS (__gconv_transform_internal_ucs2);
|
||||
__BUILTIN_TRANS (__gconv_transform_ucs2reverse_internal);
|
||||
__BUILTIN_TRANS (__gconv_transform_internal_ucs2reverse);
|
||||
__BUILTIN_TRANS (__gconv_transform_internal_ucs4);
|
||||
__BUILTIN_TRANS (__gconv_transform_ucs4_internal);
|
||||
__BUILTIN_TRANS (__gconv_transform_internal_ucs4le);
|
||||
__BUILTIN_TRANS (__gconv_transform_ucs4le_internal);
|
||||
__BUILTIN_TRANS (__gconv_transform_internal_utf16);
|
||||
__BUILTIN_TRANS (__gconv_transform_utf16_internal);
|
||||
# undef __BUITLIN_TRANS
|
||||
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* gconv_int.h */
|
326
newlib/libc/sys/linux/iconv/gconv_open.c
Normal file
326
newlib/libc/sys/linux/iconv/gconv_open.c
Normal file
@ -0,0 +1,326 @@
|
||||
/* Find matching transformation algorithms and initialize steps.
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gconv_int.h>
|
||||
|
||||
int
|
||||
internal_function
|
||||
__gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
|
||||
int flags)
|
||||
{
|
||||
struct __gconv_step *steps;
|
||||
size_t nsteps;
|
||||
__gconv_t result = NULL;
|
||||
size_t cnt = 0;
|
||||
int res;
|
||||
int conv_flags = 0;
|
||||
const char *errhand;
|
||||
const char *ignore;
|
||||
struct trans_struct *trans = NULL;
|
||||
char old_locale[20], *old_locale_p;
|
||||
char *old, *new;
|
||||
size_t len;
|
||||
|
||||
/* Find out whether any error handling method is specified. */
|
||||
errhand = strchr (toset, '/');
|
||||
if (errhand != NULL)
|
||||
errhand = strchr (errhand + 1, '/');
|
||||
if (__builtin_expect (errhand != NULL, 1))
|
||||
{
|
||||
if (*++errhand == '\0')
|
||||
errhand = NULL;
|
||||
else
|
||||
{
|
||||
/* Make copy without the error handling description. */
|
||||
char *newtoset = (char *) alloca (errhand - toset + 1);
|
||||
char *tok;
|
||||
char *ptr;
|
||||
|
||||
newtoset[errhand - toset] = '\0';
|
||||
toset = memcpy (newtoset, toset, errhand - toset);
|
||||
|
||||
/* Find the appropriate transliteration handlers. */
|
||||
old = (char *)(errhand);
|
||||
len = strlen (old) + 1;
|
||||
new = (char *) alloca (len);
|
||||
tok = (char *) memcpy (new, old, len);
|
||||
|
||||
tok = strtok_r (tok, ",", &ptr);
|
||||
|
||||
/* Set locale to default C locale. */
|
||||
old_locale_p = setlocale(LC_ALL, "C");
|
||||
strncpy(old_locale, old_locale_p, 20);
|
||||
|
||||
while (tok != NULL)
|
||||
{
|
||||
if (strcasecmp (tok, "TRANSLIT") == 0)
|
||||
{
|
||||
/* It's the builtin transliteration handling. We only
|
||||
support it for working on the internal encoding. */
|
||||
static const char *internal_trans_names[1] = { "INTERNAL" };
|
||||
struct trans_struct *lastp = NULL;
|
||||
struct trans_struct *runp;
|
||||
|
||||
for (runp = trans; runp != NULL; runp = runp->next)
|
||||
if (runp->trans_fct == __gconv_transliterate)
|
||||
break;
|
||||
else
|
||||
lastp = runp;
|
||||
|
||||
if (runp == NULL)
|
||||
{
|
||||
struct trans_struct *newp;
|
||||
|
||||
newp = (struct trans_struct *) alloca (sizeof (*newp));
|
||||
memset (newp, '\0', sizeof (*newp));
|
||||
|
||||
/* We leave the `name' field zero to signal that
|
||||
this is an internal transliteration step. */
|
||||
newp->csnames = internal_trans_names;
|
||||
newp->ncsnames = 1;
|
||||
newp->trans_fct = __gconv_transliterate;
|
||||
|
||||
if (lastp == NULL)
|
||||
trans = newp;
|
||||
else
|
||||
lastp->next = newp;
|
||||
}
|
||||
}
|
||||
else if (strcasecmp (tok, "IGNORE") == 0)
|
||||
/* Set the flag to ignore all errors. */
|
||||
conv_flags |= __GCONV_IGNORE_ERRORS;
|
||||
else
|
||||
{
|
||||
/* `tok' is possibly a module name. We'll see later
|
||||
whether we can find it. But first see that we do
|
||||
not already a module of this name. */
|
||||
struct trans_struct *lastp = NULL;
|
||||
struct trans_struct *runp;
|
||||
|
||||
for (runp = trans; runp != NULL; runp = runp->next)
|
||||
if (runp->name != NULL
|
||||
&& strcasecmp (tok, runp->name) == 0)
|
||||
break;
|
||||
else
|
||||
lastp = runp;
|
||||
|
||||
if (runp == NULL)
|
||||
{
|
||||
struct trans_struct *newp;
|
||||
|
||||
newp = (struct trans_struct *) alloca (sizeof (*newp));
|
||||
memset (newp, '\0', sizeof (*newp));
|
||||
newp->name = tok;
|
||||
|
||||
if (lastp == NULL)
|
||||
trans = newp;
|
||||
else
|
||||
lastp->next = newp;
|
||||
}
|
||||
}
|
||||
|
||||
tok = strtok_r (NULL, ",", &ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* For the source character set we ignore the error handler specification.
|
||||
XXX Is this really always the best? */
|
||||
ignore = strchr (fromset, '/');
|
||||
if (ignore != NULL && (ignore = strchr (ignore + 1, '/')) != NULL
|
||||
&& *++ignore != '\0')
|
||||
{
|
||||
char *newfromset = (char *) alloca (ignore - fromset + 1);
|
||||
|
||||
newfromset[ignore - fromset] = '\0';
|
||||
fromset = memcpy (newfromset, fromset, ignore - fromset);
|
||||
}
|
||||
|
||||
res = __gconv_find_transform (toset, fromset, &steps, &nsteps, flags);
|
||||
if (res == __GCONV_OK)
|
||||
{
|
||||
/* Find the modules. */
|
||||
struct trans_struct *lastp = NULL;
|
||||
struct trans_struct *runp;
|
||||
|
||||
for (runp = trans; runp != NULL; runp = runp->next)
|
||||
{
|
||||
if (runp->name == NULL
|
||||
|| __builtin_expect (__gconv_translit_find (runp), 0) == 0)
|
||||
lastp = runp;
|
||||
else
|
||||
/* This means we haven't found the module. Remove it. */
|
||||
(lastp == NULL ? trans : lastp->next) = runp->next;
|
||||
}
|
||||
|
||||
/* Allocate room for handle. */
|
||||
result = (__gconv_t) malloc (sizeof (struct __gconv_info)
|
||||
+ (nsteps
|
||||
* sizeof (struct __gconv_step_data)));
|
||||
if (result == NULL)
|
||||
res = __GCONV_NOMEM;
|
||||
else
|
||||
{
|
||||
size_t n;
|
||||
|
||||
/* Remember the list of steps. */
|
||||
result->__steps = steps;
|
||||
result->__nsteps = nsteps;
|
||||
|
||||
/* Clear the array for the step data. */
|
||||
memset (result->__data, '\0',
|
||||
nsteps * sizeof (struct __gconv_step_data));
|
||||
|
||||
/* Call all initialization functions for the transformation
|
||||
step implementations. */
|
||||
for (cnt = 0; cnt < nsteps; ++cnt)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
/* Would have to be done if we would not clear the whole
|
||||
array above. */
|
||||
#if 0
|
||||
/* Reset the counter. */
|
||||
result->__data[cnt].__invocation_counter = 0;
|
||||
|
||||
/* It's a regular use. */
|
||||
result->__data[cnt].__internal_use = 0;
|
||||
#endif
|
||||
|
||||
/* We use the `mbstate_t' member in DATA. */
|
||||
result->__data[cnt].__statep = &result->__data[cnt].__state;
|
||||
|
||||
/* Now see whether we can use any of the transliteration
|
||||
modules for this step. */
|
||||
for (runp = trans; runp != NULL; runp = runp->next)
|
||||
for (n = 0; n < runp->ncsnames; ++n)
|
||||
if (strcasecmp (steps[cnt].__from_name, runp->csnames[n]) == 0)
|
||||
{
|
||||
void *data = NULL;
|
||||
|
||||
/* Match! Now try the initializer. */
|
||||
if (runp->trans_init_fct == NULL
|
||||
|| (runp->trans_init_fct (&data,
|
||||
steps[cnt].__to_name)
|
||||
== __GCONV_OK))
|
||||
{
|
||||
/* Append at the end of the list. */
|
||||
struct __gconv_trans_data *newp;
|
||||
struct __gconv_trans_data **lastp;
|
||||
|
||||
newp = (struct __gconv_trans_data *)
|
||||
malloc (sizeof (struct __gconv_trans_data));
|
||||
if (newp == NULL)
|
||||
{
|
||||
res = __GCONV_NOMEM;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
newp->__trans_fct = runp->trans_fct;
|
||||
newp->__trans_context_fct = runp->trans_context_fct;
|
||||
newp->__trans_end_fct = runp->trans_end_fct;
|
||||
newp->__data = data;
|
||||
newp->__next = NULL;
|
||||
|
||||
lastp = &result->__data[cnt].__trans;
|
||||
while (*lastp != NULL)
|
||||
lastp = &(*lastp)->__next;
|
||||
|
||||
*lastp = newp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* If this is the last step we must not allocate an
|
||||
output buffer. */
|
||||
if (cnt < nsteps - 1)
|
||||
{
|
||||
result->__data[cnt].__flags = conv_flags;
|
||||
|
||||
/* Allocate the buffer. */
|
||||
size = (GCONV_NCHAR_GOAL * steps[cnt].__max_needed_to);
|
||||
|
||||
result->__data[cnt].__outbuf = (char *) malloc (size);
|
||||
if (result->__data[cnt].__outbuf == NULL)
|
||||
{
|
||||
res = __GCONV_NOMEM;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
result->__data[cnt].__outbufend =
|
||||
result->__data[cnt].__outbuf + size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Handle the last entry. */
|
||||
result->__data[cnt].__flags = conv_flags | __GCONV_IS_LAST;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (res != __GCONV_OK)
|
||||
{
|
||||
/* Something went wrong. Free all the resources. */
|
||||
int serrno;
|
||||
bail:
|
||||
serrno = errno;
|
||||
|
||||
if (result != NULL)
|
||||
{
|
||||
while (cnt-- > 0)
|
||||
{
|
||||
struct __gconv_trans_data *transp;
|
||||
|
||||
transp = result->__data[cnt].__trans;
|
||||
while (transp != NULL)
|
||||
{
|
||||
struct __gconv_trans_data *curp = transp;
|
||||
transp = transp->__next;
|
||||
|
||||
if (__builtin_expect (curp->__trans_end_fct != NULL, 0))
|
||||
curp->__trans_end_fct (curp->__data);
|
||||
|
||||
free (curp);
|
||||
}
|
||||
|
||||
free (result->__data[cnt].__outbuf);
|
||||
}
|
||||
|
||||
free (result);
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
__gconv_close_transform (steps, nsteps);
|
||||
|
||||
__set_errno (serrno);
|
||||
}
|
||||
}
|
||||
|
||||
*handle = result;
|
||||
setlocale(LC_ALL, old_locale);
|
||||
return res;
|
||||
}
|
1327
newlib/libc/sys/linux/iconv/gconv_simple.c
Normal file
1327
newlib/libc/sys/linux/iconv/gconv_simple.c
Normal file
File diff suppressed because it is too large
Load Diff
230
newlib/libc/sys/linux/iconv/gconv_trans.c
Normal file
230
newlib/libc/sys/linux/iconv/gconv_trans.c
Normal file
@ -0,0 +1,230 @@
|
||||
/* Transliteration using the locale's data.
|
||||
Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <search.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <ltdl.h>
|
||||
|
||||
#include "gconv_int.h"
|
||||
#include "localeinfo.h"
|
||||
|
||||
int
|
||||
__gconv_transliterate (struct __gconv_step *step,
|
||||
struct __gconv_step_data *step_data,
|
||||
void *trans_data __attribute__ ((unused)),
|
||||
const unsigned char *inbufstart,
|
||||
const unsigned char **inbufp,
|
||||
const unsigned char *inbufend,
|
||||
unsigned char **outbufstart, size_t *irreversible)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Structure to represent results of found (or not) transliteration
|
||||
modules. */
|
||||
struct known_trans
|
||||
{
|
||||
/* This structure must remain the first member. */
|
||||
struct trans_struct info;
|
||||
|
||||
char *fname;
|
||||
void *handle;
|
||||
int open_count;
|
||||
};
|
||||
|
||||
|
||||
/* Tree with results of previous calls to __gconv_translit_find. */
|
||||
static void *search_tree;
|
||||
|
||||
/* We modify global data. */
|
||||
__LOCK_INIT(static, lock);
|
||||
|
||||
/* Compare two transliteration entries. */
|
||||
static int
|
||||
trans_compare (const void *p1, const void *p2)
|
||||
{
|
||||
const struct known_trans *s1 = (const struct known_trans *) p1;
|
||||
const struct known_trans *s2 = (const struct known_trans *) p2;
|
||||
|
||||
return strcmp (s1->info.name, s2->info.name);
|
||||
}
|
||||
|
||||
|
||||
/* Open (maybe reopen) the module named in the struct. Get the function
|
||||
and data structure pointers we need. */
|
||||
static int
|
||||
open_translit (struct known_trans *trans)
|
||||
{
|
||||
__gconv_trans_query_fct queryfct;
|
||||
|
||||
trans->handle = __libc_dlopen (trans->fname);
|
||||
if (trans->handle == NULL)
|
||||
/* Not available. */
|
||||
return 1;
|
||||
|
||||
/* Find the required symbol. */
|
||||
queryfct = __libc_dlsym (trans->handle, "gconv_trans_context");
|
||||
if (queryfct == NULL)
|
||||
{
|
||||
/* We cannot live with that. */
|
||||
close_and_out:
|
||||
__libc_dlclose (trans->handle);
|
||||
trans->handle = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the context. */
|
||||
if (queryfct (trans->info.name, &trans->info.csnames, &trans->info.ncsnames)
|
||||
!= 0)
|
||||
goto close_and_out;
|
||||
|
||||
/* Of course we also have to have the actual function. */
|
||||
trans->info.trans_fct = __libc_dlsym (trans->handle, "gconv_trans");
|
||||
if (trans->info.trans_fct == NULL)
|
||||
goto close_and_out;
|
||||
|
||||
/* Now the optional functions. */
|
||||
trans->info.trans_init_fct =
|
||||
__libc_dlsym (trans->handle, "gconv_trans_init");
|
||||
trans->info.trans_context_fct =
|
||||
__libc_dlsym (trans->handle, "gconv_trans_context");
|
||||
trans->info.trans_end_fct =
|
||||
__libc_dlsym (trans->handle, "gconv_trans_end");
|
||||
|
||||
trans->open_count = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
__gconv_translit_find (struct trans_struct *trans)
|
||||
{
|
||||
struct known_trans **found;
|
||||
const struct path_elem *runp;
|
||||
int res = 1;
|
||||
|
||||
/* We have to have a name. */
|
||||
assert (trans->name != NULL);
|
||||
|
||||
/* Acquire the lock. */
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_acquire(lock);
|
||||
#endif
|
||||
|
||||
/* See whether we know this module already. */
|
||||
found = tfind (trans, &search_tree, trans_compare);
|
||||
if (found != NULL)
|
||||
{
|
||||
/* Is this module available? */
|
||||
if ((*found)->handle != NULL)
|
||||
{
|
||||
/* Maybe we have to reopen the file. */
|
||||
if ((*found)->handle != (void *) -1)
|
||||
/* The object is not unloaded. */
|
||||
res = 0;
|
||||
else if (open_translit (*found) == 0)
|
||||
{
|
||||
/* Copy the data. */
|
||||
*trans = (*found)->info;
|
||||
(*found)->open_count++;
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t name_len = strlen (trans->name) + 1;
|
||||
int need_so = 0;
|
||||
struct known_trans *newp;
|
||||
|
||||
/* We have to continue looking for the module. */
|
||||
if (__gconv_path_elem == NULL)
|
||||
__gconv_get_path ();
|
||||
|
||||
/* See whether we have to append .so. */
|
||||
if (name_len <= 4 || memcmp (&trans->name[name_len - 4], ".so", 3) != 0)
|
||||
need_so = 1;
|
||||
|
||||
/* Create a new entry. */
|
||||
newp = (struct known_trans *) malloc (sizeof (struct known_trans)
|
||||
+ (__gconv_max_path_elem_len
|
||||
+ name_len + 3)
|
||||
+ name_len);
|
||||
if (newp != NULL)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
/* Clear the struct. */
|
||||
memset (newp, '\0', sizeof (struct known_trans));
|
||||
|
||||
/* Store a copy of the module name. */
|
||||
newp->info.name = cp = (char *) (newp + 1);
|
||||
cp = memcpy (cp, trans->name, name_len);
|
||||
cp += name_len;
|
||||
|
||||
newp->fname = cp;
|
||||
|
||||
/* Search in all the directories. */
|
||||
for (runp = __gconv_path_elem; runp->name != NULL; ++runp)
|
||||
{
|
||||
strcpy ((char *) newp->fname, runp->name);
|
||||
while(newp->fname != '\0') newp->fname++;
|
||||
|
||||
cp = memcpy (newp->fname,
|
||||
trans->name, name_len);
|
||||
cp += name_len;
|
||||
if (need_so)
|
||||
memcpy (cp, ".so", sizeof (".so"));
|
||||
|
||||
if (open_translit (newp) == 0)
|
||||
{
|
||||
/* We found a module. */
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res)
|
||||
newp->fname = NULL;
|
||||
|
||||
/* In any case we'll add the entry to our search tree. */
|
||||
if (tsearch (newp, &search_tree, trans_compare) == NULL)
|
||||
{
|
||||
/* Yickes, this should not happen. Unload the object. */
|
||||
res = 1;
|
||||
/* XXX unload here. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_DD_LOCK
|
||||
__lock_release(lock);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
60
newlib/libc/sys/linux/iconv/hash-string.h
Normal file
60
newlib/libc/sys/linux/iconv/hash-string.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* Implements a string hashing function.
|
||||
Copyright (C) 1995, 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. */
|
||||
|
||||
/* @@ end of prolog @@ */
|
||||
|
||||
#ifndef PARAMS
|
||||
# if __STDC__
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* We assume to have `unsigned long int' value with at least 32 bits. */
|
||||
#define HASHWORDBITS 32
|
||||
|
||||
|
||||
/* Defines the so called `hashpjw' function by P.J. Weinberger
|
||||
[see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
|
||||
1986, 1987 Bell Telephone Laboratories, Inc.] */
|
||||
static unsigned long int hash_string PARAMS ((const char *__str_param));
|
||||
|
||||
static inline unsigned long int
|
||||
hash_string (str_param)
|
||||
const char *str_param;
|
||||
{
|
||||
unsigned long int hval, g;
|
||||
const char *str = str_param;
|
||||
|
||||
/* Compute the hash value for the given string. */
|
||||
hval = 0;
|
||||
while (*str != '\0')
|
||||
{
|
||||
hval <<= 4;
|
||||
hval += (unsigned long int) *str++;
|
||||
g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
|
||||
if (g != 0)
|
||||
{
|
||||
hval ^= g >> (HASHWORDBITS - 8);
|
||||
hval ^= g;
|
||||
}
|
||||
}
|
||||
return hval;
|
||||
}
|
96
newlib/libc/sys/linux/iconv/iconv.c
Normal file
96
newlib/libc/sys/linux/iconv/iconv.c
Normal file
@ -0,0 +1,96 @@
|
||||
/* Convert characters in input buffer using conversion descriptor to
|
||||
output buffer.
|
||||
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <stddef.h> /* for NULL */
|
||||
#include <errno.h>
|
||||
#include <iconv.h>
|
||||
|
||||
#include <gconv_int.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
size_t
|
||||
iconv (iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf,
|
||||
size_t *outbytesleft)
|
||||
{
|
||||
__gconv_t gcd = (__gconv_t) cd;
|
||||
char *outstart = outbuf ? *outbuf : NULL;
|
||||
size_t irreversible;
|
||||
int result;
|
||||
|
||||
if (__builtin_expect (inbuf == NULL || *inbuf == NULL, 0))
|
||||
{
|
||||
if (outbuf == NULL || *outbuf == NULL)
|
||||
result = __gconv (gcd, NULL, NULL, NULL, NULL, &irreversible);
|
||||
else
|
||||
result = __gconv (gcd, NULL, NULL, (unsigned char **) outbuf,
|
||||
(unsigned char *) (outstart + *outbytesleft),
|
||||
&irreversible);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *instart = *inbuf;
|
||||
|
||||
result = __gconv (gcd, (const unsigned char **) inbuf,
|
||||
(const unsigned char *) (*inbuf + *inbytesleft),
|
||||
(unsigned char **) outbuf,
|
||||
(unsigned char *) (*outbuf + *outbytesleft),
|
||||
&irreversible);
|
||||
|
||||
*inbytesleft -= *inbuf - instart;
|
||||
}
|
||||
if (outstart != NULL)
|
||||
*outbytesleft -= *outbuf - outstart;
|
||||
|
||||
switch (__builtin_expect (result, __GCONV_OK))
|
||||
{
|
||||
case __GCONV_ILLEGAL_DESCRIPTOR:
|
||||
__set_errno (EBADF);
|
||||
irreversible = (size_t) -1L;
|
||||
break;
|
||||
|
||||
case __GCONV_ILLEGAL_INPUT:
|
||||
__set_errno (EILSEQ);
|
||||
irreversible = (size_t) -1L;
|
||||
break;
|
||||
|
||||
case __GCONV_FULL_OUTPUT:
|
||||
__set_errno (E2BIG);
|
||||
irreversible = (size_t) -1L;
|
||||
break;
|
||||
|
||||
case __GCONV_INCOMPLETE_INPUT:
|
||||
__set_errno (EINVAL);
|
||||
irreversible = (size_t) -1L;
|
||||
break;
|
||||
|
||||
case __GCONV_EMPTY_INPUT:
|
||||
case __GCONV_OK:
|
||||
/* Nothing. */
|
||||
break;
|
||||
|
||||
default:
|
||||
assert (!"Nothing like this should happen");
|
||||
}
|
||||
|
||||
return irreversible;
|
||||
}
|
51
newlib/libc/sys/linux/iconv/iconv.h
Normal file
51
newlib/libc/sys/linux/iconv/iconv.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* 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 _ICONV_H
|
||||
#define _ICONV_H 1
|
||||
|
||||
#include <features.h>
|
||||
#define __need_size_t
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
__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. */
|
||||
extern iconv_t iconv_open (__const char *__tocode, __const char *__fromcode)
|
||||
__THROW;
|
||||
|
||||
/* 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. */
|
||||
extern int iconv_close (iconv_t __cd) __THROW;
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* iconv.h */
|
563
newlib/libc/sys/linux/iconv/iconv_charmap.c
Normal file
563
newlib/libc/sys/linux/iconv/iconv_charmap.c
Normal file
@ -0,0 +1,563 @@
|
||||
/* Convert using charmaps and possibly iconv().
|
||||
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <fcntl.h>
|
||||
#include <iconv.h>
|
||||
#include <libintl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "iconv_prog.h"
|
||||
|
||||
|
||||
/* Prototypes for a few program-wide used functions. */
|
||||
extern void *xmalloc (size_t __n);
|
||||
extern void *xcalloc (size_t __n, size_t __s);
|
||||
|
||||
|
||||
struct convtable
|
||||
{
|
||||
int term[256 / 8];
|
||||
union
|
||||
{
|
||||
struct convtable *sub;
|
||||
struct charseq *out;
|
||||
} val[256];
|
||||
};
|
||||
|
||||
|
||||
static inline struct convtable *
|
||||
allocate_table (void)
|
||||
{
|
||||
return (struct convtable *) xcalloc (1, sizeof (struct convtable));
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
is_term (struct convtable *tbl, unsigned int idx)
|
||||
{
|
||||
return tbl->term[idx / 8] & (1 << (idx % 8));
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
clear_term (struct convtable *tbl, unsigned int idx)
|
||||
{
|
||||
tbl->term[idx / 8] &= ~(1 << (idx % 8));
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
set_term (struct convtable *tbl, unsigned int idx)
|
||||
{
|
||||
tbl->term[idx / 8] |= 1 << (idx % 8);
|
||||
}
|
||||
|
||||
|
||||
/* Generate the conversion table. */
|
||||
static struct convtable *use_from_charmap (struct charmap_t *from_charmap,
|
||||
const char *to_code);
|
||||
static struct convtable *use_to_charmap (const char *from_code,
|
||||
struct charmap_t *to_charmap);
|
||||
static struct convtable *use_both_charmaps (struct charmap_t *from_charmap,
|
||||
struct charmap_t *to_charmap);
|
||||
|
||||
/* Prototypes for the functions doing the actual work. */
|
||||
static int process_block (struct convtable *tbl, char *addr, size_t len,
|
||||
FILE *output);
|
||||
static int process_fd (struct convtable *tbl, int fd, FILE *output);
|
||||
static int process_file (struct convtable *tbl, FILE *input, FILE *output);
|
||||
|
||||
|
||||
int
|
||||
charmap_conversion (const char *from_code, struct charmap_t *from_charmap,
|
||||
const char *to_code, struct charmap_t *to_charmap,
|
||||
int argc, int remaining, char *argv[], FILE *output)
|
||||
{
|
||||
struct convtable *cvtbl;
|
||||
int status = EXIT_SUCCESS;
|
||||
|
||||
/* We have three different cases to handle:
|
||||
|
||||
- both, from_charmap and to_charmap, are available. This means we
|
||||
can assume that the symbolic names match and use them to create
|
||||
the mapping.
|
||||
|
||||
- only from_charmap is available. In this case we can only hope that
|
||||
the symbolic names used are of the <Uxxxx> form in which case we
|
||||
can use a UCS4->"to_code" iconv() conversion for the second step.
|
||||
|
||||
- only to_charmap is available. This is similar, only that we would
|
||||
use iconv() for the "to_code"->UCS4 conversion.
|
||||
|
||||
We first create a table which maps input bytes into output bytes.
|
||||
Once this is done we can handle all three of the cases above
|
||||
equally. */
|
||||
if (from_charmap != NULL)
|
||||
{
|
||||
if (to_charmap == NULL)
|
||||
cvtbl = use_from_charmap (from_charmap, to_code);
|
||||
else
|
||||
cvtbl = use_both_charmaps (from_charmap, to_charmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (to_charmap != NULL);
|
||||
cvtbl = use_to_charmap (from_code, to_charmap);
|
||||
}
|
||||
|
||||
/* If we couldn't generate a table stop now. */
|
||||
if (cvtbl == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
/* We can now start the conversion. */
|
||||
if (remaining == argc)
|
||||
{
|
||||
if (process_file (cvtbl, stdin, output) != 0)
|
||||
status = EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
do
|
||||
{
|
||||
struct stat st;
|
||||
char *addr;
|
||||
int fd;
|
||||
|
||||
if (verbose)
|
||||
printf ("%s:\n", argv[remaining]);
|
||||
if (strcmp (argv[remaining], "-") == 0)
|
||||
fd = 0;
|
||||
else
|
||||
{
|
||||
fd = open (argv[remaining], O_RDONLY);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
error (0, errno, _("cannot open input file `%s'"),
|
||||
argv[remaining]);
|
||||
status = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _POSIX_MAPPED_FILES
|
||||
/* We have possibilities for reading the input file. First try
|
||||
to mmap() it since this will provide the fastest solution. */
|
||||
if (fstat (fd, &st) == 0
|
||||
&& ((addr = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE,
|
||||
fd, 0)) != MAP_FAILED))
|
||||
{
|
||||
/* Yes, we can use mmap(). The descriptor is not needed
|
||||
anymore. */
|
||||
if (close (fd) != 0)
|
||||
error (EXIT_FAILURE, errno,
|
||||
_("error while closing input `%s'"), argv[remaining]);
|
||||
|
||||
if (process_block (cvtbl, addr, st.st_size, output) < 0)
|
||||
{
|
||||
/* Something went wrong. */
|
||||
status = EXIT_FAILURE;
|
||||
|
||||
/* We don't need the input data anymore. */
|
||||
munmap ((void *) addr, st.st_size);
|
||||
|
||||
/* We cannot go on with producing output since it might
|
||||
lead to problem because the last output might leave
|
||||
the output stream in an undefined state. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* We don't need the input data anymore. */
|
||||
munmap ((void *) addr, st.st_size);
|
||||
}
|
||||
else
|
||||
#endif /* _POSIX_MAPPED_FILES */
|
||||
{
|
||||
/* Read the file in pieces. */
|
||||
if (process_fd (cvtbl, fd, output) != 0)
|
||||
{
|
||||
/* Something went wrong. */
|
||||
status = EXIT_FAILURE;
|
||||
|
||||
/* We don't need the input file anymore. */
|
||||
close (fd);
|
||||
|
||||
/* We cannot go on with producing output since it might
|
||||
lead to problem because the last output might leave
|
||||
the output stream in an undefined state. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now close the file. */
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
while (++remaining < argc);
|
||||
|
||||
/* All done. */
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_bytes (struct convtable *tbl, struct charseq *in, struct charseq *out)
|
||||
{
|
||||
int n = 0;
|
||||
unsigned int byte;
|
||||
|
||||
assert (in->nbytes > 0);
|
||||
|
||||
byte = ((unsigned char *) in->bytes)[n];
|
||||
while (n + 1 < in->nbytes)
|
||||
{
|
||||
if (is_term (tbl, byte) || tbl->val[byte].sub == NULL)
|
||||
{
|
||||
/* Note that we simply ignore a definition for a byte sequence
|
||||
which is also the prefix for a longer one. */
|
||||
clear_term (tbl, byte);
|
||||
tbl->val[byte].sub =
|
||||
(struct convtable *) xcalloc (1, sizeof (struct convtable));
|
||||
}
|
||||
|
||||
tbl = tbl->val[byte].sub;
|
||||
|
||||
byte = ((unsigned char *) in->bytes)[++n];
|
||||
}
|
||||
|
||||
/* Only add the new sequence if there is none yet and the byte sequence
|
||||
is not part of an even longer one. */
|
||||
if (! is_term (tbl, byte) && tbl->val[byte].sub == NULL)
|
||||
{
|
||||
set_term (tbl, byte);
|
||||
tbl->val[byte].out = out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct convtable *
|
||||
use_from_charmap (struct charmap_t *from_charmap, const char *to_code)
|
||||
{
|
||||
/* We iterate over all entries in the from_charmap and for those which
|
||||
have a known UCS4 representation we use an iconv() call to determine
|
||||
the mapping to the to_code charset. */
|
||||
struct convtable *rettbl;
|
||||
iconv_t cd;
|
||||
void *ptr = NULL;
|
||||
const void *key;
|
||||
size_t keylen;
|
||||
void *data;
|
||||
|
||||
cd = iconv_open (to_code, "WCHAR_T");
|
||||
if (cd == (iconv_t) -1)
|
||||
/* We cannot do anything. */
|
||||
return NULL;
|
||||
|
||||
rettbl = allocate_table ();
|
||||
|
||||
while (iterate_table (&from_charmap->char_table, &ptr, &key, &keylen, &data)
|
||||
>= 0)
|
||||
{
|
||||
struct charseq *in = (struct charseq *) data;
|
||||
|
||||
if (in->ucs4 != UNINITIALIZED_CHAR_VALUE)
|
||||
{
|
||||
/* There is a chance. Try the iconv module. */
|
||||
wchar_t inbuf[1] = { in->ucs4 };
|
||||
unsigned char outbuf[64];
|
||||
char *inptr = (char *) inbuf;
|
||||
size_t inlen = sizeof (inbuf);
|
||||
char *outptr = (char *) outbuf;
|
||||
size_t outlen = sizeof (outbuf);
|
||||
|
||||
(void) iconv (cd, &inptr, &inlen, &outptr, &outlen);
|
||||
|
||||
if (outptr != (char *) outbuf)
|
||||
{
|
||||
/* We got some output. Good, use it. */
|
||||
struct charseq *newp;
|
||||
|
||||
outlen = sizeof (outbuf) - outlen;
|
||||
assert ((char *) outbuf + outlen == outptr);
|
||||
|
||||
newp = (struct charseq *) xmalloc (sizeof (struct charseq)
|
||||
+ outlen);
|
||||
newp->name = in->name;
|
||||
newp->ucs4 = in->ucs4;
|
||||
newp->nbytes = outlen;
|
||||
memcpy (newp->bytes, outbuf, outlen);
|
||||
|
||||
add_bytes (rettbl, in, newp);
|
||||
}
|
||||
|
||||
/* Clear any possible state left behind. */
|
||||
(void) iconv (cd, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
iconv_close (cd);
|
||||
|
||||
return rettbl;
|
||||
}
|
||||
|
||||
|
||||
static struct convtable *
|
||||
use_to_charmap (const char *from_code, struct charmap_t *to_charmap)
|
||||
{
|
||||
/* We iterate over all entries in the to_charmap and for those which
|
||||
have a known UCS4 representation we use an iconv() call to determine
|
||||
the mapping to the from_code charset. */
|
||||
struct convtable *rettbl;
|
||||
iconv_t cd;
|
||||
void *ptr = NULL;
|
||||
const void *key;
|
||||
size_t keylen;
|
||||
void *data;
|
||||
|
||||
/* Note that the conversion we use here is the reverse direction. Without
|
||||
exhaustive search we cannot figure out which input yields the UCS4
|
||||
character we are looking for. Therefore we determine it the other
|
||||
way round. */
|
||||
cd = iconv_open (from_code, "WCHAR_T");
|
||||
if (cd == (iconv_t) -1)
|
||||
/* We cannot do anything. */
|
||||
return NULL;
|
||||
|
||||
rettbl = allocate_table ();
|
||||
|
||||
while (iterate_table (&to_charmap->char_table, &ptr, &key, &keylen, &data)
|
||||
>= 0)
|
||||
{
|
||||
struct charseq *out = (struct charseq *) data;
|
||||
|
||||
if (out->ucs4 != UNINITIALIZED_CHAR_VALUE)
|
||||
{
|
||||
/* There is a chance. Try the iconv module. */
|
||||
wchar_t inbuf[1] = { out->ucs4 };
|
||||
unsigned char outbuf[64];
|
||||
char *inptr = (char *) inbuf;
|
||||
size_t inlen = sizeof (inbuf);
|
||||
char *outptr = (char *) outbuf;
|
||||
size_t outlen = sizeof (outbuf);
|
||||
|
||||
(void) iconv (cd, &inptr, &inlen, &outptr, &outlen);
|
||||
|
||||
if (outptr != (char *) outbuf)
|
||||
{
|
||||
/* We got some output. Good, use it. */
|
||||
struct charseq *newp;
|
||||
|
||||
outlen = sizeof (outbuf) - outlen;
|
||||
assert ((char *) outbuf + outlen == outptr);
|
||||
|
||||
newp = (struct charseq *) xmalloc (sizeof (struct charseq)
|
||||
+ outlen);
|
||||
newp->name = out->name;
|
||||
newp->ucs4 = out->ucs4;
|
||||
newp->nbytes = outlen;
|
||||
memcpy (newp->bytes, outbuf, outlen);
|
||||
|
||||
add_bytes (rettbl, newp, out);
|
||||
}
|
||||
|
||||
/* Clear any possible state left behind. */
|
||||
(void) iconv (cd, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
iconv_close (cd);
|
||||
|
||||
return rettbl;
|
||||
}
|
||||
|
||||
|
||||
static struct convtable *
|
||||
use_both_charmaps (struct charmap_t *from_charmap,
|
||||
struct charmap_t *to_charmap)
|
||||
{
|
||||
/* In this case we iterate over all the entries in the from_charmap,
|
||||
determine the internal name, and find an appropriate entry in the
|
||||
to_charmap (if it exists). */
|
||||
struct convtable *rettbl = allocate_table ();
|
||||
void *ptr = NULL;
|
||||
const void *key;
|
||||
size_t keylen;
|
||||
void *data;
|
||||
|
||||
while (iterate_table (&from_charmap->char_table, &ptr, &key, &keylen, &data)
|
||||
>= 0)
|
||||
{
|
||||
struct charseq *in = (struct charseq *) data;
|
||||
struct charseq *out = charmap_find_value (to_charmap, key, keylen);
|
||||
|
||||
if (out != NULL)
|
||||
add_bytes (rettbl, in, out);
|
||||
}
|
||||
|
||||
return rettbl;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_block (struct convtable *tbl, char *addr, size_t len, FILE *output)
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
while (n < len)
|
||||
{
|
||||
struct convtable *cur = tbl;
|
||||
unsigned char *curp = (unsigned char *) addr;
|
||||
unsigned int byte = *curp;
|
||||
int cnt;
|
||||
struct charseq *out;
|
||||
|
||||
while (! is_term (cur, byte))
|
||||
if (cur->val[byte].sub == NULL)
|
||||
{
|
||||
/* This is a invalid sequence. Skip the first byte if we are
|
||||
ignoring errors. Otherwise punt. */
|
||||
if (! omit_invalid)
|
||||
{
|
||||
error (0, 0, _("illegal input sequence at position %Zd"), n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
n -= curp - (unsigned char *) addr;
|
||||
|
||||
byte = *(curp = (unsigned char *) ++addr);
|
||||
if (++n >= len)
|
||||
/* All converted. */
|
||||
return 0;
|
||||
|
||||
cur = tbl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur = cur->val[byte].sub;
|
||||
|
||||
if (++n >= len)
|
||||
{
|
||||
error (0, 0, _("\
|
||||
incomplete character or shift sequence at end of buffer"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
byte = *++curp;
|
||||
}
|
||||
|
||||
/* We found a final byte. Write the output bytes. */
|
||||
out = cur->val[byte].out;
|
||||
for (cnt = 0; cnt < out->nbytes; ++cnt)
|
||||
fputc_unlocked (out->bytes[cnt], output);
|
||||
|
||||
addr = (char *) curp + 1;
|
||||
++n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_fd (struct convtable *tbl, int fd, FILE *output)
|
||||
{
|
||||
/* we have a problem with reading from a desriptor since we must not
|
||||
provide the iconv() function an incomplete character or shift
|
||||
sequence at the end of the buffer. Since we have to deal with
|
||||
arbitrary encodings we must read the whole text in a buffer and
|
||||
process it in one step. */
|
||||
static char *inbuf = NULL;
|
||||
static size_t maxlen = 0;
|
||||
char *inptr = NULL;
|
||||
size_t actlen = 0;
|
||||
|
||||
while (actlen < maxlen)
|
||||
{
|
||||
ssize_t n = read (fd, inptr, maxlen - actlen);
|
||||
|
||||
if (n == 0)
|
||||
/* No more text to read. */
|
||||
break;
|
||||
|
||||
if (n == -1)
|
||||
{
|
||||
/* Error while reading. */
|
||||
error (0, errno, _("error while reading the input"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
inptr += n;
|
||||
actlen += n;
|
||||
}
|
||||
|
||||
if (actlen == maxlen)
|
||||
while (1)
|
||||
{
|
||||
ssize_t n;
|
||||
|
||||
/* Increase the buffer. */
|
||||
maxlen += 32768;
|
||||
inbuf = realloc (inbuf, maxlen);
|
||||
if (inbuf == NULL)
|
||||
error (0, errno, _("unable to allocate buffer for input"));
|
||||
inptr = inbuf + actlen;
|
||||
|
||||
do
|
||||
{
|
||||
n = read (fd, inptr, maxlen - actlen);
|
||||
|
||||
if (n == 0)
|
||||
/* No more text to read. */
|
||||
break;
|
||||
|
||||
if (n == -1)
|
||||
{
|
||||
/* Error while reading. */
|
||||
error (0, errno, _("error while reading the input"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
inptr += n;
|
||||
actlen += n;
|
||||
}
|
||||
while (actlen < maxlen);
|
||||
|
||||
if (n == 0)
|
||||
/* Break again so we leave both loops. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now we have all the input in the buffer. Process it in one run. */
|
||||
return process_block (tbl, inbuf, actlen, output);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_file (struct convtable *tbl, FILE *input, FILE *output)
|
||||
{
|
||||
/* This should be safe since we use this function only for `stdin' and
|
||||
we haven't read anything so far. */
|
||||
return process_fd (tbl, fileno (input), output);
|
||||
}
|
37
newlib/libc/sys/linux/iconv/iconv_close.c
Normal file
37
newlib/libc/sys/linux/iconv/iconv_close.c
Normal file
@ -0,0 +1,37 @@
|
||||
/* Release any resource associated with given conversion descriptor.
|
||||
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <errno.h>
|
||||
#include <iconv.h>
|
||||
|
||||
#include <gconv_int.h>
|
||||
|
||||
|
||||
int
|
||||
iconv_close (iconv_t cd)
|
||||
{
|
||||
if (__builtin_expect (cd == (iconv_t *) -1L, 0))
|
||||
{
|
||||
__set_errno (EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return __gconv_close ((__gconv_t) cd) ? -1 : 0;
|
||||
}
|
65
newlib/libc/sys/linux/iconv/iconv_open.c
Normal file
65
newlib/libc/sys/linux/iconv/iconv_open.c
Normal file
@ -0,0 +1,65 @@
|
||||
/* Get descriptor for character set conversion.
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 <errno.h>
|
||||
#include <iconv.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gconv_int.h>
|
||||
#include "gconv_charset.h"
|
||||
|
||||
|
||||
iconv_t
|
||||
iconv_open (const char *tocode, const char *fromcode)
|
||||
{
|
||||
char *tocode_conv;
|
||||
char *fromcode_conv;
|
||||
size_t tocode_len;
|
||||
size_t fromcode_len;
|
||||
__gconv_t cd;
|
||||
int res;
|
||||
|
||||
/* Normalize the name. We remove all characters beside alpha-numeric,
|
||||
'_', '-', '/', and '.'. */
|
||||
tocode_len = strlen (tocode);
|
||||
tocode_conv = alloca (tocode_len + 3);
|
||||
strip (tocode_conv, tocode);
|
||||
tocode = tocode_conv[2] == '\0' ? upstr (tocode_conv, tocode) : tocode_conv;
|
||||
|
||||
fromcode_len = strlen (fromcode);
|
||||
fromcode_conv = alloca (fromcode_len + 3);
|
||||
strip (fromcode_conv, fromcode);
|
||||
fromcode = (fromcode_conv[2] == '\0'
|
||||
? upstr (fromcode_conv, fromcode) : fromcode_conv);
|
||||
|
||||
res = __gconv_open (tocode, fromcode, &cd, 0);
|
||||
|
||||
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
|
||||
{
|
||||
/* We must set the error number according to the specs. */
|
||||
if (res == __GCONV_NOCONV || res == __GCONV_NODB)
|
||||
__set_errno (EINVAL);
|
||||
|
||||
return (iconv_t) -1;
|
||||
}
|
||||
|
||||
return (iconv_t) cd;
|
||||
}
|
1176
newlib/libc/sys/linux/iconv/iconvconfig.c
Normal file
1176
newlib/libc/sys/linux/iconv/iconvconfig.c
Normal file
File diff suppressed because it is too large
Load Diff
67
newlib/libc/sys/linux/iconv/iconvconfig.h
Normal file
67
newlib/libc/sys/linux/iconv/iconvconfig.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
|
||||
|
||||
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 <stdint.h>
|
||||
|
||||
|
||||
typedef uint16_t gidx_t;
|
||||
|
||||
|
||||
struct gconvcache_header
|
||||
{
|
||||
uint32_t magic;
|
||||
gidx_t string_offset;
|
||||
gidx_t hash_offset;
|
||||
gidx_t hash_size;
|
||||
gidx_t module_offset;
|
||||
gidx_t otherconv_offset;
|
||||
};
|
||||
|
||||
struct hash_entry
|
||||
{
|
||||
gidx_t string_offset;
|
||||
gidx_t module_idx;
|
||||
};
|
||||
|
||||
struct module_entry
|
||||
{
|
||||
gidx_t canonname_offset;
|
||||
gidx_t fromdir_offset;
|
||||
gidx_t fromname_offset;
|
||||
gidx_t todir_offset;
|
||||
gidx_t toname_offset;
|
||||
gidx_t extra_offset;
|
||||
};
|
||||
|
||||
struct extra_entry
|
||||
{
|
||||
gidx_t module_cnt;
|
||||
struct extra_entry_module
|
||||
{
|
||||
gidx_t outname_offset;
|
||||
gidx_t dir_offset;
|
||||
gidx_t name_offset;
|
||||
} module[0];
|
||||
};
|
||||
|
||||
|
||||
#define GCONVCACHE_MAGIC 0x20010324
|
||||
|
||||
|
||||
#define GCONV_MODULES_CACHE GCONV_DIR "/gconv-modules.cache"
|
100
newlib/libc/sys/linux/iconv/loadinfo.h
Normal file
100
newlib/libc/sys/linux/iconv/loadinfo.h
Normal file
@ -0,0 +1,100 @@
|
||||
/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 _LOADINFO_H
|
||||
#define _LOADINFO_H 1
|
||||
|
||||
#ifndef PARAMS
|
||||
# if __STDC__
|
||||
# define PARAMS(args) args
|
||||
# else
|
||||
# define PARAMS(args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef internal_function
|
||||
# define internal_function
|
||||
#endif
|
||||
|
||||
/* Tell the compiler when a conditional or integer expression is
|
||||
almost always true or almost always false. */
|
||||
#ifndef HAVE_BUILTIN_EXPECT
|
||||
# define __builtin_expect(expr, val) (expr)
|
||||
#endif
|
||||
|
||||
/* Encoding of locale name parts. */
|
||||
#define CEN_REVISION 1
|
||||
#define CEN_SPONSOR 2
|
||||
#define CEN_SPECIAL 4
|
||||
#define XPG_NORM_CODESET 8
|
||||
#define XPG_CODESET 16
|
||||
#define TERRITORY 32
|
||||
#define CEN_AUDIENCE 64
|
||||
#define XPG_MODIFIER 128
|
||||
|
||||
#define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE)
|
||||
#define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER)
|
||||
|
||||
|
||||
struct loaded_l10nfile
|
||||
{
|
||||
const char *filename;
|
||||
int decided;
|
||||
|
||||
const void *data;
|
||||
|
||||
struct loaded_l10nfile *next;
|
||||
struct loaded_l10nfile *successor[1];
|
||||
};
|
||||
|
||||
|
||||
/* Normalize codeset name. There is no standard for the codeset
|
||||
names. Normalization allows the user to use any of the common
|
||||
names. The return value is dynamically allocated and has to be
|
||||
freed by the caller. */
|
||||
extern const char *_nl_normalize_codeset PARAMS ((const char *codeset,
|
||||
size_t name_len));
|
||||
|
||||
extern struct loaded_l10nfile *
|
||||
_nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list,
|
||||
const char *dirlist, size_t dirlist_len, int mask,
|
||||
const char *language, const char *territory,
|
||||
const char *codeset,
|
||||
const char *normalized_codeset,
|
||||
const char *modifier, const char *special,
|
||||
const char *sponsor, const char *revision,
|
||||
const char *filename, int do_allocate));
|
||||
|
||||
|
||||
extern const char *_nl_expand_alias PARAMS ((const char *name));
|
||||
|
||||
/* normalized_codeset is dynamically allocated and has to be freed by
|
||||
the caller. */
|
||||
extern int _nl_explode_name PARAMS ((char *name, const char **language,
|
||||
const char **modifier,
|
||||
const char **territory,
|
||||
const char **codeset,
|
||||
const char **normalized_codeset,
|
||||
const char **special,
|
||||
const char **sponsor,
|
||||
const char **revision));
|
||||
|
||||
extern char *_nl_find_language PARAMS ((const char *name));
|
||||
|
||||
#endif /* loadinfo.h */
|
209
newlib/libc/sys/linux/iconv/localeinfo.h
Normal file
209
newlib/libc/sys/linux/iconv/localeinfo.h
Normal file
@ -0,0 +1,209 @@
|
||||
/* Declarations for internal libc locale interfaces
|
||||
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 _LOCALEINFO_H
|
||||
#define _LOCALEINFO_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
#include <langinfo.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* This has to be changed whenever a new locale is defined. */
|
||||
#define __LC_LAST 13
|
||||
|
||||
#include "loadinfo.h" /* For loaded_l10nfile definition. */
|
||||
|
||||
/* Magic number at the beginning of a locale data file for CATEGORY. */
|
||||
#define LIMAGIC(category) ((unsigned int) (0x20000828 ^ (category)))
|
||||
|
||||
/* Two special weight constants for the collation data. */
|
||||
#define IGNORE_CHAR 2
|
||||
|
||||
/* We use a special value for the usage counter in `locale_data' to
|
||||
signal that this data must never be removed anymore. */
|
||||
#define MAX_USAGE_COUNT (UINT_MAX - 1)
|
||||
#define UNDELETABLE UINT_MAX
|
||||
|
||||
/* Structure describing locale data in core for a category. */
|
||||
struct locale_data
|
||||
{
|
||||
const char *name;
|
||||
const char *filedata; /* Region mapping the file data. */
|
||||
off_t filesize; /* Size of the file (and the region). */
|
||||
int mmaped; /* If nonzero the data is mmaped. */
|
||||
|
||||
unsigned int usage_count; /* Counter for users. */
|
||||
|
||||
int use_translit; /* Nonzero if the mb*towv*() and wc*tomb()
|
||||
functions should use transliteration. */
|
||||
const char *options; /* Extra options from the locale name,
|
||||
not used in the path to the locale data. */
|
||||
|
||||
unsigned int nstrings; /* Number of strings below. */
|
||||
union locale_data_value
|
||||
{
|
||||
const uint32_t *wstr;
|
||||
const char *string;
|
||||
unsigned int word;
|
||||
}
|
||||
values __flexarr; /* Items, usually pointers into `filedata'. */
|
||||
};
|
||||
|
||||
/* We know three kinds of collation sorting rules. */
|
||||
enum coll_sort_rule
|
||||
{
|
||||
illegal_0__,
|
||||
sort_forward,
|
||||
sort_backward,
|
||||
illegal_3__,
|
||||
sort_position,
|
||||
sort_forward_position,
|
||||
sort_backward_position,
|
||||
sort_mask
|
||||
};
|
||||
|
||||
/* 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
|
||||
};
|
||||
|
||||
|
||||
/* Definitions for `era' information from LC_TIME. */
|
||||
#define ERA_NAME_FORMAT_MEMBERS 4
|
||||
#define ERA_M_NAME 0
|
||||
#define ERA_M_FORMAT 1
|
||||
#define ERA_W_NAME 2
|
||||
#define ERA_W_FORMAT 3
|
||||
|
||||
|
||||
/* Structure to access `era' information from LC_TIME. */
|
||||
struct era_entry
|
||||
{
|
||||
uint32_t direction; /* Contains '+' or '-'. */
|
||||
int32_t offset;
|
||||
int32_t start_date[3];
|
||||
int32_t stop_date[3];
|
||||
const char *era_name;
|
||||
const char *era_format;
|
||||
const wchar_t *era_wname;
|
||||
const wchar_t *era_wformat;
|
||||
int absolute_direction;
|
||||
/* absolute direction:
|
||||
+1 indicates that year number is higher in the future. (like A.D.)
|
||||
-1 indicates that year number is higher in the past. (like B.C.) */
|
||||
};
|
||||
|
||||
|
||||
/* LC_CTYPE specific:
|
||||
Hardwired indices for standard wide character translation mappings. */
|
||||
enum
|
||||
{
|
||||
__TOW_toupper = 0,
|
||||
__TOW_tolower = 1
|
||||
};
|
||||
|
||||
|
||||
/* LC_CTYPE specific:
|
||||
Access a wide character class with a single character index.
|
||||
_ISCTYPE (c, desc) = iswctype (btowc (c), desc).
|
||||
c must be an `unsigned char'. desc must be a nonzero wctype_t. */
|
||||
#define _ISCTYPE(c, desc) \
|
||||
(((((const uint32_t *) (desc)) - 8)[(c) >> 5] >> ((c) & 0x1f)) & 1)
|
||||
|
||||
|
||||
/* For each category declare the variable for the current locale data. */
|
||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
extern struct locale_data *_nl_current_##category;
|
||||
#include "categories.def"
|
||||
#undef DEFINE_CATEGORY
|
||||
|
||||
extern const char *const _nl_category_names[__LC_LAST];
|
||||
extern const size_t _nl_category_name_sizes[__LC_LAST];
|
||||
extern struct locale_data * *const _nl_current[__LC_LAST];
|
||||
|
||||
/* Extract the current CATEGORY locale's string for ITEM. */
|
||||
#define _NL_CURRENT(category, item) \
|
||||
(_nl_current_##category->values[_NL_ITEM_INDEX (item)].string)
|
||||
|
||||
/* Extract the current CATEGORY locale's string for ITEM. */
|
||||
#define _NL_CURRENT_WSTR(category, item) \
|
||||
((wchar_t *) (_nl_current_##category->values[_NL_ITEM_INDEX (item)].wstr))
|
||||
|
||||
/* Extract the current CATEGORY locale's word for ITEM. */
|
||||
#define _NL_CURRENT_WORD(category, item) \
|
||||
(_nl_current_##category->values[_NL_ITEM_INDEX (item)].word)
|
||||
|
||||
/* This is used in lc-CATEGORY.c to define _nl_current_CATEGORY. */
|
||||
#define _NL_CURRENT_DEFINE(category) \
|
||||
extern struct locale_data _nl_C_##category; \
|
||||
struct locale_data *_nl_current_##category = &_nl_C_##category
|
||||
|
||||
/* Load the locale data for CATEGORY from the file specified by *NAME.
|
||||
If *NAME is "", use environment variables as specified by POSIX,
|
||||
and fill in *NAME with the actual name used. The directories
|
||||
listed in LOCALE_PATH are searched for the locale files. */
|
||||
extern struct locale_data *_nl_find_locale (const char *locale_path,
|
||||
size_t locale_path_len,
|
||||
int category, const char **name);
|
||||
|
||||
/* Try to load the file described by FILE. */
|
||||
extern void _nl_load_locale (struct loaded_l10nfile *file, int category);
|
||||
|
||||
/* Free all resource. */
|
||||
extern void _nl_unload_locale (struct locale_data *locale);
|
||||
|
||||
/* Free the locale and give back all memory if the usage count is one. */
|
||||
extern void _nl_remove_locale (int locale, struct locale_data *data);
|
||||
|
||||
|
||||
/* Return `era' entry which corresponds to TP. Used in strftime. */
|
||||
extern struct era_entry *_nl_get_era_entry (const struct tm *tp);
|
||||
|
||||
/* Return `era' cnt'th entry . Used in strptime. */
|
||||
extern struct era_entry *_nl_select_era_entry (int cnt);
|
||||
|
||||
/* Return `alt_digit' which corresponds to NUMBER. Used in strftime. */
|
||||
extern const char *_nl_get_alt_digit (unsigned int number);
|
||||
|
||||
/* Similar, but now for wide characters. */
|
||||
extern const wchar_t *_nl_get_walt_digit (unsigned int number);
|
||||
|
||||
/* Parse string as alternative digit and return numeric value. */
|
||||
extern int _nl_parse_alt_digit (const char **strp);
|
||||
|
||||
/* Postload processing. */
|
||||
extern void _nl_postload_ctype (void);
|
||||
extern void _nl_postload_time (void);
|
||||
|
||||
|
||||
#endif /* localeinfo.h */
|
450
newlib/libc/sys/linux/iconv/loop.c
Normal file
450
newlib/libc/sys/linux/iconv/loop.c
Normal file
@ -0,0 +1,450 @@
|
||||
/* Conversion loop frame work.
|
||||
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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. */
|
||||
|
||||
/* This file provides a frame for the reader loop in all conversion modules.
|
||||
The actual code must (of course) be provided in the actual module source
|
||||
code but certain actions can be written down generically, with some
|
||||
customization options which are these:
|
||||
|
||||
MIN_NEEDED_INPUT minimal number of input bytes needed for the next
|
||||
conversion.
|
||||
MIN_NEEDED_OUTPUT minimal number of bytes produced by the next round
|
||||
of conversion.
|
||||
|
||||
MAX_NEEDED_INPUT you guess it, this is the maximal number of input
|
||||
bytes needed. It defaults to MIN_NEEDED_INPUT
|
||||
MAX_NEEDED_OUTPUT likewise for output bytes.
|
||||
|
||||
LOOPFCT name of the function created. If not specified
|
||||
the name is `loop' but this prevents the use
|
||||
of multiple functions in the same file.
|
||||
|
||||
BODY this is supposed to expand to the body of the loop.
|
||||
The user must provide this.
|
||||
|
||||
EXTRA_LOOP_DECLS extra arguments passed from converion loop call.
|
||||
|
||||
INIT_PARAMS code to define and initialize variables from params.
|
||||
UPDATE_PARAMS code to store result in params.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <machine/endian.h>
|
||||
#include <gconv.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <sys/param.h> /* For MIN. */
|
||||
#define __need_size_t
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
/* We have to provide support for machines which are not able to handled
|
||||
unaligned memory accesses. Some of the character encodings have
|
||||
representations with a fixed width of 2 or 4 bytes. But if we cannot
|
||||
access unaligned memory we still have to read byte-wise. */
|
||||
#undef FCTNAME2
|
||||
#if defined _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
|
||||
/* We can handle unaligned memory access. */
|
||||
# define get16(addr) *((__const uint16_t *) (addr))
|
||||
# define get32(addr) *((__const uint32_t *) (addr))
|
||||
|
||||
/* We need no special support for writing values either. */
|
||||
# define put16(addr, val) *((uint16_t *) (addr)) = (val)
|
||||
# define put32(addr, val) *((uint32_t *) (addr)) = (val)
|
||||
|
||||
# define FCTNAME2(name) name
|
||||
#else
|
||||
/* Distinguish between big endian and little endian. */
|
||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define get16(addr) \
|
||||
(((__const unsigned char *) (addr))[1] << 8 \
|
||||
| ((__const unsigned char *) (addr))[0])
|
||||
# define get32(addr) \
|
||||
(((((__const unsigned char *) (addr))[3] << 8 \
|
||||
| ((__const unsigned char *) (addr))[2]) << 8 \
|
||||
| ((__const unsigned char *) (addr))[1]) << 8 \
|
||||
| ((__const unsigned char *) (addr))[0])
|
||||
|
||||
# define put16(addr, val) \
|
||||
({ uint16_t __val = (val); \
|
||||
((unsigned char *) (addr))[0] = __val; \
|
||||
((unsigned char *) (addr))[1] = __val >> 8; \
|
||||
(void) 0; })
|
||||
# define put32(addr, val) \
|
||||
({ uint32_t __val = (val); \
|
||||
((unsigned char *) (addr))[0] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[1] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[2] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[3] = __val; \
|
||||
(void) 0; })
|
||||
# else
|
||||
# define get16(addr) \
|
||||
(((__const unsigned char *) (addr))[0] << 8 \
|
||||
| ((__const unsigned char *) (addr))[1])
|
||||
# define get32(addr) \
|
||||
(((((__const unsigned char *) (addr))[0] << 8 \
|
||||
| ((__const unsigned char *) (addr))[1]) << 8 \
|
||||
| ((__const unsigned char *) (addr))[2]) << 8 \
|
||||
| ((__const unsigned char *) (addr))[3])
|
||||
|
||||
# define put16(addr, val) \
|
||||
({ uint16_t __val = (val); \
|
||||
((unsigned char *) (addr))[1] = __val; \
|
||||
((unsigned char *) (addr))[0] = __val >> 8; \
|
||||
(void) 0; })
|
||||
# define put32(addr, val) \
|
||||
({ uint32_t __val = (val); \
|
||||
((unsigned char *) (addr))[3] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[2] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[1] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[0] = __val; \
|
||||
(void) 0; })
|
||||
# endif
|
||||
|
||||
# define FCTNAME2(name) name##_unaligned
|
||||
#endif
|
||||
#define FCTNAME(name) FCTNAME2(name)
|
||||
|
||||
|
||||
/* We need at least one byte for the next round. */
|
||||
#ifndef MIN_NEEDED_INPUT
|
||||
# error "MIN_NEEDED_INPUT definition missing"
|
||||
#endif
|
||||
|
||||
/* Let's see how many bytes we produce. */
|
||||
#ifndef MAX_NEEDED_INPUT
|
||||
# define MAX_NEEDED_INPUT MIN_NEEDED_INPUT
|
||||
#endif
|
||||
|
||||
/* We produce at least one byte in the next round. */
|
||||
#ifndef MIN_NEEDED_OUTPUT
|
||||
# error "MIN_NEEDED_OUTPUT definition missing"
|
||||
#endif
|
||||
|
||||
/* Let's see how many bytes we produce. */
|
||||
#ifndef MAX_NEEDED_OUTPUT
|
||||
# define MAX_NEEDED_OUTPUT MIN_NEEDED_OUTPUT
|
||||
#endif
|
||||
|
||||
/* Default name for the function. */
|
||||
#ifndef LOOPFCT
|
||||
# define LOOPFCT loop
|
||||
#endif
|
||||
|
||||
/* Make sure we have a loop body. */
|
||||
#ifndef BODY
|
||||
# error "Definition of BODY missing for function" LOOPFCT
|
||||
#endif
|
||||
|
||||
|
||||
/* If no arguments have to passed to the loop function define the macro
|
||||
as empty. */
|
||||
#ifndef EXTRA_LOOP_DECLS
|
||||
# define EXTRA_LOOP_DECLS
|
||||
#endif
|
||||
|
||||
|
||||
/* To make it easier for the writers of the modules, we define a macro
|
||||
to test whether we have to ignore errors. */
|
||||
#define ignore_errors_p() \
|
||||
(irreversible != NULL && (flags & __GCONV_IGNORE_ERRORS))
|
||||
|
||||
|
||||
/* Error handling with transliteration/transcription function use and
|
||||
ignoring of errors. Note that we cannot use the do while (0) trick
|
||||
since `break' and `continue' must reach certain points. */
|
||||
#define STANDARD_ERR_HANDLER(Incr) \
|
||||
{ \
|
||||
struct __gconv_trans_data *trans; \
|
||||
\
|
||||
result = __GCONV_ILLEGAL_INPUT; \
|
||||
\
|
||||
if (irreversible == NULL) \
|
||||
/* This means we are in call from __gconv_transliterate. In this \
|
||||
case we are not doing any error recovery outself. */ \
|
||||
break; \
|
||||
\
|
||||
/* First try the transliteration methods. */ \
|
||||
for (trans = step_data->__trans; trans != NULL; trans = trans->__next) \
|
||||
{ \
|
||||
result = trans->__trans_fct (step, step_data, trans->__data, *inptrp, \
|
||||
&inptr, inend, &outptr, irreversible); \
|
||||
if (result != __GCONV_ILLEGAL_INPUT) \
|
||||
break; \
|
||||
} \
|
||||
/* If any of them recognized the input continue with the loop. */ \
|
||||
if (result != __GCONV_ILLEGAL_INPUT) \
|
||||
continue; \
|
||||
\
|
||||
/* Next see whether we have to ignore the error. If not, stop. */ \
|
||||
if (! ignore_errors_p ()) \
|
||||
break; \
|
||||
\
|
||||
/* When we come here it means we ignore the character. */ \
|
||||
++*irreversible; \
|
||||
inptr += Incr; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
|
||||
/* Handling of Unicode 3.1 TAG characters. Unicode recommends
|
||||
"If language codes are not relevant to the particular processing
|
||||
operation, then they should be ignored."
|
||||
This macro is usually called right before STANDARD_ERR_HANDLER (Incr). */
|
||||
#define UNICODE_TAG_HANDLER(Character, Incr) \
|
||||
{ \
|
||||
/* TAG characters are those in the range U+E0000..U+E007F. */ \
|
||||
if (((Character) >> 7) == (0xe0000 >> 7)) \
|
||||
{ \
|
||||
inptr += Incr; \
|
||||
continue; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/* The function returns the status, as defined in gconv.h. */
|
||||
static inline int
|
||||
FCTNAME (LOOPFCT) (struct __gconv_step *step,
|
||||
struct __gconv_step_data *step_data,
|
||||
const unsigned char **inptrp, const unsigned char *inend,
|
||||
unsigned char **outptrp, const unsigned char *outend,
|
||||
size_t *irreversible EXTRA_LOOP_DECLS)
|
||||
{
|
||||
#ifdef LOOP_NEED_STATE
|
||||
mbstate_t *state = step_data->__statep;
|
||||
#endif
|
||||
#ifdef LOOP_NEED_FLAGS
|
||||
int flags = step_data->__flags;
|
||||
#endif
|
||||
#ifdef LOOP_NEED_DATA
|
||||
void *data = step->__data;
|
||||
#endif
|
||||
int result = __GCONV_EMPTY_INPUT;
|
||||
const unsigned char *inptr = *inptrp;
|
||||
unsigned char *outptr = *outptrp;
|
||||
|
||||
#ifdef INIT_PARAMS
|
||||
INIT_PARAMS;
|
||||
#endif
|
||||
|
||||
while (inptr != inend)
|
||||
{
|
||||
/* `if' cases for MIN_NEEDED_OUTPUT ==/!= 1 is made to help the
|
||||
compiler generating better code. They will be optimized away
|
||||
since MIN_NEEDED_OUTPUT is always a constant. */
|
||||
if ((MIN_NEEDED_OUTPUT != 1
|
||||
&& __builtin_expect (outptr + MIN_NEEDED_OUTPUT > outend, 0))
|
||||
|| (MIN_NEEDED_OUTPUT == 1
|
||||
&& __builtin_expect (outptr >= outend, 0)))
|
||||
{
|
||||
/* Overflow in the output buffer. */
|
||||
result = __GCONV_FULL_OUTPUT;
|
||||
break;
|
||||
}
|
||||
if (MIN_NEEDED_INPUT > 1
|
||||
&& __builtin_expect (inptr + MIN_NEEDED_INPUT > inend, 0))
|
||||
{
|
||||
/* We don't have enough input for another complete input
|
||||
character. */
|
||||
result = __GCONV_INCOMPLETE_INPUT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Here comes the body the user provides. It can stop with
|
||||
RESULT set to GCONV_INCOMPLETE_INPUT (if the size of the
|
||||
input characters vary in size), GCONV_ILLEGAL_INPUT, or
|
||||
GCONV_FULL_OUTPUT (if the output characters vary in size). */
|
||||
BODY
|
||||
}
|
||||
|
||||
/* Update the pointers pointed to by the parameters. */
|
||||
*inptrp = inptr;
|
||||
*outptrp = outptr;
|
||||
#ifdef UPDATE_PARAMS
|
||||
UPDATE_PARAMS;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Include the file a second time to define the function to handle
|
||||
unaligned access. */
|
||||
#if !defined DEFINE_UNALIGNED && !defined _STRING_ARCH_unaligned \
|
||||
&& MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \
|
||||
&& MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0
|
||||
# undef get16
|
||||
# undef get32
|
||||
# undef put16
|
||||
# undef put32
|
||||
# undef unaligned
|
||||
|
||||
# define DEFINE_UNALIGNED
|
||||
# include "loop.c"
|
||||
# undef DEFINE_UNALIGNED
|
||||
#endif
|
||||
|
||||
|
||||
#if MAX_NEEDED_INPUT > 1
|
||||
# define SINGLE(fct) SINGLE2 (fct)
|
||||
# define SINGLE2(fct) fct##_single
|
||||
static inline int
|
||||
SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||
struct __gconv_step_data *step_data,
|
||||
const unsigned char **inptrp, const unsigned char *inend,
|
||||
unsigned char **outptrp, unsigned char *outend,
|
||||
size_t *irreversible EXTRA_LOOP_DECLS)
|
||||
{
|
||||
mbstate_t *state = step_data->__statep;
|
||||
#ifdef LOOP_NEED_FLAGS
|
||||
int flags = step_data->__flags;
|
||||
#endif
|
||||
#ifdef LOOP_NEED_DATA
|
||||
void *data = step->__data;
|
||||
#endif
|
||||
int result = __GCONV_OK;
|
||||
unsigned char bytebuf[MAX_NEEDED_INPUT];
|
||||
const unsigned char *inptr = *inptrp;
|
||||
unsigned char *outptr = *outptrp;
|
||||
size_t inlen;
|
||||
|
||||
#ifdef INIT_PARAMS
|
||||
INIT_PARAMS;
|
||||
#endif
|
||||
|
||||
#ifdef UNPACK_BYTES
|
||||
UNPACK_BYTES
|
||||
#else
|
||||
/* Add the bytes from the state to the input buffer. */
|
||||
for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen)
|
||||
bytebuf[inlen] = state->__value.__wchb[inlen];
|
||||
#endif
|
||||
|
||||
/* Are there enough bytes in the input buffer? */
|
||||
if (__builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
|
||||
{
|
||||
*inptrp = inend;
|
||||
#ifdef STORE_REST
|
||||
inptr = bytebuf;
|
||||
inptrp = &inptr;
|
||||
inend = &bytebuf[inlen];
|
||||
|
||||
STORE_REST
|
||||
#else
|
||||
/* We don't have enough input for another complete input
|
||||
character. */
|
||||
while (inptr < inend)
|
||||
state->__value.__wchb[inlen++] = *inptr++;
|
||||
#endif
|
||||
|
||||
return __GCONV_INCOMPLETE_INPUT;
|
||||
}
|
||||
|
||||
/* Enough space in output buffer. */
|
||||
if ((MIN_NEEDED_OUTPUT != 1 && outptr + MIN_NEEDED_OUTPUT > outend)
|
||||
|| (MIN_NEEDED_OUTPUT == 1 && outptr >= outend))
|
||||
/* Overflow in the output buffer. */
|
||||
return __GCONV_FULL_OUTPUT;
|
||||
|
||||
/* Now add characters from the normal input buffer. */
|
||||
do
|
||||
bytebuf[inlen++] = *inptr++;
|
||||
while (inlen < MAX_NEEDED_INPUT && inptr < inend);
|
||||
|
||||
inptr = bytebuf;
|
||||
inend = &bytebuf[inlen];
|
||||
|
||||
do
|
||||
{
|
||||
BODY
|
||||
}
|
||||
while (0);
|
||||
|
||||
/* Now we either have produced an output character and consumed all the
|
||||
bytes from the state and at least one more, or the character is still
|
||||
incomplete, or we have some other error (like illegal input character,
|
||||
no space in output buffer). */
|
||||
if (__builtin_expect (inptr != bytebuf, 1))
|
||||
{
|
||||
/* We found a new character. */
|
||||
assert (inptr - bytebuf > (state->__count & 7));
|
||||
|
||||
*inptrp += inptr - bytebuf - (state->__count & 7);
|
||||
*outptrp = outptr;
|
||||
|
||||
result = __GCONV_OK;
|
||||
|
||||
/* Clear the state buffer. */
|
||||
state->__count &= ~7;
|
||||
}
|
||||
else if (result == __GCONV_INCOMPLETE_INPUT)
|
||||
{
|
||||
/* This can only happen if we have less than MAX_NEEDED_INPUT bytes
|
||||
available. */
|
||||
assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
|
||||
|
||||
*inptrp += inend - bytebuf - (state->__count & 7);
|
||||
#ifdef STORE_REST
|
||||
inptrp = &inptr;
|
||||
|
||||
STORE_REST
|
||||
#else
|
||||
/* We don't have enough input for another complete input
|
||||
character. */
|
||||
while (inptr < inend)
|
||||
state->__value.__wchb[inlen++] = *inptr++;
|
||||
#endif
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
# undef SINGLE
|
||||
# undef SINGLE2
|
||||
#endif
|
||||
|
||||
|
||||
/* We remove the macro definitions so that we can include this file again
|
||||
for the definition of another function. */
|
||||
#undef MIN_NEEDED_INPUT
|
||||
#undef MAX_NEEDED_INPUT
|
||||
#undef MIN_NEEDED_OUTPUT
|
||||
#undef MAX_NEEDED_OUTPUT
|
||||
#undef LOOPFCT
|
||||
#undef BODY
|
||||
#undef LOOPFCT
|
||||
#undef EXTRA_LOOP_DECLS
|
||||
#undef INIT_PARAMS
|
||||
#undef UPDATE_PARAMS
|
||||
#undef UNPACK_BYTES
|
||||
#undef LOOP_NEED_STATE
|
||||
#undef LOOP_NEED_FLAGS
|
||||
#undef LOOP_NEED_DATA
|
||||
#undef get16
|
||||
#undef get32
|
||||
#undef put16
|
||||
#undef put32
|
||||
#undef unaligned
|
696
newlib/libc/sys/linux/iconv/skeleton.c
Normal file
696
newlib/libc/sys/linux/iconv/skeleton.c
Normal file
@ -0,0 +1,696 @@
|
||||
/* Skeleton for a conversion module.
|
||||
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 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. */
|
||||
|
||||
/* This file can be included to provide definitions of several things
|
||||
many modules have in common. It can be customized using the following
|
||||
macros:
|
||||
|
||||
DEFINE_INIT define the default initializer. This requires the
|
||||
following symbol to be defined.
|
||||
|
||||
CHARSET_NAME string with official name of the coded character
|
||||
set (in all-caps)
|
||||
|
||||
DEFINE_FINI define the default destructor function.
|
||||
|
||||
MIN_NEEDED_FROM minimal number of bytes needed for the from-charset.
|
||||
MIN_NEEDED_TO likewise for the to-charset.
|
||||
|
||||
MAX_NEEDED_FROM maximal number of bytes needed for the from-charset.
|
||||
This macro is optional, it defaults to MIN_NEEDED_FROM.
|
||||
MAX_NEEDED_TO likewise for the to-charset.
|
||||
|
||||
DEFINE_DIRECTION_OBJECTS
|
||||
two objects will be defined to be used when the
|
||||
`gconv' function must only distinguish two
|
||||
directions. This is implied by DEFINE_INIT.
|
||||
If this macro is not defined the following
|
||||
macro must be available.
|
||||
|
||||
FROM_DIRECTION this macro is supposed to return a value != 0
|
||||
if we convert from the current character set,
|
||||
otherwise it return 0.
|
||||
|
||||
EMIT_SHIFT_TO_INIT this symbol is optional. If it is defined it
|
||||
defines some code which writes out a sequence
|
||||
of characters which bring the current state into
|
||||
the initial state.
|
||||
|
||||
FROM_LOOP name of the function implementing the conversion
|
||||
from the current characters.
|
||||
TO_LOOP likewise for the other direction
|
||||
|
||||
ONE_DIRECTION optional. If defined to 1, only one conversion
|
||||
direction is defined instead of two. In this
|
||||
case, FROM_DIRECTION should be defined to 1, and
|
||||
FROM_LOOP and TO_LOOP should have the same value.
|
||||
|
||||
SAVE_RESET_STATE in case of an error we must reset the state for
|
||||
the rerun so this macro must be defined for
|
||||
stateful encodings. It takes an argument which
|
||||
is nonzero when saving.
|
||||
|
||||
RESET_INPUT_BUFFER If the input character sets allow this the macro
|
||||
can be defined to reset the input buffer pointers
|
||||
to cover only those characters up to the error.
|
||||
|
||||
FUNCTION_NAME if not set the conversion function is named `gconv'.
|
||||
|
||||
PREPARE_LOOP optional code preparing the conversion loop. Can
|
||||
contain variable definitions.
|
||||
END_LOOP also optional, may be used to store information
|
||||
|
||||
EXTRA_LOOP_ARGS optional macro specifying extra arguments passed
|
||||
to loop function.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <gconv.h>
|
||||
#include <string.h>
|
||||
#define __need_size_t
|
||||
#define __need_NULL
|
||||
#include <stddef.h>
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
# define DL_CALL_FCT(fct, args) fct args
|
||||
|
||||
/* The direction objects. */
|
||||
#if DEFINE_DIRECTION_OBJECTS || DEFINE_INIT
|
||||
static int from_object;
|
||||
static int to_object;
|
||||
|
||||
# ifndef FROM_DIRECTION
|
||||
# define FROM_DIRECTION (step->__data == &from_object)
|
||||
# endif
|
||||
#else
|
||||
# ifndef FROM_DIRECTION
|
||||
# error "FROM_DIRECTION must be provided if direction objects are not used"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* How many bytes are needed at most for the from-charset. */
|
||||
#ifndef MAX_NEEDED_FROM
|
||||
# define MAX_NEEDED_FROM MIN_NEEDED_FROM
|
||||
#endif
|
||||
|
||||
/* Same for the to-charset. */
|
||||
#ifndef MAX_NEEDED_TO
|
||||
# define MAX_NEEDED_TO MIN_NEEDED_TO
|
||||
#endif
|
||||
|
||||
|
||||
/* Define macros which can access unaligned buffers. These macros are
|
||||
supposed to be used only in code outside the inner loops. For the inner
|
||||
loops we have other definitions which allow optimized access. */
|
||||
#ifdef _STRING_ARCH_unaligned
|
||||
/* We can handle unaligned memory access. */
|
||||
# define get16u(addr) *((__const uint16_t *) (addr))
|
||||
# define get32u(addr) *((__const uint32_t *) (addr))
|
||||
|
||||
/* We need no special support for writing values either. */
|
||||
# define put16u(addr, val) *((uint16_t *) (addr)) = (val)
|
||||
# define put32u(addr, val) *((uint32_t *) (addr)) = (val)
|
||||
#else
|
||||
/* Distinguish between big endian and little endian. */
|
||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define get16u(addr) \
|
||||
(((__const unsigned char *) (addr))[1] << 8 \
|
||||
| ((__const unsigned char *) (addr))[0])
|
||||
# define get32u(addr) \
|
||||
(((((__const unsigned char *) (addr))[3] << 8 \
|
||||
| ((__const unsigned char *) (addr))[2]) << 8 \
|
||||
| ((__const unsigned char *) (addr))[1]) << 8 \
|
||||
| ((__const unsigned char *) (addr))[0])
|
||||
|
||||
# define put16u(addr, val) \
|
||||
({ uint16_t __val = (val); \
|
||||
((unsigned char *) (addr))[0] = __val; \
|
||||
((unsigned char *) (addr))[1] = __val >> 8; \
|
||||
(void) 0; })
|
||||
# define put32u(addr, val) \
|
||||
({ uint32_t __val = (val); \
|
||||
((unsigned char *) (addr))[0] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[1] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[2] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[3] = __val; \
|
||||
(void) 0; })
|
||||
# else
|
||||
# define get16u(addr) \
|
||||
(((__const unsigned char *) (addr))[0] << 8 \
|
||||
| ((__const unsigned char *) (addr))[1])
|
||||
# define get32u(addr) \
|
||||
(((((__const unsigned char *) (addr))[0] << 8 \
|
||||
| ((__const unsigned char *) (addr))[1]) << 8 \
|
||||
| ((__const unsigned char *) (addr))[2]) << 8 \
|
||||
| ((__const unsigned char *) (addr))[3])
|
||||
|
||||
# define put16u(addr, val) \
|
||||
({ uint16_t __val = (val); \
|
||||
((unsigned char *) (addr))[1] = __val; \
|
||||
((unsigned char *) (addr))[0] = __val >> 8; \
|
||||
(void) 0; })
|
||||
# define put32u(addr, val) \
|
||||
({ uint32_t __val = (val); \
|
||||
((unsigned char *) (addr))[3] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[2] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[1] = __val; \
|
||||
__val >>= 8; \
|
||||
((unsigned char *) (addr))[0] = __val; \
|
||||
(void) 0; })
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* For conversions from a fixed width character set to another fixed width
|
||||
character set we can define RESET_INPUT_BUFFER in a very fast way. */
|
||||
#if !defined RESET_INPUT_BUFFER && !defined SAVE_RESET_STATE
|
||||
# if MIN_NEEDED_FROM == MAX_NEEDED_FROM && MIN_NEEDED_TO == MAX_NEEDED_TO
|
||||
/* We have to use these `if's here since the compiler cannot know that
|
||||
(outbuf - outerr) is always divisible by MIN_NEEDED_TO. */
|
||||
# define RESET_INPUT_BUFFER \
|
||||
if (MIN_NEEDED_FROM % MIN_NEEDED_TO == 0) \
|
||||
*inptrp -= (outbuf - outerr) * (MIN_NEEDED_FROM / MIN_NEEDED_TO); \
|
||||
else if (MIN_NEEDED_TO % MIN_NEEDED_FROM == 0) \
|
||||
*inptrp -= (outbuf - outerr) / (MIN_NEEDED_TO / MIN_NEEDED_FROM); \
|
||||
else \
|
||||
*inptrp -= ((outbuf - outerr) / MIN_NEEDED_TO) * MIN_NEEDED_FROM
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* The default init function. It simply matches the name and initializes
|
||||
the step data to point to one of the objects above. */
|
||||
#if DEFINE_INIT
|
||||
# ifndef CHARSET_NAME
|
||||
# error "CHARSET_NAME not defined"
|
||||
# endif
|
||||
|
||||
extern int gconv_init (struct __gconv_step *step);
|
||||
int
|
||||
gconv_init (struct __gconv_step *step)
|
||||
{
|
||||
/* Determine which direction. */
|
||||
if (strcmp (step->__from_name, CHARSET_NAME) == 0)
|
||||
{
|
||||
step->__data = &from_object;
|
||||
|
||||
step->__min_needed_from = MIN_NEEDED_FROM;
|
||||
step->__max_needed_from = MAX_NEEDED_FROM;
|
||||
step->__min_needed_to = MIN_NEEDED_TO;
|
||||
step->__max_needed_to = MAX_NEEDED_TO;
|
||||
}
|
||||
else if (__builtin_expect (strcmp (step->__to_name, CHARSET_NAME), 0) == 0)
|
||||
{
|
||||
step->__data = &to_object;
|
||||
|
||||
step->__min_needed_from = MIN_NEEDED_TO;
|
||||
step->__max_needed_from = MAX_NEEDED_TO;
|
||||
step->__min_needed_to = MIN_NEEDED_FROM;
|
||||
step->__max_needed_to = MAX_NEEDED_FROM;
|
||||
}
|
||||
else
|
||||
return __GCONV_NOCONV;
|
||||
|
||||
#ifdef SAVE_RESET_STATE
|
||||
step->__stateful = 1;
|
||||
#else
|
||||
step->__stateful = 0;
|
||||
#endif
|
||||
|
||||
return __GCONV_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* The default destructor function does nothing in the moment and so
|
||||
we don't define it at all. But we still provide the macro just in
|
||||
case we need it some day. */
|
||||
#if DEFINE_FINI
|
||||
#endif
|
||||
|
||||
|
||||
/* If no arguments have to passed to the loop function define the macro
|
||||
as empty. */
|
||||
#ifndef EXTRA_LOOP_ARGS
|
||||
# define EXTRA_LOOP_ARGS
|
||||
#endif
|
||||
|
||||
|
||||
/* This is the actual conversion function. */
|
||||
#ifndef FUNCTION_NAME
|
||||
# define FUNCTION_NAME gconv
|
||||
#endif
|
||||
|
||||
/* The macros are used to access the function to convert single characters. */
|
||||
#define SINGLE(fct) SINGLE2 (fct)
|
||||
#define SINGLE2(fct) fct##_single
|
||||
|
||||
|
||||
extern int FUNCTION_NAME (struct __gconv_step *step,
|
||||
struct __gconv_step_data *data,
|
||||
const unsigned char **inptrp,
|
||||
const unsigned char *inend,
|
||||
unsigned char **outbufstart, size_t *irreversible,
|
||||
int do_flush, int consume_incomplete);
|
||||
int
|
||||
FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
|
||||
const unsigned char **inptrp, const unsigned char *inend,
|
||||
unsigned char **outbufstart, size_t *irreversible, int do_flush,
|
||||
int consume_incomplete)
|
||||
{
|
||||
struct __gconv_step *next_step = step + 1;
|
||||
struct __gconv_step_data *next_data = data + 1;
|
||||
__gconv_fct fct;
|
||||
int status;
|
||||
|
||||
fct = (data->__flags & __GCONV_IS_LAST) ? NULL : next_step->__fct;
|
||||
|
||||
/* If the function is called with no input this means we have to reset
|
||||
to the initial state. The possibly partly converted input is
|
||||
dropped. */
|
||||
if (__builtin_expect (do_flush, 0))
|
||||
{
|
||||
/* This should never happen during error handling. */
|
||||
assert (outbufstart == NULL);
|
||||
|
||||
status = __GCONV_OK;
|
||||
|
||||
#ifdef EMIT_SHIFT_TO_INIT
|
||||
if (do_flush == 1)
|
||||
{
|
||||
/* We preserve the initial values of the pointer variables. */
|
||||
unsigned char *outbuf = data->__outbuf;
|
||||
unsigned char *outstart = outbuf;
|
||||
unsigned char *outend = data->__outbufend;
|
||||
|
||||
# ifdef PREPARE_LOOP
|
||||
PREPARE_LOOP
|
||||
# endif
|
||||
|
||||
# ifdef SAVE_RESET_STATE
|
||||
SAVE_RESET_STATE (1);
|
||||
# endif
|
||||
|
||||
/* Emit the escape sequence to reset the state. */
|
||||
EMIT_SHIFT_TO_INIT;
|
||||
|
||||
/* Call the steps down the chain if there are any but only if we
|
||||
successfully emitted the escape sequence. This should only
|
||||
fail if the output buffer is full. If the input is invalid
|
||||
it should be discarded since the user wants to start from a
|
||||
clean state. */
|
||||
if (status == __GCONV_OK)
|
||||
{
|
||||
if (data->__flags & __GCONV_IS_LAST)
|
||||
/* Store information about how many bytes are available. */
|
||||
data->__outbuf = outbuf;
|
||||
else
|
||||
{
|
||||
/* Write out all output which was produced. */
|
||||
if (outbuf > outstart)
|
||||
{
|
||||
const unsigned char *outerr = outstart;
|
||||
int result;
|
||||
|
||||
result = DL_CALL_FCT (fct, (next_step, next_data,
|
||||
&outerr, outbuf, NULL,
|
||||
irreversible, 0,
|
||||
consume_incomplete));
|
||||
|
||||
if (result != __GCONV_EMPTY_INPUT)
|
||||
{
|
||||
if (__builtin_expect (outerr != outbuf, 0))
|
||||
{
|
||||
/* We have a problem. Undo the conversion. */
|
||||
outbuf = outstart;
|
||||
|
||||
/* Restore the state. */
|
||||
# ifdef SAVE_RESET_STATE
|
||||
SAVE_RESET_STATE (0);
|
||||
# endif
|
||||
}
|
||||
|
||||
/* Change the status. */
|
||||
status = result;
|
||||
}
|
||||
}
|
||||
|
||||
if (status == __GCONV_OK)
|
||||
/* Now flush the remaining steps. */
|
||||
status = DL_CALL_FCT (fct, (next_step, next_data, NULL,
|
||||
NULL, NULL, irreversible, 1,
|
||||
consume_incomplete));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Clear the state object. There might be bytes in there from
|
||||
previous calls with CONSUME_INCOMPLETE == 1. But don't emit
|
||||
escape sequences. */
|
||||
memset (data->__statep, '\0', sizeof (*data->__statep));
|
||||
|
||||
if (! (data->__flags & __GCONV_IS_LAST))
|
||||
/* Now flush the remaining steps. */
|
||||
status = DL_CALL_FCT (fct, (next_step, next_data, NULL, NULL,
|
||||
NULL, irreversible, do_flush,
|
||||
consume_incomplete));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We preserve the initial values of the pointer variables. */
|
||||
const unsigned char *inptr = *inptrp;
|
||||
unsigned char *outbuf = (__builtin_expect (outbufstart == NULL, 1)
|
||||
? data->__outbuf : *outbufstart);
|
||||
unsigned char *outend = data->__outbufend;
|
||||
unsigned char *outstart;
|
||||
/* This variable is used to count the number of characters we
|
||||
actually converted. */
|
||||
size_t lirreversible = 0;
|
||||
size_t *lirreversiblep = irreversible ? &lirreversible : NULL;
|
||||
#if defined _STRING_ARCH_unaligned \
|
||||
|| MIN_NEEDED_FROM == 1 || MAX_NEEDED_FROM % MIN_NEEDED_FROM != 0 \
|
||||
|| MIN_NEEDED_TO == 1 || MAX_NEEDED_TO % MIN_NEEDED_TO != 0
|
||||
# define unaligned 0
|
||||
#else
|
||||
int unaligned;
|
||||
# define GEN_unaligned(name) GEN_unaligned2 (name)
|
||||
# define GEN_unaligned2(name) name##_unaligned
|
||||
#endif
|
||||
|
||||
#ifdef PREPARE_LOOP
|
||||
PREPARE_LOOP
|
||||
#endif
|
||||
|
||||
#if MAX_NEEDED_FROM > 1 || MAX_NEEDED_TO > 1
|
||||
/* If the function is used to implement the mb*towc*() or wc*tomb*()
|
||||
functions we must test whether any bytes from the last call are
|
||||
stored in the `state' object. */
|
||||
if (((MAX_NEEDED_FROM > 1 && MAX_NEEDED_TO > 1)
|
||||
|| (MAX_NEEDED_FROM > 1 && FROM_DIRECTION)
|
||||
|| (MAX_NEEDED_TO > 1 && !FROM_DIRECTION))
|
||||
&& consume_incomplete && (data->__statep->__count & 7) != 0)
|
||||
{
|
||||
/* Yep, we have some bytes left over. Process them now.
|
||||
But this must not happen while we are called from an
|
||||
error handler. */
|
||||
assert (outbufstart == NULL);
|
||||
|
||||
# if MAX_NEEDED_FROM > 1
|
||||
if (MAX_NEEDED_TO == 1 || FROM_DIRECTION)
|
||||
status = SINGLE(FROM_LOOP) (step, data, inptrp, inend, &outbuf,
|
||||
outend, lirreversiblep
|
||||
EXTRA_LOOP_ARGS);
|
||||
# endif
|
||||
# if MAX_NEEDED_FROM > 1 && MAX_NEEDED_TO > 1 && !ONE_DIRECTION
|
||||
else
|
||||
# endif
|
||||
# if MAX_NEEDED_TO > 1 && !ONE_DIRECTION
|
||||
status = SINGLE(TO_LOOP) (step, data, inptrp, inend, &outbuf,
|
||||
outend, lirreversiblep EXTRA_LOOP_ARGS);
|
||||
# endif
|
||||
|
||||
if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined _STRING_ARCH_unaligned \
|
||||
&& MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \
|
||||
&& MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0
|
||||
/* The following assumes that encodings, which have a variable length
|
||||
what might unalign a buffer even though it is a aligned in the
|
||||
beginning, either don't have the minimal number of bytes as a divisor
|
||||
of the maximum length or have a minimum length of 1. This is true
|
||||
for all known and supported encodings. */
|
||||
unaligned = ((FROM_DIRECTION
|
||||
&& ((uintptr_t) inptr % MIN_NEEDED_FROM != 0
|
||||
|| ((data->__flags & __GCONV_IS_LAST)
|
||||
&& (uintptr_t) outbuf % MIN_NEEDED_TO != 0)))
|
||||
|| (!FROM_DIRECTION
|
||||
&& (((data->__flags & __GCONV_IS_LAST)
|
||||
&& (uintptr_t) outbuf % MIN_NEEDED_FROM != 0)
|
||||
|| (uintptr_t) inptr % MIN_NEEDED_TO != 0)));
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
struct __gconv_trans_data *trans;
|
||||
|
||||
/* Remember the start value for this round. */
|
||||
inptr = *inptrp;
|
||||
/* The outbuf buffer is empty. */
|
||||
outstart = outbuf;
|
||||
|
||||
#ifdef SAVE_RESET_STATE
|
||||
SAVE_RESET_STATE (1);
|
||||
#endif
|
||||
|
||||
if (__builtin_expect (!unaligned, 1))
|
||||
{
|
||||
if (FROM_DIRECTION)
|
||||
/* Run the conversion loop. */
|
||||
status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
|
||||
lirreversiblep EXTRA_LOOP_ARGS);
|
||||
else
|
||||
/* Run the conversion loop. */
|
||||
status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
|
||||
lirreversiblep EXTRA_LOOP_ARGS);
|
||||
}
|
||||
#if !defined _STRING_ARCH_unaligned \
|
||||
&& MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \
|
||||
&& MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0
|
||||
else
|
||||
{
|
||||
if (FROM_DIRECTION)
|
||||
/* Run the conversion loop. */
|
||||
status = GEN_unaligned (FROM_LOOP) (step, data, inptrp, inend,
|
||||
&outbuf, outend,
|
||||
lirreversiblep
|
||||
EXTRA_LOOP_ARGS);
|
||||
else
|
||||
/* Run the conversion loop. */
|
||||
status = GEN_unaligned (TO_LOOP) (step, data, inptrp, inend,
|
||||
&outbuf, outend,
|
||||
lirreversiblep
|
||||
EXTRA_LOOP_ARGS);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we were called as part of an error handling module we
|
||||
don't do anything else here. */
|
||||
if (__builtin_expect (outbufstart != NULL, 0))
|
||||
{
|
||||
*outbufstart = outbuf;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Give the transliteration module the chance to store the
|
||||
original text and the result in case it needs a context. */
|
||||
for (trans = data->__trans; trans != NULL; trans = trans->__next)
|
||||
if (trans->__trans_context_fct != NULL)
|
||||
DL_CALL_FCT (trans->__trans_context_fct,
|
||||
(trans->__data, inptr, *inptrp, outstart, outbuf));
|
||||
|
||||
/* We finished one use of the loops. */
|
||||
++data->__invocation_counter;
|
||||
|
||||
/* If this is the last step leave the loop, there is nothing
|
||||
we can do. */
|
||||
if (__builtin_expect (data->__flags & __GCONV_IS_LAST, 0))
|
||||
{
|
||||
/* Store information about how many bytes are available. */
|
||||
data->__outbuf = outbuf;
|
||||
|
||||
/* Remember how many non-identical characters we
|
||||
converted in a irreversible way. */
|
||||
*irreversible += lirreversible;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Write out all output which was produced. */
|
||||
if (__builtin_expect (outbuf > outstart, 1))
|
||||
{
|
||||
const unsigned char *outerr = data->__outbuf;
|
||||
int result;
|
||||
|
||||
result = DL_CALL_FCT (fct, (next_step, next_data, &outerr,
|
||||
outbuf, NULL, irreversible, 0,
|
||||
consume_incomplete));
|
||||
|
||||
if (result != __GCONV_EMPTY_INPUT)
|
||||
{
|
||||
if (__builtin_expect (outerr != outbuf, 0))
|
||||
{
|
||||
#ifdef RESET_INPUT_BUFFER
|
||||
RESET_INPUT_BUFFER;
|
||||
#else
|
||||
/* We have a problem with the in on of the functions
|
||||
below. Undo the conversion upto the error point. */
|
||||
size_t nstatus;
|
||||
|
||||
/* Reload the pointers. */
|
||||
*inptrp = inptr;
|
||||
outbuf = outstart;
|
||||
|
||||
/* Restore the state. */
|
||||
# ifdef SAVE_RESET_STATE
|
||||
SAVE_RESET_STATE (0);
|
||||
# endif
|
||||
|
||||
if (__builtin_expect (!unaligned, 1))
|
||||
{
|
||||
if (FROM_DIRECTION)
|
||||
/* Run the conversion loop. */
|
||||
nstatus = FROM_LOOP (step, data, inptrp, inend,
|
||||
&outbuf, outerr,
|
||||
lirreversiblep
|
||||
EXTRA_LOOP_ARGS);
|
||||
else
|
||||
/* Run the conversion loop. */
|
||||
nstatus = TO_LOOP (step, data, inptrp, inend,
|
||||
&outbuf, outerr,
|
||||
lirreversiblep
|
||||
EXTRA_LOOP_ARGS);
|
||||
}
|
||||
# if !defined _STRING_ARCH_unaligned \
|
||||
&& MIN_NEEDED_FROM != 1 && MAX_NEEDED_FROM % MIN_NEEDED_FROM == 0 \
|
||||
&& MIN_NEEDED_TO != 1 && MAX_NEEDED_TO % MIN_NEEDED_TO == 0
|
||||
else
|
||||
{
|
||||
if (FROM_DIRECTION)
|
||||
/* Run the conversion loop. */
|
||||
nstatus = GEN_unaligned (FROM_LOOP) (step, data,
|
||||
inptrp, inend,
|
||||
&outbuf,
|
||||
outerr,
|
||||
lirreversiblep
|
||||
EXTRA_LOOP_ARGS);
|
||||
else
|
||||
/* Run the conversion loop. */
|
||||
nstatus = GEN_unaligned (TO_LOOP) (step, data,
|
||||
inptrp, inend,
|
||||
&outbuf, outerr,
|
||||
lirreversiblep
|
||||
EXTRA_LOOP_ARGS);
|
||||
}
|
||||
# endif
|
||||
|
||||
/* We must run out of output buffer space in this
|
||||
rerun. */
|
||||
assert (outbuf == outerr);
|
||||
assert (nstatus == __GCONV_FULL_OUTPUT);
|
||||
|
||||
/* If we haven't consumed a single byte decrement
|
||||
the invocation counter. */
|
||||
if (__builtin_expect (outbuf == outstart, 0))
|
||||
--data->__invocation_counter;
|
||||
#endif /* reset input buffer */
|
||||
}
|
||||
|
||||
/* Change the status. */
|
||||
status = result;
|
||||
}
|
||||
else
|
||||
/* All the output is consumed, we can make another run
|
||||
if everything was ok. */
|
||||
if (status == __GCONV_FULL_OUTPUT)
|
||||
{
|
||||
status = __GCONV_OK;
|
||||
outbuf = data->__outbuf;
|
||||
}
|
||||
}
|
||||
|
||||
if (status != __GCONV_OK)
|
||||
break;
|
||||
|
||||
/* Reset the output buffer pointer for the next round. */
|
||||
outbuf = data->__outbuf;
|
||||
}
|
||||
|
||||
#ifdef END_LOOP
|
||||
END_LOOP
|
||||
#endif
|
||||
|
||||
/* If we are supposed to consume all character store now all of the
|
||||
remaining characters in the `state' object. */
|
||||
#if MAX_NEEDED_FROM > 1 || MAX_NEEDED_TO > 1
|
||||
if (((MAX_NEEDED_FROM > 1 && MAX_NEEDED_TO > 1)
|
||||
|| (MAX_NEEDED_FROM > 1 && FROM_DIRECTION)
|
||||
|| (MAX_NEEDED_TO > 1 && !FROM_DIRECTION))
|
||||
&& __builtin_expect (consume_incomplete, 0)
|
||||
&& status == __GCONV_INCOMPLETE_INPUT)
|
||||
{
|
||||
# ifdef STORE_REST
|
||||
mbstate_t *state = data->__statep;
|
||||
|
||||
STORE_REST
|
||||
# else
|
||||
size_t cnt;
|
||||
|
||||
/* Make sure the remaining bytes fit into the state objects
|
||||
buffer. */
|
||||
assert (inend - *inptrp < 4);
|
||||
|
||||
for (cnt = 0; *inptrp < inend; ++cnt)
|
||||
data->__statep->__value.__wchb[cnt] = *(*inptrp)++;
|
||||
data->__statep->__count &= ~7;
|
||||
data->__statep->__count |= cnt;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#undef DEFINE_INIT
|
||||
#undef CHARSET_NAME
|
||||
#undef DEFINE_FINI
|
||||
#undef MIN_NEEDED_FROM
|
||||
#undef MIN_NEEDED_TO
|
||||
#undef MAX_NEEDED_FROM
|
||||
#undef MAX_NEEDED_TO
|
||||
#undef DEFINE_DIRECTION_OBJECTS
|
||||
#undef FROM_DIRECTION
|
||||
#undef EMIT_SHIFT_TO_INIT
|
||||
#undef FROM_LOOP
|
||||
#undef TO_LOOP
|
||||
#undef SAVE_RESET_STATE
|
||||
#undef RESET_INPUT_BUFFER
|
||||
#undef FUNCTION_NAME
|
||||
#undef PREPARE_LOOP
|
||||
#undef END_LOOP
|
||||
#undef ONE_DIRECTION
|
||||
#undef STORE_REST
|
341
newlib/libc/sys/linux/iconv/strtab.c
Normal file
341
newlib/libc/sys/linux/iconv/strtab.c
Normal file
@ -0,0 +1,341 @@
|
||||
/* C string table handling.
|
||||
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
|
||||
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
|
||||
struct Strent
|
||||
{
|
||||
const char *string;
|
||||
size_t len;
|
||||
struct Strent *next;
|
||||
struct Strent *left;
|
||||
struct Strent *right;
|
||||
size_t offset;
|
||||
char reverse[0];
|
||||
};
|
||||
|
||||
|
||||
struct memoryblock
|
||||
{
|
||||
struct memoryblock *next;
|
||||
char memory[0];
|
||||
};
|
||||
|
||||
|
||||
struct Strtab
|
||||
{
|
||||
struct Strent *root;
|
||||
struct memoryblock *memory;
|
||||
char *backp;
|
||||
size_t left;
|
||||
size_t total;
|
||||
|
||||
struct Strent null;
|
||||
};
|
||||
|
||||
|
||||
/* Cache for the pagesize. We correct this value a bit so that `malloc'
|
||||
is not allocating more than a page. */
|
||||
static size_t ps;
|
||||
|
||||
|
||||
extern void *xmalloc (size_t n) __attribute_malloc__;
|
||||
|
||||
/* Prototypes for our functions that are used from iconvconfig.c. If
|
||||
you change these, change also iconvconfig.c. */
|
||||
/* Create new C string table object in memory. */
|
||||
extern struct Strtab *strtabinit (void);
|
||||
|
||||
/* Free resources allocated for C string table ST. */
|
||||
extern void strtabfree (struct Strtab *st);
|
||||
|
||||
/* Add string STR (length LEN is != 0) to C string table ST. */
|
||||
extern struct Strent *strtabadd (struct Strtab *st, const char *str,
|
||||
size_t len);
|
||||
|
||||
/* Finalize string table ST and store size in *SIZE and return a pointer. */
|
||||
extern void *strtabfinalize (struct Strtab *st, size_t *size);
|
||||
|
||||
/* Get offset in string table for string associated with SE. */
|
||||
extern size_t strtaboffset (struct Strent *se);
|
||||
|
||||
|
||||
struct Strtab *
|
||||
strtabinit (void)
|
||||
{
|
||||
struct Strtab *ret;
|
||||
|
||||
if (ps == 0)
|
||||
{
|
||||
ps = sysconf (_SC_PAGESIZE) - 2 * sizeof (void *);
|
||||
assert (sizeof (struct memoryblock) < ps);
|
||||
}
|
||||
|
||||
ret = (struct Strtab *) calloc (1, sizeof (struct Strtab));
|
||||
if (ret != NULL)
|
||||
{
|
||||
ret->null.len = 1;
|
||||
ret->null.string = "";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
morememory (struct Strtab *st, size_t len)
|
||||
{
|
||||
struct memoryblock *newmem;
|
||||
|
||||
if (len < ps)
|
||||
len = ps;
|
||||
newmem = (struct memoryblock *) malloc (len);
|
||||
if (newmem == NULL)
|
||||
abort ();
|
||||
|
||||
newmem->next = st->memory;
|
||||
st->memory = newmem;
|
||||
st->backp = newmem->memory;
|
||||
st->left = len - offsetof (struct memoryblock, memory);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
strtabfree (struct Strtab *st)
|
||||
{
|
||||
struct memoryblock *mb = st->memory;
|
||||
|
||||
while (mb != NULL)
|
||||
{
|
||||
void *old = mb;
|
||||
mb = mb->next;
|
||||
free (old);
|
||||
}
|
||||
|
||||
free (st);
|
||||
}
|
||||
|
||||
|
||||
static struct Strent *
|
||||
newstring (struct Strtab *st, const char *str, size_t len)
|
||||
{
|
||||
struct Strent *newstr;
|
||||
size_t align;
|
||||
int i;
|
||||
|
||||
/* Compute the amount of padding needed to make the structure aligned. */
|
||||
align = ((__alignof__ (struct Strent)
|
||||
- (((uintptr_t) st->backp)
|
||||
& (__alignof__ (struct Strent) - 1)))
|
||||
& (__alignof__ (struct Strent) - 1));
|
||||
|
||||
/* Make sure there is enough room in the memory block. */
|
||||
if (st->left < align + sizeof (struct Strent) + len)
|
||||
{
|
||||
morememory (st, sizeof (struct Strent) + len);
|
||||
align = 0;
|
||||
}
|
||||
|
||||
/* Create the reserved string. */
|
||||
newstr = (struct Strent *) (st->backp + align);
|
||||
newstr->string = str;
|
||||
newstr->len = len;
|
||||
newstr->next = NULL;
|
||||
newstr->left = NULL;
|
||||
newstr->right = NULL;
|
||||
newstr->offset = 0;
|
||||
for (i = len - 2; i >= 0; --i)
|
||||
newstr->reverse[i] = str[len - 2 - i];
|
||||
newstr->reverse[len - 1] = '\0';
|
||||
st->backp += align + sizeof (struct Strent) + len;
|
||||
st->left -= align + sizeof (struct Strent) + len;
|
||||
|
||||
return newstr;
|
||||
}
|
||||
|
||||
|
||||
/* XXX This function should definitely be rewritten to use a balancing
|
||||
tree algorith (AVL, red-black trees). For now a simple, correct
|
||||
implementation is enough. */
|
||||
static struct Strent **
|
||||
searchstring (struct Strent **sep, struct Strent *newstr)
|
||||
{
|
||||
int cmpres;
|
||||
|
||||
/* More strings? */
|
||||
if (*sep == NULL)
|
||||
{
|
||||
*sep = newstr;
|
||||
return sep;
|
||||
}
|
||||
|
||||
/* Compare the strings. */
|
||||
cmpres = memcmp ((*sep)->reverse, newstr->reverse,
|
||||
MIN ((*sep)->len, newstr->len) - 1);
|
||||
if (cmpres == 0)
|
||||
/* We found a matching string. */
|
||||
return sep;
|
||||
else if (cmpres > 0)
|
||||
return searchstring (&(*sep)->left, newstr);
|
||||
else
|
||||
return searchstring (&(*sep)->right, newstr);
|
||||
}
|
||||
|
||||
|
||||
/* Add new string. The actual string is assumed to be permanent. */
|
||||
struct Strent *
|
||||
strtabadd (struct Strtab *st, const char *str, size_t len)
|
||||
{
|
||||
struct Strent *newstr;
|
||||
struct Strent **sep;
|
||||
|
||||
/* Compute the string length if the caller doesn't know it. */
|
||||
if (len == 0)
|
||||
len = strlen (str) + 1;
|
||||
|
||||
/* Make sure all "" strings get offset 0. */
|
||||
if (len == 1)
|
||||
return &st->null;
|
||||
|
||||
/* Allocate memory for the new string and its associated information. */
|
||||
newstr = newstring (st, str, len);
|
||||
|
||||
/* Search in the array for the place to insert the string. If there
|
||||
is no string with matching prefix and no string with matching
|
||||
leading substring, create a new entry. */
|
||||
sep = searchstring (&st->root, newstr);
|
||||
if (*sep != newstr)
|
||||
{
|
||||
/* This is not the same entry. This means we have a prefix match. */
|
||||
if ((*sep)->len > newstr->len)
|
||||
{
|
||||
struct Strent *subs;
|
||||
|
||||
for (subs = (*sep)->next; subs; subs = subs->next)
|
||||
if (subs->len == newstr->len)
|
||||
{
|
||||
/* We have an exact match with a substring. Free the memory
|
||||
we allocated. */
|
||||
st->left += st->backp - (char *) newstr;
|
||||
st->backp = (char *) newstr;
|
||||
|
||||
return subs;
|
||||
}
|
||||
|
||||
/* We have a new substring. This means we don't need the reverse
|
||||
string of this entry anymore. */
|
||||
st->backp -= newstr->len;
|
||||
st->left += newstr->len;
|
||||
|
||||
newstr->next = (*sep)->next;
|
||||
(*sep)->next = newstr;
|
||||
}
|
||||
else if ((*sep)->len != newstr->len)
|
||||
{
|
||||
/* When we get here it means that the string we are about to
|
||||
add has a common prefix with a string we already have but
|
||||
it is longer. In this case we have to put it first. */
|
||||
st->total += newstr->len - (*sep)->len;
|
||||
newstr->next = *sep;
|
||||
newstr->left = (*sep)->left;
|
||||
newstr->right = (*sep)->right;
|
||||
*sep = newstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have an exact match. Free the memory we allocated. */
|
||||
st->left += st->backp - (char *) newstr;
|
||||
st->backp = (char *) newstr;
|
||||
|
||||
newstr = *sep;
|
||||
}
|
||||
}
|
||||
else
|
||||
st->total += newstr->len;
|
||||
|
||||
return newstr;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
copystrings (struct Strent *nodep, char **freep, size_t *offsetp)
|
||||
{
|
||||
struct Strent *subs;
|
||||
|
||||
if (nodep->left != NULL)
|
||||
copystrings (nodep->left, freep, offsetp);
|
||||
|
||||
/* Process the current node. */
|
||||
nodep->offset = *offsetp;
|
||||
*freep = (char *) memcpy (*freep, nodep->string, nodep->len);
|
||||
*freep += nodep->len;
|
||||
*offsetp += nodep->len;
|
||||
|
||||
for (subs = nodep->next; subs != NULL; subs = subs->next)
|
||||
{
|
||||
assert (subs->len < nodep->len);
|
||||
subs->offset = nodep->offset + nodep->len - subs->len;
|
||||
}
|
||||
|
||||
if (nodep->right != NULL)
|
||||
copystrings (nodep->right, freep, offsetp);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
strtabfinalize (struct Strtab *st, size_t *size)
|
||||
{
|
||||
size_t copylen;
|
||||
char *endp;
|
||||
char *retval;
|
||||
|
||||
/* Fill in the information. */
|
||||
endp = retval = (char *) xmalloc (st->total + 1);
|
||||
|
||||
/* Always put an empty string at the beginning so that a zero offset
|
||||
can mean error. */
|
||||
*endp++ = '\0';
|
||||
|
||||
/* Now run through the tree and add all the string while also updating
|
||||
the offset members of the elfstrent records. */
|
||||
copylen = 1;
|
||||
copystrings (st->root, &endp, ©len);
|
||||
assert (copylen == st->total + 1);
|
||||
assert (endp = retval + st->total + 1);
|
||||
*size = copylen;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
strtaboffset (struct Strent *se)
|
||||
{
|
||||
return se->offset;
|
||||
}
|
109
newlib/libc/sys/linux/include/arpa/ftp.h
Normal file
109
newlib/libc/sys/linux/include/arpa/ftp.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)ftp.h 8.1 (Berkeley) 6/2/93
|
||||
*/
|
||||
|
||||
#ifndef _ARPA_FTP_H_
|
||||
#define _ARPA_FTP_H_
|
||||
|
||||
/* 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 /* !_FTP_H_ */
|
156
newlib/libc/sys/linux/include/arpa/inet.h
Normal file
156
newlib/libc/sys/linux/include/arpa/inet.h
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* -
|
||||
* 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.
|
||||
*
|
||||
* @(#)inet.h 8.1 (Berkeley) 6/2/93
|
||||
* From: Id: inet.h,v 8.5 1997/01/29 08:48:09 vixie Exp $
|
||||
* $FreeBSD: src/include/arpa/inet.h,v 1.22 2002/04/10 10:51:53 mike Exp $
|
||||
*/
|
||||
|
||||
#ifndef _ARPA_INET_H_
|
||||
#define _ARPA_INET_H_
|
||||
|
||||
/* External definitions for functions in inet(3), addr2ascii(3) */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <machine/ansi.h>
|
||||
|
||||
/* Required for byteorder(3) functions. */
|
||||
#include <machine/endian.h>
|
||||
|
||||
#define INET_ADDRSTRLEN 16
|
||||
#define INET6_ADDRSTRLEN 46
|
||||
|
||||
#ifndef _UINT16_T_DECLARED
|
||||
typedef __uint16_t uint16_t;
|
||||
#define _UINT16_T_DECLARED
|
||||
#endif
|
||||
|
||||
#ifndef _UINT32_T_DECLARED
|
||||
typedef __uint32_t uint32_t;
|
||||
#define _UINT32_T_DECLARED
|
||||
#endif
|
||||
|
||||
#ifndef _IN_ADDR_T_DECLARED
|
||||
typedef uint32_t in_addr_t;
|
||||
#define _IN_ADDR_T_DECLARED
|
||||
#endif
|
||||
|
||||
#ifndef _IN_PORT_T_DECLARED
|
||||
typedef uint16_t in_port_t;
|
||||
#define _IN_PORT_T_DECLARED
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_SOURCE
|
||||
#ifdef _BSD_SIZE_T_
|
||||
typedef _BSD_SIZE_T_ size_t;
|
||||
#undef _BSD_SIZE_T_
|
||||
#endif
|
||||
#endif /* !_POSIX_SOURCE */
|
||||
|
||||
/*
|
||||
* XXX socklen_t is used by a POSIX.1-2001 interface, but not required by
|
||||
* POSIX.1-2001.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __socklen_t_defined
|
||||
typedef unsigned int socklen_t;
|
||||
#define __socklen_t_defined 1
|
||||
#endif
|
||||
|
||||
#ifdef _BSD_SOCKLEN_T_
|
||||
typedef _BSD_SOCKLEN_T_ socklen_t;
|
||||
#undef _BSD_SOCKLEN_T_
|
||||
#endif
|
||||
|
||||
#ifndef _STRUCT_IN_ADDR_DECLARED
|
||||
struct in_addr {
|
||||
in_addr_t s_addr;
|
||||
};
|
||||
#define _STRUCT_IN_ADDR_DECLARED
|
||||
#endif
|
||||
|
||||
#define inet_addr __inet_addr
|
||||
#define inet_aton __inet_aton
|
||||
#define inet_lnaof __inet_lnaof
|
||||
#define inet_makeaddr __inet_makeaddr
|
||||
#define inet_neta __inet_neta
|
||||
#define inet_netof __inet_netof
|
||||
#define inet_network __inet_network
|
||||
#define inet_net_ntop __inet_net_ntop
|
||||
#define inet_net_pton __inet_net_pton
|
||||
#define inet_ntoa __inet_ntoa
|
||||
#define inet_pton __inet_pton
|
||||
#define inet_ntop __inet_ntop
|
||||
#define inet_nsap_addr __inet_nsap_addr
|
||||
#define inet_nsap_ntoa __inet_nsap_ntoa
|
||||
|
||||
__BEGIN_DECLS
|
||||
in_addr_t inet_addr(const char *);
|
||||
char *inet_ntoa(struct in_addr);
|
||||
const char *inet_ntop(int, const void *, char *, socklen_t);
|
||||
int inet_pton(int, const char *, void *);
|
||||
|
||||
int ascii2addr(int, const char *, void *);
|
||||
char *addr2ascii(int, const void *, int, char *);
|
||||
int inet_aton(const char *, struct in_addr *);
|
||||
in_addr_t inet_lnaof(struct in_addr);
|
||||
struct in_addr inet_makeaddr(in_addr_t, in_addr_t);
|
||||
char * inet_neta(in_addr_t, char *, size_t);
|
||||
in_addr_t inet_netof(struct in_addr);
|
||||
in_addr_t inet_network(const char *);
|
||||
char *inet_net_ntop(int, const void *, int, char *, size_t);
|
||||
int inet_net_pton(int, const char *, void *, size_t);
|
||||
unsigned inet_nsap_addr(const char *, unsigned char *, int);
|
||||
char *inet_nsap_ntoa(int, const unsigned char *, char *);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_ARPA_INET_H_ */
|
449
newlib/libc/sys/linux/include/arpa/nameser.h
Normal file
449
newlib/libc/sys/linux/include/arpa/nameser.h
Normal file
@ -0,0 +1,449 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* From: Id: nameser.h,v 8.16 1998/02/06 00:35:58 halley Exp
|
||||
* $FreeBSD: src/include/arpa/nameser.h,v 1.16 2002/03/23 17:24:55 imp Exp $
|
||||
*/
|
||||
|
||||
#ifndef _ARPA_NAMESER_H_
|
||||
#define _ARPA_NAMESER_H_
|
||||
|
||||
#define BIND_4_COMPAT
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/cdefs.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 (__NAMESER > 19931104)". do not
|
||||
* compare for equality; rather, use it to determine whether your libnameser.a
|
||||
* is new enough to contain a certain feature.
|
||||
*/
|
||||
|
||||
/* XXXRTH I made this bigger than __BIND in 4.9.5 T6B */
|
||||
#define __NAMESER 19961001 /* 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]; /* XXX need to malloc */
|
||||
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) ((rr).type + 0)
|
||||
#define ns_rr_class(rr) ((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
|
||||
} 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 RR-like structure is particular to UPDATE.
|
||||
*/
|
||||
struct ns_updrec {
|
||||
struct ns_updrec *r_prev; /* prev record */
|
||||
struct ns_updrec *r_next; /* next record */
|
||||
u_int8_t r_section; /* ZONE/PREREQUISITE/UPDATE */
|
||||
char * r_dname; /* owner of the RR */
|
||||
u_int16_t r_class; /* class number */
|
||||
u_int16_t r_type; /* type number */
|
||||
u_int32_t r_ttl; /* time to live */
|
||||
u_char * r_data; /* rdata fields as text string */
|
||||
u_int16_t r_size; /* size of r_data field */
|
||||
int r_opcode; /* type of operation */
|
||||
/* following fields for private use by the resolver/server routines */
|
||||
struct ns_updrec *r_grpnext; /* next record when grouped */
|
||||
struct databuf *r_dp; /* databuf to process */
|
||||
struct databuf *r_deldp; /* databuf's deleted/overwritten */
|
||||
u_int16_t r_zone; /* zone number on server */
|
||||
};
|
||||
typedef struct ns_updrec ns_updrec;
|
||||
|
||||
/*
|
||||
* Currently defined type values for resources and queries.
|
||||
*/
|
||||
typedef enum __ns_type {
|
||||
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_opt = 41, /* OPT pseudo-RR, RFC2761 */
|
||||
/* Query type values which do not appear in resource records. */
|
||||
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_max = 65536
|
||||
} ns_type;
|
||||
|
||||
/*
|
||||
* Values for class field
|
||||
*/
|
||||
typedef enum __ns_class {
|
||||
ns_c_in = 1, /* Internet. */
|
||||
/* Class 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;
|
||||
|
||||
/*
|
||||
* 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_EXPERIMENTAL 0x2000 /* Security is *mandatory* if bit=0 */
|
||||
#define NS_KEY_RESERVED3 0x1000 /* reserved - must be zero */
|
||||
#define NS_KEY_RESERVED4 0x0800 /* reserved - must be zero */
|
||||
#define NS_KEY_USERACCOUNT 0x0400 /* key is assoc. with a user acct */
|
||||
#define NS_KEY_ENTITY 0x0200 /* key is assoc. with entity eg host */
|
||||
#define NS_KEY_ZONEKEY 0x0100 /* key is zone key */
|
||||
#define NS_KEY_IPSEC 0x0080 /* key is for IPSEC (host or user)*/
|
||||
#define NS_KEY_EMAIL 0x0040 /* key is for email (MIME security) */
|
||||
#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_RESERVED3 | \
|
||||
NS_KEY_RESERVED4 | \
|
||||
NS_KEY_RESERVED10 | \
|
||||
NS_KEY_RESERVED11 )
|
||||
|
||||
/* 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_EXPIRE_ONLY 253 /* No alg, no security */
|
||||
#define NS_ALG_PRIVATE_OID 254 /* Key begins with OID giving alg */
|
||||
|
||||
/* 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)
|
||||
|
||||
/* 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)))
|
||||
|
||||
|
||||
/*
|
||||
* Inline versions of get/put short/long. Pointer is advanced.
|
||||
*/
|
||||
#define NS_GET16(s, cp) { \
|
||||
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; \
|
||||
}
|
||||
|
||||
#define NS_GET32(l, cp) { \
|
||||
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; \
|
||||
}
|
||||
|
||||
#define NS_PUT16(s, cp) { \
|
||||
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; \
|
||||
}
|
||||
|
||||
#define NS_PUT32(l, cp) { \
|
||||
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; \
|
||||
}
|
||||
|
||||
/*
|
||||
* ANSI C identifier hiding.
|
||||
*/
|
||||
#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_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_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
|
||||
|
||||
__BEGIN_DECLS
|
||||
u_int ns_get16(const u_char *);
|
||||
u_long ns_get32(const u_char *);
|
||||
void ns_put16(u_int, u_char *);
|
||||
void ns_put32(u_long, u_char *);
|
||||
int ns_initparse(const u_char *, int, ns_msg *);
|
||||
int ns_parserr(ns_msg *, ns_sect, int, ns_rr *);
|
||||
int ns_sprintrr(const ns_msg *, const ns_rr *,
|
||||
const char *, const char *, char *, size_t);
|
||||
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);
|
||||
int ns_format_ttl(u_long, char *, size_t);
|
||||
int ns_parse_ttl(const char *, u_long *);
|
||||
int ns_name_ntop(const u_char *, char *, size_t);
|
||||
int ns_name_pton(const char *, u_char *, size_t);
|
||||
int ns_name_unpack(const u_char *, const u_char *,
|
||||
const u_char *, u_char *, size_t);
|
||||
int ns_name_pack(const u_char *, u_char *, int,
|
||||
const u_char **, const u_char **);
|
||||
int ns_name_uncompress(const u_char *, const u_char *,
|
||||
const u_char *, char *, size_t);
|
||||
int ns_name_compress(const char *, u_char *, size_t,
|
||||
const u_char **, const u_char **);
|
||||
int ns_name_skip(const u_char **, const u_char *);
|
||||
__END_DECLS
|
||||
|
||||
#ifdef BIND_4_COMPAT
|
||||
#include <arpa/nameser_compat.h>
|
||||
#endif
|
||||
|
||||
#endif /* !_ARPA_NAMESER_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user