diff options
author | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-16 18:49:26 +0900 |
---|---|---|
committer | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-30 00:39:06 +0900 |
commit | fcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch) | |
tree | 64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/tool |
Fresh start
Diffstat (limited to 'jni/ruby/tool')
47 files changed, 11453 insertions, 0 deletions
diff --git a/jni/ruby/tool/asm_parse.rb b/jni/ruby/tool/asm_parse.rb new file mode 100644 index 0000000..e39580c --- /dev/null +++ b/jni/ruby/tool/asm_parse.rb @@ -0,0 +1,51 @@ +stat = {} + +while line = ARGF.gets + if /\[start\] (\w+)/ =~ line + name = $1 + puts '--------------------------------------------------------------' + puts line + size = 0 + len = 0 + + while line = ARGF.gets + if /\[start\] (\w+)/ =~ line + puts "\t; # length: #{len}, size: #{size}" + puts "\t; # !!" + stat[name] = [len, size] + # + name = $1 + puts '--------------------------------------------------------------' + puts line + size = 0 + len = 0 + next + end + + unless /(\ALM)|(\ALB)|(\A\.)|(\A\/)/ =~ line + puts line + if /\[length = (\d+)\]/ =~ line + len += $1.to_i + size += 1 + end + end + + + if /__NEXT_INSN__/ !~ line && /\[end \] (\w+)/ =~ line + ename = $1 + if name != ename + puts "!! start with #{name}, but end with #{ename}" + end + stat[ename] = [len, size] + puts "\t; # length: #{len}, size: #{size}" + break + end + end + end +end + +stat.sort_by{|a, b| -b[0] * 1000 - a[0]}.each{|a, b| + puts "#{a}\t#{b.join("\t")}" +} +puts "total length :\t#{stat.inject(0){|r, e| r+e[1][0]}}" +puts "total size :\t#{stat.inject(0){|r, e| r+e[1][1]}}" diff --git a/jni/ruby/tool/bisect.sh b/jni/ruby/tool/bisect.sh new file mode 100755 index 0000000..fb22bf4 --- /dev/null +++ b/jni/ruby/tool/bisect.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# usage: +# edit $(srcdir)/test.rb +# git bisect start `git svn find-rev <rBADREV>` `git svn find-rev <rGOODREV>` +# cd <builddir> +# make bisect (or bisect-ruby for full ruby) + +if [ "x" = "x$MAKE" ]; then + MAKE=make +fi + +case $1 in + miniruby | ruby ) # (miniruby|ruby) <srcdir> + srcdir=$2 + builddir=`pwd` # assume pwd is builddir + path=$builddir/_bisect.sh + echo "path: $path" + cp $0 $path + cd $srcdir + echo "git bisect run $path run-$1" + git bisect run $path run-$1 + ;; + run-miniruby ) + cd ${0%/*} # assume a copy of this script is in builddir + $MAKE Makefile + $MAKE mini || exit 125 + $MAKE run || exit 1 + ;; + run-ruby ) + cd ${0%/*} # assume a copy of this script is in builddir + $MAKE Makefile + $MAKE program || exit 125 + $MAKE runruby || exit 1 + ;; + "" ) + echo foo bar + ;; + * ) + echo unkown command "'$cmd'" + ;; +esac +exit 0 diff --git a/jni/ruby/tool/build-transcode b/jni/ruby/tool/build-transcode new file mode 100755 index 0000000..fa71155 --- /dev/null +++ b/jni/ruby/tool/build-transcode @@ -0,0 +1,16 @@ +#!/bin/sh + +[ "$1" -a -d "$1" ] && { cd "$1" || exit $?; } && shift +[ "$#" = 0 ] && set enc/trans/*.trans +for src; do + case "$src" in + *.trans) + c="`dirname $src`/`basename $src .trans`.c" + ${BASERUBY-ruby} tool/transcode-tblgen.rb -vo "$c" "$src" + ;; + *) + echo "$0: don't know how to deal with $src" + continue + ;; + esac +done diff --git a/jni/ruby/tool/change_maker.rb b/jni/ruby/tool/change_maker.rb new file mode 100755 index 0000000..2bbc275 --- /dev/null +++ b/jni/ruby/tool/change_maker.rb @@ -0,0 +1,34 @@ +#! ./miniruby + +def diff2index(cmd, *argv) + lines = [] + path = nil + output = `#{cmd} #{argv.join(" ")}` + if defined? Encoding::BINARY + output.force_encoding Encoding::BINARY + end + output.each_line do |line| + case line + when /^Index: (\S*)/, /^diff --git [a-z]\/(\S*) [a-z]\/\1/ + path = $1 + when /^@@\s*-[,\d]+ +\+(\d+)[,\d]*\s*@@(?: +([A-Za-z_][A-Za-z_0-9 ]*[A-Za-z_0-9]))?/ + line = $1.to_i + ent = "\t* #{path}" + ent << " (#{$2})" if $2 + lines << "#{ent}:" + end + end + lines.uniq! + lines.empty? ? nil : lines +end + +if `svnversion` =~ /^\d+/ + cmd = "svn diff --diff-cmd=diff -x-pU0" + change = diff2index(cmd, ARGV) +elsif File.directory?(".git") + cmd = "git diff -U0" + change = diff2index(cmd, ARGV) || diff2index(cmd, "--cached", ARGV) +else + abort "does not seem to be under a vcs" +end +puts change if change diff --git a/jni/ruby/tool/config.guess b/jni/ruby/tool/config.guess new file mode 100755 index 0000000..fddac42 --- /dev/null +++ b/jni/ruby/tool/config.guess @@ -0,0 +1,1438 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-07-03' + +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches to <config-patches@gnu.org>. + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include <features.h> + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/jni/ruby/tool/config.sub b/jni/ruby/tool/config.sub new file mode 100755 index 0000000..f018151 --- /dev/null +++ b/jni/ruby/tool/config.sub @@ -0,0 +1,1813 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-07-28' + +# This file 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 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to <config-patches@gnu.org>. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/jni/ruby/tool/downloader.rb b/jni/ruby/tool/downloader.rb new file mode 100644 index 0000000..8f169d5 --- /dev/null +++ b/jni/ruby/tool/downloader.rb @@ -0,0 +1,178 @@ +require 'open-uri' +begin + require 'net/https' + $rubygems_schema = 'https' + + # open-uri of ruby 2.2.0 accept an array of PEMs as ssl_ca_cert, but old + # versions are not. so, patching OpenSSL::X509::Store#add_file instead. + class OpenSSL::X509::Store + alias orig_add_file add_file + def add_file(pems) + Array(pems).each do |pem| + if File.directory?(pem) + add_path pem + else + orig_add_file pem + end + end + end + end + # since open-uri internally checks ssl_ca_cert by File.directory?, to allow + # accept an array. + class <<File + alias orig_directory? directory? + def File.directory? files + files.is_a?(Array) ? false : orig_directory?(files) + end + end +rescue LoadError + $rubygems_schema = 'http' +end + +class Downloader + class GNU < self + def self.download(name, *rest) + super("http://gcc.gnu.org/git/?p=gcc.git;a=blob_plain;f=#{name};hb=master", name, *rest) + end + end + + class RubyGems < self + def self.download(name, dir = nil, ims = true, options = {}) + options[:ssl_ca_cert] = Dir.glob(File.expand_path("../lib/rubygems/ssl_certs/*.pem", File.dirname(__FILE__))) + if $rubygems_schema != 'https' + warn "*** using http instead of https ***" + end + super("#{$rubygems_schema}://rubygems.org/downloads/#{name}", name, dir, ims, options) + end + end + + Gems = RubyGems + + class Unicode < self + def self.download(name, *rest) + super("http://www.unicode.org/Public/#{name}", name, *rest) + end + end + + def self.mode_for(data) + /\A#!/ =~ data ? 0755 : 0644 + end + + def self.http_options(file, since) + options = {} + if since + case since + when true + since = (File.mtime(file).httpdate rescue nil) + when Time + since = since.httpdate + end + if since + options['If-Modified-Since'] = since + end + end + options + end + + # Downloader.download(url, name, [dir, [ims]]) + # + # Update a file from url if newer version is available. + # Creates the file if the file doesn't yet exist; however, the + # directory where the file is being created has to exist already. + # If +ims+ is false, always download url regardless of its last + # modified time. + # + # Example usage: + # download 'http://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt', + # 'UnicodeData.txt', 'enc/unicode/data' + def self.download(url, name, dir = nil, ims = true, options = {}) + file = dir ? File.join(dir, File.basename(name)) : name + if ims.nil? and File.exist?(file) + if $VERBOSE + $stdout.puts "#{name} already exists" + $stdout.flush + end + return true + end + url = URI(url) + if $VERBOSE + $stdout.print "downloading #{name} ... " + $stdout.flush + end + begin + data = url.read(options.merge(http_options(file, ims.nil? ? true : ims))) + rescue OpenURI::HTTPError => http_error + if http_error.message =~ /^304 / # 304 Not Modified + if $VERBOSE + $stdout.puts "not modified" + $stdout.flush + end + return true + end + raise + rescue Timeout::Error + if ims.nil? and File.exist?(file) + puts "Request for #{url} timed out, using old version." + return true + end + raise + rescue SocketError + if ims.nil? and File.exist?(file) + puts "No network connection, unable to download #{url}, using old version." + return true + end + raise + end + mtime = nil + open(file, "wb", 0600) do |f| + f.write(data) + f.chmod(mode_for(data)) + mtime = data.meta["last-modified"] + end + if mtime + mtime = Time.httpdate(mtime) + File.utime(mtime, mtime, file) + end + if $VERBOSE + $stdout.puts "done" + $stdout.flush + end + true + rescue => e + raise "failed to download #{name}\n#{e.message}: #{url}" + end +end + +if $0 == __FILE__ + ims = true + until ARGV.empty? + case ARGV[0] + when '-d' + destdir = ARGV[1] + ARGV.shift + when '-e' + ims = nil + when '-a' + ims = true + when /\A-/ + abort "#{$0}: unknown option #{ARGV[0]}" + else + break + end + ARGV.shift + end + dl = Downloader.constants.find do |name| + ARGV[0].casecmp(name.to_s) == 0 + end unless ARGV.empty? + $VERBOSE = true + if dl + dl = Downloader.const_get(dl) + ARGV.shift + ARGV.each do |name| + dl.download(name, destdir, ims) + end + else + abort "usage: #{$0} url name" unless ARGV.size == 2 + Downloader.download(ARGV[0], ARGV[1], destdir, ims) + end +end diff --git a/jni/ruby/tool/enc-emoji-citrus-gen.rb b/jni/ruby/tool/enc-emoji-citrus-gen.rb new file mode 100644 index 0000000..5037cbd --- /dev/null +++ b/jni/ruby/tool/enc-emoji-citrus-gen.rb @@ -0,0 +1,131 @@ +require File.expand_path('../jisx0208', __FILE__) + +ENCODES = [ + { + :name => "SHIFT_JIS-DOCOMO", + :src_zone => [0xF8..0xFC, 0x40..0xFC, 8], + :dst_ilseq => 0xFFFE, + :map => [ + [0xE63E..0xE757, JISX0208::Char.from_sjis(0xF89F)], + ], + }, + { + :name => "ISO-2022-JP-KDDI", + :src_zone => [0x21..0x7E, 0x21..0x7E, 8], + :dst_ilseq => 0xFFFE, + :map => [ + [0xE468..0xE5B4, JISX0208::Char.new(0x7521)], + [0xE5B5..0xE5CC, JISX0208::Char.new(0x7867)], + [0xE5CD..0xE5DF, JISX0208::Char.new(0x7921)], + [0xEA80..0xEAFA, JISX0208::Char.new(0x7934)], + [0xEAFB..0xEB0D, JISX0208::Char.new(0x7854)], + [0xEB0E..0xEB8E, JISX0208::Char.new(0x7A51)], + ], + }, + { + :name => "SHIFT_JIS-KDDI", + :src_zone => [0xF3..0xFC, 0x40..0xFC, 8], + :dst_ilseq => 0xFFFE, + :map => [ + [0xE468..0xE5B4, JISX0208::Char.from_sjis(0xF640)], + [0xE5B5..0xE5CC, JISX0208::Char.from_sjis(0xF7E5)], + [0xE5CD..0xE5DF, JISX0208::Char.from_sjis(0xF340)], + [0xEA80..0xEAFA, JISX0208::Char.from_sjis(0xF353)], + [0xEAFB..0xEB0D, JISX0208::Char.from_sjis(0xF7D2)], + [0xEB0E..0xEB8E, JISX0208::Char.from_sjis(0xF3CF)], + ], + }, + { + :name => "SHIFT_JIS-SOFTBANK", + :src_zone => [0xF3..0xFC, 0x40..0xFC, 8], + :dst_ilseq => 0xFFFE, + :map => [ + [0xE001..0xE05A, JISX0208::Char.from_sjis(0xF941)], + [0xE101..0xE15A, JISX0208::Char.from_sjis(0xF741)], + [0xE201..0xE25A, JISX0208::Char.from_sjis(0xF7A1)], + [0xE301..0xE34D, JISX0208::Char.from_sjis(0xF9A1)], + [0xE401..0xE44C, JISX0208::Char.from_sjis(0xFB41)], + [0xE501..0xE53E, JISX0208::Char.from_sjis(0xFBA1)], + ], + }, +] + +def zone(*args) + bits = args.pop + [*args.map{|range| "0x%02X-0x%02X" % [range.begin, range.end] }, bits].join(' / ') +end + +def header(params) + (<<END_HEADER_TEMPLATE % [params[:name], zone(*params[:src_zone]), params[:dst_ilseq]]) +# DO NOT EDIT THIS FILE DIRECTLY + +TYPE ROWCOL +NAME %s +SRC_ZONE %s +OOB_MODE ILSEQ +DST_ILSEQ 0x%04X +DST_UNIT_BITS 16 +END_HEADER_TEMPLATE +end + +def generate_to_ucs(params, pairs) + pairs.sort_by! {|u, c| c } + name = "EMOJI_#{params[:name]}%UCS" + open("#{name}.src", "w") do |io| + io.print header(params.merge(name: name.tr('%', '/'))) + io.puts + io.puts "BEGIN_MAP" + io.print pairs.inject("") {|acc, uc| acc += "0x%04X = 0x%04X\n" % uc.reverse } + io.puts "END_MAP" + end +end + +def generate_from_ucs(params, pairs) + pairs.sort_by! {|u, c| u } + name = "UCS%EMOJI_#{params[:name]}" + open("#{name}.src", "w") do |io| + io.print header(params.merge(name: name.tr('%', '/'))) + io.puts + io.puts "BEGIN_MAP" + io.print pairs.inject("") {|acc, uc| acc += "0x%04X = 0x%04X\n" % uc } + io.puts "END_MAP" + end +end + +def make_pairs(code_map) + pairs = code_map.inject([]) {|acc, (range, ch)| + acc += range.map{|uni| pair = [uni, Integer(ch)]; ch = ch.succ; next pair } + } +end + +ENCODES.each do |params| + pairs = make_pairs(params[:map], ¶ms[:conv]) + generate_to_ucs(params, pairs) + generate_from_ucs(params, pairs) +end + +# generate KDDI-UNDOC for Shift_JIS-KDDI +kddi_sjis_map = ENCODES.select{|enc| enc[:name] == "SHIFT_JIS-KDDI"}.first[:map] +pairs = kddi_sjis_map.inject([]) {|acc, (range, ch)| + acc += range.map{|uni| pair = [ch.to_sjis - 0x700, Integer(ch)]; ch = ch.succ; next pair } +} +params = { + :name => "SHIFT_JIS-KDDI-UNDOC", + :src_zone => [0xF3..0xFC, 0x40..0xFC, 8], + :dst_ilseq => 0xFFFE, +} +generate_from_ucs(params, pairs) +generate_to_ucs(params, pairs) + +# generate KDDI-UNDOC for ISO-2022-JP-KDDI +kddi_2022_map = ENCODES.select{|enc| enc[:name] == "ISO-2022-JP-KDDI"}.first[:map] +pairs = kddi_2022_map.each_with_index.inject([]) {|acc, ((range, ch), i)| + sjis = kddi_sjis_map[i][1] + acc += range.map{|uni| pair = [sjis.to_sjis - 0x700, Integer(ch)]; ch = ch.succ; sjis = sjis.succ; next pair } +} +params = { + :name => "ISO-2022-JP-KDDI-UNDOC", + :src_zone => [0x21..0x7E, 0x21..0x7E, 8], + :dst_ilseq => 0xFFFE, +} +generate_from_ucs(params, pairs) diff --git a/jni/ruby/tool/enc-emoji4unicode.rb b/jni/ruby/tool/enc-emoji4unicode.rb new file mode 100644 index 0000000..1e7d459 --- /dev/null +++ b/jni/ruby/tool/enc-emoji4unicode.rb @@ -0,0 +1,133 @@ +#!/usr/bin/env ruby + +# example: +# ./enc-emoji4unicode.rb emoji4unicode.xml > ../enc/trans/emoji-exchange-tbl.rb + +require 'rexml/document' +require File.expand_path("../transcode-tblgen", __FILE__) + +class EmojiTable + VERBOSE_MODE = false + + def initialize(xml_path) + @doc = REXML::Document.new File.open(xml_path) + @kddi_undoc = make_kddi_undoc_map() + end + + def conversion(from_carrier, to_carrier, &block) + REXML::XPath.each(@doc.root, '//e') do |e| + from = e.attribute(from_carrier.downcase).to_s + to = e.attribute(to_carrier.downcase).to_s + text_fallback = e.attribute('text_fallback').to_s + name = e.attribute('name').to_s + if from =~ /^(?:\*|\+)(.+)$/ # proposed or unified + from = $1 + end + if from.empty? || from !~ /^[0-9A-F]+$/ + # do nothing + else + from_utf8 = [from.hex].pack("U").unpack("H*").first + if to =~ /^(?:>|\*)?([0-9A-F\+]+)$/ + str_to = $1 + if str_to =~ /^\+/ # unicode "proposed" begins at "+" + proposal = true + str_to.sub!(/^\+/, '') + else + proposal = false + end + tos = str_to.split('+') + to_utf8 = tos.map(&:hex).pack("U*").unpack("H*").first + comment = "[%s] U+%X -> %s" % [name, from.hex, tos.map{|c| "U+%X"%c.hex}.join(' ')] + block.call(:from => from_utf8, + :to => to_utf8, + :comment => comment, + :fallback => false, + :proposal => proposal) + elsif to.empty? + if text_fallback.empty? + comment = "[%s] U+%X -> U+3013 (GETA)" % [name, from.hex] + block.call(:from => from_utf8, + :to => "\u{3013}".unpack("H*").first, + :comment => comment, # geta + :fallback => true, + :proposal => false) + else + to_utf8 = text_fallback.unpack("H*").first + comment = %([%s] U+%X -> "%s") % [name, from.hex, text_fallback] + block.call(:from => from_utf8, + :to => to_utf8, + :comment => comment, + :fallback => true, + :proposal => false) + end + else + raise "something wrong: %s -> %s" % [from, to] + end + end + end + end + + def generate(io, from_carrier, to_carrier) + from_encoding = (from_carrier == "Unicode") ? "UTF-8" : "UTF8-"+from_carrier + to_encoding = (to_carrier == "Unicode" ) ? "UTF-8" : "UTF8-"+to_carrier + io.puts "EMOJI_EXCHANGE_TBL['#{from_encoding}']['#{to_encoding}'] = [" + io.puts " # for documented codepoints" if from_carrier == "KDDI" + self.conversion(from_carrier, to_carrier) do |params| + from, to = params[:from], %Q{"#{params[:to]}"} + to = ":undef" if params[:fallback] || params[:proposal] + io.puts %{ ["#{from}", #{to}], # #{params[:comment]}} + end + if from_carrier == "KDDI" + io.puts " # for undocumented codepoints" + self.conversion(from_carrier, to_carrier) do |params| + from, to = params[:from], %Q{"#{params[:to]}"} + to = ":undef" if params[:fallback] || params[:proposal] + unicode = utf8_to_ucs(from) + undoc = ucs_to_utf8(@kddi_undoc[unicode]) + io.puts %{ ["#{undoc}", #{to}], # #{params[:comment]}} + end + end + io.puts "]" + io.puts + end + + private + + def utf8_to_ucs(cp) + return [cp].pack("H*").unpack("U*").first + end + + def ucs_to_utf8(cp) + return [cp].pack("U*").unpack("H*").first + end + + def make_kddi_undoc_map() + pub_to_sjis = citrus_decode_mapsrc( + "mskanji", 2, "UCS/EMOJI_SHIFT_JIS-KDDI").sort_by{|u, s| s} + sjis_to_undoc = citrus_decode_mapsrc( + "mskanji", 2, "EMOJI_SHIFT_JIS-KDDI-UNDOC/UCS").sort_by{|s, u| s} + return pub_to_sjis.zip(sjis_to_undoc).inject({}) {|h, rec| + raise "no match sjis codepoint" if rec[0][1] != rec[1][0] + h[rec[0][0]] = rec[1][1] + next h + } + end +end + +if ARGV.empty? + puts "usage: #$0 [emoji4unicode.xml]" + exit 1 +end +$srcdir = File.expand_path("../../enc/trans", __FILE__) +emoji_table = EmojiTable.new(ARGV[0]) + +companies = %w(DoCoMo KDDI SoftBank Unicode) + +io = STDOUT +io.puts "EMOJI_EXCHANGE_TBL = Hash.new{|h,k| h[k] = {}}" +companies.each do |from_company| + companies.each do |to_company| + next if from_company == to_company + emoji_table.generate(io, from_company, to_company) + end +end diff --git a/jni/ruby/tool/enc-unicode.rb b/jni/ruby/tool/enc-unicode.rb new file mode 100755 index 0000000..38140ab --- /dev/null +++ b/jni/ruby/tool/enc-unicode.rb @@ -0,0 +1,371 @@ +#!/usr/bin/env ruby + +# Creates the data structures needed by Onigurma to map Unicode codepoints to +# property names and POSIX character classes +# +# To use this, get UnicodeData.txt, Scripts.txt, PropList.txt, +# PropertyAliases.txt, PropertyValueAliases.txt, DerivedCoreProperties.txt, +# DerivedAge.txt and Blocks.txt from unicode.org. +# (http://unicode.org/Public/UNIDATA/) And run following command. +# ruby1.9 tool/enc-unicode.rb data_dir > enc/unicode/name2ctype.kwd +# You can get source file for gperf. After this, simply make ruby. + +unless ARGV.size == 1 + $stderr.puts "Usage: #{$0} data_directory" + exit(1) +end + +POSIX_NAMES = %w[NEWLINE Alpha Blank Cntrl Digit Graph Lower Print Punct Space Upper XDigit Word Alnum ASCII] + +def pair_codepoints(codepoints) + + # We have a sorted Array of codepoints that we wish to partition into + # ranges such that the start- and endpoints form an inclusive set of + # codepoints with property _property_. Note: It is intended that some ranges + # will begin with the value with which they end, e.g. 0x0020 -> 0x0020 + + codepoints.sort! + last_cp = codepoints.first + pairs = [[last_cp, nil]] + codepoints[1..-1].each do |codepoint| + next if last_cp == codepoint + + # If the current codepoint does not follow directly on from the last + # codepoint, the last codepoint represents the end of the current range, + # and the current codepoint represents the start of the next range. + if last_cp.next != codepoint + pairs[-1][-1] = last_cp + pairs << [codepoint, nil] + end + last_cp = codepoint + end + + # The final pair has as its endpoint the last codepoint for this property + pairs[-1][-1] = codepoints.last + pairs +end + +def parse_unicode_data(file) + last_cp = 0 + data = {'Any' => (0x0000..0x10ffff).to_a, 'Assigned' => [], + 'ASCII' => (0..0x007F).to_a, 'NEWLINE' => [0x0a], 'Cn' => []} + beg_cp = nil + IO.foreach(file) do |line| + fields = line.split(';') + cp = fields[0].to_i(16) + + case fields[1] + when /\A<(.*),\s*First>\z/ + beg_cp = cp + next + when /\A<(.*),\s*Last>\z/ + cps = (beg_cp..cp).to_a + else + beg_cp = cp + cps = [cp] + end + + # The Cn category represents unassigned characters. These are not listed in + # UnicodeData.txt so we must derive them by looking for 'holes' in the range + # of listed codepoints. We increment the last codepoint seen and compare it + # with the current codepoint. If the current codepoint is less than + # last_cp.next we have found a hole, so we add the missing codepoint to the + # Cn category. + data['Cn'].concat((last_cp.next...beg_cp).to_a) + + # Assigned - Defined in unicode.c; interpreted as every character in the + # Unicode range minus the unassigned characters + data['Assigned'].concat(cps) + + # The third field denotes the 'General' category, e.g. Lu + (data[fields[2]] ||= []).concat(cps) + + # The 'Major' category is the first letter of the 'General' category, e.g. + # 'Lu' -> 'L' + (data[fields[2][0,1]] ||= []).concat(cps) + last_cp = cp + end + + # The last Cn codepoint should be 0x10ffff. If it's not, append the missing + # codepoints to Cn and C + cn_remainder = (last_cp.next..0x10ffff).to_a + data['Cn'] += cn_remainder + data['C'] += data['Cn'] + + # Special case for LC (Cased_Letter). LC = Ll + Lt + Lu + data['LC'] = data['Ll'] + data['Lt'] + data['Lu'] + + # Define General Category properties + gcps = data.keys.sort - POSIX_NAMES + + # Returns General Category Property names and the data + [gcps, data] +end + +def define_posix_props(data) + # We now derive the character classes (POSIX brackets), e.g. [[:alpha:]] + # + + data['Alpha'] = data['Alphabetic'] + data['Upper'] = data['Uppercase'] + data['Lower'] = data['Lowercase'] + data['Punct'] = data['Punctuation'] + data['Digit'] = data['Decimal_Number'] + data['XDigit'] = (0x0030..0x0039).to_a + (0x0041..0x0046).to_a + + (0x0061..0x0066).to_a + data['Alnum'] = data['Alpha'] + data['Digit'] + data['Space'] = data['White_Space'] + data['Blank'] = data['Space_Separator'] + [0x0009] + data['Cntrl'] = data['Cc'] + data['Word'] = data['Alpha'] + data['Mark'] + data['Digit'] + data['Connector_Punctuation'] + data['Graph'] = data['Any'] - data['Space'] - data['Cntrl'] - + data['Surrogate'] - data['Unassigned'] + data['Print'] = data['Graph'] + data['Space_Separator'] +end + +def parse_scripts(data, categories) + files = [ + {:fn => 'DerivedCoreProperties.txt', :title => 'Derived Property'}, + {:fn => 'Scripts.txt', :title => 'Script'}, + {:fn => 'PropList.txt', :title => 'Binary Property'} + ] + current = nil + cps = [] + names = {} + files.each do |file| + IO.foreach(get_file(file[:fn])) do |line| + if /^# Total code points: / =~ line + data[current] = cps + categories[current] = file[:title] + (names[file[:title]] ||= []) << current + cps = [] + elsif /^([0-9a-fA-F]+)(?:..([0-9a-fA-F]+))?\s*;\s*(\w+)/ =~ line + current = $3 + $2 ? cps.concat(($1.to_i(16)..$2.to_i(16)).to_a) : cps.push($1.to_i(16)) + end + end + end + # All code points not explicitly listed for Script + # have the value Unknown (Zzzz). + data['Unknown'] = (0..0x10ffff).to_a - data.values_at(*names['Script']).flatten + categories['Unknown'] = 'Script' + names.values.flatten << 'Unknown' +end + +def parse_aliases(data) + kv = {} + IO.foreach(get_file('PropertyAliases.txt')) do |line| + next unless /^(\w+)\s*; (\w+)/ =~ line + data[$1] = data[$2] + kv[normalize_propname($1)] = normalize_propname($2) + end + IO.foreach(get_file('PropertyValueAliases.txt')) do |line| + next unless /^(sc|gc)\s*; (\w+)\s*; (\w+)(?:\s*; (\w+))?/ =~ line + if $1 == 'gc' + data[$3] = data[$2] + data[$4] = data[$2] + kv[normalize_propname($3)] = normalize_propname($2) + kv[normalize_propname($4)] = normalize_propname($2) if $4 + else + data[$2] = data[$3] + data[$4] = data[$3] + kv[normalize_propname($2)] = normalize_propname($3) + kv[normalize_propname($4)] = normalize_propname($3) if $4 + end + end + kv +end + +# According to Unicode6.0.0/ch03.pdf, Section 3.1, "An update version +# never involves any additions to the character repertoire." Versions +# in DerivedAge.txt should always be /\d+\.\d+/ +def parse_age(data) + current = nil + last_constname = nil + cps = [] + ages = [] + IO.foreach(get_file('DerivedAge.txt')) do |line| + if /^# Total code points: / =~ line + constname = constantize_agename(current) + # each version matches all previous versions + cps.concat(data[last_constname]) if last_constname + data[constname] = cps + make_const(constname, cps, "Derived Age #{current}") + ages << current + last_constname = constname + cps = [] + elsif /^([0-9a-fA-F]+)(?:..([0-9a-fA-F]+))?\s*;\s*(\d+\.\d+)/ =~ line + current = $3 + $2 ? cps.concat(($1.to_i(16)..$2.to_i(16)).to_a) : cps.push($1.to_i(16)) + end + end + ages +end + +def parse_block(data) + current = nil + last_constname = nil + cps = [] + blocks = [] + IO.foreach(get_file('Blocks.txt')) do |line| + if /^([0-9a-fA-F]+)\.\.([0-9a-fA-F]+);\s*(.*)/ =~ line + cps = ($1.to_i(16)..$2.to_i(16)).to_a + constname = constantize_blockname($3) + data[constname] = cps + make_const(constname, cps, "Block") + blocks << constname + end + end + + # All code points not belonging to any of the named blocks + # have the value No_Block. + no_block = (0..0x10ffff).to_a - data.values_at(*blocks).flatten + constname = constantize_blockname("No_Block") + make_const(constname, no_block, "Block") + blocks << constname +end + +# shim for Ruby 1.8 +unless {}.respond_to?(:key) + class Hash + alias key index + end +end + +$const_cache = {} +# make_const(property, pairs, name): Prints a 'static const' structure for a +# given property, group of paired codepoints, and a human-friendly name for +# the group +def make_const(prop, data, name) + puts "\n/* '#{prop}': #{name} */" + if origprop = $const_cache.key(data) + puts "#define CR_#{prop} CR_#{origprop}" + else + $const_cache[prop] = data + pairs = pair_codepoints(data) + puts "static const OnigCodePoint CR_#{prop}[] = {" + # The first element of the constant is the number of pairs of codepoints + puts "\t#{pairs.size}," + pairs.each do |pair| + pair.map! { |c| c == 0 ? '0x0000' : sprintf("%0#6x", c) } + puts "\t#{pair.first}, #{pair.last}," + end + puts "}; /* CR_#{prop} */" + end +end + +def normalize_propname(name) + name = name.downcase + name.delete!('- _') + name +end + +def constantize_agename(name) + "Age_#{name.sub(/\./, '_')}" +end + +def constantize_blockname(name) + "In_#{name.gsub(/\W/, '_')}" +end + +def get_file(name) + File.join(ARGV[0], name) +end + + +# Write Data +puts '%{' +puts '#define long size_t' +props, data = parse_unicode_data(get_file('UnicodeData.txt')) +categories = {} +props.concat parse_scripts(data, categories) +aliases = parse_aliases(data) +define_posix_props(data) +POSIX_NAMES.each do |name| + make_const(name, data[name], "[[:#{name}:]]") +end +print "\n#ifdef USE_UNICODE_PROPERTIES" +props.each do |name| + category = categories[name] || + case name.size + when 1 then 'Major Category' + when 2 then 'General Category' + else '-' + end + make_const(name, data[name], category) +end +print "\n#ifdef USE_UNICODE_AGE_PROPERTIES" +ages = parse_age(data) +puts "#endif /* USE_UNICODE_AGE_PROPERTIES */" +blocks = parse_block(data) +puts '#endif /* USE_UNICODE_PROPERTIES */' +puts(<<'__HEREDOC') + +static const OnigCodePoint* const CodeRanges[] = { +__HEREDOC +POSIX_NAMES.each{|name|puts" CR_#{name},"} +puts "#ifdef USE_UNICODE_PROPERTIES" +props.each{|name| puts" CR_#{name},"} +puts "#ifdef USE_UNICODE_AGE_PROPERTIES" +ages.each{|name| puts" CR_#{constantize_agename(name)},"} +puts "#endif /* USE_UNICODE_AGE_PROPERTIES */" +blocks.each{|name|puts" CR_#{name},"} + +puts(<<'__HEREDOC') +#endif /* USE_UNICODE_PROPERTIES */ +}; +struct uniname2ctype_struct { + int name, ctype; +}; + +static const struct uniname2ctype_struct *uniname2ctype_p(const char *, unsigned int); +%} +struct uniname2ctype_struct; +%% +__HEREDOC +i = -1 +name_to_index = {} +POSIX_NAMES.each do |name| + i += 1 + next if name == 'NEWLINE' + name = normalize_propname(name) + name_to_index[name] = i + puts"%-40s %3d" % [name + ',', i] +end +puts "#ifdef USE_UNICODE_PROPERTIES" +props.each do |name| + i += 1 + name = normalize_propname(name) + name_to_index[name] = i + puts "%-40s %3d" % [name + ',', i] +end +aliases.each_pair do |k, v| + next if name_to_index[k] + next unless v = name_to_index[v] + puts "%-40s %3d" % [k + ',', v] +end +puts "#ifdef USE_UNICODE_AGE_PROPERTIES" +ages.each do |name| + i += 1 + name = "age=#{name}" + name_to_index[name] = i + puts "%-40s %3d" % [name + ',', i] +end +puts "#endif /* USE_UNICODE_AGE_PROPERTIES */" +blocks.each do |name| + i += 1 + name = normalize_propname(name) + name_to_index[name] = i + puts "%-40s %3d" % [name + ',', i] +end +puts(<<'__HEREDOC') +#endif /* USE_UNICODE_PROPERTIES */ +%% +static int +uniname2ctype(const UChar *name, unsigned int len) +{ + const struct uniname2ctype_struct *p = uniname2ctype_p((const char *)name, len); + if (p) return p->ctype; + return -1; +} +__HEREDOC diff --git a/jni/ruby/tool/eval.rb b/jni/ruby/tool/eval.rb new file mode 100644 index 0000000..18e645a --- /dev/null +++ b/jni/ruby/tool/eval.rb @@ -0,0 +1,159 @@ + +require './rbconfig' +require 'fileutils' +require 'pp' + +Ruby = ENV['RUBY'] || RbConfig.ruby +# + +OPTIONS = %w{ + opt-direct-threaded-code + opt-basic-operations + opt-operands-unification + opt-instructions-unification + opt-inline-method-cache + opt-stack-caching +}.map{|opt| + '--disable-' + opt +} + +opts = OPTIONS.dup +Configs = OPTIONS.map{|opt| + o = opts.dup + opts.delete(opt) + o +} + [[]] + +pp Configs if $DEBUG + + +def exec_cmd(cmd) + puts cmd + unless system(cmd) + p cmd + raise "error" + end +end + +def dirname idx + "ev-#{idx}" +end + +def build + Configs.each_with_index{|config, idx| + dir = dirname(idx) + FileUtils.rm_rf(dir) if FileTest.exist?(dir) + Dir.mkdir(dir) + FileUtils.cd(dir){ + exec_cmd("#{Ruby} ../extconf.rb " + config.join(" ")) + exec_cmd("make clean test-all") + } + } +end + +def check + Configs.each_with_index{|c, idx| + puts "= #{idx}" + system("#{Ruby} -r ev-#{idx}/yarvcore -e 'puts YARVCore::OPTS'") + } +end + +def bench_each idx + puts "= #{idx}" + 5.times{|count| + print count + FileUtils.cd(dirname(idx)){ + exec_cmd("make benchmark OPT=-y ITEMS=#{ENV['ITEMS']} > ../b#{idx}-#{count}") + } + } + puts +end + +def bench + # return bench_each(6) + Configs.each_with_index{|c, idx| + bench_each idx + } +end + +def parse_result data + flag = false + stat = [] + data.each{|line| + if flag + if /(\w+)\t([\d\.]+)/ =~ line + stat << [$1, $2.to_f] + else + raise "not a data" + end + + end + if /benchmark summary/ =~ line + flag = true + end + } + stat +end + +def calc_each data + data.sort! + data.pop # remove max + data.shift # remove min + + data.inject(0.0){|res, e| + res += e + } / data.size +end + +def calc_stat stats + stat = [] + stats[0].each_with_index{|e, idx| + bm = e[0] + vals = stats.map{|st| + st[idx][1] + } + [bm, calc_each(vals)] + } +end + +def stat + total = [] + Configs.each_with_index{|c, idx| + stats = [] + 5.times{|count| + file = "b#{idx}-#{count}" + # p file + open(file){|f| + stats << parse_result(f.read) + } + } + # merge stats + total << calc_stat(stats) + total + } + # pp total + total[0].each_with_index{|e, idx| + bm = e[0] + # print "#{bm}\t" + total.each{|st| + print st[idx][1], "\t" + } + puts + } +end + +ARGV.each{|cmd| + case cmd + when 'build' + build + when 'check' + check + when 'bench' + bench + when 'stat' + stat + else + raise + end +} + diff --git a/jni/ruby/tool/expand-config.rb b/jni/ruby/tool/expand-config.rb new file mode 100755 index 0000000..fb2edd0 --- /dev/null +++ b/jni/ruby/tool/expand-config.rb @@ -0,0 +1,7 @@ +STDOUT.binmode +ARGF.each do |line| + line.gsub!(/@([a-z_]\w*)@/i) { + (RbConfig::MAKEFILE_CONFIG[$1] or "").gsub(/\$\((.+?)\)/, %Q[${\\1}]) + } + puts line +end diff --git a/jni/ruby/tool/extlibs.rb b/jni/ruby/tool/extlibs.rb new file mode 100755 index 0000000..09db055 --- /dev/null +++ b/jni/ruby/tool/extlibs.rb @@ -0,0 +1,143 @@ +#!/usr/bin/ruby +require 'fileutils' +require 'digest' +require_relative 'downloader' + +cache_dir = ".downloaded-cache" +FileUtils.mkdir_p(cache_dir) + +def do_download(url, base, cache_dir) + Downloader.download(url, base, cache_dir, nil) +end + +def do_checksum(cache, chksums) + chksums.each do |sum| + name, sum = sum.split(/:/) + if $VERBOSE + $stdout.print "checking #{name} of #{cache} ..." + $stdout.flush + end + hd = Digest(name.upcase).file(cache).hexdigest + if hd == sum + if $VERBOSE + $stdout.puts " OK" + $stdout.flush + end + else + if $VERBOSE + $stdout.puts " NG" + $stdout.flush + end + raise "checksum mismatch: #{cache}, #{name}:#{hd}, expected #{sum}" + end + end +end + +def do_extract(cache, dir) + if $VERBOSE + $stdout.puts "extracting #{cache} into #{dir}" + $stdout.flush + end + ext = File.extname(cache) + case ext + when '.gz', '.tgz' + f = IO.popen(["gzip", "-dc", cache]) + cache = cache.chomp('.gz') + when '.bz2', '.tbz' + f = IO.popen(["bzip2", "-dc", cache]) + cache = cache.chomp('.bz2') + when '.xz', '.txz' + f = IO.popen(["xz", "-dc", cache]) + cache = cache.chomp('.xz') + else + inp = cache + end + inp ||= f.binmode + ext = File.extname(cache) + case ext + when '.tar', /\A\.t[gbx]z\z/ + pid = Process.spawn("tar", "xpf", "-", in: inp, chdir: dir) + when '.zip' + pid = Process.spawn("unzip", inp, "-d", dir) + end + f.close if f + Process.wait(pid) + $?.success? or raise "failed to extract #{cache}" +end + +def do_patch(dest, patch, args) + if $VERBOSE + $stdout.puts "applying #{patch} under #{dest}" + $stdout.flush + end + Process.wait(Process.spawn("patch", *args, in: File.join(dest, patch), chdir: dest)) + $?.success? or raise "failed to patch #{patch}" +end + +case ARGV[0] +when '--download' + mode = :download + ARGV.shift +when '--extract' + mode = :extract + ARGV.shift +when '--patch' + mode = :patch + ARGV.shift +when '--all' + mode = :all + ARGV.shift +else + mode = :all +end + +success = true +ARGV.each do |dir| + Dir.glob("#{dir}/**/extlibs") do |list| + if $VERBOSE + $stdout.puts "downloading for #{list}" + $stdout.flush + end + extracted = false + dest = File.dirname(list) + IO.foreach(list) do |line| + line.sub!(/\s*#.*/, '') + if /^\t/ =~ line + if extracted and (mode == :all or mode == :patch) + patch, *args = line.split + do_patch(dest, patch, args) + end + next + end + url, *chksums = line.split(' ') + next unless url + extracted = false + base = File.basename(url) + cache = File.join(cache_dir, base) + target = File.join(dest, base[/.*(?=\.tar(?:\.\w+)?\z)/]) + begin + case mode + when :download + do_download(url, base, cache_dir) + do_checksum(cache, chksums) + when :extract + unless File.directory?(target) + do_checksum(cache, chksums) + extracted = do_extract(cache, dest) + end + when :all + do_download(url, base, cache_dir) + unless File.directory?(target) + do_checksum(cache, chksums) + extracted = do_extract(cache, dest) + end + end + rescue => e + warn e.inspect + success = false + end + end + end +end + +exit(success) diff --git a/jni/ruby/tool/fake.rb b/jni/ruby/tool/fake.rb new file mode 100644 index 0000000..7d3a471 --- /dev/null +++ b/jni/ruby/tool/fake.rb @@ -0,0 +1,30 @@ +class File + sep = ("\\" if RUBY_PLATFORM =~ /mswin|bccwin|mingw/) + if sep != ALT_SEPARATOR + remove_const :ALT_SEPARATOR + ALT_SEPARATOR = sep + end +end + +$:.unshift(builddir) +posthook = proc do + mkconfig = RbConfig::MAKEFILE_CONFIG + extout = File.expand_path(mkconfig["EXTOUT"], builddir) + $arch_hdrdir = "#{extout}/include/$(arch)" + $ruby = baseruby + untrace_var(:$ruby, posthook) +end +prehook = proc do |extmk| + unless extmk + config = RbConfig::CONFIG + mkconfig = RbConfig::MAKEFILE_CONFIG + mkconfig["top_srcdir"] = $top_srcdir = top_srcdir + mkconfig["rubyhdrdir"] = "$(top_srcdir)/include" + mkconfig["builddir"] = config["builddir"] = builddir + config["rubyhdrdir"] = File.join(mkconfig["top_srcdir"], "include") + mkconfig["libdir"] = config["libdir"] = mkconfig["topdir"] + trace_var(:$ruby, posthook) + end + untrace_var(:$extmk, prehook) +end +trace_var(:$extmk, prehook) diff --git a/jni/ruby/tool/file2lastrev.rb b/jni/ruby/tool/file2lastrev.rb new file mode 100755 index 0000000..616c5f7 --- /dev/null +++ b/jni/ruby/tool/file2lastrev.rb @@ -0,0 +1,68 @@ +#!/usr/bin/env ruby + +require 'optparse' + +# this file run with BASERUBY, which may be older than 1.9, so no +# require_relative +require File.expand_path('../vcs', __FILE__) + +Program = $0 + +@output = nil +def self.output=(output) + if @output and @output != output + raise "you can specify only one of --changed, --revision.h and --doxygen" + end + @output = output +end +@suppress_not_found = false + +srcdir = nil +parser = OptionParser.new {|opts| + opts.on("--srcdir=PATH", "use PATH as source directory") do |path| + srcdir = path + end + opts.on("--changed", "changed rev") do + self.output = :changed + end + opts.on("--revision.h", "RUBY_REVISION macro") do + self.output = :revision_h + end + opts.on("--doxygen", "Doxygen format") do + self.output = :doxygen + end + opts.on("--modified", "modified time") do + self.output = :modified + end + opts.on("-q", "--suppress_not_found") do + @suppress_not_found = true + end +} +parser.parse! rescue abort "#{File.basename(Program)}: #{$!}\n#{parser}" + +srcdir ||= File.dirname(File.dirname(Program)) +begin + vcs = VCS.detect(srcdir) +rescue VCS::NotFoundError => e + abort "#{File.basename(Program)}: #{e.message}" unless @suppress_not_found +else + begin + last, changed, modified = vcs.get_revisions(ARGV.shift) + rescue => e + abort "#{File.basename(Program)}: #{e.message}" unless @suppress_not_found + exit false + end +end + +case @output +when :changed, nil + puts changed +when :revision_h + puts "#define RUBY_REVISION #{changed.to_i}" +when :doxygen + puts "r#{changed}/r#{last}" +when :modified + puts modified.strftime('%Y-%m-%dT%H:%M:%S%z') +else + raise "unknown output format `#{@output}'" +end diff --git a/jni/ruby/tool/gen_dummy_probes.rb b/jni/ruby/tool/gen_dummy_probes.rb new file mode 100755 index 0000000..c19f9d5 --- /dev/null +++ b/jni/ruby/tool/gen_dummy_probes.rb @@ -0,0 +1,28 @@ +#!/usr/bin/ruby +# -*- coding: us-ascii -*- + +text = ARGF.read +text.gsub!(/^(?!#)(.*)/){$1.upcase} + +# remove comments +text.gsub!(%r'(?:^ *)?/\*.*?\*/\n?'m, '') + +# remove the pragma declarations +text.gsub!(/^#pragma.*\n/, '') + +# replace the provider section with the start of the header file +text.gsub!(/PROVIDER RUBY \{/, "#ifndef\t_PROBES_H\n#define\t_PROBES_H\n#define DTRACE_PROBES_DISABLED 1\n") + +# finish up the #ifndef sandwich +text.gsub!(/\};/, "\n#endif\t/* _PROBES_H */") + +text.gsub!(/__/, '_') + +text.gsub!(/\((.+?)(?=\);)/) { + "(arg" << (0..$1.count(',')).to_a.join(", arg") +} + +text.gsub!(/ *PROBE ([^\(]*)(\([^\)]*\));/, "#define RUBY_DTRACE_\\1_ENABLED() 0\n#define RUBY_DTRACE_\\1\\2\ do \{ \} while\(0\)") +puts "/* -*- c -*- */" +print text + diff --git a/jni/ruby/tool/gen_ruby_tapset.rb b/jni/ruby/tool/gen_ruby_tapset.rb new file mode 100755 index 0000000..c34fb88 --- /dev/null +++ b/jni/ruby/tool/gen_ruby_tapset.rb @@ -0,0 +1,105 @@ +#!/usr/bin/ruby +# -*- coding: us-ascii -*- +# usage: ./ruby gen_ruby_tapset.rb --ruby-path=/path/to/ruby probes.d > output + +require "optparse" + +def set_argument (argname, nth) + # remove C style type info + argname.gsub!(/.+ (.+)/, '\1') # e.g. char *hoge -> *hoge + argname.gsub!(/^\*/, '') # e.g. *filename -> filename + + "#{argname} = $arg#{nth}" +end + +ruby_path = "/usr/local/ruby" + +opts = OptionParser.new +opts.on("--ruby-path=PATH"){|v| ruby_path = v} +opts.parse!(ARGV) + +text = ARGF.read + +# remove preprocessor directives +text.gsub!(/^#.*$/, '') + +# remove provider name +text.gsub!(/^provider ruby \{/, "") +text.gsub!(/^\};/, "") + +# probename() +text.gsub!(/probe (.+)\( *\);/) { + probe_name = $1 + probe = <<-End + probe #{probe_name} = process("ruby").provider("ruby").mark("#{probe_name}") + { + } + End +} + +# probename(arg1) +text.gsub!(/ *probe (.+)\(([^,)]+)\);/) { + probe_name = $1 + arg1 = $2 + + probe = <<-End + probe #{probe_name} = process("ruby").provider("ruby").mark("#{probe_name}") + { + #{set_argument(arg1, 1)} + } + End +} + +# probename(arg1, arg2) +text.gsub!(/ *probe (.+)\(([^,)]+),([^,)]+)\);/) { + probe_name = $1 + arg1 = $2 + arg2 = $3 + + probe = <<-End + probe #{probe_name} = process("#{ruby_path}").provider("ruby").mark("#{probe_name}") + { + #{set_argument(arg1, 1)} + #{set_argument(arg2, 2)} + } + End +} + +# probename(arg1, arg2, arg3) +text.gsub!(/ *probe (.+)\(([^,)]+),([^,)]+),([^,)]+)\);/) { + probe_name = $1 + arg1 = $2 + arg2 = $3 + arg3 = $4 + + probe = <<-End + probe #{probe_name} = process("#{ruby_path}").provider("ruby").mark("#{probe_name}") + { + #{set_argument(arg1, 1)} + #{set_argument(arg2, 2)} + #{set_argument(arg3, 3)} + } + End +} + +# probename(arg1, arg2, arg3, arg4) +text.gsub!(/ *probe (.+)\(([^,)]+),([^,)]+),([^,)]+),([^,)]+)\);/) { + probe_name = $1 + arg1 = $2 + arg2 = $3 + arg3 = $4 + arg4 = $5 + + probe = <<-End + probe #{probe_name} = process("#{ruby_path}").provider("ruby").mark("#{probe_name}") + { + #{set_argument(arg1, 1)} + #{set_argument(arg2, 2)} + #{set_argument(arg3, 3)} + #{set_argument(arg4, 4)} + } + End +} + +print text + diff --git a/jni/ruby/tool/generic_erb.rb b/jni/ruby/tool/generic_erb.rb new file mode 100644 index 0000000..6641b0e --- /dev/null +++ b/jni/ruby/tool/generic_erb.rb @@ -0,0 +1,42 @@ +# -*- coding: us-ascii -*- +require 'erb' +require 'optparse' +require 'fileutils' +$:.unshift(File.dirname(__FILE__)) +require 'vpath' + +vpath = VPath.new +timestamp = nil +output = nil +ifchange = nil +source = false + +opt = OptionParser.new do |o| + o.on('-t', '--timestamp[=PATH]') {|v| timestamp = v || true} + o.on('-o', '--output=PATH') {|v| output = v} + o.on('-c', '--[no-]if-change') {|v| ifchange = v} + o.on('-x', '--source') {source = true} + vpath.def_options(o) + o.order!(ARGV) +end +template = ARGV.shift or abort opt.to_s +erb = ERB.new(File.read(template), nil, '%-') +erb.filename = template +result = source ? erb.src : erb.result +if output + if ifchange and (vpath.open(output, "rb") {|f| f.read} rescue nil) == result + puts "#{output} unchanged" + else + open(output, "wb") {|f| f.print result} + puts "#{output} updated" + end + if timestamp + if timestamp == true + dir, base = File.split(output) + timestamp = File.join(dir, ".time." + base) + end + FileUtils.touch(timestamp) + end +else + print result +end diff --git a/jni/ruby/tool/id2token.rb b/jni/ruby/tool/id2token.rb new file mode 100755 index 0000000..191b872 --- /dev/null +++ b/jni/ruby/tool/id2token.rb @@ -0,0 +1,24 @@ +#! /usr/bin/ruby -p +# -*- coding: us-ascii -*- +BEGIN { + require 'optparse' + $:.unshift(File.dirname(__FILE__)) + require 'vpath' + vpath = VPath.new + header = nil + + opt = OptionParser.new do |o| + vpath.def_options(o) + header = o.order!(ARGV).shift + end or abort opt.opt_s + + TOKENS = {} + h = vpath.read(header) rescue abort("#{header} not found in #{vpath.inspect}") + h.scan(/^#define\s+RUBY_TOKEN_(\w+)\s+(\d+)/) do |token, id| + TOKENS[token] = id + end + + TOKENS_RE = /\bRUBY_TOKEN\((#{TOKENS.keys.join('|')})\)\s*(?=\s)/ +} + +$_.gsub!(TOKENS_RE) {TOKENS[$1]} if /^%token/ =~ $_ diff --git a/jni/ruby/tool/ifchange b/jni/ruby/tool/ifchange new file mode 100755 index 0000000..488e9db --- /dev/null +++ b/jni/ruby/tool/ifchange @@ -0,0 +1,61 @@ +#!/bin/sh +# usage: ifchange target temporary + +set -e +timestamp= +keepsuffix= +empty= +until [ $# -eq 0 ]; do + case "$1" in + --timestamp) + timestamp=. + ;; + --timestamp=*) + timestamp=`expr \( "$1" : '[^=]*=\(.*\)' \)` + ;; + --keep) + keepsuffix=.old + ;; + --keep=*) + keepsuffix=`expr \( "$1" : '[^=]*=\(.*\)' \)` + ;; + --empty) + empty=yes + ;; + *) + break + ;; + esac + shift +done + +target="$1" +temp="$2" +if [ "$temp" = - ]; then + temp="tmpdata$$.tmp~" + cat > "$temp" || exit $? + trap 'rm -f "$temp"' 0 +fi + +if [ -f "$target" -a ! -${empty:+f}${empty:-s} "$temp" ] || cmp "$target" "$temp" >/dev/null 2>&1; then + echo "$target unchanged" + rm -f "$temp" +else + echo "$target updated" + [ x"${keepsuffix}" = x ] || mv -f "$target" "${target}${keepsuffix}" + mv -f "$temp" "$target" +fi + +if [ -n "${timestamp}" ]; then + if [ x"${timestamp}" = x. ]; then + case "$target" in + */*) + timestamp=`dirname "$target"`/.time.`basename "$target"` + ;; + *) + timestamp=.time."$target" + ;; + esac + fi + : > "$timestamp" +fi diff --git a/jni/ruby/tool/insns2vm.rb b/jni/ruby/tool/insns2vm.rb new file mode 100755 index 0000000..f518707 --- /dev/null +++ b/jni/ruby/tool/insns2vm.rb @@ -0,0 +1,15 @@ +#!ruby + +require 'optparse' + +Version = %w$Revision: 11626 $[1..-1] + +require "#{File.join(File.dirname(__FILE__), 'instruction')}" + +if $0 == __FILE__ + opts = ARGV.options + maker = RubyVM::SourceCodeGenerator.def_options(opts) + files = opts.parse! + generator = maker.call + generator.generate(files) +end diff --git a/jni/ruby/tool/install-sh b/jni/ruby/tool/install-sh new file mode 100644 index 0000000..af97fa6 --- /dev/null +++ b/jni/ruby/tool/install-sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# Just only for using AC_PROG_INSTALL in configure.in. +# See autoconf.info for more detail. + +cat <<EOF >&2 +Ruby uses a BSD-compatible install(1) if possible. If not, Ruby +provides its own install(1) alternative. + +This script a place holder for AC_PROG_INSTALL in configure.in. + +Please report a bug in Ruby to http://bugs.ruby-lang.org if you see +this message. + +Thank you. +EOF +exit 1 diff --git a/jni/ruby/tool/instruction.rb b/jni/ruby/tool/instruction.rb new file mode 100755 index 0000000..16d97f5 --- /dev/null +++ b/jni/ruby/tool/instruction.rb @@ -0,0 +1,1343 @@ +#!./miniruby +# -*- coding: us-ascii -*- +# +# + +require 'erb' +$:.unshift(File.dirname(__FILE__)) +require 'vpath' + +class RubyVM + class Instruction + def initialize name, opes, pops, rets, comm, body, tvars, sp_inc, + orig = self, defopes = [], type = nil, + nsc = [], psc = [[], []] + + @name = name + @opes = opes # [[type, name], ...] + @pops = pops # [[type, name], ...] + @rets = rets # [[type, name], ...] + @comm = comm # {:c => category, :e => en desc, :j => ja desc} + @body = body # '...' + + @orig = orig + @defopes = defopes + @type = type + @tvars = tvars + + @nextsc = nsc + @pushsc = psc + @sc = [] + @unifs = [] + @optimized = [] + @is_sc = false + @sp_inc = sp_inc + end + + def add_sc sci + @sc << sci + sci.set_sc + end + + attr_reader :name, :opes, :pops, :rets + attr_reader :body, :comm + attr_reader :nextsc, :pushsc + attr_reader :orig, :defopes, :type + attr_reader :sc + attr_reader :unifs, :optimized + attr_reader :is_sc + attr_reader :tvars + attr_reader :sp_inc + + def set_sc + @is_sc = true + end + + def add_unif insns + @unifs << insns + end + + def add_optimized insn + @optimized << insn + end + + def sp_increase_c_expr + if(pops.any?{|t, v| v == '...'} || + rets.any?{|t, v| v == '...'}) + # user definition + raise "no sp increase definition" if @sp_inc.nil? + ret = "int inc = 0;\n" + + @opes.each_with_index{|(t, v), i| + if (t == 'rb_num_t' && ((re = /\b#{v}\b/n) =~ @sp_inc)) || + (@defopes.any?{|t, val| re =~ val}) + ret << " int #{v} = FIX2INT(opes[#{i}]);\n" + elsif (t == 'CALL_INFO' && ((re = /\b#{v}\b/n) =~ @sp_inc)) + ret << " CALL_INFO #{v} = (CALL_INFO)(opes[#{i}]);\n" + end + } + + @defopes.each_with_index{|((t, var), val), i| + if t == 'rb_num_t' && val != '*' && /\b#{var}\b/ =~ @sp_inc + ret << " #{t} #{var} = #{val};\n" + end + } + + ret << " #{@sp_inc};\n" + ret << " return depth + inc;" + ret + else + "return depth + #{rets.size - pops.size};" + end + end + + def inspect + "#<Instruction:#{@name}>" + end + end + + class InstructionsLoader + def initialize opts = {} + @insns = [] + @insn_map = {} + + @vpath = opts[:VPATH] || File + @use_const = opts[:use_const] + @verbose = opts[:verbose] + @destdir = opts[:destdir] + + (@vm_opts = load_vm_opts).each {|k, v| + @vm_opts[k] = opts[k] if opts.key?(k) + } + + load_insns_def opts[:"insns.def"] || 'insns.def' + + load_opt_operand_def opts[:"opope.def"] || 'defs/opt_operand.def' + load_insn_unification_def opts[:"unif.def"] || 'defs/opt_insn_unif.def' + make_stackcaching_insns if vm_opt?('STACK_CACHING') + end + + attr_reader :vpath + attr_reader :destdir + + %w[use_const verbose].each do |attr| + attr_reader attr + alias_method "#{attr}?", attr + remove_method attr + end + + def [](s) + @insn_map[s.to_s] + end + + def each + @insns.each{|insn| + yield insn + } + end + + def size + @insns.size + end + + ### + private + + def vm_opt? name + @vm_opts[name] + end + + def load_vm_opts file = nil + file ||= 'vm_opts.h' + opts = {} + vpath.open(file) do |f| + f.grep(/^\#define\s+OPT_([A-Z_]+)\s+(\d+)/) do + opts[$1] = !$2.to_i.zero? + end + end + opts + end + + SKIP_COMMENT_PATTERN = Regexp.compile(Regexp.escape('/** ##skip')) + + include Enumerable + + def add_insn insn + @insns << insn + @insn_map[insn.name] = insn + end + + def make_insn name, opes, pops, rets, comm, body, sp_inc + add_insn Instruction.new(name, opes, pops, rets, comm, body, [], sp_inc) + end + + # str -> [[type, var], ...] + def parse_vars line + raise unless /\((.*?)\)/ =~ line + vars = $1.split(',') + vars.map!{|v| + if /\s*(\S+)\s+(\S+)\s*/ =~ v + type = $1 + var = $2 + elsif /\s*\.\.\.\s*/ =~ v + type = var = '...' + else + raise + end + [type, var] + } + vars + end + + def parse_comment comm + c = 'others' + j = '' + e = '' + comm.each_line{|line| + case line + when /@c (.+)/ + c = $1 + when /@e (.+)/ + e = $1 + when /@e\s*$/ + e = '' + when /@j (.+)$/ + j = $1 + when /@j\s*$/ + j = '' + end + } + { :c => c, + :e => e, + :j => j, + } + end + + def load_insns_def file + body = insn = opes = pops = rets = nil + comment = '' + + vpath.open(file) {|f| + f.instance_variable_set(:@line_no, 0) + class << f + def line_no + @line_no + end + def gets + @line_no += 1 + super + end + end + + while line = f.gets + line.chomp! + case line + + when SKIP_COMMENT_PATTERN + while line = f.gets.chomp + if /\s+\*\/$/ =~ line + break + end + end + + # collect instruction comment + when /^\/\*\*$/ + while line = f.gets + if /\s+\*\/\s*$/ =~ line + break + else + comment << line + end + end + + # start instruction body + when /^DEFINE_INSN$/ + insn = f.gets.chomp + opes = parse_vars(f.gets.chomp) + pops = parse_vars(f.gets.chomp).reverse + rets_str = f.gets.chomp + rets = parse_vars(rets_str).reverse + comment = parse_comment(comment) + insn_in = true + body = '' + + sp_inc = rets_str[%r"//\s*(.+)", 1] + + raise unless /^\{$/ =~ f.gets.chomp + line_no = f.line_no + + # end instruction body + when /^\}/ + if insn_in + body.instance_variable_set(:@line_no, line_no) + body.instance_variable_set(:@file, f.path) + insn = make_insn(insn, opes, pops, rets, comment, body, sp_inc) + insn_in = false + comment = '' + end + + else + if insn_in + body << line + "\n" + end + end + end + } + end + + ## opt op + def load_opt_operand_def file + vpath.foreach(file) {|line| + line = line.gsub(/\#.*/, '').strip + next if line.length == 0 + break if /__END__/ =~ line + /(\S+)\s+(.+)/ =~ line + insn = $1 + opts = $2 + add_opt_operand insn, opts.split(/,/).map{|e| e.strip} + } if file + end + + def label_escape label + label.gsub(/\(/, '_O_'). + gsub(/\)/, '_C_'). + gsub(/\*/, '_WC_') + end + + def add_opt_operand insn_name, opts + insn = @insn_map[insn_name] + opes = insn.opes + + if opes.size != opts.size + raise "operand size mismatch for #{insn.name} (opes: #{opes.size}, opts: #{opts.size})" + end + + ninsn = insn.name + '_OP_' + opts.map{|e| label_escape(e)}.join('_') + nopes = [] + defv = [] + + opts.each_with_index{|e, i| + if e == '*' + nopes << opes[i] + end + defv << [opes[i], e] + } + + make_insn_operand_optimized(insn, ninsn, nopes, defv) + end + + def make_insn_operand_optimized orig_insn, name, opes, defopes + comm = orig_insn.comm.dup + comm[:c] = 'optimize' + add_insn insn = Instruction.new( + name, opes, orig_insn.pops, orig_insn.rets, comm, + orig_insn.body, orig_insn.tvars, orig_insn.sp_inc, + orig_insn, defopes) + orig_insn.add_optimized insn + end + + ## insn unif + def load_insn_unification_def file + vpath.foreach(file) {|line| + line = line.gsub(/\#.*/, '').strip + next if line.length == 0 + break if /__END__/ =~ line + make_unified_insns line.split.map{|e| + raise "unknown insn: #{e}" unless @insn_map[e] + @insn_map[e] + } + } if file + end + + def all_combination sets + ret = sets.shift.map{|e| [e]} + + sets.each{|set| + prev = ret + ret = [] + prev.each{|ary| + set.each{|e| + eary = ary.dup + eary << e + ret << eary + } + } + } + ret + end + + def make_unified_insns insns + if vm_opt?('UNIFY_ALL_COMBINATION') + insn_sets = insns.map{|insn| + [insn] + insn.optimized + } + + all_combination(insn_sets).each{|insns_set| + make_unified_insn_each insns_set + } + else + make_unified_insn_each insns + end + end + + def mk_private_val vals, i, redef + vals.dup.map{|v| + # v[0] : type + # v[1] : var name + + v = v.dup + if v[0] != '...' + redef[v[1]] = v[0] + v[1] = "#{v[1]}_#{i}" + end + v + } + end + + def mk_private_val2 vals, i, redef + vals.dup.map{|v| + # v[0][0] : type + # v[0][1] : var name + # v[1] : default val + + pv = v.dup + v = pv[0] = pv[0].dup + if v[0] != '...' + redef[v[1]] = v[0] + v[1] = "#{v[1]}_#{i}" + end + pv + } + end + + def make_unified_insn_each insns + names = [] + opes = [] + pops = [] + rets = [] + comm = { + :c => 'optimize', + :e => 'unified insn', + :j => 'unified insn', + } + body = '' + passed = [] + tvars = [] + defopes = [] + sp_inc = '' + + insns.each_with_index{|insn, i| + names << insn.name + redef_vars = {} + + e_opes = mk_private_val(insn.opes, i, redef_vars) + e_pops = mk_private_val(insn.pops, i, redef_vars) + e_rets = mk_private_val(insn.rets, i, redef_vars) + # ToDo: fix it + e_defs = mk_private_val2(insn.defopes, i, redef_vars) + + passed_vars = [] + while pvar = e_pops.pop + rvar = rets.pop + if rvar + raise "unsupported unif insn: #{insns.inspect}" if rvar[0] == '...' + passed_vars << [pvar, rvar] + tvars << rvar + else + e_pops.push pvar + break + end + end + + opes.concat e_opes + pops.concat e_pops + rets.concat e_rets + defopes.concat e_defs + sp_inc += "#{insn.sp_inc}" + + body += "{ /* unif: #{i} */\n" + + passed_vars.map{|rpvars| + pv = rpvars[0] + rv = rpvars[1] + "#define #{pv[1]} #{rv[1]}" + }.join("\n") + + "\n" + + redef_vars.map{|v, type| + "#define #{v} #{v}_#{i}" + }.join("\n") + "\n" + + insn.body + + passed_vars.map{|rpvars| + "#undef #{rpvars[0][1]}" + }.join("\n") + + "\n" + + redef_vars.keys.map{|v| + "#undef #{v}" + }.join("\n") + + "\n}\n" + } + + tvars_ary = [] + tvars.each{|tvar| + unless opes.any?{|var| + var[1] == tvar[1] + } || defopes.any?{|pvar| + pvar[0][1] == tvar[1] + } + tvars_ary << tvar + end + } + add_insn insn = Instruction.new("UNIFIED_" + names.join('_'), + opes, pops, rets.reverse, comm, body, + tvars_ary, sp_inc) + insn.defopes.replace defopes + insns[0].add_unif [insn, insns] + end + + ## sc + SPECIAL_INSN_FOR_SC_AFTER = { + /\Asend/ => [:a], + /\Aend/ => [:a], + /\Ayield/ => [:a], + /\Aclassdef/ => [:a], + /\Amoduledef/ => [:a], + } + FROM_SC = [[], [:a], [:b], [:a, :b], [:b, :a]] + + def make_stackcaching_insns + pops = rets = nil + + @insns.dup.each{|insn| + opops = insn.pops + orets = insn.rets + oopes = insn.opes + ocomm = insn.comm + oname = insn.name + + after = SPECIAL_INSN_FOR_SC_AFTER.find {|k, v| k =~ oname} + + insns = [] + FROM_SC.each{|from| + name, pops, rets, pushs1, pushs2, nextsc = + *calc_stack(insn, from, after, opops, orets) + + make_insn_sc(insn, name, oopes, pops, rets, [pushs1, pushs2], nextsc) + } + } + end + + def make_insn_sc orig_insn, name, opes, pops, rets, pushs, nextsc + comm = orig_insn.comm.dup + comm[:c] = 'optimize(sc)' + + scinsn = Instruction.new( + name, opes, pops, rets, comm, + orig_insn.body, orig_insn.tvars, orig_insn.sp_inc, + orig_insn, orig_insn.defopes, :sc, nextsc, pushs) + + add_insn scinsn + orig_insn.add_sc scinsn + end + + def self.complement_name st + "#{st[0] ? st[0] : 'x'}#{st[1] ? st[1] : 'x'}" + end + + def add_stack_value st + len = st.length + if len == 0 + st[0] = :a + [nil, :a] + elsif len == 1 + if st[0] == :a + st[1] = :b + else + st[1] = :a + end + [nil, st[1]] + else + st[0], st[1] = st[1], st[0] + [st[1], st[1]] + end + end + + def calc_stack insn, ofrom, oafter, opops, orets + from = ofrom.dup + pops = opops.dup + rets = orets.dup + rest_scr = ofrom.dup + + pushs_before = [] + pushs= [] + + pops.each_with_index{|e, i| + if e[0] == '...' + pushs_before = from + from = [] + end + r = from.pop + break unless r + pops[i] = pops[i].dup << r + } + + if oafter + from = oafter + from.each_with_index{|r, i| + rets[i] = rets[i].dup << r if rets[i] + } + else + rets = rets.reverse + rets.each_with_index{|e, i| + break if e[0] == '...' + pushed, r = add_stack_value from + rets[i] = rets[i].dup << r + if pushed + if rest_scr.pop + pushs << pushed + end + + if i - 2 >= 0 + rets[i-2].pop + end + end + } + end + + if false #|| insn.name =~ /test3/ + p ofrom + p pops + p rets + p pushs_before + p pushs + p from + exit + end + + ret = ["#{insn.name}_SC_#{InstructionsLoader.complement_name(ofrom)}_#{complement_name(from)}", + pops, rets, pushs_before, pushs, from] + end + end + + class SourceCodeGenerator + def initialize insns + @insns = insns + end + + attr_reader :insns + + def generate + raise "should not reach here" + end + + def vpath + @insns.vpath + end + + def verbose? + @insns.verbose? + end + + def use_const? + @insns.use_const? + end + + def build_string + @lines = [] + yield + @lines.join("\n") + end + + EMPTY_STRING = ''.freeze + + def commit str = EMPTY_STRING + @lines << str + end + + def comment str + @lines << str if verbose? + end + + def output_path(fn) + d = @insns.destdir + fn = File.join(d, fn) if d + fn + end + end + + ################################################################### + # vm.inc + class VmBodyGenerator < SourceCodeGenerator + # vm.inc + def generate + vm_body = '' + @insns.each{|insn| + vm_body << "\n" + vm_body << make_insn_def(insn) + } + src = vpath.read('template/vm.inc.tmpl') + ERB.new(src).result(binding) + end + + def generate_from_insnname insnname + make_insn_def @insns[insnname.to_s] + end + + ####### + private + + def make_header_prepare_stack insn + comment " /* prepare stack status */" + + push_ba = insn.pushsc + raise "unsupport" if push_ba[0].size > 0 && push_ba[1].size > 0 + + n = 0 + push_ba.each {|pushs| n += pushs.length} + commit " CHECK_VM_STACK_OVERFLOW_FOR_INSN(REG_CFP, #{n});" if n > 0 + push_ba.each{|pushs| + pushs.each{|r| + commit " PUSH(SCREG(#{r}));" + } + } + end + + def make_header_operands insn + comment " /* declare and get from iseq */" + + vars = insn.opes + n = 0 + ops = [] + + vars.each_with_index{|(type, var), i| + if type == '...' + break + end + + # skip make operands when body has no reference to this operand + # TODO: really needed? + re = /\b#{var}\b/n + if re =~ insn.body or re =~ insn.sp_inc or insn.rets.any?{|t, v| re =~ v} or re =~ 'ic' or re =~ 'ci' + ops << " #{type} #{var} = (#{type})GET_OPERAND(#{i+1});" + end + + n += 1 + } + @opn = n + + # reverse or not? + # ops.join + commit ops.reverse + end + + def make_header_default_operands insn + vars = insn.defopes + + vars.each{|e| + next if e[1] == '*' + if use_const? + commit " const #{e[0][0]} #{e[0][1]} = #{e[1]};" + else + commit " #define #{e[0][1]} #{e[1]}" + end + } + end + + def make_footer_default_operands insn + comment " /* declare and initialize default opes */" + if use_const? + commit + else + vars = insn.defopes + + vars.each{|e| + next if e[1] == '*' + commit "#undef #{e[0][1]}" + } + end + end + + def make_header_stack_pops insn + comment " /* declare and pop from stack */" + + n = 0 + pops = [] + vars = insn.pops + vars.each_with_index{|iter, i| + type, var, r = *iter + if type == '...' + break + end + if r + pops << " #{type} #{var} = SCREG(#{r});" + else + pops << " #{type} #{var} = TOPN(#{n});" + n += 1 + end + } + @popn = n + + # reverse or not? + commit pops.reverse + end + + def make_header_temporary_vars insn + comment " /* declare temporary vars */" + + insn.tvars.each{|var| + commit " #{var[0]} #{var[1]};" + } + end + + def make_header_stack_val insn + comment "/* declare stack push val */" + + vars = insn.opes + insn.pops + insn.defopes.map{|e| e[0]} + + insn.rets.each{|var| + if vars.all?{|e| e[1] != var[1]} && var[1] != '...' + commit " #{var[0]} #{var[1]};" + end + } + end + + def make_header_analysis insn + commit " COLLECT_USAGE_INSN(BIN(#{insn.name}));" + insn.opes.each_with_index{|op, i| + commit " COLLECT_USAGE_OPERAND(BIN(#{insn.name}), #{i}, #{op[1]});" + } + end + + def make_header_pc insn + commit " ADD_PC(1+#{@opn});" + commit " PREFETCH(GET_PC());" + end + + def make_header_popn insn + comment " /* management */" + commit " POPN(#{@popn});" if @popn > 0 + end + + def make_header_debug insn + comment " /* for debug */" + commit " DEBUG_ENTER_INSN(\"#{insn.name}\");" + end + + def make_header_defines insn + commit " #define CURRENT_INSN_#{insn.name} 1" + commit " #define INSN_IS_SC() #{insn.sc ? 0 : 1}" + commit " #define INSN_LABEL(lab) LABEL_#{insn.name}_##lab" + commit " #define LABEL_IS_SC(lab) LABEL_##lab##_###{insn.sc.size == 0 ? 't' : 'f'}" + end + + def each_footer_stack_val insn + insn.rets.reverse_each{|v| + break if v[1] == '...' + yield v + } + end + + def make_footer_stack_val insn + comment " /* push stack val */" + + n = 0 + each_footer_stack_val(insn){|v| + n += 1 unless v[2] + } + commit " CHECK_VM_STACK_OVERFLOW_FOR_INSN(REG_CFP, #{n});" if n > 0 + each_footer_stack_val(insn){|v| + if v[2] + commit " SCREG(#{v[2]}) = #{v[1]};" + else + commit " PUSH(#{v[1]});" + end + } + end + + def make_footer_undefs insn + commit "#undef CURRENT_INSN_#{insn.name}" + commit "#undef INSN_IS_SC" + commit "#undef INSN_LABEL" + commit "#undef LABEL_IS_SC" + end + + def make_header insn + commit "INSN_ENTRY(#{insn.name}){" + make_header_prepare_stack insn + commit "{" + make_header_stack_val insn + make_header_default_operands insn + make_header_operands insn + make_header_stack_pops insn + make_header_temporary_vars insn + # + make_header_debug insn + make_header_pc insn + make_header_popn insn + make_header_defines insn + make_header_analysis insn + commit "{" + end + + def make_footer insn + make_footer_stack_val insn + make_footer_default_operands insn + make_footer_undefs insn + commit " END_INSN(#{insn.name});}}}" + end + + def make_insn_def insn + build_string do + make_header insn + if line = insn.body.instance_variable_get(:@line_no) + file = insn.body.instance_variable_get(:@file) + commit "#line #{line+1} \"#{file}\"" + commit insn.body + commit '#line __CURRENT_LINE__ "__CURRENT_FILE__"' + else + insn.body + end + make_footer(insn) + end + end + end + + ################################################################### + # vmtc.inc + class VmTCIncGenerator < SourceCodeGenerator + def generate + + insns_table = build_string do + @insns.each{|insn| + commit " LABEL_PTR(#{insn.name})," + } + end + + insn_end_table = build_string do + @insns.each{|insn| + commit " ELABEL_PTR(#{insn.name}),\n" + } + end + + ERB.new(vpath.read('template/vmtc.inc.tmpl')).result(binding) + end + end + + ################################################################### + # insns_info.inc + class InsnsInfoIncGenerator < SourceCodeGenerator + def generate + insns_info_inc + end + + ### + private + + def op2typesig op + case op + when /^OFFSET/ + "TS_OFFSET" + when /^rb_num_t/ + "TS_NUM" + when /^lindex_t/ + "TS_LINDEX" + when /^VALUE/ + "TS_VALUE" + when /^ID/ + "TS_ID" + when /GENTRY/ + "TS_GENTRY" + when /^IC/ + "TS_IC" + when /^CALL_INFO/ + "TS_CALLINFO" + when /^\.\.\./ + "TS_VARIABLE" + when /^CDHASH/ + "TS_CDHASH" + when /^ISEQ/ + "TS_ISEQ" + when /rb_insn_func_t/ + "TS_FUNCPTR" + else + raise "unknown op type: #{op}" + end + end + + TYPE_CHARS = { + 'TS_OFFSET' => 'O', + 'TS_NUM' => 'N', + 'TS_LINDEX' => 'L', + 'TS_VALUE' => 'V', + 'TS_ID' => 'I', + 'TS_GENTRY' => 'G', + 'TS_IC' => 'K', + 'TS_CALLINFO' => 'C', + 'TS_CDHASH' => 'H', + 'TS_ISEQ' => 'S', + 'TS_VARIABLE' => '.', + 'TS_FUNCPTR' => 'F', + } + + # insns_info.inc + def insns_info_inc + # insn_type_chars + insn_type_chars = TYPE_CHARS.map{|t, c| + "#define #{t} '#{c}'" + }.join("\n") + + # insn_names + insn_names = '' + @insns.each{|insn| + insn_names << " \"#{insn.name}\",\n" + } + + # operands info + operands_info = '' + operands_num_info = '' + + @insns.each{|insn| + opes = insn.opes + operands_info << ' ' + ot = opes.map{|type, var| + TYPE_CHARS.fetch(op2typesig(type)) + } + operands_info << "\"#{ot.join}\"" << ",\n" + + num = opes.size + 1 + operands_num_info << " #{num},\n" + } + + # stack num + stack_num_info = '' + @insns.each{|insn| + num = insn.rets.size + stack_num_info << " #{num},\n" + } + + # stack increase + stack_increase = '' + @insns.each{|insn| + stack_increase << <<-EOS + case BIN(#{insn.name}):{ + #{insn.sp_increase_c_expr} + } + EOS + } + ERB.new(vpath.read('template/insns_info.inc.tmpl')).result(binding) + end + end + + ################################################################### + # insns.inc + class InsnsIncGenerator < SourceCodeGenerator + def generate + i=0 + insns = build_string do + @insns.each{|insn| + commit " %-30s = %d," % ["BIN(#{insn.name})", i] + i+=1 + } + end + + ERB.new(vpath.read('template/insns.inc.tmpl')).result(binding) + end + end + + ################################################################### + # minsns.inc + class MInsnsIncGenerator < SourceCodeGenerator + def generate + i=0 + defs = build_string do + @insns.each{|insn| + commit " rb_define_const(mYarvInsns, %-30s, INT2FIX(%d));" % + ["\"I#{insn.name}\"", i] + i+=1 + } + end + ERB.new(vpath.read('template/minsns.inc.tmpl')).result(binding) + end + end + + ################################################################### + # optinsn.inc + class OptInsnIncGenerator < SourceCodeGenerator + def generate + optinsn_inc + end + + ### + private + + def val_as_type op + type = op[0][0] + val = op[1] + + case type + when /^long/, /^rb_num_t/, /^lindex_t/ + "INT2FIX(#{val})" + when /^VALUE/ + val + when /^ID/ + "INT2FIX(#{val})" + when /^ISEQ/, /^rb_insn_func_t/ + val + when /GENTRY/ + raise + when /^\.\.\./ + raise + else + raise "type: #{type}" + end + end + + # optinsn.inc + def optinsn_inc + rule = '' + opt_insns_map = Hash.new{|h, k| h[k] = []} + + @insns.each{|insn| + next if insn.defopes.size == 0 + next if insn.type == :sc + next if /^UNIFIED/ =~ insn.name.to_s + + originsn = insn.orig + opt_insns_map[originsn] << insn + } + + rule = build_string do + opt_insns_map.each{|originsn, optinsns| + commit "case BIN(#{originsn.name}):" + + optinsns.sort_by{|opti| + opti.defopes.find_all{|e| e[1] == '*'}.size + }.each{|opti| + commit " if(" + i = 0 + commit " " + opti.defopes.map{|opinfo| + i += 1 + next if opinfo[1] == '*' + "insnobj->operands[#{i-1}] == #{val_as_type(opinfo)}" + }.compact.join('&& ') + commit " ){" + idx = 0 + n = 0 + opti.defopes.each{|opinfo| + if opinfo[1] == '*' + if idx != n + commit " insnobj->operands[#{idx}] = insnobj->operands[#{n}];" + end + idx += 1 + else + # skip + end + n += 1 + } + commit " insnobj->insn_id = BIN(#{opti.name});" + commit " insnobj->operand_size = #{idx};" + commit " break;\n }\n" + } + commit " break;"; + } + end + + ERB.new(vpath.read('template/optinsn.inc.tmpl')).result(binding) + end + end + + ################################################################### + # optunifs.inc + class OptUnifsIncGenerator < SourceCodeGenerator + def generate + unif_insns_each = '' + unif_insns = '' + unif_insns_data = [] + + insns = @insns.find_all{|insn| !insn.is_sc} + insns.each{|insn| + size = insn.unifs.size + if size > 0 + insn.unifs.sort_by{|unif| -unif[1].size}.each_with_index{|unif, i| + + uni_insn, uni_insns = *unif + uni_insns = uni_insns[1..-1] + unif_insns_each << "static const int UNIFIED_#{insn.name}_#{i}[] = {" + + " BIN(#{uni_insn.name}), #{uni_insns.size + 2},\n " + + uni_insns.map{|e| "BIN(#{e.name})"}.join(", ") + "};\n" + } + else + + end + if size > 0 + unif_insns << "static const int *const UNIFIED_#{insn.name}[] = {(int *)#{size+1},\n" + unif_insns << (0...size).map{|e| " UNIFIED_#{insn.name}_#{e}"}.join(",\n") + "};\n" + unif_insns_data << " UNIFIED_#{insn.name}" + else + unif_insns_data << " 0" + end + } + unif_insns_data = "static const int *const *const unified_insns_data[] = {\n" + + unif_insns_data.join(",\n") + "};\n" + ERB.new(vpath.read('template/optunifs.inc.tmpl')).result(binding) + end + end + + ################################################################### + # opt_sc.inc + class OptSCIncGenerator < SourceCodeGenerator + def generate + sc_insn_info = [] + @insns.each{|insn| + insns = insn.sc + if insns.size > 0 + insns = ['SC_ERROR'] + insns.map{|e| " BIN(#{e.name})"} + else + insns = Array.new(6){'SC_ERROR'} + end + sc_insn_info << " {\n#{insns.join(",\n")}}" + } + sc_insn_info = sc_insn_info.join(",\n") + + sc_insn_next = @insns.map{|insn| + " SCS_#{InstructionsLoader.complement_name(insn.nextsc).upcase}" + + (verbose? ? " /* #{insn.name} */" : '') + }.join(",\n") + ERB.new(vpath.read('template/opt_sc.inc.tmpl')).result(binding) + end + end + + ################################################################### + # yasmdata.rb + class YASMDataRbGenerator < SourceCodeGenerator + def generate + insn_id2no = '' + @insns.each_with_index{|insn, i| + insn_id2no << " :#{insn.name} => #{i},\n" + } + ERB.new(vpath.read('template/yasmdata.rb.tmpl')).result(binding) + end + end + + ################################################################### + # yarvarch.* + class YARVDocGenerator < SourceCodeGenerator + def generate + + end + + def desc lang + d = '' + i = 0 + cat = nil + @insns.each{|insn| + seq = insn.opes.map{|t,v| v}.join(' ') + before = insn.pops.reverse.map{|t,v| v}.join(' ') + after = insn.rets.reverse.map{|t,v| v}.join(' ') + + if cat != insn.comm[:c] + d << "** #{insn.comm[:c]}\n\n" + cat = insn.comm[:c] + end + + d << "*** #{insn.name}\n" + d << "\n" + d << insn.comm[lang] + "\n\n" + d << ":instruction sequence: 0x%02x #{seq}\n" % i + d << ":stack: #{before} => #{after}\n\n" + i+=1 + } + d + end + + def desc_ja + d = desc :j + ERB.new(vpath.read('template/yarvarch.ja')).result(binding) + end + + def desc_en + d = desc :e + ERB.new(vpath.read('template/yarvarch.en')).result(binding) + end + end + + class SourceCodeGenerator + Files = { # codes + 'vm.inc' => VmBodyGenerator, + 'vmtc.inc' => VmTCIncGenerator, + 'insns.inc' => InsnsIncGenerator, + 'insns_info.inc' => InsnsInfoIncGenerator, + # 'minsns.inc' => MInsnsIncGenerator, + 'optinsn.inc' => OptInsnIncGenerator, + 'optunifs.inc' => OptUnifsIncGenerator, + 'opt_sc.inc' => OptSCIncGenerator, + 'yasmdata.rb' => YASMDataRbGenerator, + } + + def generate args = [] + args = Files.keys if args.empty? + args.each{|fn| + s = Files[fn].new(@insns).generate + open(output_path(fn), 'w') {|f| f.puts(s)} + } + end + + def self.def_options(opt) + opts = { + :"insns.def" => 'insns.def', + :"opope.def" => 'defs/opt_operand.def', + :"unif.def" => 'defs/opt_insn_unif.def', + } + + opt.on("-Dname", /\AOPT_(\w+)\z/, "enable VM option") {|s, v| + opts[v] = true + } + opt.on("--enable=name[,name...]", Array, + "enable VM options (without OPT_ prefix)") {|*a| + a.each {|v| opts[v] = true} + } + opt.on("-Uname", /\AOPT_(\w+)\z/, "disable VM option") {|s, v| + opts[v] = false + } + opt.on("--disable=name[,name...]", Array, + "disable VM options (without OPT_ prefix)") {|*a| + a.each {|v| opts[v] = false} + } + opt.on("-i", "--insnsdef=FILE", "--instructions-def", + "instructions definition file") {|n| + opts[:insns_def] = n + } + opt.on("-o", "--opt-operanddef=FILE", "--opt-operand-def", + "vm option: operand definition file") {|n| + opts[:opope_def] = n + } + opt.on("-u", "--opt-insnunifdef=FILE", "--opt-insn-unif-def", + "vm option: instruction unification file") {|n| + opts[:unif_def] = n + } + opt.on("-C", "--[no-]use-const", + "use consts for default operands instead of macros") {|v| + opts[:use_const] = v + } + opt.on("-d", "--destdir", "--output-directory=DIR", + "make output file underneath DIR") {|v| + opts[:destdir] = v + } + opt.on("-V", "--[no-]verbose") {|v| + opts[:verbose] = v + } + + vpath = VPath.new + vpath.def_options(opt) + + proc { + opts[:VPATH] = vpath + build opts + } + end + + def self.build opts, vpath = ['./'] + opts[:VPATH] ||= VPath.new(*vpath) + self.new InstructionsLoader.new(opts) + end + end +end + diff --git a/jni/ruby/tool/jisx0208.rb b/jni/ruby/tool/jisx0208.rb new file mode 100644 index 0000000..921f574 --- /dev/null +++ b/jni/ruby/tool/jisx0208.rb @@ -0,0 +1,84 @@ +module JISX0208 + class Char + class << self + def from_sjis(sjis) + unless 0x8140 <= sjis && sjis <= 0xFCFC + raise ArgumentError, "out of the range of JIS X 0208: 0x#{sjis.to_s(16)}" + end + sjis_hi, sjis_lo = sjis >> 8, sjis & 0xFF + sjis_hi = (sjis_hi - ((sjis_hi <= 0x9F) ? 0x80 : 0xC0)) << 1 + if sjis_lo <= 0x9E + sjis_hi -= 1 + sjis_lo -= (sjis_lo <= 0x7E) ? 0x3F : 0x40 + else + sjis_lo -= 0x9E + end + return self.new(sjis_hi, sjis_lo) + end + end + + def initialize(row, cell=nil) + if cell + @code = row_cell_to_code(row, cell) + else + @code = row.to_int + end + end + + def ==(other) + if self.class === other + return Integer(self) == Integer(other) + end + return super(other) + end + + def to_int + return @code + end + + def hi + Integer(self) >> 8 + end + + def lo + Integer(self) & 0xFF + end + + def row + self.hi - 0x20 + end + + def cell + self.lo - 0x20 + end + + def succ + succ_hi, succ_lo = self.hi, self.lo + 1 + if succ_lo > 0x7E + succ_lo = 0x21 + succ_hi += 1 + end + return self.class.new(succ_hi << 8 | succ_lo) + end + + def to_sjis + h, l = self.hi, self.lo + h = (h + 1) / 2 + ((0x21..0x5E).include?(h) ? 0x70 : 0xB0) + l += self.hi.odd? ? 0x1F + ((l >= 0x60) ? 1 : 0) : 0x7E + return h << 8 | l + end + + def inspect + "#<JISX0208::Char:#{self.object_id.to_s(16)} sjis=#{self.to_sjis.to_s(16)} jis=#{self.to_int.to_s(16)}>" + end + + private + + def row_cell_to_code(row, cell) + unless 0 < row && (1..94).include?(cell) + raise ArgumentError, "out of row-cell range: #{row}-#{cell}" + end + return (row + 0x20) << 8 | (cell + 0x20) + end + end +end diff --git a/jni/ruby/tool/make-snapshot b/jni/ruby/tool/make-snapshot new file mode 100755 index 0000000..46387cf --- /dev/null +++ b/jni/ruby/tool/make-snapshot @@ -0,0 +1,378 @@ +#!/usr/bin/ruby -s +# -*- coding: us-ascii -*- +require 'uri' +require 'digest/md5' +require 'digest/sha2' +require 'fileutils' +require 'tmpdir' +require File.expand_path("../vcs", __FILE__) +STDOUT.sync = true + +$srcdir ||= nil +$exported = nil if ($exported ||= nil) == "" +$archname = nil if ($archname ||= nil) == "" +$keep_temp ||= nil +$patch_file ||= nil +$packages ||= nil +$digests ||= nil +$tooldir = File.expand_path("..", __FILE__) + +def usage + <<USAGE +usage: #{File.basename $0} [option...] new-directory-to-save [version ...] +options: + -srcdir=PATH source directory path + -exported=PATH make snapshot from already exported working directory + -archname=NAME make the basename of snapshots NAME + -keep_temp keep temporary working directory + -patch_file=PATCH apply PATCH file after export + -packages=PKG[,...] make PKG packages (#{PACKAGES.keys.join(", ")}) + -digests=ALG[,...] show ALG digests (#{DIGESTS.join(", ")}) +version: + trunk, stable, branches/*, tags/*, X.Y, X.Y.Z, X.Y.Z-pL +each versions may be followed by optional @revision. +USAGE +end + +DIGESTS = %w[MD5 SHA256 SHA512] +PACKAGES = { + "bzip" => %w".tar.bz2 bzip2 -c", + "gzip" => %w".tar.gz gzip -c", + "xz" => %w".tar.xz xz -c", + "zip" => %w".zip zip -qr", +} + +ENV["LC_ALL"] = ENV["LANG"] = "C" +SVNURL = URI.parse("http://svn.ruby-lang.org/repos/ruby/") +RUBY_VERSION_PATTERN = /^\#define\s+RUBY_VERSION\s+"([\d.]+)"/ + +ENV["VPATH"] ||= "include/ruby" +YACC = ENV["YACC"] ||= "bison" +ENV["BASERUBY"] ||= "ruby" +ENV["RUBY"] ||= "ruby" +ENV["MV"] ||= "mv" +ENV["RM"] ||= "rm -f" +ENV["MINIRUBY"] ||= "ruby" +ENV["PROGRAM"] ||= "ruby" +ENV["AUTOCONF"] ||= "autoconf" +ENV["BUILTIN_TRANSOBJS"] ||= "newline.o" + +class String + # for older ruby + alias bytesize size unless method_defined?(:bytesize) +end + +class Dir + def self.mktmpdir(path) + path = File.join(tmpdir, path+"-#{$$}-#{rand(100000)}") + begin + mkdir(path) + rescue Errno::EEXIST + path.succ! + retry + end + path + end unless respond_to?(:mktmpdir) +end + +$packages &&= $packages.split(/[, ]+/).tap {|pkg| + pkg -= PACKAGES.keys + pkg.empty? or abort "#{File.basename $0}: unknown packages - #{pkg.join(", ")}" +} +$packages ||= PACKAGES.keys + +$digests &&= $digests.split(/[, ]+/).tap {|dig| + dig -= DIGESTS + dig.empty? or abort "#{File.basename $0}: unknown digests - #{dig.join(", ")}" +} +$digests ||= DIGESTS + +$patch_file &&= File.expand_path($patch_file) +path = ENV["PATH"].split(File::PATH_SEPARATOR) +%w[YACC BASERUBY RUBY MV MINIRUBY].each do |var| + cmd = ENV[var] + unless path.any? {|dir| + file = File.expand_path(cmd, dir) + File.file?(file) and File.executable?(file) + } + abort "#{File.basename $0}: #{var} command not found - #{cmd}" + end +end + +%w[BASERUBY RUBY MINIRUBY].each do |var| + `#{ENV[var]} --disable-gem -e1 2>&1` + if $?.success? + ENV[var] += ' --disable-gem' + end +end + +if defined?($help) or defined?($_help) + puts usage + exit +end +unless destdir = ARGV.shift + abort usage +end +revisions = ARGV.empty? ? ["trunk"] : ARGV +unless tmp = $exported + FileUtils.mkpath(destdir) + destdir = File.expand_path(destdir) + tmp = Dir.mktmpdir("ruby-snapshot") + FileUtils.mkpath(tmp) + at_exit { + Dir.chdir "/" + FileUtils.rm_rf(tmp) + } unless $keep_temp +end + +def package(vcs, rev, destdir, tmp = nil) + patchlevel = false + prerelease = false + if revision = rev[/@(\d+)\z/, 1] + rev = $` + end + case rev + when /\Atrunk\z/ + url = vcs.trunk + when /\Abranches\// + url = vcs.branch($') + when /\Atags\// + url = vcs.tag($') + when /\Astable\z/ + vcs.branch_list("ruby_[0-9]*") {|n| url = n[/\Aruby_\d+_\d+\z/]} + url &&= vcs.branch(url) + when /\A(.*)\.(.*)\.(.*)-(preview|rc)(\d+)/ + prerelease = true + tag = "#{$4}#{$5}" + url = vcs.tag("v#{$1}_#{$2}_#{$3}_#{$4}#{$5}") + when /\A(.*)\.(.*)\.(.*)-p(\d+)/ + patchlevel = true + tag = "p#{$4}" + url = vcs.tag("v#{$1}_#{$2}_#{$3}_#{$4}") + when /\A(\d+)\.(\d+)(?:\.(\d+))?\z/ + if $3 && ($1 > "2" || $1 == "2" && $2 >= "1") + patchlevel = true + tag = "" + url = vcs.tag("v#{$1}_#{$2}_#{$3}") + else + url = vcs.branch("ruby_#{rev.tr('.', '_')}") + end + else + warn "#{$0}: unknown version - #{rev}" + return + end + revision ||= vcs.get_revisions(url)[1] + version = nil + unless revision + url = vcs.trunk + vcs.grep(RUBY_VERSION_PATTERN, url, "version.h") {version = $1} + unless rev == version + warn "#{$0}: #{rev} not found" + return + end + revision = vcs.get_revisions(url)[1] + end + v = nil + if $exported + if String === $exported + v = $exported + end + else + v = "ruby" + puts "Exporting #{rev}@#{revision}" + exported = tmp ? File.join(tmp, v) : v + unless vcs.export(revision, url, exported) {|line| print line} + warn("Export failed") + return + end + if $srcdir + Dir.glob($srcdir + "/{tool/config.{guess,sub},gems/*.gem,.downloaded-cache/*}") do |file| + puts "copying #{file}" + dest = exported + file[$srcdir.size..-1] + FileUtils.mkpath(File.dirname(dest)) + begin + FileUtils.ln(file, dest, force: true) + rescue SystemCallError + FileUtils.cp(file, dest, preserve: true) + end + end + end + end + + Dir.chdir(tmp) if tmp + + if !File.directory?(v) + v = Dir.glob("ruby-*").select(&File.method(:directory?)) + v.size == 1 or abort "not exported" + v = v[0] + end + open("#{v}/revision.h", "wb") {|f| f.puts "#define RUBY_REVISION #{revision}"} + open("#{v}/.revision.time", "wb") {} + version ||= (versionhdr = IO.read("#{v}/version.h"))[RUBY_VERSION_PATTERN, 1] + version or return + if patchlevel + unless tag.empty? + versionhdr ||= IO.read("#{v}/version.h") + patchlevel = versionhdr[/^\#define\s+RUBY_PATCHLEVEL\s+(\d+)/, 1] + tag = (patchlevel ? "p#{patchlevel}" : "r#{revision}") + end + elsif prerelease + versionhdr ||= IO.read("#{v}/version.h") + versionhdr.sub!(/^\#define\s+RUBY_PATCHLEVEL_STR\s+"\K.+?(?=")/, tag) + IO.write("#{v}/version.h", versionhdr) + else + tag ||= "r#{revision}" + end + unless v == $exported + if $archname + n = $archname + elsif tag.empty? + n = "ruby-#{version}" + else + n = "ruby-#{version}-#{tag}" + end + File.directory?(n) or File.rename v, n + v = n + end + system(*%W"patch -d #{v} -p0 -i #{$patch_file}") if $patch_file + if !$exported or $patch_file + "take a breath, and go ahead".scan(/./) {|c|print c; sleep(c == "," ? 0.7 : 0.05)}; puts + end + def (clean = []).add(n) push(n); n end + Dir.chdir(v) do + File.open(clean.add("cross.rb"), "w") do |f| + f.puts "Object.__send__(:remove_const, :CROSS_COMPILING) if defined?(CROSS_COMPILING)" + f.puts "CROSS_COMPILING=true" + end + unless File.exist?("configure") + print "creating configure..." + unless system([ENV["AUTOCONF"]]*2) + puts " failed" + return + end + puts " done" + end + clean.add("autom4te.cache") + print "creating prerequisites..." + if File.file?("common.mk") && /^prereq/ =~ commonmk = IO.read("common.mk") + puts + extout = clean.add('tmp') + File.open(clean.add("config.status"), "w") {|f| + f.puts "s,@configure_args@,|#_!!_#|,g" + f.puts "s,@EXTOUT@,|#_!!_#|#{extout},g" + f.puts "s,@bindir@,|#_!!_#|,g" + f.puts "s,@ruby_install_name@,|#_!!_#|,g" + f.puts "s,@ARCH_FLAG@,|#_!!_#|,g" + f.puts "s,@CFLAGS@,|#_!!_#|,g" + f.puts "s,@CPPFLAGS@,|#_!!_#|,g" + f.puts "s,@CXXFLAGS@,|#_!!_#|,g" + f.puts "s,@LDFLAGS@,|#_!!_#|,g" + f.puts "s,@DLDFLAGS@,|#_!!_#|,g" + f.puts "s,@LIBEXT@,|#_!!_#|a,g" + f.puts "s,@OBJEXT@,|#_!!_#|o,g" + f.puts "s,@EXEEXT@,|#_!!_#|,g" + f.puts "s,@LIBRUBY@,|#_!!_#|libruby.a,g" + f.puts "s,@LIBRUBY_A@,|#_!!_#|libruby.a,g" + f.puts "s,@RM@,|#_!!_#|rm -f,g" + f.puts "s,@CP@,|#_!!_#|cp,g" + f.puts "s,@rubyarchdir@,|#_!!_#|,g" + } + FileUtils.mkpath(hdrdir = "#{extout}/include/ruby") + File.open("#{hdrdir}/config.h", "w") {} + miniruby = ENV['MINIRUBY'] + " -I. -rcross" + mk = IO.read("Makefile.in").gsub(/^@.*\n/, '').gsub(/@([A-Za-z_]\w*)@/) {ENV[$1]} + mk << commonmk.gsub(/(?<!#)\{[^{}]*\}/, "") + cmd = %W[make -f - + srcdir=. CHDIR=cd NULLCMD=: + PATH_SEPARATOR=#{File::PATH_SEPARATOR} + IFCHANGE=tool/ifchange MAKEDIRS=mkdir\ -p + RMALL=rm\ -fr + MINIRUBY=#{miniruby} + RUNRUBY=#{miniruby} + RUBY=#{ENV["RUBY"]} + HAVE_BASERUBY=yes + BASERUBY=#{ENV["BASERUBY"]} + PWD=#{Dir.pwd} + prereq] + IO.popen(cmd, "w") do |f| + f.puts mk + f.puts "after-update::", "clean-cache $(CLEAN_CACHE): after-update", "prereq: clean-cache $(CLEAN_CACHE)" + end + clean.push("rbconfig.rb", ".rbconfig.time", "enc.mk") + print "prerequisites" + else + system(*%W"#{YACC} -o parse.c parse.y") + end + FileUtils.rm_rf(clean) + unless $?.success? + puts " failed" + return + end + puts " done" + end + + if v == "." + v = File.basename(Dir.pwd) + Dir.chdir ".." + else + Dir.chdir(File.dirname(v)) + v = File.basename(v) + end + + tarball = nil + return $packages.collect do |mesg| + (ext, *cmd) = PACKAGES[mesg] + File.directory?(destdir) or FileUtils.mkpath(destdir) + file = File.join(destdir, "#{$archname||v}#{ext}") + case ext + when /\.tar/ + if tarball + next if tarball.empty? + else + tarball = "#{$archname||v}.tar" + print "creating tarball... #{tarball}" + if system("tar", "cf", tarball, v) + puts " done" + else + puts " failed" + tarball = "" + next + end + end + print "creating #{mesg} tarball... #{file}" + done = system(*cmd, tarball, out: file) + else + print "creating #{mesg} archive... #{file}" + done = system(*cmd, file, v) + end + if done + puts " done" + file + else + puts " failed" + nil + end + end.compact +ensure + FileUtils.rm_rf(v) if v and !$exported and !$keep_temp +end + +vcs = (VCS.detect($srcdir) rescue nil if $srcdir) || VCS::SVN.new(SVNURL) + +success = true +revisions.collect {|rev| package(vcs, rev, destdir, tmp)}.flatten.each do |name| + if !name + success = false + next + end + str = open(name, "rb") {|f| f.read} + puts "* #{name}" + puts " SIZE: #{str.bytesize} bytes" + $digests.each do |alg| + printf " %-8s%s\n", "#{alg}:", Digest.const_get(alg).hexdigest(str) + end +end + +exit false if !success + +# vim:fileencoding=US-ASCII sw=2 ts=4 noexpandtab ff=unix diff --git a/jni/ruby/tool/mdoc2man.rb b/jni/ruby/tool/mdoc2man.rb new file mode 100755 index 0000000..49058af --- /dev/null +++ b/jni/ruby/tool/mdoc2man.rb @@ -0,0 +1,465 @@ +#!/usr/bin/env ruby +### +### mdoc2man - mdoc to man converter +### +### Quick usage: mdoc2man.rb < mdoc_manpage.8 > man_manpage.8 +### +### Ported from Perl by Akinori MUSHA. +### +### Copyright (c) 2001 University of Illinois Board of Trustees +### Copyright (c) 2001 Mark D. Roth +### Copyright (c) 2002, 2003 Akinori MUSHA +### 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 +### Illinois at Urbana, and their contributors. +### 4. The University nor the names of their +### contributors may be used to endorse or promote products derived from +### this software without specific prior written permission. +### +### THIS SOFTWARE IS PROVIDED BY THE TRUSTEES 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 TRUSTEES 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. +### +### $Id: mdoc2man.rb 31573 2011-05-15 11:55:52Z nobu $ +### + +class Mdoc2Man + ANGLE = 1 + OPTION = 2 + PAREN = 3 + + RE_PUNCT = /^[!"'),\.\/:;>\?\]`]$/ + + def initialize + @name = @date = @id = nil + @refauthors = @reftitle = @refissue = @refdate = @refopt = nil + + @optlist = 0 ### 1 = bullet, 2 = enum, 3 = tag, 4 = item + @oldoptlist = 0 + @nospace = 0 ### 0, 1, 2 + @enum = 0 + @synopsis = true + @reference = false + @ext = false + @extopt = false + @literal = false + end + + def mdoc2man(i, o) + i.each { |line| + if /^\./ !~ line + o.print line + o.print ".br\n" if @literal + next + end + + line.slice!(0, 1) + + next if /\\"/ =~ line + + line = parse_macro(line) and o.print line + } + + initialize + end + + def parse_macro(line) + words = line.split + retval = '' + + quote = [] + dl = false + + while word = words.shift + case word + when RE_PUNCT + while q = quote.pop + case q + when OPTION + retval << ']' + when PAREN + retval << ')' + when ANGLE + retval << '>' + end + end + retval << word + next + when 'Li', 'Pf' + @nospace = 1 + next + when 'Xo' + @ext = true + retval << ' ' unless retval.empty? || /[\n ]\z/ =~ retval + next + when 'Xc' + @ext = false + retval << "\n" unless @extopt + break + when 'Bd' + @literal = true if words[0] == '-literal' + retval << "\n" + break + when 'Ed' + @literal = false + break + when 'Ns' + @nospace = 1 if @nospace == 0 + retval.chomp!(' ') + next + when 'No' + retval.chomp!(' ') + retval << words.shift + next + when 'Dq' + retval << '``' + begin + retval << words.shift << ' ' + end until words.empty? || RE_PUNCT =~ words[0] + retval.chomp!(' ') + retval << '\'\'' + @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0] + next + when 'Sq', 'Ql' + retval << '`' << words.shift << '\'' + @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0] + next + # when 'Ic' + # retval << '\\fB' << words.shift << '\\fP' + # next + when 'Oo' + #retval << "[\\c\n" + @extopt = true + @nospace = 1 if @nospace == 0 + retval << '[' + next + when 'Oc' + @extopt = false + retval << ']' + next + when 'Ao' + @nospace = 1 if @nospace == 0 + retval << '<' + next + when 'Ac' + retval << '>' + next + end + + retval << ' ' if @nospace == 0 && !(retval.empty? || /[\n ]\z/ =~ retval) + @nospace = 0 if @nospace == 1 + + case word + when 'Dd' + @date = words.join(' ') + return nil + when 'Dt' + if words.size >= 2 && words[1] == '""' && + /^(.*)\(([0-9])\)$/ =~ words[0] + words[0] = $1 + words[1] = $2 + end + @id = words.join(' ') + return nil + when 'Os' + retval << '.TH ' << @id << ' "' << @date << '" "' << + words.join(' ') << '"' + break + when 'Sh' + retval << '.SH' + @synopsis = (words[0] == 'SYNOPSIS') + next + when 'Xr' + retval << '\\fB' << words.shift << + '\\fP(' << words.shift << ')' << (words.shift||'') + break + when 'Rs' + @refauthors = [] + @reftitle = '' + @refissue = '' + @refdate = '' + @refopt = '' + @reference = true + break + when 'Re' + retval << "\n" + + # authors + while @refauthors.size > 1 + retval << @refauthors.shift << ', ' + end + retval << 'and ' unless retval.empty? + retval << @refauthors.shift + + # title + retval << ', \\fI' << @reftitle << '\\fP' + + # issue + retval << ', ' << @refissue unless @refissue.empty? + + # date + retval << ', ' << @refdate unless @refdate.empty? + + # optional info + retval << ', ' << @refopt unless @refopt.empty? + + retval << ".\n" + + @reference = false + break + when 'An' + next + when 'Dl' + retval << ".nf\n" << '\\& ' + dl = true + next + when 'Ux' + retval << "UNIX" + next + end + + if @reference + case word + when '%A' + @refauthors.unshift(words.join(' ')) + break + when '%T' + @reftitle = words.join(' ') + @reftitle.sub!(/^"/, '') + @reftitle.sub!(/"$/, '') + break + when '%N' + @refissue = words.join(' ') + break + when '%D' + @refdate = words.join(' ') + break + when '%O' + @refopt = words.join(' ') + break + end + end + + case word + when 'Nm' + name = words.empty? ? @name : words.shift + @name ||= name + retval << ".br\n" if @synopsis + retval << "\\fB" << name << "\\fP" + @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0] + next + when 'Nd' + retval << '\\-' + next + when 'Fl' + retval << '\\fB\\-' << words.shift << '\\fP' + @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0] + next + when 'Ar' + retval << '\\fI' + if words.empty? + retval << 'file ...\\fP' + else + retval << words.shift << '\\fP' + while words[0] == '|' + retval << ' ' << words.shift << ' \\fI' << words.shift << '\\fP' + end + @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0] + next + end + when 'Cm' + retval << '\\fB' << words.shift << '\\fP' + while RE_PUNCT =~ words[0] + retval << words.shift + end + next + when 'Op' + quote << OPTION + @nospace = 1 if @nospace == 0 + retval << '[' + # words.push(words.pop + ']') + next + when 'Aq' + quote << ANGLE + @nospace = 1 if @nospace == 0 + retval << '<' + # words.push(words.pop + '>') + next + when 'Pp' + retval << "\n" + next + when 'Ss' + retval << '.SS' + next + end + + if word == 'Pa' && !quote.include?(OPTION) + retval << '\\fI' + retval << '\\&' if /^\./ =~ words[0] + retval << words.shift << '\\fP' + while RE_PUNCT =~ words[0] + retval << words.shift + end + # @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0] + next + end + + case word + when 'Dv' + retval << '.BR' + next + when 'Em', 'Ev' + retval << '.IR' + next + when 'Pq' + retval << '(' + @nospace = 1 + quote << PAREN + next + when 'Sx', 'Sy' + retval << '.B ' << words.join(' ') + break + when 'Ic' + retval << '\\fB' + until words.empty? || RE_PUNCT =~ words[0] + case words[0] + when 'Op' + words.shift + retval << '[' + words.push(words.pop + ']') + next + when 'Aq' + words.shift + retval << '<' + words.push(words.pop + '>') + next + when 'Ar' + words.shift + retval << '\\fI' << words.shift << '\\fP' + else + retval << words.shift + end + + retval << ' ' if @nospace == 0 + end + + retval.chomp!(' ') + retval << '\\fP' + retval << words.shift unless words.empty? + break + when 'Bl' + @oldoptlist = @optlist + + case words[0] + when '-bullet' + @optlist = 1 + when '-enum' + @optlist = 2 + @enum = 0 + when '-tag' + @optlist = 3 + when '-item' + @optlist = 4 + end + + break + when 'El' + @optlist = @oldoptlist + next + end + + if @optlist != 0 && word == 'It' + case @optlist + when 1 + # bullets + retval << '.IP \\(bu' + when 2 + # enum + @enum += 1 + retval << '.IP ' << @enum << '.' + when 3 + # tags + retval << ".TP\n" + case words[0] + when 'Pa', 'Ev' + words.shift + retval << '.B' + end + when 4 + # item + retval << ".IP\n" + end + + next + end + + case word + when 'Sm' + case words[0] + when 'off' + @nospace = 2 + when 'on' + # retval << "\n" + @nospace = 0 + end + words.shift + next + end + + retval << word + end + + return nil if retval == '.' + + retval.sub!(/\A\.([^a-zA-Z])/, "\\1") + # retval.chomp!(' ') + + while q = quote.pop + case q + when OPTION + retval << ']' + when PAREN + retval << ')' + when ANGLE + retval << '>' + end + end + + # retval << ' ' unless @nospace == 0 || retval.empty? || /\n\z/ =~ retval + + retval << ' ' unless !@ext || @extopt || / $/ =~ retval + + retval << "\n" unless @ext || @extopt || retval.empty? || /\n\z/ =~ retval + + retval << ".fi\n" if dl + + return retval + end + + def self.mdoc2man(i, o) + new.mdoc2man(i, o) + end +end + +if $0 == __FILE__ + Mdoc2Man.mdoc2man(ARGF, STDOUT) +end diff --git a/jni/ruby/tool/merger.rb b/jni/ruby/tool/merger.rb new file mode 100755 index 0000000..9449938 --- /dev/null +++ b/jni/ruby/tool/merger.rb @@ -0,0 +1,259 @@ +#!/bin/sh +# -*- ruby -*- +exec "${RUBY-ruby}" "-x" "$0" "$@" && [ ] if false +#!ruby +# This needs ruby 1.9 and subversion. +# run this in a repository to commit. + +require 'date' +require 'tempfile' + +$repos = 'svn+ssh://svn@ci.ruby-lang.org/ruby/' +ENV['LC_ALL'] = 'C' + +def help + puts <<-end +simple backport + ruby #$0 1234 + +range backport + ruby #$0 1234:5678 + +backport from other branch + ruby #$0 17502 mvm + +revision increment + ruby #$0 revisionup + +tagging major release + ruby #$0 tag 2.2.0 + +tagging patch release (about 2.1.0 or later, it means X.Y.Z (Z > 0) release) + ruby #$0 tag + +tagging preview/RC + ruby #$0 tag 2.2.0-preview1 + +* all operations shall be applied to the working directory. +end +end + +def version + v = p = nil + open 'version.h', 'rb' do |f| + f.each_line do |l| + case l + when /^#define RUBY_VERSION "(\d)\.(\d)\.(\d)"$/ + v = $~.captures + when /^#define RUBY_PATCHLEVEL (-?\d+)$/ + p = $1 + end + end + end + return v, p +end + +def interactive str, editfile = nil + loop do + yield + STDERR.puts "#{str} ([y]es|[a]bort|[r]etry#{'|[e]dit' if editfile})" + case STDIN.gets + when /\Aa/i then exit + when /\Ar/i then redo + when /\Ay/i then break + when /\Ae/i then system(ENV["EDITOR"], editfile) + else exit + end + end +end + +def version_up + d = DateTime.now + d = d.new_offset(Rational(9,24)) # we need server locale (i.e. japanese) time + system(*%w'svn revert version.h') + v, p = version + + teeny = v[2] + case v + when %w/1 9 2/ + teeny = 1 + end + + p = p.to_i + if p != -1 + p += 1 + end + + str = open 'version.h', 'rb' do |f| f.read end + [%W[RUBY_VERSION "#{v.join '.'}"], + %W[RUBY_VERSION_CODE #{v.join ''}], + %W[RUBY_VERSION_MAJOR #{v[0]}], + %W[RUBY_VERSION_MINOR #{v[1]}], + %W[RUBY_VERSION_TEENY #{teeny}], + %W[RUBY_RELEASE_DATE "#{d.strftime '%Y-%m-%d'}"], + %W[RUBY_RELEASE_CODE #{d.strftime '%Y%m%d'}], + %W[RUBY_PATCHLEVEL #{p}], + %W[RUBY_RELEASE_YEAR #{d.year}], + %W[RUBY_RELEASE_MONTH #{d.month}], + %W[RUBY_RELEASE_DAY #{d.day}], + ].each do |(k, i)| + str.sub!(/^(#define\s+#{k}\s+).*$/, "\\1#{i}") + end + str.sub!(/\s+\z/m, '') + fn = sprintf 'version.h.tmp.%032b', rand(1 << 31) + File.rename 'version.h', fn + open 'version.h', 'wb' do |f| + f.puts str + end + File.unlink fn +end + +def tag intv_p = false, relname=nil + # relname: + # * 2.2.0-preview1 + # * 2.2.0-rc1 + # * 2.2.0 + v, pl = version + x = v.join('_') + if relname + abort "patchlevel is not -1 but '#{pl}' for preview or rc" if pl != '-1' && /-(?:preview|rc)/ =~ relname + abort "patchlevel is not 0 but '#{pl}' for the first release" if pl != '0' && /-(?:preview|rc)/ !~ relname + pl = relname[/-(.*)\z/, 1] + curver = v.join('.') + (pl ? '-' + pl : '') + if relname != curver + abort "given relname '#{relname}' conflicts current version '#{curver}'" + end + branch_url = `svn info`[/URL: (.*)/, 1] + else + if pl == '-1' + abort "no relname is given and not in a release branch even if this is patch release" + end + branch_url = $repos + 'branches/ruby_' + if v[0] < "2" || (v[0] == "2" && v[1] < "1") + abort "patchlevel must be greater than 0 for patch release" if pl == "0" + branch_url << x + else + abort "teeny must be greater than 0 for patch release" if v[2] == "0" + branch_url << x.sub(/_\d+$/, '') + end + end + tagname = 'v' + x + (v[0] < "2" || (v[0] == "2" && v[1] < "1") || /^(?:preview|rc)/ =~ pl ? '_' + pl : '') + tag_url = $repos + 'tags/' + tagname + if intv_p + interactive "OK? svn cp -m \"add tag #{tagname}\" #{branch_url} #{tag_url}" do + end + end + system(*%w'svn cp -m', "add tag #{tagname}", branch_url, tag_url) +end + +def default_merge_branch + %r{^URL: .*/branches/ruby_1_8_} =~ `svn info` ? 'branches/ruby_1_8' : 'trunk' +end + +case ARGV[0] +when "up", /\A(ver|version|rev|revision|lv|level|patch\s*level)\s*up/ + version_up + system 'svn diff version.h' +when "tag" + tag :interactive, ARGV[1] +when nil, "-h", "--help" + help + exit +else + system 'svn up' + + if /--ticket=(.*)/ =~ ARGV[0] + tickets = $1.split(/,/).map{|num| " [Backport ##{num}]"} + ARGV.shift + else + tickets = [] + end + + q = $repos + (ARGV[1] || default_merge_branch) + revstr = ARGV[0].delete('^, :\-0-9') + revs = revstr.split(/[,\s]+/) + log = '' + log_svn = '' + + revs.each do |rev| + case rev + when /\A\d+:\d+\z/ + r = ['-r', rev] + when /\A(\d+)-(\d+)\z/ + rev = "#{$1.to_i-1}:#$2" + r = ['-r', rev] + when /\A\d+\z/ + r = ['-c', rev] + when nil then + puts "#$0 revision" + exit + else + puts "invalid revision part '#{rev}' in '#{ARGV[0]}'" + exit + end + + l = IO.popen %w'svn diff' + r + %w'--diff-cmd=diff -x -pU0' + [File.join(q, 'ChangeLog')] do |f| + f.read + end + + log << l + log_svn << l.lines.grep(/^\+\t/).join.gsub(/^\+/, '').gsub(/^\t\*/, "\n\t\*") + + if log_svn.empty? + log_svn = IO.popen %w'svn log ' + r + [q] do |f| + f.read + end.sub(/\A-+\nr.*\n/, '').sub(/\n-+\n\z/, '').gsub(/^(?=\S)/, "\t") + end + + a = %w'svn merge --accept=postpone' + r + [q] + STDERR.puts a.join(' ') + + system(*a) + system(*%w'svn revert ChangeLog') if /^\+/ =~ l + end + + if `svn diff --diff-cmd=diff -x -upw`.empty? + interactive 'Only ChangeLog is modified, right?' do + end + end + + if /^\+/ =~ log + system(*%w'svn revert ChangeLog') + IO.popen %w'patch -p0', 'wb' do |f| + f.write log.gsub(/\+(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [ 123][0-9] [012][0-9]:[0-5][0-9]:[0-5][0-9] \d\d\d\d/, + # this format-time-string was from the file local variables of ChangeLog + '+'+Time.now.strftime('%a %b %e %H:%M:%S %Y')) + end + system(*%w'touch ChangeLog') # needed somehow, don't know why... + else + STDERR.puts '*** You should write ChangeLog NOW!!! ***' + end + + version_up + f = Tempfile.new 'merger.rb' + f.printf "merge revision(s) %s:%s\n", revstr, tickets.join + f.write log_svn + f.flush + f.close + + interactive 'conflicts resolved?', f.path do + IO.popen(ENV["PAGER"] || "less", "w") do |g| + g << `svn stat` + g << "\n\n" + f.open + g << f.read + f.close + g << "\n\n" + g << `svn diff --diff-cmd=diff -x -upw` + end + end + + if system(*%w'svn ci -F', f.path) + # tag :interactive # no longer needed. + system 'rm -f subversion.commitlog' + else + puts 'commit failed; try again.' + end + + f.close(true) +end diff --git a/jni/ruby/tool/mkconfig.rb b/jni/ruby/tool/mkconfig.rb new file mode 100755 index 0000000..30a259d --- /dev/null +++ b/jni/ruby/tool/mkconfig.rb @@ -0,0 +1,290 @@ +#!./miniruby -s + +# avoid warnings with -d. +$install_name ||= nil +$so_name ||= nil + +srcdir = File.expand_path('../..', __FILE__) +$:.replace [srcdir+"/lib"] unless defined?(CROSS_COMPILING) +$:.unshift(".") + +require "fileutils" +mkconfig = File.basename($0) + +rbconfig_rb = ARGV[0] || 'rbconfig.rb' +unless File.directory?(dir = File.dirname(rbconfig_rb)) + FileUtils.makedirs(dir, :verbose => true) +end + +version = RUBY_VERSION +config = "" +def config.write(arg) + concat(arg.to_s) +end +$stdout = config + +fast = {'prefix'=>TRUE, 'ruby_install_name'=>TRUE, 'INSTALL'=>TRUE, 'EXEEXT'=>TRUE} +print %[ +# This file was created by #{mkconfig} when ruby was built. Any +# changes made to this file will be lost the next time ruby is built. + +module RbConfig + RUBY_VERSION.start_with?("#{version}"[/^[0-9]+[.][0-9]+[.]/]) or + raise "ruby lib version (#{version}) doesn't match executable version (\#{RUBY_VERSION})" + +] + +arch = RUBY_PLATFORM +win32 = /mswin/ =~ arch +universal = /universal.*darwin/ =~ arch +v_fast = [] +v_others = [] +vars = {} +continued_name = nil +continued_line = nil +install_name = nil +so_name = nil +File.foreach "config.status" do |line| + next if /^#/ =~ line + name = nil + case line + when /^s([%,])@(\w+)@\1(?:\|\#_!!_\#\|)?(.*)\1/ + name = $2 + val = $3.gsub(/\\(?=,)/, '') + when /^S\["(\w+)"\]\s*=\s*"(.*)"\s*(\\)?$/ + name = $1 + val = $2 + if $3 + continued_line = [val] + continued_name = name + next + end + when /^"(.*)"\s*(\\)?$/ + next if !continued_line + continued_line << $1 + next if $2 + continued_line.each {|s| s.sub!(/\\n\z/, "\n")} + val = continued_line.join + name = continued_name + continued_line = nil + when /^(?:ac_given_)?INSTALL=(.*)/ + v_fast << " CONFIG[\"INSTALL\"] = " + $1 + "\n" + end + + if name + case name + when /^(?:ac_.*|configure_input|(?:top_)?srcdir|\w+OBJS)$/; next + when /^(?:X|(?:MINI|RUN|BASE)RUBY$)/; next + when /^(?:MAJOR|MINOR|TEENY)$/; vars[name] = val; next + when /^LIBRUBY_D?LD/; next + when /^RUBY_INSTALL_NAME$/; next vars[name] = (install_name = val).dup if $install_name + when /^RUBY_SO_NAME$/; next vars[name] = (so_name = val).dup if $so_name + when /^arch$/; if val.empty? then val = arch else arch = val end + when /^sitearch$/; val = '$(arch)' if val.empty? + end + case val + when /^\$\(ac_\w+\)$/; next + when /^\$\{ac_\w+\}$/; next + when /^\$ac_\w+$/; next + end + if /^program_transform_name$/ =~ name + val.sub!(/\As(\\?\W)(?:\^|\${1,2})\1\1(;|\z)/, '') + if val.empty? + $install_name ||= "ruby" + next + end + unless $install_name + $install_name = "ruby" + val.gsub!(/\$\$/, '$') + val.scan(%r[\G[\s;]*(/(?:\\.|[^/])*/)?([sy])(\\?\W)((?:(?!\3)(?:\\.|.))*)\3((?:(?!\3)(?:\\.|.))*)\3([gi]*)]) do + |addr, cmd, sep, pat, rep, opt| + if addr + Regexp.new(addr[/\A\/(.*)\/\z/, 1]) =~ $install_name or next + end + case cmd + when 's' + pat = Regexp.new(pat, opt.include?('i')) + if opt.include?('g') + $install_name.gsub!(pat, rep) + else + $install_name.sub!(pat, rep) + end + when 'y' + $install_name.tr!(Regexp.quote(pat), rep) + end + end + end + end + eq = win32 && vars[name] ? '<< "\n"' : '=' + vars[name] = val + if name == "configure_args" + val.gsub!(/--with-out-ext/, "--without-ext") + end + val = val.gsub(/\$(?:\$|\{?(\w+)\}?)/) {$1 ? "$(#{$1})" : $&}.dump + case name + when /^prefix$/ + val = "(TOPDIR || DESTDIR + #{val})" + when /^ARCH_FLAG$/ + val = "arch_flag || #{val}" if universal + when /^UNIVERSAL_ARCHNAMES$/ + universal, val = val, 'universal' if universal + when /^arch$/ + if universal + val.sub!(/universal/, %q[#{arch && universal[/(?:\A|\s)#{Regexp.quote(arch)}=(\S+)/, 1] || '\&'}]) + end + end + v = " CONFIG[\"#{name}\"] #{eq} #{val}\n" + if fast[name] + v_fast << v + else + v_others << v + end + case name + when "ruby_version" + version = val[/\A"(.*)"\z/, 1] + end + end +# break if /^CEOF/ +end + +drive = File::PATH_SEPARATOR == ';' + +def vars.expand(val, config = self) + newval = val.gsub(/\$\$|\$\(([^()]+)\)|\$\{([^{}]+)\}/) { + var = $& + if !(v = $1 || $2) + '$' + elsif key = config[v = v[/\A[^:]+(?=(?::(.*?)=(.*))?\z)/]] + pat, sub = $1, $2 + config[v] = false + config[v] = expand(key, config) + key = key.gsub(/#{Regexp.quote(pat)}(?=\s|\z)/n) {sub} if pat + key + else + var + end + } + val.replace(newval) unless newval == val + val +end +prefix = vars.expand(vars["prefix"] ||= "") +rubyarchdir = vars.expand(vars["rubyarchdir"] ||= "") +relative_archdir = rubyarchdir.rindex(prefix, 0) ? rubyarchdir[prefix.size..-1] : rubyarchdir +print " TOPDIR = File.dirname(__FILE__).chomp!(#{relative_archdir.dump})\n" +print " DESTDIR = ", (drive ? "TOPDIR && TOPDIR[/\\A[a-z]:/i] || " : ""), "'' unless defined? DESTDIR\n" +print <<'ARCH' if universal + arch_flag = ENV['ARCHFLAGS'] || ((e = ENV['RC_ARCHS']) && e.split.uniq.map {|a| "-arch #{a}"}.join(' ')) + arch = arch_flag && arch_flag[/\A\s*-arch\s+(\S+)\s*\z/, 1] +ARCH +print " universal = #{universal}\n" if universal +print " CONFIG = {}\n" +print " CONFIG[\"DESTDIR\"] = DESTDIR\n" + +versions = {} +IO.foreach(File.join(srcdir, "version.h")) do |l| + m = /^\s*#\s*define\s+RUBY_(PATCHLEVEL)\s+(-?\d+)/.match(l) + if m + versions[m[1]] = m[2] + break + end +end +IO.foreach(File.join(srcdir, "include/ruby/version.h")) do |l| + m = /^\s*#\s*define\s+RUBY_API_VERSION_(MAJOR|MINOR|TEENY)\s+(-?\d+)/.match(l) + if m + versions[m[1]] = m[2] + break if versions.size == 4 + end +end +%w[MAJOR MINOR TEENY PATCHLEVEL].each do |v| + print " CONFIG[#{v.dump}] = #{versions[v].dump}\n" +end + +dest = drive ? %r'= "(?!\$[\(\{])(?i:[a-z]:)' : %r'= "(?!\$[\(\{])' +v_disabled = {} +v_others.collect! do |x| + if /^\s*CONFIG\["((?!abs_|old)[a-z]+(?:_prefix|dir))"\]/ === x + name = $1 + if /= "no"$/ =~ x + v_disabled[name] = true + v_others.delete(name) + next + end + x.sub(dest, '= "$(DESTDIR)') + else + x + end +end +v_others.compact! + +if $install_name + if install_name and vars.expand("$(RUBY_INSTALL_NAME)") == $install_name + $install_name = install_name + end + v_fast << " CONFIG[\"ruby_install_name\"] = \"" + $install_name + "\"\n" + v_fast << " CONFIG[\"RUBY_INSTALL_NAME\"] = \"" + $install_name + "\"\n" +end +if $so_name + if so_name and vars.expand("$(RUBY_SO_NAME)") == $so_name + $so_name = so_name + end + v_fast << " CONFIG[\"RUBY_SO_NAME\"] = \"" + $so_name + "\"\n" +end + +print(*v_fast) +print(*v_others) +print <<EOS + CONFIG["archdir"] = "$(rubyarchdir)" + CONFIG["topdir"] = File.dirname(__FILE__) + MAKEFILE_CONFIG = {} + CONFIG.each{|k,v| MAKEFILE_CONFIG[k] = v.dup} + def RbConfig::expand(val, config = CONFIG) + newval = val.gsub(/\\$\\$|\\$\\(([^()]+)\\)|\\$\\{([^{}]+)\\}/) { + var = $& + if !(v = $1 || $2) + '$' + elsif key = config[v = v[/\\A[^:]+(?=(?::(.*?)=(.*))?\\z)/]] + pat, sub = $1, $2 + config[v] = false + config[v] = RbConfig::expand(key, config) + key = key.gsub(/\#{Regexp.quote(pat)}(?=\\s|\\z)/n) {sub} if pat + key + else + var + end + } + val.replace(newval) unless newval == val + val + end + CONFIG.each_value do |val| + RbConfig::expand(val) + end + + # returns the absolute pathname of the ruby command. + def RbConfig.ruby + File.join( + RbConfig::CONFIG["bindir"], + RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"] + ) + end +end +CROSS_COMPILING = nil unless defined? CROSS_COMPILING +EOS + +$stdout = STDOUT +mode = IO::RDWR|IO::CREAT +mode |= IO::BINARY if defined?(IO::BINARY) +open(rbconfig_rb, mode) do |f| + if $timestamp and f.stat.size == config.size and f.read == config + puts "#{rbconfig_rb} unchanged" + else + puts "#{rbconfig_rb} updated" + f.rewind + f.truncate(0) + f.print(config) + end +end +if String === $timestamp + FileUtils.touch($timestamp) +end + +# vi:set sw=2: diff --git a/jni/ruby/tool/mkrunnable.rb b/jni/ruby/tool/mkrunnable.rb new file mode 100755 index 0000000..7d37418 --- /dev/null +++ b/jni/ruby/tool/mkrunnable.rb @@ -0,0 +1,122 @@ +#!./miniruby +# -*- coding: us-ascii -*- + +require './rbconfig' +require 'fileutils' + +case ARGV[0] +when "-n" + ARGV.shift + include FileUtils::DryRun +when "-v" + ARGV.shift + include FileUtils::Verbose +else + include FileUtils +end + +module Mswin + def ln_safe(src, dest, *opt) + cmd = ["mklink", dest.tr("/", "\\"), src.tr("/", "\\")] + cmd[1, 0] = opt + # TODO: use RUNAS or something + puts cmd.join(" ") + end + + def ln_dir_safe(src, dest) + ln_safe(src, dest, "/d") + end +end + +def ln_safe(src, dest) + link = File.readlink(dest) rescue nil + return if link == src + ln_sf(src, dest) +end + +alias ln_dir_safe ln_safe + +if /mingw|mswin/ =~ (CROSS_COMPILING || RUBY_PLATFORM) + extend Mswin +end + +def clean_path(path) + path = "#{path}/".gsub(/(\A|\/)(?:\.\/)+/, '\1').tr_s('/', '/') + nil while path.sub!(/[^\/]+\/\.\.\//, '') + path +end + +def relative_path_from(path, base) + path = clean_path(path) + base = clean_path(base) + path, base = [path, base].map{|s|s.split("/")} + until path.empty? or base.empty? or path[0] != base[0] + path.shift + base.shift + end + path, base = [path, base].map{|s|s.join("/")} + if /(\A|\/)\.\.\// =~ base + File.expand_path(path) + else + base.gsub!(/[^\/]+/, '..') + File.join(base, path) + end +end + +def ln_relative(src, dest) + parent = File.dirname(dest) + File.directory?(parent) or mkdir_p(parent) + ln_safe(relative_path_from(src, parent), dest) +end + +def ln_dir_relative(src, dest) + parent = File.dirname(dest) + File.directory?(parent) or mkdir_p(parent) + ln_dir_safe(relative_path_from(src, parent), dest) +end + +config = RbConfig::MAKEFILE_CONFIG.merge("prefix" => ".", "exec_prefix" => ".") +config.each_value {|s| RbConfig.expand(s, config)} +srcdir = config["srcdir"] ||= File.dirname(__FILE__) +top_srcdir = config["top_srcdir"] ||= File.dirname(srcdir) +extout = ARGV[0] || config["EXTOUT"] +version = config["ruby_version"] +arch = config["arch"] +bindir = config["bindir"] +libdirname = config["libdirname"] +libdir = config[libdirname || "libdir"] +vendordir = config["vendordir"] +rubylibdir = config["rubylibdir"] +rubyarchdir = config["rubyarchdir"] +archdir = "#{extout}/#{arch}" +rubylibs = [vendordir, rubylibdir, rubyarchdir] +[bindir, libdir, archdir].uniq.each do |dir| + File.directory?(dir) or mkdir_p(dir) +end + +exeext = config["EXEEXT"] +ruby_install_name = config["ruby_install_name"] +rubyw_install_name = config["rubyw_install_name"] +goruby_install_name = "go" + ruby_install_name +[ruby_install_name, rubyw_install_name, goruby_install_name].map do |ruby| + ruby += exeext + if ruby and !ruby.empty? + ln_relative(ruby, "#{bindir}/#{ruby}") + end +end +so = config["LIBRUBY_SO"] +libruby = [config["LIBRUBY_A"]] +if /\.dll\z/i =~ so + ln_relative(so, "#{bindir}/#{so}") +else + libruby << so +end +libruby.concat(config["LIBRUBY_ALIASES"].split) +libruby.each {|lib|ln_relative(lib, "#{libdir}/#{lib}")} +ln_dir_relative("#{extout}/common", rubylibdir) +rubyarchdir.sub!(rubylibdir, "#{extout}/common") +vendordir.sub!(rubylibdir, "#{extout}/common") +ln_dir_relative(archdir, rubyarchdir) +vendordir.sub!(rubyarchdir, archdir) +ln_dir_relative("#{top_srcdir}/lib", vendordir) +ln_relative("rbconfig.rb", "#{archdir}/rbconfig.rb") diff --git a/jni/ruby/tool/node_name.rb b/jni/ruby/tool/node_name.rb new file mode 100755 index 0000000..fef7720 --- /dev/null +++ b/jni/ruby/tool/node_name.rb @@ -0,0 +1,6 @@ +#! ./miniruby +while gets + if ~/enum node_type \{/..~/^\};/ + ~/(NODE_.+),/ and puts(" case #{$1}:\n\treturn \"#{$1}\";") + end +end diff --git a/jni/ruby/tool/parse.rb b/jni/ruby/tool/parse.rb new file mode 100644 index 0000000..6243d7a --- /dev/null +++ b/jni/ruby/tool/parse.rb @@ -0,0 +1,13 @@ +$file = ARGV[0] +$str = ARGF.read.sub(/^__END__.*\z/m, '') +puts '# ' + '-' * 70 +puts "# target program: " +puts '# ' + '-' * 70 +puts $str +puts '# ' + '-' * 70 + +$parsed = RubyVM::InstructionSequence.compile_file($file) +puts "# disasm result: " +puts '# ' + '-' * 70 +puts $parsed.disasm +puts '# ' + '-' * 70 diff --git a/jni/ruby/tool/probes_to_wiki.rb b/jni/ruby/tool/probes_to_wiki.rb new file mode 100644 index 0000000..ba8204c --- /dev/null +++ b/jni/ruby/tool/probes_to_wiki.rb @@ -0,0 +1,16 @@ +### +# Converts the probes.d file to redmine wiki format. Usage: +# +# ruby tool/probes_to_wiki.rb probes.d + +File.read(ARGV[0]).scan(/\/\*.*?\*\//m).grep(/ruby/) do |comment| + comment.gsub!(/^(\/\*|[ ]*)|\*\/$/, '').strip! + puts + comment.each_line.with_index do |line, i| + if i == 0 + puts "=== #{line.chomp}" + else + puts line.gsub(/`([^`]*)`/, '(({\1}))') + end + end +end diff --git a/jni/ruby/tool/rbinstall.rb b/jni/ruby/tool/rbinstall.rb new file mode 100755 index 0000000..db36a21 --- /dev/null +++ b/jni/ruby/tool/rbinstall.rb @@ -0,0 +1,763 @@ +#!./miniruby + +begin + load "./rbconfig.rb" +rescue LoadError + CONFIG = Hash.new {""} +else + include RbConfig + $".unshift File.expand_path("./rbconfig.rb") +end + +srcdir = File.expand_path('../..', __FILE__) +unless defined?(CROSS_COMPILING) and CROSS_COMPILING + $:.replace([srcdir+"/lib", Dir.pwd]) +end +require 'fileutils' +require 'shellwords' +require 'optparse' +require 'optparse/shellwords' +require 'ostruct' +require 'rubygems' + +STDOUT.sync = true +File.umask(0) + +def parse_args(argv = ARGV) + $mantype = 'doc' + $destdir = nil + $extout = nil + $make = 'make' + $mflags = [] + $install = [] + $installed_list = nil + $dryrun = false + $rdocdir = nil + $data_mode = 0644 + $prog_mode = 0755 + $dir_mode = nil + $script_mode = nil + $strip = false + $cmdtype = (if File::ALT_SEPARATOR == '\\' + File.exist?("rubystub.exe") ? 'exe' : 'bat' + end) + mflags = [] + opt = OptionParser.new + opt.on('-n', '--dry-run') {$dryrun = true} + opt.on('--dest-dir=DIR') {|dir| $destdir = dir} + opt.on('--extout=DIR') {|dir| $extout = (dir unless dir.empty?)} + opt.on('--make=COMMAND') {|make| $make = make} + opt.on('--mantype=MAN') {|man| $mantype = man} + opt.on('--make-flags=FLAGS', '--mflags', Shellwords) do |v| + if arg = v.first + arg.insert(0, '-') if /\A[^-][^=]*\Z/ =~ arg + end + $mflags.concat(v) + end + opt.on('-i', '--install=TYPE', $install_procs.keys) do |ins| + $install << ins + end + opt.on('--data-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| + $data_mode = mode + end + opt.on('--prog-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| + $prog_mode = mode + end + opt.on('--dir-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| + $dir_mode = mode + end + opt.on('--script-mode=OCTAL-MODE', OptionParser::OctalInteger) do |mode| + $script_mode = mode + end + opt.on('--installed-list [FILENAME]') {|name| $installed_list = name} + opt.on('--rdoc-output [DIR]') {|dir| $rdocdir = dir} + opt.on('--cmd-type=TYPE', %w[bat cmd plain]) {|cmd| $cmdtype = (cmd unless cmd == 'plain')} + opt.on('--[no-]strip') {|strip| $strip = strip} + + opt.order!(argv) do |v| + case v + when /\AINSTALL[-_]([-\w]+)=(.*)/ + argv.unshift("--#{$1.tr('_', '-')}=#{$2}") + when /\A\w[-\w+]*=\z/ + mflags << v + when /\A\w[-\w+]*\z/ + $install << v.intern + else + raise OptionParser::InvalidArgument, v + end + end rescue abort "#{$!.message}\n#{opt.help}" + + unless defined?(RbConfig) + puts opt.help + exit + end + + $make, *rest = Shellwords.shellwords($make) + $mflags.unshift(*rest) unless rest.empty? + $mflags.unshift(*mflags) + + def $mflags.set?(flag) + grep(/\A-(?!-).*#{flag.chr}/i) { return true } + false + end + def $mflags.defined?(var) + grep(/\A#{var}=(.*)/) {return block_given? ? yield($1) : $1} + false + end + + if $mflags.set?(?n) + $dryrun = true + else + $mflags << '-n' if $dryrun + end + + $destdir ||= $mflags.defined?("DESTDIR") + if $extout ||= $mflags.defined?("EXTOUT") + RbConfig.expand($extout) + end + + $continue = $mflags.set?(?k) + + if $installed_list ||= $mflags.defined?('INSTALLED_LIST') + RbConfig.expand($installed_list, RbConfig::CONFIG) + $installed_list = open($installed_list, "ab") + $installed_list.sync = true + end + + $rdocdir ||= $mflags.defined?('RDOCOUT') + + $dir_mode ||= $prog_mode | 0700 + $script_mode ||= $prog_mode +end + +$install_procs = Hash.new {[]} +def install?(*types, &block) + $install_procs[:all] <<= block + types.each do |type| + $install_procs[type] <<= block + end +end + +def strip_file(files) + if !defined?($strip_command) and (cmd = CONFIG["STRIP"]) + case cmd + when "", "true", ":" then return + else $strip_command = Shellwords.shellwords(cmd) + end + elsif !$strip_command + return + end + system(*($strip_command + [files].flatten)) +end + +def install(src, dest, options = {}) + options = options.clone + strip = options.delete(:strip) + options[:preserve] = true + d = with_destdir(dest) + super(src, d, options) + srcs = Array(src) + if strip + d = srcs.map {|src| File.join(d, File.basename(src))} if $made_dirs[dest] + strip_file(d) + end + if $installed_list + dest = srcs.map {|src| File.join(dest, File.basename(src))} if $made_dirs[dest] + $installed_list.puts dest + end +end + +def ln_sf(src, dest) + super(src, with_destdir(dest)) + $installed_list.puts dest if $installed_list +end + +$made_dirs = {} +def makedirs(dirs) + dirs = fu_list(dirs) + dirs.collect! do |dir| + realdir = with_destdir(dir) + realdir unless $made_dirs.fetch(dir) do + $made_dirs[dir] = true + $installed_list.puts(File.join(dir, "")) if $installed_list + File.directory?(realdir) + end + end.compact! + super(dirs, :mode => $dir_mode) unless dirs.empty? +end + +FalseProc = proc {false} +def path_matcher(pat) + if pat and !pat.empty? + proc {|f| pat.any? {|n| File.fnmatch?(n, f)}} + else + FalseProc + end +end + +def install_recursive(srcdir, dest, options = {}) + opts = options.clone + noinst = opts.delete(:no_install) + glob = opts.delete(:glob) || "*" + maxdepth = opts.delete(:maxdepth) + subpath = (srcdir.size+1)..-1 + prune = [] + skip = [] + if noinst + if Array === noinst + prune = noinst.grep(/#{File::SEPARATOR}/o).map!{|f| f.chomp(File::SEPARATOR)} + skip = noinst.grep(/\A[^#{File::SEPARATOR}]*\z/o) + else + if noinst.index(File::SEPARATOR) + prune = [noinst] + else + skip = [noinst] + end + end + end + skip |= %w"#*# *~ *.old *.bak *.orig *.rej *.diff *.patch *.core" + prune = path_matcher(prune) + skip = path_matcher(skip) + File.directory?(srcdir) or return rescue return + paths = [[srcdir, dest, 0]] + found = [] + while file = paths.shift + found << file + file, d, dir = *file + if dir + depth = dir + 1 + next if maxdepth and maxdepth < depth + files = [] + Dir.foreach(file) do |f| + src = File.join(file, f) + d = File.join(dest, dir = src[subpath]) + stat = File.lstat(src) rescue next + if stat.directory? + files << [src, d, depth] if maxdepth != depth and /\A\./ !~ f and !prune[dir] + elsif stat.symlink? + # skip + else + files << [src, d, false] if File.fnmatch?(glob, f) and !skip[f] + end + end + paths.insert(0, *files) + end + end + for src, d, dir in found + if dir + makedirs(d) + else + makedirs(d[/.*(?=\/)/m]) + if block_given? + yield src, d, opts + else + install src, d, opts + end + end + end +end + +def open_for_install(path, mode) + data = open(realpath = with_destdir(path), "rb") {|f| f.read} rescue nil + newdata = yield + unless $dryrun + unless newdata == data + open(realpath, "wb", mode) {|f| f.write newdata} + end + File.chmod(mode, realpath) + end + $installed_list.puts path if $installed_list +end + +def with_destdir(dir) + return dir if !$destdir or $destdir.empty? + dir = dir.sub(/\A\w:/, '') if File::PATH_SEPARATOR == ';' + $destdir + dir +end + +def prepare(mesg, basedir, subdirs=nil) + return unless basedir + case + when !subdirs + dirs = basedir + when subdirs.size == 0 + subdirs = nil + when subdirs.size == 1 + dirs = [basedir = File.join(basedir, subdirs)] + subdirs = nil + else + dirs = [basedir, *subdirs.collect {|dir| File.join(basedir, dir)}] + end + printf("installing %-18s %s%s\n", "#{mesg}:", basedir, + (subdirs ? " (#{subdirs.join(', ')})" : "")) + makedirs(dirs) +end + +def CONFIG.[](name, mandatory = false) + value = super(name) + if mandatory + raise "CONFIG['#{name}'] must be set" if !value or value.empty? + end + value +end + +exeext = CONFIG["EXEEXT"] + +ruby_install_name = CONFIG["ruby_install_name", true] +rubyw_install_name = CONFIG["rubyw_install_name"] +goruby_install_name = "go" + ruby_install_name + +bindir = CONFIG["bindir", true] +libdir = CONFIG[CONFIG.fetch("libdirname", "libdir"), true] +rubyhdrdir = CONFIG["rubyhdrdir", true] +archhdrdir = CONFIG["rubyarchhdrdir"] || (rubyhdrdir + "/" + CONFIG['arch']) +rubylibdir = CONFIG["rubylibdir", true] +archlibdir = CONFIG["rubyarchdir", true] +sitelibdir = CONFIG["sitelibdir"] +sitearchlibdir = CONFIG["sitearchdir"] +vendorlibdir = CONFIG["vendorlibdir"] +vendorarchlibdir = CONFIG["vendorarchdir"] +mandir = CONFIG["mandir", true] +docdir = CONFIG["docdir", true] +configure_args = Shellwords.shellwords(CONFIG["configure_args"]) +enable_shared = CONFIG["ENABLE_SHARED"] == 'yes' +dll = CONFIG["LIBRUBY_SO", enable_shared] +lib = CONFIG["LIBRUBY", true] +arc = CONFIG["LIBRUBY_A", true] +major = CONFIG["MAJOR", true] +minor = CONFIG["MINOR", true] +load_relative = configure_args.include?("--enable-load-relative") + +install?(:local, :arch, :bin, :'bin-arch') do + prepare "binary commands", bindir + + install ruby_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip + if rubyw_install_name and !rubyw_install_name.empty? + install rubyw_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip + end + if File.exist? goruby_install_name+exeext + install goruby_install_name+exeext, bindir, :mode => $prog_mode, :strip => $strip + end + if enable_shared and dll != lib + install dll, bindir, :mode => $prog_mode, :strip => $strip + end +end + +install?(:local, :arch, :lib) do + prepare "base libraries", libdir + + install lib, libdir, :mode => $prog_mode, :strip => $strip unless lib == arc + install arc, libdir, :mode => $data_mode + if dll == lib and dll != arc + for link in CONFIG["LIBRUBY_ALIASES"].split + ln_sf(dll, File.join(libdir, link)) + end + end + + prepare "arch files", archlibdir + install "rbconfig.rb", archlibdir, :mode => $data_mode + if CONFIG["ARCHFILE"] + for file in CONFIG["ARCHFILE"].split + install file, archlibdir, :mode => $data_mode + end + end +end + +install?(:local, :arch, :data) do + pc = CONFIG["ruby_pc"] + if pc and File.file?(pc) and File.size?(pc) + prepare "pkgconfig data", pkgconfigdir = File.join(libdir, "pkgconfig") + install pc, pkgconfigdir, :mode => $data_mode + end +end + +install?(:ext, :arch, :'ext-arch') do + prepare "extension objects", archlibdir + noinst = %w[-* -*/] | (CONFIG["no_install_files"] || "").split + install_recursive("#{$extout}/#{CONFIG['arch']}", archlibdir, :no_install => noinst, :mode => $prog_mode, :strip => $strip) + prepare "extension objects", sitearchlibdir + prepare "extension objects", vendorarchlibdir +end +install?(:ext, :arch, :hdr, :'arch-hdr') do + prepare "extension headers", archhdrdir + install_recursive("#{$extout}/include/#{CONFIG['arch']}", archhdrdir, :glob => "*.h", :mode => $data_mode) +end +install?(:ext, :comm, :'ext-comm') do + prepare "extension scripts", rubylibdir + install_recursive("#{$extout}/common", rubylibdir, :mode => $data_mode) + prepare "extension scripts", sitelibdir + prepare "extension scripts", vendorlibdir +end +install?(:ext, :comm, :hdr, :'comm-hdr') do + hdrdir = rubyhdrdir + "/ruby" + prepare "extension headers", hdrdir + install_recursive("#{$extout}/include/ruby", hdrdir, :glob => "*.h", :mode => $data_mode) +end + +install?(:doc, :rdoc) do + if $rdocdir + ridatadir = File.join(CONFIG['ridir'], CONFIG['ruby_version'], "system") + prepare "rdoc", ridatadir + install_recursive($rdocdir, ridatadir, :mode => $data_mode) + end +end +install?(:doc, :capi) do + prepare "capi-docs", docdir + install_recursive "doc/capi", docdir+"/capi", :mode => $data_mode +end + +if load_relative + PROLOG_SCRIPT = <<EOS +#!/bin/sh\n# -*- ruby -*- +bindir=`#{CONFIG["CHDIR"]} "${0%/*}" 2>/dev/null; pwd` +EOS + if CONFIG["LIBRUBY_RELATIVE"] != 'yes' and libpathenv = CONFIG["LIBPATHENV"] + pathsep = File::PATH_SEPARATOR + PROLOG_SCRIPT << <<EOS +prefix="${bindir%/bin}" +export #{libpathenv}="$prefix/lib${#{libpathenv}#{pathsep}+#{pathsep}$#{libpathenv}}" +EOS + end + PROLOG_SCRIPT << %Q[exec "$bindir/#{ruby_install_name}" -x "$0" "$@"\n] +else + PROLOG_SCRIPT = nil +end + +install?(:local, :comm, :bin, :'bin-comm') do + prepare "command scripts", bindir + + ruby_shebang = File.join(bindir, ruby_install_name) + if File::ALT_SEPARATOR + ruby_bin = ruby_shebang.tr(File::SEPARATOR, File::ALT_SEPARATOR) + if $cmdtype == 'exe' + stub = File.open("rubystub.exe", "rb") {|f| f.read} << "\n" rescue nil + end + end + if trans = CONFIG["program_transform_name"] + exp = [] + trans.gsub!(/\$\$/, '$') + trans.scan(%r[\G[\s;]*(/(?:\\.|[^/])*/)?([sy])(\\?\W)((?:(?!\3)(?:\\.|.))*)\3((?:(?!\3)(?:\\.|.))*)\3([gi]*)]) do + |addr, cmd, sep, pat, rep, opt| + addr &&= Regexp.new(addr[/\A\/(.*)\/\z/, 1]) + case cmd + when 's' + next if pat == '^' and rep.empty? + exp << [addr, (opt.include?('g') ? :gsub! : :sub!), + Regexp.new(pat, opt.include?('i')), rep.gsub(/&/){'\&'}] + when 'y' + exp << [addr, :tr!, Regexp.quote(pat), rep] + end + end + trans = proc do |base| + exp.each {|addr, opt, pat, rep| base.__send__(opt, pat, rep) if !addr or addr =~ base} + base + end + elsif /ruby/ =~ ruby_install_name + trans = proc {|base| ruby_install_name.sub(/ruby/, base)} + else + trans = proc {|base| base} + end + install_recursive(File.join(srcdir, "bin"), bindir, :maxdepth => 1) do |src, cmd| + cmd = cmd.sub(/[^\/]*\z/m) {|n| RbConfig.expand(trans[n])} + + shebang = '' + body = '' + open(src, "rb") do |f| + shebang = f.gets + body = f.read + end + shebang or raise "empty file - #{src}" + if PROLOG_SCRIPT + shebang.sub!(/\A(\#!.*?ruby\b)?/) {PROLOG_SCRIPT + ($1 || "#!ruby\n")} + else + shebang.sub!(/\A\#!.*?ruby\b/) {"#!" + ruby_shebang} + end + shebang.sub!(/\r$/, '') + body.gsub!(/\r$/, '') + + cmd << ".#{$cmdtype}" if $cmdtype + open_for_install(cmd, $script_mode) do + case $cmdtype + when "exe" + stub + shebang + body + when "bat" + [<<-"EOH".gsub(/^\s+/, ''), shebang, body, "__END__\n:endofruby\n"].join.gsub(/$/, "\r") + @echo off + @if not "%~d0" == "~d0" goto WinNT + #{ruby_bin} -x "#{cmd}" %1 %2 %3 %4 %5 %6 %7 %8 %9 + @goto endofruby + :WinNT + "%~dp0#{ruby_install_name}" -x "%~f0" %* + @goto endofruby + EOH + when "cmd" + <<"/EOH" << shebang << body +@"%~dp0#{ruby_install_name}" -x "%~f0" %* +@exit /b %ERRORLEVEL% +/EOH + else + shebang + body + end + end + end +end + +install?(:local, :comm, :lib) do + prepare "library scripts", rubylibdir + noinst = %w[README* *.txt *.rdoc *.gemspec] + install_recursive(File.join(srcdir, "lib"), rubylibdir, :no_install => noinst, :mode => $data_mode) +end + +install?(:local, :comm, :hdr, :'comm-hdr') do + prepare "common headers", rubyhdrdir + + noinst = [] + unless RUBY_PLATFORM =~ /mswin|mingw|bccwin/ + noinst << "win32.h" + end + noinst = nil if noinst.empty? + install_recursive(File.join(srcdir, "include"), rubyhdrdir, :no_install => noinst, :glob => "*.h", :mode => $data_mode) +end + +install?(:local, :comm, :man) do + mdocs = Dir["#{srcdir}/man/*.[1-9]"] + prepare "manpages", mandir, ([] | mdocs.collect {|mdoc| mdoc[/\d+$/]}).sort.collect {|sec| "man#{sec}"} + + mandir = File.join(mandir, "man") + has_goruby = File.exist?(goruby_install_name+exeext) + require File.join(srcdir, "tool/mdoc2man.rb") if $mantype != "doc" + mdocs.each do |mdoc| + next unless File.file?(mdoc) and open(mdoc){|fh| fh.read(1) == '.'} + base = File.basename(mdoc) + if base == "goruby.1" + next unless has_goruby + end + + destdir = mandir + (section = mdoc[/\d+$/]) + destname = ruby_install_name.sub(/ruby/, base.chomp(".#{section}")) + destfile = File.join(destdir, "#{destname}.#{section}") + + if $mantype == "doc" + install mdoc, destfile, :mode => $data_mode + else + class << (w = []) + alias print push + end + open(mdoc) {|r| Mdoc2Man.mdoc2man(r, w)} + open_for_install(destfile, $data_mode) {w.join("")} + end + end +end + +module RbInstall + module Specs + class FileCollector + def initialize(base_dir) + @base_dir = base_dir + end + + def collect + (ruby_libraries + built_libraries).sort + end + + private + def type + /\/(ext|lib)?\/.*?\z/ =~ @base_dir + $1 + end + + def ruby_libraries + case type + when "ext" + prefix = "#{$extout}/common/" + base = "#{prefix}#{relative_base}" + when "lib" + base = @base_dir + prefix = base.sub(/lib\/.*?\z/, "") + "lib/" + end + + Dir.glob("#{base}{.rb,/**/*.rb}").collect do |ruby_source| + remove_prefix(prefix, ruby_source) + end + end + + def built_libraries + case type + when "ext" + prefix = "#{$extout}/#{CONFIG['arch']}/" + base = "#{prefix}#{relative_base}" + Dir.glob("#{base}{.so,/**/*.so}").collect do |built_library| + remove_prefix(prefix, built_library) + end + when "lib" + [] + end + end + + def relative_base + /\/#{Regexp.escape(type)}\/(.*?)\z/ =~ @base_dir + $1 + end + + def remove_prefix(prefix, string) + string.sub(/\A#{Regexp.escape(prefix)}/, "") + end + end + + class Reader < Struct.new(:src) + def gemspec + @gemspec ||= begin + spec = Gem::Specification.load(src) || raise("invalid spec in #{src}") + file_collector = FileCollector.new(File.dirname(src)) + spec.files = file_collector.collect + spec + end + end + + def spec_source + @gemspec.to_ruby + end + end + + class Generator < Struct.new(:name, :base_dir, :src, :execs) + def gemspec + @gemspec ||= eval spec_source + end + + def spec_source + <<-GEMSPEC +Gem::Specification.new do |s| + s.name = #{name.dump} + s.version = #{version.dump} + s.summary = "This #{name} is bundled with Ruby" + s.executables = #{execs.inspect} + s.files = #{files.inspect} +end + GEMSPEC + end + + private + def version + version = open(src) { |f| + f.find { |s| /^\s*\w*VERSION\s*=(?!=)/ =~ s } + } or return + version.split(%r"=\s*", 2)[1].strip[/\A([\'\"])(.*?)\1/, 2] + end + + def files + file_collector = FileCollector.new(base_dir) + file_collector.collect + end + end + end +end +# :startdoc: + +install?(:ext, :comm, :gem) do + $:.unshift(File.join(srcdir, "lib")) + require("rubygems.rb") + gem_dir = Gem.default_dir + directories = Gem.ensure_gem_subdirectories(gem_dir, :mode => $dir_mode) + prepare "default gems", gem_dir, directories + + spec_dir = File.join(gem_dir, directories.grep(/^spec/)[0]) + default_spec_dir = "#{spec_dir}/default" + makedirs(default_spec_dir) + + gems = {} + File.foreach(File.join(srcdir, "defs/default_gems")) do |line| + line.chomp! + line.sub!(/\s*#.*/, '') + next if line.empty? + words = [] + line.scan(/\G\s*([^\[\]\s]+|\[([^\[\]]*)\])/) do + words << ($2 ? $2.split : $1) + end + name, base_dir, src, execs = *words + next unless name and base_dir and src + + src = File.join(srcdir, src) + base_dir = File.join(srcdir, base_dir) + specgen = RbInstall::Specs::Generator.new(name, base_dir, src, execs || []) + gems[name] ||= specgen + end + + Dir.glob(srcdir+"/{lib,ext}/**/*.gemspec").each do |src| + specgen = RbInstall::Specs::Reader.new(src) + gems[specgen.gemspec.name] ||= specgen + end + + gems.sort.each do |name, specgen| + gemspec = specgen.gemspec + base_dir = specgen.src.sub(/\A#{Regexp.escape(srcdir)}\//, "") + full_name = "#{gemspec.name}-#{gemspec.version}" + + puts "#{" "*30}#{gemspec.name} #{gemspec.version}" + gemspec_path = File.join(default_spec_dir, "#{full_name}.gemspec") + open_for_install(gemspec_path, $data_mode) do + specgen.spec_source + end + + unless gemspec.executables.empty? then + bin_dir = File.join(gem_dir, 'gems', full_name, 'bin') + makedirs(bin_dir) + + execs = gemspec.executables.map {|exec| File.join(srcdir, 'bin', exec)} + install(execs, bin_dir, :mode => $prog_mode) + end + end +end + +install?(:ext, :comm, :gem) do + begin + require "zlib" + rescue LoadError + end + if defined?(Zlib) + require 'pathname' + gem_dir = Gem.default_dir + directories = Gem.ensure_gem_subdirectories(gem_dir, :mode => $dir_mode) + prepare "bundle gems", gem_dir, directories + Dir.glob(srcdir+'/gems/*.gem').each do |gem| + Gem.install gem, Gem::Requirement.default, :install_dir => with_destdir(Gem.dir), :domain => :local, :ignore_dependencies => true + gemname = Pathname(gem).basename + puts "#{" "*30}#{gemname}" + end + # fix directory permissions + # TODO: Gem.install should accept :dir_mode option or something + File.chmod($dir_mode, *Dir.glob(with_destdir(Gem.dir)+"/**/")) + # fix .gemspec permissions + File.chmod($data_mode, *Dir.glob(with_destdir(Gem.dir)+"/specifications/*.gemspec")) + else + puts "skip installing bundle gems because of lacking zlib" + end +end + +parse_args() + +include FileUtils +include FileUtils::NoWrite if $dryrun +@fileutils_output = STDOUT +@fileutils_label = '' + +all = $install.delete(:all) +$install << :local << :ext if $install.empty? +installs = $install.map do |inst| + if !(procs = $install_procs[inst]) || procs.empty? + next warn("unknown install target - #{inst}") + end + procs +end +installs.flatten! +installs.uniq! +installs |= $install_procs[:all] if all +installs.each do |block| + dir = Dir.pwd + begin + block.call + ensure + Dir.chdir(dir) + end +end + +# vi:set sw=2: diff --git a/jni/ruby/tool/rbuninstall.rb b/jni/ruby/tool/rbuninstall.rb new file mode 100755 index 0000000..1a11766 --- /dev/null +++ b/jni/ruby/tool/rbuninstall.rb @@ -0,0 +1,67 @@ +#! /usr/bin/ruby -nl +BEGIN { + $dryrun = false + $tty = STDOUT.tty? + until ARGV.empty? + case ARGV[0] + when /\A--destdir=(.*)/ + $destdir = $1 + when /\A-n\z/ + $dryrun = true + when /\A--(?:no-)?tty\z/ + $tty = !$1 + else + break + end + ARGV.shift + end + $dirs = [] + $files = [] +} +list = ($_.chomp!('/') ? $dirs : $files) +$_ = File.join($destdir, $_) if $destdir +list << $_ +END { + status = true + $\ = ors = (!$dryrun and $tty) ? "\e[K\r" : "\n" + $files.each do |file| + print "rm #{file}" + unless $dryrun + begin + File.unlink(file) + rescue Errno::ENOENT + rescue + status = false + puts $! + end + end + end + unlink = {} + $dirs.each do |dir| + unlink[dir] = true + end + while dir = $dirs.pop + print "rmdir #{dir}" + unless $dryrun + begin + begin + unlink.delete(dir) + Dir.rmdir(dir) + rescue Errno::ENOTDIR + raise unless File.symlink?(dir) + File.unlink(dir) + end + rescue Errno::ENOENT, Errno::ENOTEMPTY + rescue + status = false + puts $! + else + parent = File.dirname(dir) + $dirs.push(parent) unless parent == dir or unlink[parent] + end + end + end + $\ = nil + print ors.chomp + exit(status) +} diff --git a/jni/ruby/tool/redmine-backporter.rb b/jni/ruby/tool/redmine-backporter.rb new file mode 100755 index 0000000..121aa3e --- /dev/null +++ b/jni/ruby/tool/redmine-backporter.rb @@ -0,0 +1,416 @@ +#!/usr/bin/env ruby +require 'open-uri' +require 'openssl' +require 'net/http' +require 'json' +require 'io/console' +require 'stringio' +require 'strscan' +require 'optparse' +require 'pp' + +VERSION = '0.0.1' + +opts = OptionParser.new +target_version = nil +repo_path = nil +api_key = nil +ssl_verify = true +opts.on('-k REDMINE_API_KEY', '--key=REDMINE_API_KEY', 'specify your REDMINE_API_KEY') {|v| api_key = v} +opts.on('-t TARGET_VERSION', '--target=TARGET_VARSION', /\A\d(?:\.\d)+\z/, 'specify target version (ex: 2.1)') {|v| target_version = v} +opts.on('-r RUBY_REPO_PATH', '--repository=RUBY_REPO_PATH', 'specify repository path') {|v| repo_path = v} +opts.on('--[no-]ssl-verify', TrueClass, 'use / not use SSL verify') {|v| ssl_verify = v} +opts.version = VERSION +opts.parse!(ARGV) + +http_options = {use_ssl: true} +http_options[:verify_mode] = OpenSSL::SSL::VERIFY_NONE unless ssl_verify +openuri_options = {} +openuri_options[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE unless ssl_verify + +TARGET_VERSION = target_version || ENV['TARGET_VERSION'] || (raise 'need to specify TARGET_VERSION') +RUBY_REPO_PATH = repo_path || ENV['RUBY_REPO_PATH'] +BACKPORT_CF_KEY = 'cf_5' +STATUS_CLOSE = 5 +REDMINE_API_KEY = api_key || ENV['REDMINE_API_KEY'] || (raise 'need to specify REDMINE_API_KEY') +REDMINE_BASE = 'https://bugs.ruby-lang.org' + +@query = { + 'f[]' => BACKPORT_CF_KEY, + "op[#{BACKPORT_CF_KEY}]" => '~', + "v[#{BACKPORT_CF_KEY}][]" => "#{TARGET_VERSION}: REQUIRED", + 'limit' => 40, + 'status_id' => STATUS_CLOSE, + 'sort' => 'updated_on' +} + +PRIORITIES = { + 'Low' => [:white, :blue], + 'Normal' => [], + 'High' => [:red], + 'Urgent' => [:red, :white], + 'Immediate' => [:red, :white, {underscore: true}], +} +COLORS = { + black: 30, + red: 31, + green: 32, + yellow: 33, + blue: 34, + magenta: 35, + cyan: 36, + white: 37, +} + +class String + def color(fore=nil, back=nil, bold: false, underscore: false) + seq = "" + if bold + seq << "\e[1m" + end + if underscore + seq << "\e[2m" + end + if fore + c = COLORS[fore] + raise "unknown foreground color #{fore}" unless c + seq << "\e[#{c}m" + end + if back + c = COLORS[back] + raise "unknown background color #{back}" unless c + seq << "\e[#{c + 10}m" + end + if seq.empty? + self + else + seq << self << "\e[0m" + end + end +end + +def wcwidth(wc) + return 8 if wc == "\t" + n = wc.ord + if n < 0x20 + 0 + elsif n < 0x80 + 1 + else + 2 + end +end + +def fold(str, col) + i = 0 + size = str.size + len = 0 + while i < size + case c = str[i] + when "\r", "\n" + len = 0 + else + d = wcwidth(c) + len += d + if len == col + str.insert(i+1, "\n") + len = 0 + i += 2 + next + elsif len > col + str.insert(i, "\n") + len = d + i += 2 + next + end + end + i += 1 + end + str +end + +class StringScanner + # lx: limit of x (colmns of screen) + # ly: limit of y (rows of screen) + def getrows(lx, ly) + cp1 = charpos + x = 0 + y = 0 + until eos? + case c = getch + when "\r" + x = 0 + when "\n" + x = 0 + y += 1 + when "\t" + x += 8 + when /[\x00-\x7f]/ + # halfwidth + x += 1 + else + # fullwidth + x += 2 + end + + if x > lx + x = 0 + y += 1 + unscan + end + if y >= ly + return string[cp1...charpos] + end + end + string[cp1..-1] + end +end + +def more(sio) + console = IO.console + ly, lx = console.winsize + ly -= 1 + str = sio.string + cls = "\r" + (" " * lx) + "\r" + + ss = StringScanner.new(str) + + rows = ss.getrows(lx, ly) + puts rows + until ss.eos? + print ":" + case c = console.getch + when ' ' + rows = ss.getrows(lx, ly) + puts cls + rows + when 'j', "\r" + rows = ss.getrows(lx, 1) + puts cls + rows + when "q" + print cls + break + else + print "\b" + end + end +end + +def mergeinfo + `svn propget svn:mergeinfo #{RUBY_REPO_PATH}` +end + +def find_svn_log(pattern) + `svn log --xml --stop-on-copy --search='#{pattern}' #{RUBY_REPO_PATH}` +end + +def show_last_journal(http, uri) + res = http.get("#{uri.path}?include=journals") + res.value + h = JSON(res.body) + x = h["issue"] + raise "no issue" unless x + x = x["journals"] + raise "no journals" unless x + x = x.last + puts "== #{x["user"]["name"]} (#{x["created_on"]})" + x["details"].each do |y| + puts JSON(y) + end + puts x["notes"] +end + +def backport_command_string + " backport --ticket=#{@issue} #{@changesets.join(',')}" +end + +console = IO.console +row, col = console.winsize +@query['limit'] = row - 2 +puts "Backporter #{VERSION}".color(bold: true) + " for #{TARGET_VERSION}" + +@issues = nil +@issue = nil +@changesets = nil +while true + print '> ' + begin + l = gets + rescue Interrupt + break + end + l.strip! if l + case l + when 'ls' + uri = URI(REDMINE_BASE+'/projects/ruby-trunk/issues.json?'+URI.encode_www_form(@query)) + # puts uri + res = JSON(uri.read(openuri_options)) + @issues = issues = res["issues"] + from = res["offset"] + 1 + total = res["total_count"] + to = from + issues.size - 1 + puts "#{from}-#{to} / #{total}" + issues.each_with_index do |x, i| + id = "##{x["id"]}".color(*PRIORITIES[x["priority"]["name"]]) + puts "#{'%2d' % i} #{id} #{x["priority"]["name"][0]} #{x["status"]["name"][0]} #{x["subject"][0,80]}" + end + when /\A(?:show +)?(\d+)\z/ + id = $1.to_i + id = @issues[id]["id"] if @issues && id < @issues.size + @issue = id + uri = "#{REDMINE_BASE}/issues/#{id}" + uri = URI(uri+".json?include=children,attachments,relations,changesets,journals") + res = JSON(uri.read(openuri_options)) + i = res["issue"] + unless i["changesets"] + abort "You don't have view_changesets permission" + end + id = "##{i["id"]}".color(*PRIORITIES[i["priority"]["name"]]) + sio = StringIO.new + sio.puts <<eom +#{i["subject"]} +#{i["project"]["name"]} [#{i["tracker"]["name"]} #{id}] #{i["status"]["name"]} (#{i["created_on"]}) +author: #{i["author"]["name"]} +assigned: #{i["assigned_to"].to_h["name"]} +eom + i["custom_fields"].each do |x| + sio.puts "%-10s: %s" % [x["name"], x["value"]] + end + #res["attachements"].each do |x| + #end + sio.puts i["description"] + sio.puts + sio.puts "= changesets" + @changesets = [] + i["changesets"].each do |x| + @changesets << x["revision"] + sio.puts "== #{x["revision"]} #{x["committed_on"]} #{x["user"]["name"] rescue nil}" + sio.puts x["comments"] + end + if i["journals"] && !i["journals"].empty? + sio.puts "= journals" + i["journals"].each do |x| + sio.puts "== #{x["user"]["name"]} (#{x["created_on"]})" + x["details"].each do |y| + sio.puts JSON(y) + end + sio.puts x["notes"] + end + end + more(sio) + + when 's' + unless @issue + puts "ticket not selected" + next + end + puts backport_command_string + + when /\Adone(?: +(\d+))?(?: -- +(.*))?\z/ + notes = $2 + notes.strip! if notes + if $1 + i = $1.to_i + i = @issues[i]["id"] if @issues && i < @issues.size + @issue = i + end + unless @issue + puts "ticket not selected" + next + end + + log = find_svn_log("##@issue]") + if log && /revision="(?<rev>\d+)/ =~ log + str = log[/merge revision\(s\) ([^:]+)(?=:)/] + str.insert(5, "d") + str = "ruby_#{TARGET_VERSION.tr('.','_')} r#{rev} #{str}." + if notes + str << "\n" + str << notes + end + notes = str + else + puts "no commit is found whose log include ##@issue" + next + end + puts notes + + uri = URI("#{REDMINE_BASE}/issues/#{@issue}.json") + Net::HTTP.start(uri.host, uri.port, http_options) do |http| + res = http.get(uri.path) + data = JSON(res.body) + h = data["issue"]["custom_fields"].find{|x|x["id"]==5} + if h and val = h["value"] + case val[/(?:\A|, )#{Regexp.quote TARGET_VERSION}: ([^,]+)/, 1] + when 'REQUIRED', 'UNKNOWN', 'DONTNEED', 'WONTFIX' + val[*$~.offset(1)] = 'DONE' + when 'DONE' # , /\A\d+\z/ + puts 'already backport is done' + next # already done + when nil + val << ", #{TARGET_VERSION}: DONE" + else + raise "unknown status '#$1'" + end + else + val = '#{TARGET_VERSION}: DONE' + end + + data = { "issue" => { "custom_fields" => [ {"id"=>5, "value" => val} ] } } + data['issue']['notes'] = notes if notes + res = http.put(uri.path, JSON(data), + 'X-Redmine-API-Key' => REDMINE_API_KEY, + 'Content-Type' => 'application/json') + res.value + + show_last_journal(http, uri) + end + when /\Aclose(?: +(\d+))?\z/ + if $1 + i = $1.to_i + i = @issues[i]["id"] if @issues && i < @issues.size + @issue = i + end + unless @issue + puts "ticket not selected" + next + end + + uri = URI("#{REDMINE_BASE}/issues/#{@issue}.json") + Net::HTTP.start(uri.host, uri.port, http_options) do |http| + data = { "issue" => { "status_id" => STATUS_CLOSE } } + res = http.put(uri.path, JSON(data), + 'X-Redmine-API-Key' => REDMINE_API_KEY, + 'Content-Type' => 'application/json') + res.value + + show_last_journal(http, uri) + end + when /\last(?: +(\d+))?\z/ + if $1 + i = $1.to_i + i = @issues[i]["id"] if @issues && i < @issues.size + @issue = i + end + unless @issue + puts "ticket not selected" + next + end + + uri = URI("#{REDMINE_BASE}/issues/#{@issue}.json") + Net::HTTP.start(uri.host, uri.port, http_options) do |http| + show_last_journal(http, uri) + end + when '' + when nil, 'quit', 'exit' + exit + when 'help' + puts 'ls '.color(bold: true) + ' show all required tickets' + puts 'show TICKET '.color(bold: true) + ' show the detail of the TICKET, and select it' + puts 'TICKET '.color(bold: true) + ' show the backport option of the selected ticket for merger.rb' + puts 'done [TICKET] [-- NOTE]'.color(bold: true) + ' set Backport field of the TICKET to DONE' + puts 'close [TICKET] '.color(bold: true) + ' close the TICKET' + puts 'last [TICKET] '.color(bold: true) + ' show the last journal of the TICKET' + else + puts "error #{l.inspect}" + end +end diff --git a/jni/ruby/tool/release.sh b/jni/ruby/tool/release.sh new file mode 100755 index 0000000..4c1d7cc --- /dev/null +++ b/jni/ruby/tool/release.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +RUBYDIR=/home/ftp/pub/ruby +EXTS='.tar.gz .tar.bz2 .tar.xz .zip' + +releases=`ls ruby-*|grep -o 'ruby-[0-9]\.[0-9]\.[0-9]\(-\(preview\|rc\|p\)[0-9]\{1,4\}\)\?'|uniq` + +# check files +for r in $releases +do + echo "checking files for $r..." + for ext in $EXTS + do + if ! [ -f $r$ext ];then + echo "ERROR: $r$ext not found" + exit 1 + fi + done + echo "files are ok" +done + +# version directory +for r in $releases +do + xy=`echo $r|grep -o '[0-9]\.[0-9]'` + preview=`echo $r|grep -o -- '-\(preview\|rc\)'` + dir="${RUBYDIR}/$xy" + echo "$dir" + mkdir -p $dir + for ext in $EXTS + do + cp $r$ext $dir/$r$ext + ln -sf $xy/$r$ext ${RUBYDIR}/$r$ext + if [ x$preview = x ];then + ln -sf $xy/$r$ext ${RUBYDIR}/ruby-$xy-stable$ext + fi + done +done diff --git a/jni/ruby/tool/rmdirs b/jni/ruby/tool/rmdirs new file mode 100755 index 0000000..6dcf984 --- /dev/null +++ b/jni/ruby/tool/rmdirs @@ -0,0 +1,11 @@ +#!/bin/sh +for dir do + while rmdir "$dir" >/dev/null 2>&1 && + parent=`expr "$dir" : '\(.*\)/[^/][^/]*'`; do + case "$parent" in + . | .. | "$dir") break;; + *) dir="$parent";; + esac + done +done +true diff --git a/jni/ruby/tool/rubytest.rb b/jni/ruby/tool/rubytest.rb new file mode 100755 index 0000000..a06c400 --- /dev/null +++ b/jni/ruby/tool/rubytest.rb @@ -0,0 +1,30 @@ +#! ./miniruby + +exit if defined?(CROSS_COMPILING) and CROSS_COMPILING +ruby = ENV["RUBY"] +unless ruby + load './rbconfig.rb' + ruby = "./#{RbConfig::CONFIG['ruby_install_name']}#{RbConfig::CONFIG['EXEEXT']}" +end +unless File.exist? ruby + print "#{ruby} is not found.\n" + print "Try `make' first, then `make test', please.\n" + exit false +end +ARGV[0] and opt = ARGV[0][/\A--run-opt=(.*)/, 1] and ARGV.shift + +$stderr.reopen($stdout) +error = '' + +srcdir = File.expand_path('..', File.dirname(__FILE__)) +`#{ruby} #{opt} #{srcdir}/sample/test.rb #{ARGV.join(' ')}`.each_line do |line| + if line =~ /^end of test/ + print "\ntest succeeded\n" + exit true + end + error << line if %r:^(sample/test.rb|not): =~ line +end +puts +print error +print "test failed\n" +exit false diff --git a/jni/ruby/tool/runruby.rb b/jni/ruby/tool/runruby.rb new file mode 100755 index 0000000..86b9327 --- /dev/null +++ b/jni/ruby/tool/runruby.rb @@ -0,0 +1,99 @@ +#!./miniruby + +show = false +precommand = [] +while arg = ARGV[0] + break ARGV.shift if arg == '--' + /\A--([-\w]+)(?:=(.*))?\z/ =~ arg or break + arg, value = $1, $2 + re = Regexp.new('\A'+arg.gsub(/\w+\b/, '\&\\w*')+'\z', "i") + case + when re =~ "srcdir" + srcdir = value + when re =~ "archdir" + archdir = value + when re =~ "cpu" + precommand << "arch" << "-arch" << value + when re =~ "extout" + extout = value + when re =~ "pure" + # obsolete switch do nothing + when re =~ "debugger" + require 'shellwords' + precommand.concat(value ? (Shellwords.shellwords(value) unless value == "no") : %w"gdb --args") + when re =~ "precommand" + require 'shellwords' + precommand.concat(Shellwords.shellwords(value)) + when re =~ "show" + show = true + else + break + end + ARGV.shift +end + +unless defined?(File.realpath) + def File.realpath(*args) + Dir.chdir(expand_path(*args)) do + Dir.pwd + end + end +end + +srcdir ||= File.realpath('..', File.dirname(__FILE__)) +archdir ||= '.' + +abs_archdir = File.expand_path(archdir) +$:.unshift(abs_archdir) + +config = File.read(conffile = File.join(abs_archdir, 'rbconfig.rb')) +config.sub!(/^(\s*)RUBY_VERSION\s*==.*(\sor\s*)$/, '\1true\2') +config = Module.new {module_eval(config, conffile)}::RbConfig::CONFIG + +ruby = File.join(archdir, config["RUBY_INSTALL_NAME"]+config['EXEEXT']) +unless File.exist?(ruby) + abort "#{ruby} is not found.\nTry `make' first, then `make test', please.\n" +end + +libs = [abs_archdir] +extout ||= config["EXTOUT"] +if extout + abs_extout = File.expand_path(extout, abs_archdir) + libs << File.expand_path("common", abs_extout) << File.expand_path(config['arch'], abs_extout) +end +libs << File.expand_path("lib", srcdir) +config["bindir"] = abs_archdir + +env = {} + +env["RUBY"] = File.expand_path(ruby) +env["PATH"] = [abs_archdir, ENV["PATH"]].compact.join(File::PATH_SEPARATOR) + +if e = ENV["RUBYLIB"] + libs |= e.split(File::PATH_SEPARATOR) +end +env["RUBYLIB"] = $:.replace(libs).join(File::PATH_SEPARATOR) + +libruby_so = File.join(abs_archdir, config['LIBRUBY_SO']) +if File.file?(libruby_so) + if e = config['LIBPATHENV'] and !e.empty? + env[e] = [abs_archdir, ENV[e]].compact.join(File::PATH_SEPARATOR) + end + if /linux/ =~ RUBY_PLATFORM + env["LD_PRELOAD"] = [libruby_so, ENV["LD_PRELOAD"]].compact.join(' ') + end +end + +ENV.update env + +cmd = [ruby] +cmd.concat(ARGV) +cmd.unshift(*precommand) unless precommand.empty? + +if show + require 'shellwords' + env.each {|k,v| puts "#{k}=#{v}"} + puts Shellwords.join(cmd) +end + +exec(*cmd) diff --git a/jni/ruby/tool/strip-rdoc.rb b/jni/ruby/tool/strip-rdoc.rb new file mode 100755 index 0000000..1902cb5 --- /dev/null +++ b/jni/ruby/tool/strip-rdoc.rb @@ -0,0 +1,23 @@ +#!ruby + +ARGF.binmode +source = ARGF.read +source = source.gsub(%r{/\*([!*])((?!\*/).+?)\*/}m) do |comment| + marker, comment = $1, $2 + next "/**#{comment}*/" unless /^\s*\*\s?\-\-\s*$/ =~ comment + doxybody = nil + comment.each_line do |line| + if doxybody + if /^\s*\*\s?\+\+\s*$/ =~ line + break + end + doxybody << line + else + if /^\s*\*\s?--\s*$/ =~ line + doxybody = "\n" + end + end + end + "/*#{marker}#{doxybody}*/" +end +print source diff --git a/jni/ruby/tool/test/test_jisx0208.rb b/jni/ruby/tool/test/test_jisx0208.rb new file mode 100644 index 0000000..d323c84 --- /dev/null +++ b/jni/ruby/tool/test/test_jisx0208.rb @@ -0,0 +1,40 @@ +require 'test/unit' + +require '../tool/jisx0208' + +class Test_JISX0208_Char < Test::Unit::TestCase + def test_create_with_row_cell + assert_equal JISX0208::Char.new(0x2121), JISX0208::Char.new(1, 1) + end + + def test_succ + assert_equal JISX0208::Char.new(0x2221), JISX0208::Char.new(0x217e).succ + assert_equal JISX0208::Char.new(2, 1), JISX0208::Char.new(1, 94).succ + assert_equal JISX0208::Char.new(0x7f21), JISX0208::Char.new(0x7e7e).succ + end + + def test_to_shift_jis + assert_equal 0x895C, JISX0208::Char.new(0x313D).to_sjis + assert_equal 0x895C, JISX0208::Char.from_sjis(0x895C).to_sjis + assert_equal 0xF3DE, JISX0208::Char.from_sjis(0xF3DE).to_sjis + assert_equal 0xFC40, JISX0208::Char.from_sjis(0xFC40).to_sjis + end + + def test_from_sjis + assert_raise(ArgumentError) { JISX0208::Char.from_sjis(-1) } + assert_raise(ArgumentError) { JISX0208::Char.from_sjis(0x10000) } + assert_nothing_raised { JISX0208::Char.from_sjis(0x8140) } + assert_nothing_raised { JISX0208::Char.from_sjis(0xFCFC) } + assert_equal JISX0208::Char.new(0x313D), JISX0208::Char.from_sjis(0x895C) + end + + def test_row + assert_equal 1, JISX0208::Char.new(0x2121).row + assert_equal 94, JISX0208::Char.new(0x7E7E).row + end + + def test_cell + assert_equal 1, JISX0208::Char.new(0x2121).cell + assert_equal 94, JISX0208::Char.new(0x7E7E).cell + end +end diff --git a/jni/ruby/tool/transcode-tblgen.rb b/jni/ruby/tool/transcode-tblgen.rb new file mode 100644 index 0000000..832d9a4 --- /dev/null +++ b/jni/ruby/tool/transcode-tblgen.rb @@ -0,0 +1,1074 @@ +require 'optparse' +require 'erb' +require 'fileutils' +require 'pp' + +class Array + unless [].respond_to? :product + def product(*args) + if args.empty? + self.map {|e| [e] } + else + result = [] + self.each {|e0| + result.concat args.first.product(*args[1..-1]).map {|es| [e0, *es] } + } + result + end + end + end +end + +class String + unless "".respond_to? :start_with? + def start_with?(*prefixes) + prefixes.each {|prefix| + return true if prefix.length <= self.length && prefix == self[0, prefix.length] + } + false + end + end +end + +NUM_ELEM_BYTELOOKUP = 2 + +C_ESC = { + "\\" => "\\\\", + '"' => '\"', + "\n" => '\n', +} + +0x00.upto(0x1f) {|ch| C_ESC[[ch].pack("C")] ||= "\\%03o" % ch } +0x7f.upto(0xff) {|ch| C_ESC[[ch].pack("C")] = "\\%03o" % ch } +C_ESC_PAT = Regexp.union(*C_ESC.keys) + +def c_esc(str) + '"' + str.gsub(C_ESC_PAT) { C_ESC[$&] } + '"' +end + +HEX2 = /(?:[0-9A-Fa-f]{2})/ + +class ArrayCode + def initialize(type, name) + @type = type + @name = name + @len = 0; + @content = '' + end + + def length + @len + end + + def insert_at_last(num, str) + newnum = self.length + num + @content << str + @len += num + end + + def to_s + <<"End" +static const #{@type} +#{@name}[#{@len}] = { +#{@content}}; +End + end +end + +class Action + def initialize(value) + @value = value + end + attr_reader :value + + def hash + @value.hash + end + + def eql?(other) + self.class == other.class && + @value == other.value + end + alias == eql? +end + +class Branch + def initialize(byte_min, byte_max, child_tree) + @byte_min = byte_min + @byte_max = byte_max + @child_tree = child_tree + @hash = byte_min.hash ^ byte_max.hash ^ child_tree.hash + end + attr_reader :byte_min, :byte_max, :child_tree, :hash + + def eql?(other) + self.class == other.class && + @hash == other.hash && + @byte_min == other.byte_min && + @byte_max == other.byte_max && + @child_tree == other.child_tree + end + alias == eql? +end + +class ActionMap + def self.parse_to_rects(mapping) + rects = [] + n = 0 + mapping.each {|pat, action| + pat = pat.to_s + if /\A\s*\(empset\)\s*\z/ =~ pat + next + elsif /\A\s*\(empstr\)\s*\z/ =~ pat + rects << ['', '', action] + n += 1 + elsif /\A\s*(#{HEX2}+)\s*\z/o =~ pat + hex = $1.upcase + rects << [hex, hex, action] + elsif /\A\s*((#{HEX2}|\{#{HEX2}(?:-#{HEX2})?(,#{HEX2}(?:-#{HEX2})?)*\})+(\s+|\z))*\z/o =~ pat + pat = pat.upcase + pat.scan(/\S+/) { + pat1 = $& + ranges_list = [] + pat1.scan(/#{HEX2}|\{([^\}]*)\}/o) { + ranges_list << [] + if !$1 + ranges_list.last << [$&,$&] + else + set = {} + $1.scan(/(#{HEX2})(?:-(#{HEX2}))?/o) { + if !$2 + c = $1.to_i(16) + set[c] = true + else + b = $1.to_i(16) + e = $2.to_i(16) + b.upto(e) {|c| set[c] = true } + end + } + i = nil + 0.upto(256) {|j| + if set[j] + if !i + i = j + end + if !set[j+1] + ranges_list.last << ["%02X" % i, "%02X" % j] + i = nil + end + end + } + end + } + first_ranges = ranges_list.shift + first_ranges.product(*ranges_list).each {|range_list| + min = range_list.map {|x, y| x }.join + max = range_list.map {|x, y| y }.join + rects << [min, max, action] + } + } + else + raise ArgumentError, "invalid pattern: #{pat.inspect}" + end + } + rects + end + + def self.unambiguous_action(actions0) + actions = actions0.uniq + if actions.length == 1 + actions[0] + else + actions.delete(:nomap0) + if actions.length == 1 + actions[0] + else + raise ArgumentError, "ambiguous actions: #{actions0.inspect}" + end + end + end + + def self.build_tree(rects) + expand(rects) {|prefix, actions| + unambiguous_action(actions) + } + end + + def self.parse(mapping) + rects = parse_to_rects(mapping) + tree = build_tree(rects) + self.new(tree) + end + + def self.merge_rects(*rects_list) + if rects_list.length < 2 + raise ArgumentError, "not enough arguments" + end + + all_rects = [] + rects_list.each_with_index {|rects, i| + all_rects.concat rects.map {|min, max, action| [min, max, [i, action]] } + } + + tree = expand(all_rects) {|prefix, actions| + args = Array.new(rects_list.length) { [] } + actions.each {|i, action| + args[i] << action + } + yield(prefix, *args) + } + + self.new(tree) + end + + def self.merge(*mappings, &block) + merge_rects(*mappings.map {|m| parse_to_rects(m) }, &block) + end + + def self.merge2(map1, map2, &block) + rects1 = parse_to_rects(map1) + rects2 = parse_to_rects(map2) + + actions = [] + all_rects = [] + + rects1.each {|rect| + min, max, action = rect + rect[2] = actions.length + actions << action + all_rects << rect + } + + boundary = actions.length + + rects2.each {|rect| + min, max, action = rect + rect[2] = actions.length + actions << action + all_rects << rect + } + + tree = expand(all_rects) {|prefix, as0| + as1 = [] + as2 = [] + as0.each {|i| + if i < boundary + as1 << actions[i] + else + as2 << actions[i] + end + } + yield(prefix, as1, as2) + } + + self.new(tree) + end + + def self.expand(rects, &block) + #numsing = numreg = 0 + #rects.each {|min, max, action| if min == max then numsing += 1 else numreg += 1 end } + #puts "#{numsing} singleton mappings and #{numreg} region mappings." + singleton_rects = [] + region_rects = [] + rects.each {|rect| + min, max, action = rect + if min == max + singleton_rects << rect + else + region_rects << rect + end + } + @singleton_rects = singleton_rects.sort_by {|min, max, action| min } + @singleton_rects.reverse! + ret = expand_rec("", region_rects, &block) + @singleton_rects = nil + ret + end + + TMPHASH = {} + def self.expand_rec(prefix, region_rects, &block) + return region_rects if region_rects.empty? && !((s_rect = @singleton_rects.last) && s_rect[0].start_with?(prefix)) + if region_rects.empty? ? s_rect[0].length == prefix.length : region_rects[0][0].empty? + h = TMPHASH + while (s_rect = @singleton_rects.last) && s_rect[0].start_with?(prefix) + min, max, action = @singleton_rects.pop + raise ArgumentError, "ambiguous pattern: #{prefix}" if min.length != prefix.length + h[action] = true + end + region_rects.each {|min, max, action| + raise ArgumentError, "ambiguous pattern: #{prefix}" if !min.empty? + h[action] = true + } + tree = Action.new(block.call(prefix, h.keys)) + h.clear + else + tree = [] + each_firstbyte_range(prefix, region_rects) {|byte_min, byte_max, r_rects2| + if byte_min == byte_max + prefix2 = prefix + "%02X" % byte_min + else + prefix2 = prefix + "{%02X-%02X}" % [byte_min, byte_max] + end + child_tree = expand_rec(prefix2, r_rects2, &block) + tree << Branch.new(byte_min, byte_max, child_tree) + } + end + return tree + end + + def self.each_firstbyte_range(prefix, region_rects) + index_from = TMPHASH + + region_ary = [] + region_rects.each {|min, max, action| + raise ArgumentError, "ambiguous pattern: #{prefix}" if min.empty? + min_firstbyte = min[0,2].to_i(16) + min_rest = min[2..-1] + max_firstbyte = max[0,2].to_i(16) + max_rest = max[2..-1] + region_ary << [min_firstbyte, max_firstbyte, [min_rest, max_rest, action]] + index_from[min_firstbyte] = true + index_from[max_firstbyte+1] = true + } + + byte_from = Array.new(index_from.size) + bytes = index_from.keys + bytes.sort! + bytes.reverse! + bytes.each_with_index {|byte, i| + index_from[byte] = i + byte_from[i] = byte + } + + region_rects_ary = Array.new(index_from.size) { [] } + region_ary.each {|min_firstbyte, max_firstbyte, rest_elt| + index_from[min_firstbyte].downto(index_from[max_firstbyte+1]+1) {|i| + region_rects_ary[i] << rest_elt + } + } + + index_from.clear + + r_rects = region_rects_ary.pop + region_byte = byte_from.pop + prev_r_start = region_byte + prev_r_rects = [] + while r_rects && (s_rect = @singleton_rects.last) && (seq = s_rect[0]).start_with?(prefix) + singleton_byte = seq[prefix.length, 2].to_i(16) + min_byte = singleton_byte < region_byte ? singleton_byte : region_byte + if prev_r_start < min_byte && !prev_r_rects.empty? + yield prev_r_start, min_byte-1, prev_r_rects + end + if region_byte < singleton_byte + prev_r_start = region_byte + prev_r_rects = r_rects + r_rects = region_rects_ary.pop + region_byte = byte_from.pop + elsif region_byte > singleton_byte + yield singleton_byte, singleton_byte, prev_r_rects + prev_r_start = singleton_byte+1 + else # region_byte == singleton_byte + prev_r_start = region_byte+1 + prev_r_rects = r_rects + r_rects = region_rects_ary.pop + region_byte = byte_from.pop + yield singleton_byte, singleton_byte, prev_r_rects + end + end + + while r_rects + if prev_r_start < region_byte && !prev_r_rects.empty? + yield prev_r_start, region_byte-1, prev_r_rects + end + prev_r_start = region_byte + prev_r_rects = r_rects + r_rects = region_rects_ary.pop + region_byte = byte_from.pop + end + + while (s_rect = @singleton_rects.last) && (seq = s_rect[0]).start_with?(prefix) + singleton_byte = seq[prefix.length, 2].to_i(16) + yield singleton_byte, singleton_byte, [] + end + end + + def initialize(tree) + @tree = tree + end + + def inspect + "\#<#{self.class}:" + + @tree.inspect + + ">" + end + + def max_input_length_rec(tree) + case tree + when Action + 0 + else + tree.map {|branch| + max_input_length_rec(branch.child_tree) + }.max + 1 + end + end + + def max_input_length + max_input_length_rec(@tree) + end + + def empty_action + if @tree.kind_of? Action + @tree.value + else + nil + end + end + + OffsetsMemo = {} + InfosMemo = {} + + def format_offsets(min, max, offsets) + offsets = offsets[min..max] + code = "%d, %d,\n" % [min, max] + 0.step(offsets.length-1,16) {|i| + code << " " + code << offsets[i,8].map {|off| "%3d," % off.to_s }.join('') + if i+8 < offsets.length + code << " " + code << offsets[i+8,8].map {|off| "%3d," % off.to_s }.join('') + end + code << "\n" + } + code + end + + UsedName = {} + + StrMemo = {} + + def str_name(bytes) + size = @bytes_code.length + rawbytes = [bytes].pack("H*") + + n = nil + if !n && !(suf = rawbytes.gsub(/[^A-Za-z0-9_]/, '')).empty? && !UsedName[nn = "str1_" + suf] then n = nn end + if !n && !UsedName[nn = "str1_" + bytes] then n = nn end + n ||= "str1s_#{size}" + + StrMemo[bytes] = n + UsedName[n] = true + n + end + + def gen_str(bytes) + if n = StrMemo[bytes] + n + else + len = bytes.length/2 + size = @bytes_code.length + n = str_name(bytes) + @bytes_code.insert_at_last(1 + len, + "\#define #{n} makeSTR1(#{size})\n" + + " makeSTR1LEN(#{len})," + bytes.gsub(/../, ' 0x\&,') + "\n\n") + n + end + end + + def generate_info(info) + case info + when :nomap, :nomap0 + # :nomap0 is low priority. it never collides. + "NOMAP" + when :undef + "UNDEF" + when :invalid + "INVALID" + when :func_ii + "FUNii" + when :func_si + "FUNsi" + when :func_io + "FUNio" + when :func_so + "FUNso" + when /\A(#{HEX2})\z/o + "o1(0x#$1)" + when /\A(#{HEX2})(#{HEX2})\z/o + "o2(0x#$1,0x#$2)" + when /\A(#{HEX2})(#{HEX2})(#{HEX2})\z/o + "o3(0x#$1,0x#$2,0x#$3)" + when /funsio\((\d+)\)/ + "funsio(#{$1})" + when /\A(#{HEX2})(3[0-9])(#{HEX2})(3[0-9])\z/o + "g4(0x#$1,0x#$2,0x#$3,0x#$4)" + when /\A(f[0-7])(#{HEX2})(#{HEX2})(#{HEX2})\z/o + "o4(0x#$1,0x#$2,0x#$3,0x#$4)" + when /\A(#{HEX2}){4,259}\z/o + gen_str(info.upcase) + when /\A\/\*BYTE_LOOKUP\*\// # pointer to BYTE_LOOKUP structure + $'.to_s + else + raise "unexpected action: #{info.inspect}" + end + end + + def format_infos(infos) + infos = infos.map {|info| generate_info(info) } + maxlen = infos.map {|info| info.length }.max + columns = maxlen <= 16 ? 4 : 2 + code = "" + 0.step(infos.length-1, columns) {|i| + code << " " + is = infos[i,columns] + is.each {|info| + code << sprintf(" %#{maxlen}s,", info) + } + code << "\n" + } + code + end + + def generate_lookup_node(name, table) + bytes_code = @bytes_code + words_code = @words_code + offsets = [] + infos = [] + infomap = {} + min = max = nil + table.each_with_index {|action, byte| + action ||= :invalid + if action != :invalid + min = byte if !min + max = byte + end + unless o = infomap[action] + infomap[action] = o = infos.length + infos[o] = action + end + offsets[byte] = o + } + infomap.clear + if !min + min = max = 0 + end + + offsets_key = [min, max, offsets[min..max]] + if n = OffsetsMemo[offsets_key] + offsets_name = n + else + offsets_name = "#{name}_offsets" + OffsetsMemo[offsets_key] = offsets_name + size = bytes_code.length + bytes_code.insert_at_last(2+max-min+1, + "\#define #{offsets_name} #{size}\n" + + format_offsets(min,max,offsets) + "\n") + end + + if n = InfosMemo[infos] + infos_name = n + else + infos_name = "#{name}_infos" + InfosMemo[infos] = infos_name + + size = words_code.length + words_code.insert_at_last(infos.length, + "\#define #{infos_name} WORDINDEX2INFO(#{size})\n" + + format_infos(infos) + "\n") + end + + size = words_code.length + words_code.insert_at_last(NUM_ELEM_BYTELOOKUP, + "\#define #{name} WORDINDEX2INFO(#{size})\n" + + <<"End" + "\n") + #{offsets_name}, + #{infos_name}, +End + end + + PreMemo = {} + NextName = "a" + + def generate_node(name_hint=nil) + if n = PreMemo[@tree] + return n + end + + table = Array.new(0x100, :invalid) + @tree.each {|branch| + byte_min, byte_max, child_tree = branch.byte_min, branch.byte_max, branch.child_tree + rest = ActionMap.new(child_tree) + if a = rest.empty_action + table.fill(a, byte_min..byte_max) + else + name_hint2 = nil + if name_hint + name_hint2 = "#{name_hint}_#{byte_min == byte_max ? '%02X' % byte_min : '%02Xto%02X' % [byte_min, byte_max]}" + end + v = "/*BYTE_LOOKUP*/" + rest.gennode(@bytes_code, @words_code, name_hint2) + table.fill(v, byte_min..byte_max) + end + } + + if !name_hint + name_hint = "fun_" + NextName + NextName.succ! + end + + PreMemo[@tree] = name_hint + + generate_lookup_node(name_hint, table) + name_hint + end + + def gennode(bytes_code, words_code, name_hint=nil) + @bytes_code = bytes_code + @words_code = words_code + name = generate_node(name_hint) + @bytes_code = nil + @words_code = nil + return name + end +end + +def citrus_mskanji_cstomb(csid, index) + case csid + when 0 + index + when 1 + index + 0x80 + when 2, 3 + row = index >> 8 + raise "invalid byte sequence" if row < 0x21 + if csid == 3 + if row <= 0x2F + offset = (row == 0x22 || row >= 0x26) ? 0xED : 0xF0 + elsif row >= 0x4D && row <= 0x7E + offset = 0xCE + else + raise "invalid byte sequence" + end + else + raise "invalid byte sequence" if row > 0x97 + offset = (row < 0x5F) ? 0x81 : 0xC1 + end + col = index & 0xFF + raise "invalid byte sequence" if (col < 0x21 || col > 0x7E) + + row -= 0x21 + col -= 0x21 + if (row & 1) == 0 + col += 0x40 + col += 1 if (col >= 0x7F) + else + col += 0x9F; + end + row = row / 2 + offset + (row << 8) | col + end.to_s(16) +end + +def citrus_euc_cstomb(csid, index) + case csid + when 0x0000 + index + when 0x8080 + index | 0x8080 + when 0x0080 + index | 0x8E80 + when 0x8000 + index | 0x8F8080 + end.to_s(16) +end + +def citrus_stateless_iso_cstomb(csid, index) + (index | 0x8080 | (csid << 16)).to_s(16) +end + +def citrus_cstomb(ces, csid, index) + case ces + when 'mskanji' + citrus_mskanji_cstomb(csid, index) + when 'euc' + citrus_euc_cstomb(csid, index) + when 'stateless_iso' + citrus_stateless_iso_cstomb(csid, index) + end +end + +SUBDIR = %w/APPLE AST BIG5 CNS CP EBCDIC EMOJI GB GEORGIAN ISO646 ISO-8859 JIS KAZAKH KOI KS MISC TCVN/ + + +def citrus_decode_mapsrc(ces, csid, mapsrcs) + table = [] + mapsrcs.split(',').each do |mapsrc| + path = [$srcdir] + mode = nil + if mapsrc.rindex(/UCS(?:@[A-Z]+)?/, 0) + mode = :from_ucs + from = mapsrc[$&.size+1..-1] + path << SUBDIR.find{|x| from.rindex(x, 0) } + else + mode = :to_ucs + path << SUBDIR.find{|x| mapsrc.rindex(x, 0) } + end + if /\bUCS@(BMP|SMP|SIP|TIP|SSP)\b/ =~ mapsrc + plane = {"BMP"=>0, "SMP"=>1, "SIP"=>2, "TIP"=>3, "SSP"=>14}[$1] + else + plane = 0 + end + plane <<= 16 + path << mapsrc.gsub(':', '@') + path = File.join(*path) + path << ".src" + path[path.rindex('/')] = '%' + STDERR.puts 'load mapsrc %s' % path if VERBOSE_MODE + open(path) do |f| + f.each_line do |l| + break if /^BEGIN_MAP/ =~ l + end + f.each_line do |l| + next if /^\s*(?:#|$)/ =~ l + break if /^END_MAP/ =~ l + case mode + when :from_ucs + case l + when /0x(\w+)\s*-\s*0x(\w+)\s*=\s*INVALID/ + # Citrus OOB_MODE + when /(0x\w+)\s*=\s*(0x\w+)/ + table.push << [plane | $1.hex, citrus_cstomb(ces, csid, $2.hex)] + else + raise "unknown notation '%s'"% l + end + when :to_ucs + case l + when /(0x\w+)\s*=\s*(0x\w+)/ + table.push << [citrus_cstomb(ces, csid, $1.hex), plane | $2.hex] + else + raise "unknown notation '%s'"% l + end + end + end + end + end + return table +end + +def import_ucm(path) + to_ucs = [] + from_ucs = [] + File.foreach(File.join($srcdir, "ucm", path)) do |line| + uc, bs, fb = nil + if /^<U([0-9a-fA-F]+)>\s*([\+0-9a-fA-Fx\\]+)\s*\|(\d)/ =~ line + uc = $1.hex + bs = $2.delete('x\\') + fb = $3.to_i + next if uc < 128 && uc == bs.hex + elsif /^([<U0-9a-fA-F>+]+)\s*([\+0-9a-fA-Fx\\]+)\s*\|(\d)/ =~ line + uc = $1.scan(/[0-9a-fA-F]+>/).map(&:hex).pack("U*").unpack("H*")[0] + bs = $2.delete('x\\') + fb = $3.to_i + end + to_ucs << [bs, uc] if fb == 0 || fb == 3 + from_ucs << [uc, bs] if fb == 0 || fb == 1 + end + [to_ucs, from_ucs] +end + +def encode_utf8(map) + r = [] + map.each {|k, v| + # integer means UTF-8 encoded sequence. + k = [k].pack("U").unpack("H*")[0].upcase if Integer === k + v = [v].pack("U").unpack("H*")[0].upcase if Integer === v + r << [k,v] + } + r +end + +UnspecifiedValidEncoding = Object.new + +def transcode_compile_tree(name, from, map, valid_encoding) + map = encode_utf8(map) + h = {} + map.each {|k, v| + h[k] = v unless h[k] # use first mapping + } + if valid_encoding.equal? UnspecifiedValidEncoding + valid_encoding = ValidEncoding.fetch(from) + end + if valid_encoding + am = ActionMap.merge2(h, {valid_encoding => :undef}) {|prefix, as1, as2| + a1 = as1.empty? ? nil : ActionMap.unambiguous_action(as1) + a2 = as2.empty? ? nil : ActionMap.unambiguous_action(as2) + if !a2 + raise "invalid mapping: #{prefix}" + end + a1 || a2 + } + else + am = ActionMap.parse(h) + end + h.clear + + max_input = am.max_input_length + defined_name = am.gennode(TRANSCODE_GENERATED_BYTES_CODE, TRANSCODE_GENERATED_WORDS_CODE, name) + return defined_name, max_input +end + +TRANSCODERS = [] +TRANSCODE_GENERATED_TRANSCODER_CODE = '' + +def transcode_tbl_only(from, to, map, valid_encoding=UnspecifiedValidEncoding) + if VERBOSE_MODE + if from.empty? || to.empty? + STDERR.puts "converter for #{from.empty? ? to : from}" + else + STDERR.puts "converter from #{from} to #{to}" + end + end + id_from = from.tr('^0-9A-Za-z', '_') + id_to = to.tr('^0-9A-Za-z', '_') + if from == "UTF-8" + tree_name = "to_#{id_to}" + elsif to == "UTF-8" + tree_name = "from_#{id_from}" + else + tree_name = "from_#{id_from}_to_#{id_to}" + end + real_tree_name, max_input = transcode_compile_tree(tree_name, from, map, valid_encoding) + return map, tree_name, real_tree_name, max_input +end + +def transcode_tblgen(from, to, map, valid_encoding=UnspecifiedValidEncoding) + map, tree_name, real_tree_name, max_input = transcode_tbl_only(from, to, map, valid_encoding) + transcoder_name = "rb_#{tree_name}" + TRANSCODERS << transcoder_name + input_unit_length = UnitLength[from] + max_output = map.map {|k,v| String === v ? v.length/2 : 1 }.max + transcoder_code = <<"End" +static const rb_transcoder +#{transcoder_name} = { + #{c_esc from}, #{c_esc to}, #{real_tree_name}, + TRANSCODE_TABLE_INFO, + #{input_unit_length}, /* input_unit_length */ + #{max_input}, /* max_input */ + #{max_output}, /* max_output */ + asciicompat_converter, /* asciicompat_type */ + 0, NULL, NULL, /* state_size, state_init, state_fini */ + NULL, NULL, NULL, NULL, + NULL, NULL, NULL +}; +End + TRANSCODE_GENERATED_TRANSCODER_CODE << transcoder_code + '' +end + +def transcode_generate_node(am, name_hint=nil) + STDERR.puts "converter for #{name_hint}" if VERBOSE_MODE + name = am.gennode(TRANSCODE_GENERATED_BYTES_CODE, TRANSCODE_GENERATED_WORDS_CODE, name_hint) + '' +end + +def transcode_generated_code + TRANSCODE_GENERATED_BYTES_CODE.to_s + + TRANSCODE_GENERATED_WORDS_CODE.to_s + + "\#define TRANSCODE_TABLE_INFO " + + "#{OUTPUT_PREFIX}byte_array, #{TRANSCODE_GENERATED_BYTES_CODE.length}, " + + "#{OUTPUT_PREFIX}word_array, #{TRANSCODE_GENERATED_WORDS_CODE.length}, " + + "((int)sizeof(unsigned int))\n" + + TRANSCODE_GENERATED_TRANSCODER_CODE +end + +def transcode_register_code + code = '' + TRANSCODERS.each {|transcoder_name| + code << " rb_register_transcoder(&#{transcoder_name});\n" + } + code +end + +UnitLength = { + 'UTF-16BE' => 2, + 'UTF-16LE' => 2, + 'UTF-32BE' => 4, + 'UTF-32LE' => 4, +} +UnitLength.default = 1 + +ValidEncoding = { + '1byte' => '{00-ff}', + '2byte' => '{00-ff}{00-ff}', + '4byte' => '{00-ff}{00-ff}{00-ff}{00-ff}', + 'US-ASCII' => '{00-7f}', + 'UTF-8' => '{00-7f} + {c2-df}{80-bf} + e0{a0-bf}{80-bf} + {e1-ec}{80-bf}{80-bf} + ed{80-9f}{80-bf} + {ee-ef}{80-bf}{80-bf} + f0{90-bf}{80-bf}{80-bf} + {f1-f3}{80-bf}{80-bf}{80-bf} + f4{80-8f}{80-bf}{80-bf}', + 'UTF-16BE' => '{00-d7,e0-ff}{00-ff} + {d8-db}{00-ff}{dc-df}{00-ff}', + 'UTF-16LE' => '{00-ff}{00-d7,e0-ff} + {00-ff}{d8-db}{00-ff}{dc-df}', + 'UTF-32BE' => '0000{00-d7,e0-ff}{00-ff} + 00{01-10}{00-ff}{00-ff}', + 'UTF-32LE' => '{00-ff}{00-d7,e0-ff}0000 + {00-ff}{00-ff}{01-10}00', + 'EUC-JP' => '{00-7f} + {a1-fe}{a1-fe} + 8e{a1-fe} + 8f{a1-fe}{a1-fe}', + 'CP51932' => '{00-7f} + {a1-fe}{a1-fe} + 8e{a1-fe}', + 'EUC-JIS-2004' => '{00-7f} + {a1-fe}{a1-fe} + 8e{a1-fe} + 8f{a1-fe}{a1-fe}', + 'Shift_JIS' => '{00-7f} + {81-9f,e0-fc}{40-7e,80-fc} + {a1-df}', + 'EUC-KR' => '{00-7f} + {a1-fe}{a1-fe}', + 'CP949' => '{00-7f} + {81-fe}{41-5a,61-7a,81-fe}', + 'Big5' => '{00-7f} + {81-fe}{40-7e,a1-fe}', + 'EUC-TW' => '{00-7f} + {a1-fe}{a1-fe} + 8e{a1-b0}{a1-fe}{a1-fe}', + 'GBK' => '{00-80} + {81-fe}{40-7e,80-fe}', + 'GB18030' => '{00-7f} + {81-fe}{40-7e,80-fe} + {81-fe}{30-39}{81-fe}{30-39}', +} + +def ValidEncoding(enc) + ValidEncoding.fetch(enc) +end + +def set_valid_byte_pattern(encoding, pattern_or_label) + pattern = + if ValidEncoding[pattern_or_label] + ValidEncoding[pattern_or_label] + else + pattern_or_label + end + if ValidEncoding[encoding] and ValidEncoding[encoding]!=pattern + raise ArgumentError, "trying to change valid byte pattern for encoding #{encoding} from #{ValidEncoding[encoding]} to #{pattern}" + end + ValidEncoding[encoding] = pattern +end + +# the following may be used in different places, so keep them here for the moment +set_valid_byte_pattern 'ASCII-8BIT', '1byte' +set_valid_byte_pattern 'Windows-31J', 'Shift_JIS' +set_valid_byte_pattern 'eucJP-ms', 'EUC-JP' + +def make_signature(filename, src) + "src=#{filename.dump}, len=#{src.length}, checksum=#{src.sum}" +end + +if __FILE__ == $0 + start_time = Time.now + + output_filename = nil + verbose_mode = false + force_mode = false + + op = OptionParser.new + op.def_option("--help", "show help message") { puts op; exit 0 } + op.def_option("--verbose", "verbose mode") { verbose_mode = true } + op.def_option("--force", "force table generation") { force_mode = true } + op.def_option("--output=FILE", "specify output file") {|arg| output_filename = arg } + op.parse! + + VERBOSE_MODE = verbose_mode + + OUTPUT_FILENAME = output_filename + OUTPUT_PREFIX = output_filename ? File.basename(output_filename)[/\A[A-Za-z0-9_]*/] : "" + OUTPUT_PREFIX.sub!(/\A_+/, '') + OUTPUT_PREFIX.sub!(/_*\z/, '_') + + TRANSCODE_GENERATED_BYTES_CODE = ArrayCode.new("unsigned char", "#{OUTPUT_PREFIX}byte_array") + TRANSCODE_GENERATED_WORDS_CODE = ArrayCode.new("unsigned int", "#{OUTPUT_PREFIX}word_array") + + arg = ARGV.shift + $srcdir = File.dirname(arg) + $:.unshift $srcdir unless $:.include? $srcdir + src = File.read(arg) + src.force_encoding("ascii-8bit") if src.respond_to? :force_encoding + this_script = File.read(__FILE__) + this_script.force_encoding("ascii-8bit") if this_script.respond_to? :force_encoding + + base_signature = "/* autogenerated. */\n" + base_signature << "/* #{make_signature(File.basename(__FILE__), this_script)} */\n" + base_signature << "/* #{make_signature(File.basename(arg), src)} */\n" + + if !force_mode && output_filename && File.readable?(output_filename) + old_signature = File.open(output_filename) {|f| f.gets("").chomp } + chk_signature = base_signature.dup + old_signature.each_line {|line| + if %r{/\* src="([0-9a-z_.-]+)",} =~ line + name = $1 + next if name == File.basename(arg) || name == File.basename(__FILE__) + path = File.join($srcdir, name) + if File.readable? path + chk_signature << "/* #{make_signature(name, File.read(path))} */\n" + end + end + } + if old_signature == chk_signature + now = Time.now + File.utime(now, now, output_filename) + STDERR.puts "already up-to-date: #{output_filename}" if VERBOSE_MODE + exit + end + end + + if VERBOSE_MODE + if output_filename + STDERR.puts "generating #{output_filename} ..." + end + end + + libs1 = $".dup + erb = ERB.new(src, nil, '%') + erb.filename = arg + erb_result = erb.result(binding) + libs2 = $".dup + + libs = libs2 - libs1 + lib_sigs = '' + libs.each {|lib| + lib = File.basename(lib) + path = File.join($srcdir, lib) + if File.readable? path + lib_sigs << "/* #{make_signature(lib, File.read(path))} */\n" + end + } + + result = '' + result << base_signature + result << lib_sigs + result << "\n" + result << erb_result + result << "\n" + + if output_filename + new_filename = output_filename + ".new" + FileUtils.mkdir_p(File.dirname(output_filename)) + File.open(new_filename, "wb") {|f| f << result } + File.rename(new_filename, output_filename) + tms = Process.times + elapsed = Time.now - start_time + STDERR.puts "done. (#{'%.2f' % tms.utime}user #{'%.2f' % tms.stime}system #{'%.2f' % elapsed}elapsed)" if VERBOSE_MODE + else + print result + end +end diff --git a/jni/ruby/tool/update-deps b/jni/ruby/tool/update-deps new file mode 100755 index 0000000..2e7a7e7 --- /dev/null +++ b/jni/ruby/tool/update-deps @@ -0,0 +1,615 @@ +#!/usr/bin/ruby + +# tool/update-deps verify makefile dependencies. + +# Requirements: +# gcc 4.5 (for -save-temps=obj option) +# GNU make (for -p option) +# +# Warning: ccache (and similar tools) must be disabled for +# -save-temps=obj to work properly. +# +# Usage: +# 1. Compile ruby with -save-temps=obj option. +# Ex. ./configure debugflags='-save-temps=obj -g' && make all golf +# 2. Run tool/update-deps to show dependency problems. +# Ex. ruby tool/update-deps +# 3. Use --fix to fix makefiles. +# Ex. ruby tool/update-deps --fix +# +# Other usages: +# * Fix makefiles using previously detected dependency problems +# Ex. ruby tool/update-deps --actual-fix [file] +# "ruby tool/update-deps --fix" is same as "ruby tool/update-deps | ruby tool/update-deps --actual-fix". + +require 'optparse' +require 'stringio' +require 'pathname' +require 'open3' +require 'pp' + +# When out-of-place bulid, files may be built in source directory or +# build directory. +# Some files are always built in the source directory. +# Some files are always built in the build directory. +# Some files are built in the source directory for tarball but build directory for repository (svn). + +=begin +How to build test directories. + +VER=2.2.0 +REV=48577 +tar xf ruby-$VER-r$REV.tar.xz +cp -a ruby-$VER-r$REV tarball_source_dir_original +mv ruby-$VER-r$REV tarball_source_dir_after_build +svn co -q -r$REV http://svn.ruby-lang.org/repos/ruby/trunk ruby +(cd ruby; autoconf) +cp -a ruby repo_source_dir_original +mv ruby repo_source_dir_after_build +mkdir tarball_build_dir repo_build_dir tarball_install_dir repo_install_dir +(cd tarball_build_dir; ../tarball_source_dir_after_build/configure --prefix=$(cd ../tarball_install_dir; pwd) && make all golf install) > tarball.log 2>&1 +(cd repo_build_dir; ../repo_source_dir_after_build/configure --prefix=$(cd ../repo_install_dir; pwd) && make all golf install) > repo.log 2>&1 +ruby -rpp -rfind -e ' +ds = %w[ + repo_source_dir_original + repo_source_dir_after_build + repo_build_dir + tarball_source_dir_original + tarball_source_dir_after_build + tarball_build_dir +] +files = {} +ds.each {|d| + files[d] = {} + Dir.chdir(d) { Find.find(".") {|f| files[d][f] = true if %r{\.(c|h|inc|dmyh)\z} =~ f } } +} +result = {} +files_union = files.values.map {|h| h.keys }.flatten.uniq.sort +files_union.each {|f| + k = files.map {|d,h| h[f] ? d : nil }.compact.sort + next if k == %w[repo_source_dir_after_build repo_source_dir_original tarball_source_dir_after_build tarball_source_dir_original] + next if k == %w[repo_build_dir tarball_build_dir] && File.basename(f) == "extconf.h" + result[k] ||= [] + result[k] << f +} +result.each {|k,v| + k.each {|d| + puts d + } + v.each {|f| + puts " " + f.sub(%r{\A\./}, "") + } + puts +} +' | tee compare.log +=end + +# Files built in the source directory. +# They can be referenced as $(top_srcdir)/filename. +# % ruby -e 'def g(d) Dir.chdir(d) { Dir["**/*.{c,h,inc,dmyh}"] } end; puts((g("repo_source_dir_after_build") - g("repo_source_dir_original")).sort)' +FILES_IN_SOURCE_DIRECTORY = %w[ + revision.h +] + +# Files built in the build directory (except extconf.h). +# They can be referenced as $(topdir)/filename. +# % ruby -e 'def g(d) Dir.chdir(d) { Dir["**/*.{c,h,inc,dmyh}"] } end; puts(g("tarball_build_dir").reject {|f| %r{/extconf.h\z} =~ f }.sort)' +FILES_IN_BUILD_DIRECTORY = %w[ + encdb.h + ext/etc/constdefs.h + ext/socket/constdefs.c + ext/socket/constdefs.h + probes.h + transdb.h + verconf.h +] + +# They are built in the build directory if the source is obtained from the repository. +# However they are pre-built for tarball and they exist in the source directory extracted from the tarball. +# % ruby -e 'def g(d) Dir.chdir(d) { Dir["**/*.{c,h,inc,dmyh}"] } end; puts((g("repo_build_dir") & g("tarball_source_dir_original")).sort)' +FILES_NEED_VPATH = %w[ + ext/rbconfig/sizeof/sizes.c + ext/ripper/eventids1.c + ext/ripper/eventids2table.c + ext/ripper/ripper.c + golf_prelude.c + id.c + id.h + insns.inc + insns_info.inc + known_errors.inc + lex.c + miniprelude.c + newline.c + node_name.inc + opt_sc.inc + optinsn.inc + optunifs.inc + parse.c + parse.h + prelude.c + probes.dmyh + vm.inc + vmtc.inc + + enc/trans/big5.c + enc/trans/chinese.c + enc/trans/emoji.c + enc/trans/emoji_iso2022_kddi.c + enc/trans/emoji_sjis_docomo.c + enc/trans/emoji_sjis_kddi.c + enc/trans/emoji_sjis_softbank.c + enc/trans/escape.c + enc/trans/gb18030.c + enc/trans/gbk.c + enc/trans/iso2022.c + enc/trans/japanese.c + enc/trans/japanese_euc.c + enc/trans/japanese_sjis.c + enc/trans/korean.c + enc/trans/single_byte.c + enc/trans/utf8_mac.c + enc/trans/utf_16_32.c +] + +# Multiple files with same filename. +# It is not good idea to refer them using VPATH. +# Files in FILES_SAME_NAME_INC is referenced using $(hdrdir). +# Files in FILES_SAME_NAME_TOP is referenced using $(top_srcdir). +# include/ruby.h is referenced using $(top_srcdir) because mkmf.rb replaces +# $(hdrdir)/ruby.h to $(hdrdir)/ruby/ruby.h + +FILES_SAME_NAME_INC = %w[ + include/ruby/ruby.h + include/ruby/version.h +] + +FILES_SAME_NAME_TOP = %w[ + include/ruby.h + version.h +] + +# Other source files exist in the source directory. + +def in_makefile(target, source) + target = target.to_s + source = source.to_s + case target + when %r{\A[^/]*\z} + target2 = "#{target.sub(/\.o\z/, '.$(OBJEXT)')}" + case source + when *FILES_IN_SOURCE_DIRECTORY then source2 = "$(top_srcdir)/#{source}" + when *FILES_IN_BUILD_DIRECTORY then source2 = "{$(VPATH)}#{source}" # VPATH is not used now but it may changed in future. + when *FILES_NEED_VPATH then source2 = "{$(VPATH)}#{source}" + when *FILES_SAME_NAME_INC then source2 = "$(hdrdir)/#{source.sub(%r{\Ainclude/},'')}" + when *FILES_SAME_NAME_TOP then source2 = "$(top_srcdir)/#{source}" + when 'thread_pthread.c' then source2 = '{$(VPATH)}thread_$(THREAD_MODEL).c' + when 'thread_pthread.h' then source2 = '{$(VPATH)}thread_$(THREAD_MODEL).h' + when %r{\A[^/]*\z} then source2 = "{$(VPATH)}#{File.basename source}" + when %r{\A\.ext/include/[^/]+/ruby/} then source2 = "{$(VPATH)}#{$'}" + when %r{\Ainclude/ruby/} then source2 = "{$(VPATH)}#{$'}" + when %r{\Aenc/} then source2 = "{$(VPATH)}#{$'}" + when %r{\Amissing/} then source2 = "{$(VPATH)}#{$'}" + when %r{\Accan/} then source2 = "$(CCAN_DIR)/#{$'}" + when %r{\Adefs/} then source2 = "{$(VPATH)}#{source}" + else source2 = "$(top_srcdir)/#{source}" + end + ["common.mk", target2, source2] + when %r{\Aenc/} + target2 = "#{target.sub(/\.o\z/, '.$(OBJEXT)')}" + case source + when *FILES_IN_SOURCE_DIRECTORY then source2 = "$(top_srcdir)/#{source}" + when *FILES_IN_BUILD_DIRECTORY then source2 = source + when *FILES_NEED_VPATH then source2 = source + when *FILES_SAME_NAME_INC then source2 = "$(hdrdir)/#{source.sub(%r{\Ainclude/},'')}" + when *FILES_SAME_NAME_TOP then source2 = "$(top_srcdir)/#{source}" + when %r{\A\.ext/include/[^/]+/ruby/} then source2 = $' + when %r{\Ainclude/ruby/} then source2 = $' + when %r{\Aenc/} then source2 = source + else source2 = "$(top_srcdir)/#{source}" + end + ["enc/depend", target2, source2] + when %r{\Aext/} + unless File.exist?("#{File.dirname(target)}/extconf.rb") + warn "warning: not found: #{File.dirname(target)}/extconf.rb" + end + target2 = File.basename(target) + relpath = Pathname(source).relative_path_from(Pathname(target).dirname).to_s + case source + when *FILES_IN_SOURCE_DIRECTORY then source2 = "$(top_srcdir)/#{source}" + when *FILES_IN_BUILD_DIRECTORY then source2 = relpath + when *FILES_NEED_VPATH then source2 = "{$(VPATH)}#{File.basename source}" + when *FILES_SAME_NAME_INC then source2 = "$(hdrdir)/#{source.sub(%r{\Ainclude/},'')}" + when *FILES_SAME_NAME_TOP then source2 = "$(top_srcdir)/#{source}" + when %r{\A\.ext/include/[^/]+/ruby/} then source2 = "$(arch_hdrdir)/ruby/#{$'}" + when %r{\Ainclude/} then source2 = "$(hdrdir)/#{$'}" + when %r{\A#{Regexp.escape File.dirname(target)}/extconf\.h\z} then source2 = "$(RUBY_EXTCONF_H)" + when %r{\A#{Regexp.escape File.dirname(target)}/} then source2 = $' + else source2 = "$(top_srcdir)/#{source}" + end + ["#{File.dirname(target)}/depend", target2, source2] + else + raise "unexpected target: #{target}" + end +end + +DEPENDENCIES_SECTION_START_MARK = "\# AUTOGENERATED DEPENDENCIES START\n" +DEPENDENCIES_SECTION_END_MARK = "\# AUTOGENERATED DEPENDENCIES END\n" + +def init_global + ENV['LC_ALL'] = 'C' + + $opt_fix = false + $opt_a = false + $opt_actual_fix = false + $i_not_found = false +end + +def optionparser + op = OptionParser.new + op.banner = 'Usage: ruby tool/update-deps' + op.def_option('-a', 'show valid dependencies') { $opt_a = true } + op.def_option('--fix') { $opt_fix = true } + op.def_option('--actual-fix') { $opt_actual_fix = true } + op +end + +def read_make_deps(cwd) + dependencies = {} + make_p, make_p_stderr, make_p_status = Open3.capture3("make -p all miniruby ruby golf") + File.open('update-deps.make.out.log', 'w') {|f| f.print make_p } + File.open('update-deps.make.err.log', 'w') {|f| f.print make_p_stderr } + if !make_p_status.success? + puts make_p_stderr + raise "make failed" + end + dirstack = [cwd] + curdir = nil + make_p.scan(%r{Entering\ directory\ ['`](.*)'| + ^\#\ (GNU\ Make)\ | + ^CURDIR\ :=\ (.*)| + ^([/0-9a-zA-Z._-]+):(.*)\n((?:\#.*\n)*)| + ^\#\ (Finished\ Make\ data\ base\ on)\ | + Leaving\ directory\ ['`](.*)'}x) { + directory_enter = $1 + data_base_start = $2 + data_base_curdir = $3 + rule_target = $4 + rule_sources = $5 + rule_desc = $6 + data_base_end = $7 + directory_leave = $8 + #p $~ + if directory_enter + enter_dir = Pathname(directory_enter) + #p [:enter, enter_dir] + dirstack.push enter_dir + elsif data_base_start + curdir = nil + elsif data_base_curdir + curdir = Pathname(data_base_curdir) + elsif rule_target && rule_sources && rule_desc && + /Modification time never checked/ !~ rule_desc # This pattern match eliminates rules which VPATH is not expanded. + target = rule_target + deps = rule_sources + deps = deps.scan(%r{[/0-9a-zA-Z._-]+}) + next if /\.o\z/ !~ target.to_s + next if /\A\./ =~ target.to_s # skip rules such as ".c.o" + #p [curdir, target, deps] + dir = curdir || dirstack.last + dependencies[dir + target] ||= [] + dependencies[dir + target] |= deps.map {|dep| dir + dep } + elsif data_base_end + curdir = nil + elsif directory_leave + leave_dir = Pathname(directory_leave) + #p [:leave, leave_dir] + if leave_dir != dirstack.last + warn "unexpected leave_dir : #{dirstack.last.inspect} != #{leave_dir.inspect}" + end + dirstack.pop + end + } + dependencies +end + +#def guess_compiler_wd(filename, hint0) +# hint = hint0 +# begin +# guess = hint + filename +# if guess.file? +# return hint +# end +# hint = hint.parent +# end while hint.to_s != '.' +# raise ArgumentError, "can not find #{filename} (hint: #{hint0})" +#end + +def read_single_cc_deps(path_i, cwd) + files = {} + path_i.each_line.with_index {|line, lineindex| + next if /\A\# \d+ "(.*)"/ !~ line + files[$1] = lineindex + } + # gcc emits {# 1 "/absolute/directory/of/the/source/file//"} at 2nd line. + compiler_wd = files.keys.find {|f| %r{\A/.*//\z} =~ f } + if compiler_wd + files.delete compiler_wd + compiler_wd = Pathname(compiler_wd.sub(%r{//\z}, '')) + else + raise "compiler working directory not found" + end + deps = [] + files.each_key {|dep| + next if %r{\A<.*>\z} =~ dep # omit <command-line>, etc. + dep = Pathname(dep) + if dep.relative? + dep = compiler_wd + dep + end + if !dep.file? + warn "warning: file not found: #{dep}" + next + end + next if !dep.to_s.start_with?(cwd.to_s) # omit system headers. + deps << dep + } + deps +end + +def read_cc_deps(cwd) + deps = {} + Pathname.glob('**/*.o').sort.each {|fn_o| + fn_i = fn_o.sub_ext('.i') + if !fn_i.exist? + warn "warning: not found: #{fn_i}" + $i_not_found = true + next + end + path_o = cwd + fn_o + path_i = cwd + fn_i + deps[path_o] = read_single_cc_deps(path_i, cwd) + } + deps +end + +def concentrate(dependencies, cwd) + deps = {} + dependencies.keys.sort.each {|target| + sources = dependencies[target] + target = target.relative_path_from(cwd) + sources = sources.map {|s| + rel = s.relative_path_from(cwd) + rel + } + if %r{\A\.\.(/|\z)} =~ target.to_s + warn "warning: out of tree target: #{target}" + next + end + sources = sources.reject {|s| + if %r{\A\.\.(/|\z)} =~ s.to_s + warn "warning: out of tree source: #{s}" + true + else + false + end + } + deps[target] = sources + } + deps +end + +def sort_paths(paths) + paths.sort_by {|t| + ary = t.to_s.split(%r{/}) + ary.map.with_index {|e, i| i == ary.length-1 ? [0, e] : [1, e] } # regular file first, directories last. + } +end + +def show_deps(tag, deps) + targets = sort_paths(deps.keys) + targets.each {|t| + sources = sort_paths(deps[t]) + sources.each {|s| + puts "#{tag} #{t}: #{s}" + } + } +end + +def detect_dependencies(out=$stdout) + cwd = Pathname.pwd + make_deps = read_make_deps(cwd) + #pp make_deps + make_deps = concentrate(make_deps, cwd) + #pp make_deps + cc_deps = read_cc_deps(cwd) + #pp cc_deps + cc_deps = concentrate(cc_deps, cwd) + #pp cc_deps + return make_deps, cc_deps +end + +def compare_deps(make_deps, cc_deps, out=$stdout) + targets = make_deps.keys | cc_deps.keys + + makefiles = {} + + make_lines_hash = {} + make_deps.each {|t, sources| + sources.each {|s| + makefile, t2, s2 = in_makefile(t, s) + makefiles[makefile] = true + make_lines_hash[makefile] ||= Hash.new(false) + make_lines_hash[makefile]["#{t2}: #{s2}"] = true + } + } + + cc_lines_hash = {} + cc_deps.each {|t, sources| + sources.each {|s| + makefile, t2, s2 = in_makefile(t, s) + makefiles[makefile] = true + cc_lines_hash[makefile] ||= Hash.new(false) + cc_lines_hash[makefile]["#{t2}: #{s2}"] = true + } + } + + makefiles.keys.sort.each {|makefile| + cc_lines = cc_lines_hash[makefile] || Hash.new(false) + make_lines = make_lines_hash[makefile] || Hash.new(false) + content = begin + File.read(makefile) + rescue Errno::ENOENT + '' + end + if /^#{Regexp.escape DEPENDENCIES_SECTION_START_MARK} + ((?:.*\n)*) + #{Regexp.escape DEPENDENCIES_SECTION_END_MARK}/x =~ content + pre_post_part = [$`, $'] + current_lines = Hash.new(false) + $1.each_line {|line| current_lines[line.chomp] = true } + (cc_lines.keys | current_lines.keys | make_lines.keys).sort.each {|line| + status = [cc_lines[line], current_lines[line], make_lines[line]] + case status + when [true, true, true] + # no problem + when [true, true, false] + out.puts "warning #{makefile} : #{line} (make doesn't detect written dependency)" + when [true, false, true] + out.puts "add_auto #{makefile} : #{line} (harmless)" # This is automatically updatable. + when [true, false, false] + out.puts "add_auto #{makefile} : #{line} (harmful)" # This is automatically updatable. + when [false, true, true] + out.puts "del_cc #{makefile} : #{line}" # Not automatically updatable because build on other OS may need the dependency. + when [false, true, false] + out.puts "del_cc #{makefile} : #{line} (Curious. make doesn't detect this dependency.)" # Not automatically updatable because build on other OS may need the dependency. + when [false, false, true] + out.puts "del_make #{makefile} : #{line}" # Not automatically updatable because the dependency is written manually. + else + raise "unexpected status: #{status.inspect}" + end + } + else + (cc_lines.keys | make_lines.keys).sort.each {|line| + status = [cc_lines[line], make_lines[line]] + case status + when [true, true] + # no problem + when [true, false] + out.puts "add_manual #{makefile} : #{line}" # Not automatically updatable because makefile has no section to update automatically. + when [false, true] + out.puts "del_manual #{makefile} : #{line}" # Not automatically updatable because makefile has no section to update automatically. + else + raise "unexpected status: #{status.inspect}" + end + } + end + } +end + +def main_show(out=$stdout) + make_deps, cc_deps = detect_dependencies(out) + compare_deps(make_deps, cc_deps, out) +end + +def extract_deplines(problems) + adds = {} + others = {} + problems.each_line {|line| + case line + when /\Aadd_auto (\S+) : ((\S+): (\S+))/ + (adds[$1] ||= []) << [line, "#{$2}\n"] + when /\A(?:del_cc|del_make|add_manual|del_manual|warning) (\S+) : / + (others[$1] ||= []) << line + else + raise "unexpected line: #{line.inspect}" + end + } + return adds, others +end + +def main_actual_fix(problems) + adds, others = extract_deplines(problems) + (adds.keys | others.keys).sort.each {|makefile| + content = begin + File.read(makefile) + rescue Errno::ENOENT + nil + end + + if content && + /^#{Regexp.escape DEPENDENCIES_SECTION_START_MARK} + ((?:.*\n)*) + #{Regexp.escape DEPENDENCIES_SECTION_END_MARK}/x =~ content + pre_dep_post = [$`, $1, $'] + else + pre_dep_post = nil + end + + if pre_dep_post && adds[makefile] + pre_lines, dep_lines, post_lines = pre_dep_post + dep_lines = dep_lines.lines.to_a + add_lines = adds[makefile].map(&:last) + new_lines = (dep_lines | add_lines).sort.uniq + new_content = [ + pre_lines, + DEPENDENCIES_SECTION_START_MARK, + *new_lines, + DEPENDENCIES_SECTION_END_MARK, + post_lines + ].join + if content != new_content + puts "modified: #{makefile}" + tmp_makefile = "#{makefile}.new.#{$$}" + File.write(tmp_makefile, new_content) + File.rename tmp_makefile, makefile + (add_lines - dep_lines).each {|line| puts " added #{line}" } + else + puts "not modified: #{makefile}" + end + if others[makefile] + others[makefile].each {|line| puts " #{line}" } + end + else + if pre_dep_post + puts "no addtional lines: #{makefile}" + elsif content + puts "no dependencies section: #{makefile}" + else + puts "no makefile: #{makefile}" + end + if adds[makefile] + puts " warning: dependencies section was exist at previous phase." + end + if adds[makefile] + adds[makefile].map(&:first).each {|line| puts " #{line}" } + end + if others[makefile] + others[makefile].each {|line| puts " #{line}" } + end + end + } +end + +def main_fix + problems = StringIO.new + main_show(problems) + main_actual_fix(problems.string) +end + +def run + op = optionparser + op.parse!(ARGV) + if $opt_actual_fix + main_actual_fix(ARGF.read) + elsif $opt_fix + main_fix + else + main_show + end +end + +init_global +run +if $i_not_found + warn "warning: missing *.i files, see help in #$0 and ensure ccache is disabled" +end diff --git a/jni/ruby/tool/vcs.rb b/jni/ruby/tool/vcs.rb new file mode 100644 index 0000000..66d2764 --- /dev/null +++ b/jni/ruby/tool/vcs.rb @@ -0,0 +1,256 @@ +# vcs + +ENV.delete('PWD') + +unless File.respond_to? :realpath + require 'pathname' + def File.realpath(arg) + Pathname(arg).realpath.to_s + end +end + +def IO.pread(*args) + STDERR.puts(*args.inspect) if $DEBUG + popen(*args) {|f|f.read} +end + +if RUBY_VERSION < "1.9" + class IO + @orig_popen = method(:popen) + + if defined?(fork) + def self.popen(command, *rest, &block) + if !(Array === command) + @orig_popen.call(command, *rest, &block) + elsif block + @orig_popen.call("-", *rest) {|f| f ? yield(f) : exec(*command)} + else + @orig_popen.call("-", *rest) or exec(*command) + end + end + else + require 'shellwords' + def self.popen(command, *rest, &block) + command = command.shelljoin if Array === command + @orig_popen.call(command, *rest, &block) + end + end + end +end + +class VCS + class NotFoundError < RuntimeError; end + + @@dirs = [] + def self.register(dir) + @@dirs << [dir, self] + end + + def self.detect(path) + @@dirs.each do |dir, klass| + return klass.new(path) if File.directory?(File.join(path, dir)) + prev = path + loop { + curr = File.realpath(File.join(prev, '..')) + break if curr == prev # stop at the root directory + return klass.new(path) if File.directory?(File.join(curr, dir)) + prev = curr + } + end + raise VCS::NotFoundError, "does not seem to be under a vcs: #{path}" + end + + def initialize(path) + @srcdir = path + super() + end + + NullDevice = defined?(IO::NULL) ? IO::NULL : + %w[/dev/null NUL NIL: NL:].find {|dev| File.exist?(dev)} + + # return a pair of strings, the last revision and the last revision in which + # +path+ was modified. + def get_revisions(path) + if String === path or path.respond_to?(:to_path) + path = relative_to(path) + end + last, changed, modified, *rest = ( + begin + if NullDevice + save_stderr = STDERR.dup + STDERR.reopen NullDevice, 'w' + end + self.class.get_revisions(path, @srcdir) + ensure + if save_stderr + STDERR.reopen save_stderr + save_stderr.close + end + end + ) + last or raise VCS::NotFoundError, "last revision not found" + changed or raise VCS::NotFoundError, "changed revision not found" + if modified + /\A(\d+)-(\d+)-(\d+)\D(\d+):(\d+):(\d+(?:\.\d+)?)\s*(?:Z|([-+]\d\d)(\d\d))\z/ =~ modified or + raise "unknown time format - #{modified}" + match = $~[1..6].map { |x| x.to_i } + off = $7 ? "#{$7}:#{$8}" : "+00:00" + match << off + begin + modified = Time.new(*match) + rescue ArgumentError + modified = Time.utc(*$~[1..6]) + $7.to_i * 3600 + $8.to_i * 60 + end + end + return last, changed, modified, *rest + end + + def relative_to(path) + if path + srcdir = File.realpath(@srcdir) + path = File.realdirpath(path) + list1 = srcdir.split(%r{/}) + list2 = path.split(%r{/}) + while !list1.empty? && !list2.empty? && list1.first == list2.first + list1.shift + list2.shift + end + if list1.empty? && list2.empty? + "." + else + ([".."] * list1.length + list2).join("/") + end + else + '.' + end + end + + class SVN < self + register(".svn") + + def self.get_revisions(path, srcdir = nil) + if srcdir and (String === path or path.respond_to?(:to_path)) + path = File.join(srcdir, path) + end + info_xml = IO.pread(%W"svn info --xml #{path}") + _, last, _, changed, _ = info_xml.split(/revision="(\d+)"/) + modified = info_xml[/<date>([^<>]*)/, 1] + [last, changed, modified] + end + + def url + unless defined?(@url) + url = IO.pread(%W"svn info --xml #{@srcdir}")[/<root>(.*)<\/root>/, 1] + @url = URI.parse(url+"/") if url + end + @url + end + + def branch(name) + url + "branches/#{name}" + end + + def tag(name) + url + "tags/#{name}" + end + + def trunk + url + "trunk" + end + + def branch_list(pat) + IO.popen(%W"svn ls #{branch('')}") do |f| + f.each do |line| + line.chomp! + line.chomp!('/') + yield(line) if File.fnmatch?(pat, line) + end + end + end + + def grep(pat, tag, *files, &block) + cmd = %W"svn cat" + files.map! {|n| File.join(tag, n)} if tag + set = block.binding.eval("proc {|match| $~ = match}") + IO.popen([cmd, *files]) do |f| + f.grep(pat) do |s| + set[$~] + yield s + end + end + end + + def export(revision, url, dir) + IO.popen(%W"svn export -r #{revision} #{url} #{dir}") do |pipe| + pipe.each {|line| /^A/ =~ line or yield line} + end + $?.success? + end + end + + class GIT < self + register(".git") + + def self.get_revisions(path, srcdir = nil) + logcmd = %W[git log -n1 --date=iso] + logcmd[1, 0] = ["-C", srcdir] if srcdir + logcmd << "--grep=^ *git-svn-id: .*@[0-9][0-9]*" + idpat = /git-svn-id: .*?@(\d+) \S+\Z/ + log = IO.pread(logcmd) + last = log[idpat, 1] + if path + log = IO.pread(logcmd + [path]) + changed = log[idpat, 1] + else + changed = last + end + modified = log[/^Date:\s+(.*)/, 1] + [last, changed, modified] + end + + def branch(name) + name + end + + alias tag branch + + def trunk + branch("trunk") + end + + def stable + cmd = %W"git for-each-ref --format=\%(refname:short) refs/heads/ruby_[0-9]*" + cmd[1, 0] = ["-C", @srcdir] if @srcdir + branch(IO.pread(cmd)[/.*^(ruby_\d+_\d+)$/m, 1]) + end + + def branch_list(pat) + cmd = %W"git for-each-ref --format=\%(refname:short) refs/heads/#{pat}" + cmd[1, 0] = ["-C", @srcdir] if @srcdir + IO.popen(cmd) {|f| + f.each {|line| + line.chomp! + yield line + } + } + end + + def grep(pat, tag, *files, &block) + cmd = %W[git grep -h --perl-regexp #{tag} --] + cmd[1, 0] = ["-C", @srcdir] if @srcdir + set = block.binding.eval("proc {|match| $~ = match}") + IO.popen([cmd, *files]) do |f| + f.grep(pat) do |s| + set[$~] + yield s + end + end + end + + def export(revision, url, dir) + ret = system("git", "clone", "-s", (@srcdir || '.'), "-b", url, dir) + FileUtils.rm_rf("#{dir}/.git") if ret + ret + end + end +end diff --git a/jni/ruby/tool/vpath.rb b/jni/ruby/tool/vpath.rb new file mode 100644 index 0000000..48ab148 --- /dev/null +++ b/jni/ruby/tool/vpath.rb @@ -0,0 +1,87 @@ +# -*- coding: us-ascii -*- + +class VPath + attr_accessor :separator + + def initialize(*list) + @list = list + @additional = [] + @separator = nil + end + + def inspect + list.inspect + end + + def search(meth, base, *rest) + begin + meth.call(base, *rest) + rescue Errno::ENOENT => error + list.each do |dir| + return meth.call(File.join(dir, base), *rest) rescue nil + end + raise error + end + end + + def process(*args, &block) + search(File.method(__callee__), *args, &block) + end + + alias stat process + alias lstat process + + def open(*args) + f = search(File.method(:open), *args) + if block_given? + begin + yield f + ensure + f.close unless f.closed? + end + else + f + end + end + + def read(*args) + open(*args) {|f| f.read} + end + + def foreach(file, *args, &block) + open(file) {|f| f.each(*args, &block)} + end + + def def_options(opt) + opt.on("-I", "--srcdir=DIR", "add a directory to search path") {|dir| + @additional << dir + } + opt.on("-L", "--vpath=PATH LIST", "add directories to search path") {|dirs| + @additional << [dirs] + } + opt.on("--path-separator=SEP", /\A(?:\W\z|\.(\W).+)/, "separator for vpath") {|sep, vsep| + # hack for msys make. + @separator = vsep || sep + } + end + + def list + @additional.reject! do |dirs| + case dirs + when String + @list << dirs + when Array + raise "--path-separator option is needed for vpath list" unless @separator + # @separator ||= (require 'rbconfig'; RbConfig::CONFIG["PATH_SEPARATOR"]) + @list.concat(dirs[0].split(@separator)) + end + true + end + @list + end + + def strip(path) + prefix = list.map {|dir| Regexp.quote(dir)} + path.sub(/\A#{prefix.join('|')}(?:\/|\z)/, '') + end +end diff --git a/jni/ruby/tool/vtlh.rb b/jni/ruby/tool/vtlh.rb new file mode 100644 index 0000000..fcd3630 --- /dev/null +++ b/jni/ruby/tool/vtlh.rb @@ -0,0 +1,15 @@ +# ARGF = open('ha') +cd = `pwd`.chomp + '/' +ARGF.each{|line| + if /^0x([a-z0-9]+),/ =~ line + stat = line.split(',') + addr = stat[0].hex + 0x00400000 + retired = stat[2].to_i + ticks = stat[3].to_i + + src = `addr2line -e miniruby.exe #{addr.to_s(16)}`.chomp + src.sub!(cd, '') + puts '%-40s 0x%08x %8d %8d' % [src, addr, retired, ticks] + end +} + diff --git a/jni/ruby/tool/ytab.sed b/jni/ruby/tool/ytab.sed new file mode 100755 index 0000000..46317db --- /dev/null +++ b/jni/ruby/tool/ytab.sed @@ -0,0 +1,37 @@ +#!/bin/sed -f +/^int yydebug;/{ +i\ +#ifndef yydebug +a\ +#endif +} +/^extern int yydebug;/{ +i\ +#ifndef yydebug +a\ +#endif +} +/^yydestruct.*yymsg/,/#endif/{ + /^yydestruct/{ + /parser/!{ + h + s/^/ruby_parser_&/ + s/)$/, parser)/ + /\*/s/parser)$/struct parser_params *&/ + } + } + /^#endif/{ + x + /^./{ + i\ + struct parser_params *parser; + a\ +#define yydestruct(m, t, v) ruby_parser_yydestruct(m, t, v, parser) + } + x + } +} +s/^\([ ]*\)\(yyerror[ ]*([ ]*parser,\)/\1parser_\2/ +s!^ *extern char \*getenv();!/* & */! +s/^\(#.*\)".*\.tab\.c"/\1"parse.c"/ +/^\(#.*\)".*\.y"/s:\\\\:/:g |