imported brians code
authoradam <adam@megacz.com>
Tue, 16 Mar 2004 02:17:57 +0000 (18:17 -0800)
committeradam <adam@megacz.com>
Tue, 16 Mar 2004 02:17:57 +0000 (18:17 -0800)
darcs-hash:20040316021757-5007d-1291b958e0af75914befcfde6fcfb47d2c6b25c3.gz

52 files changed:
Makefile [new file with mode: 0644]
doc/COPYING [new file with mode: 0644]
doc/ChangeLog [new file with mode: 0644]
src/org/xwt/mips/ClassFileCompiler.java [new file with mode: 0644]
src/org/xwt/mips/ClassLoader.java [new file with mode: 0644]
src/org/xwt/mips/Compiler.java [new file with mode: 0644]
src/org/xwt/mips/ELF.java [new file with mode: 0644]
src/org/xwt/mips/Interpreter.java [new file with mode: 0644]
src/org/xwt/mips/JavaSourceCompiler.java [new file with mode: 0644]
src/org/xwt/mips/Registers.java [new file with mode: 0644]
src/org/xwt/mips/Runtime.java [new file with mode: 0644]
src/org/xwt/mips/UnixRuntime.java [new file with mode: 0644]
src/org/xwt/mips/crt0.c [new file with mode: 0644]
src/org/xwt/mips/linker.ld [new file with mode: 0644]
src/org/xwt/mips/support.s [new file with mode: 0644]
src/org/xwt/mips/support_aux.c [new file with mode: 0644]
src/org/xwt/mips/syscalls.h [new file with mode: 0644]
src/org/xwt/mips/util/SeekableByteArray.java [new file with mode: 0644]
src/org/xwt/mips/util/SeekableData.java [new file with mode: 0644]
src/org/xwt/mips/util/SeekableFile.java [new file with mode: 0644]
src/org/xwt/mips/util/SeekableInputStream.java [new file with mode: 0644]
src/tests/CXXTest.cc [new file with mode: 0644]
src/tests/CallTest.java [new file with mode: 0644]
src/tests/Echo.java [new file with mode: 0644]
src/tests/EchoHelper.c [new file with mode: 0644]
src/tests/Env.java [new file with mode: 0644]
src/tests/FDTest.java [new file with mode: 0644]
src/tests/FTBench.c [new file with mode: 0644]
src/tests/Fork.c [new file with mode: 0644]
src/tests/FreeTypeDemo.java [new file with mode: 0644]
src/tests/FreeTypeDemoHelper.c [new file with mode: 0644]
src/tests/Hello.c [new file with mode: 0644]
src/tests/MSPack.java [new file with mode: 0644]
src/tests/MSPackBench.c [new file with mode: 0644]
src/tests/MSPackHelper.c [new file with mode: 0644]
src/tests/Paranoia.c [new file with mode: 0644]
src/tests/Simple.c [new file with mode: 0644]
src/tests/SpeedTest.java [new file with mode: 0644]
src/tests/Test.c [new file with mode: 0644]
src/tests/check.sh [new file with mode: 0755]
upstream/Makefile [new file with mode: 0644]
upstream/patches/binutils-no64.patch [new file with mode: 0644]
upstream/patches/boehm-gc.patch [new file with mode: 0644]
upstream/patches/busybox.patch [new file with mode: 0644]
upstream/patches/freetype.patch [new file with mode: 0644]
upstream/patches/ft-nostdio.patch [new file with mode: 0644]
upstream/patches/gcc-fdata-sections-bss.patch [new file with mode: 0644]
upstream/patches/gcc-fixes.patch [new file with mode: 0644]
upstream/patches/libmspack.patch [new file with mode: 0644]
upstream/patches/newlib-malloc.patch [new file with mode: 0644]
upstream/patches/newlib-mips.patch [new file with mode: 0644]
upstream/patches/newlib-tzset.patch [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..3ea8fac
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,357 @@
+# 
+# What to build
+#
+
+doc/nestedvm.ivme04.pdf: doc/nestedvm.ivme04.tex doc/acmconf.cls
+       cd doc; pdflatex nestedvm.ivme04.tex
+
+pdf: doc/nestedvm.ivme04.pdf
+       open doc/nestedvm.ivme04.pdf
+
+# Java sources that are part of the compiler/interpreter
+java_sources = $(wildcard src/org/xwt/mips/*.java) $(wildcard src/org/xwt/mips/util/*.java)
+
+# Java sources that are part of the compiler/interpreter that are
+# generated from other sources
+java_gen_sources = $(patsubst %,build/org/xwt/mips/%.java, UsermodeConstants)
+
+# C sources that are part of the compiler/interpreter
+mips_sources = crt0.c support_aux.c
+mips_asm_sources = support.s
+
+mips2java_root = $(shell pwd)
+build = $(mips2java_root)/build
+tasks = upstream/tasks
+
+#
+# MIPS Settings (don't change these)
+#
+flags = -march=mips1
+MIPS_CC = mips-unknown-elf-gcc
+MIPS_CXX = mips-unknown-elf-g++
+
+# Be VERY careful about changing any of these as they can break binary 
+# compatibility and create hard to find bugs
+mips_optflags = -O3 -g \
+       -fno-rename-registers -freduce-all-givs \
+       -fno-peephole -fno-peephole2 -fmove-all-movables -fno-schedule-insns \
+       -fno-delayed-branch \
+       -mmemcpy \
+       -ffunction-sections -fdata-sections \
+       -falign-functions=512
+
+MIPS_CFLAGS = $(mips_optflags) $(flags) -I. -Wall -Wno-unused -Werror
+MIPS_LD = mips-unknown-elf-gcc
+MIPS_LDFLAGS= \
+       $(flags) -L$(build)/org/xwt/mips --static \
+       -T $(mips2java_root)/src/org/xwt/mips/linker.ld -Wl,--gc-sections
+MIPS_STRIP = mips-unknown-elf-strip
+
+# Java compiler/VM settings
+JAVAC = javac
+JAVA = java
+ifeq ($(firstword $(JAVAC)),gcj)
+       JAVAC_NODEBUG_FLAGS = -g0
+else
+       JAVAC_NODEBUG_FLAGS = -g:none
+endif
+
+CLASSPATH = build:upstream/build/bcel/bcel-5.1.jar
+
+GCJ = gcj
+EXE_EXT = 
+
+#####
+
+java_classes = \
+       $(java_sources:src/%.java=build/%.class) \
+       $(java_gen_sources:%.java=%.class)
+
+mips_objects = $(mips_sources:%.c=build/org/xwt/mips/%.o) $(mips_asm_sources:%.s=build/org/xwt/mips/%.o)
+
+.SECONDARY:
+
+PATH := $(mips2java_root)/upstream/install/bin:$(PATH)
+export PATH
+
+#
+# General Build Stuff
+#
+all: $(java_classes) $(mips_objects)
+ifdef NATIVE_MIPS2JAVA_COMPILER
+all: build/mips2java$(EXE_EXT) $(mips_objects)
+endif
+
+$(tasks)/%:
+       $(MAKE) -C upstream tasks/$* MIPS_LDFLAGS="$(MIPS_LDFLAGS)" MIPS_CFLAGS="$(flags) $(mips_optflags)"
+
+upstream_clean_%:
+       $(MAKE) -C upstream clean_$*
+
+errno_h = upstream/install/mips-unknown-elf/include/sys/errno.h
+$(errno_h): $(tasks)/build_newlib
+
+unistd_h = upstream/install/mips-unknown-elf/include/sys/unistd.h
+$(unistd_h): $(tasks)/build_newlib
+
+#
+# Interpreter/Compiler/Runtime Java Compilation
+#
+
+# This works around a gcj -C bug
+ifeq ($(firstword $(JAVAC)),gcj)
+build/org/xwt/mips/util/.Dummy.class:
+       mkdir -p `dirname $@`
+       touch $@
+$(java_classes): build/org/xwt/mips/util/.Dummy.class
+endif
+
+$(java_classes): $(tasks)/unpack_bcel $(java_sources) $(java_gen_sources)
+       $(JAVAC) -classpath $(CLASSPATH) -d build $(java_sources) $(java_gen_sources)
+
+build/org/xwt/mips/UsermodeConstants.java: src/org/xwt/mips/syscalls.h $(errno_h) $(unistd_h)
+       @mkdir -p `dirname $@`
+       cat $^ |\
+               (FILE=org.xwt.mips.UsermodeConstants;\
+                C="`echo $$FILE | sed 's/.*\.\([^\.]*\)$$/\1/;'`";\
+                P="`echo $$FILE | sed -n 's/\(.*\)\..*/\1/p;'`";\
+                [ -n "$$P" ] && echo "package $$P;";\
+                echo "public interface $$C {";\
+                tr '\t' ' ' | sed -n ';\
+                s/  */ /g;\
+                s/ *\# *define \([A-Z_][A-Za-z0-9_]*\) \([0-9][0-9x]*\)/    public static final int \1 = \2;/p';\
+                echo "}") > $@
+
+# FIXME: We're cramming more than we need into the binary here
+build/mips2java$(EXE_EXT): $(java_sources) $(java_gen_sources)
+       @mkdir -p `dirname $@`
+       $(GCJ) -s -o $@ --main=org.xwt.mips.Compiler $(java_sources) $(java_gen_sources)
+
+#
+# MIPS Binary compilation
+#
+build/%.o: src/%.c $(tasks)/full_toolchain
+       @mkdir -p `dirname $@`
+       $(MIPS_CC) $(MIPS_CFLAGS) $($(notdir $*)_CFLAGS) -c -o $@ $<
+
+build/%.o: src/%.s $(tasks)/full_toolchain
+       @mkdir -p `dirname $@`
+       $(MIPS_CC) -x assembler-with-cpp -c -o $@ $<
+
+%.s: %.c $(tasks)/full_toolchain
+       $(MIPS_CC) $(MIPS_CFLAGS) $($(notdir $*)_CFLAGS) -c -S -o $@ $<
+
+build/%.mips: build/%.o $(mips_objects)
+       $(MIPS_LD) -o $@ $< $(MIPS_LDFLAGS) $($(notdir $*)_LDFLAGS)
+
+build/%.mips: src/%.cc $(tasks)/full_toolchain $(mips_objects)
+       @mkdir -p `dirname $@`
+       $(MIPS_CXX) $(MIPS_CFLAGS) $($(notdir $*)_CFLAGS) $(MIPS_LDFLAGS) $($(notdir $*)_LDFLAGS) -o $@ $<
+
+build/%.mips.stripped: build/%.mips
+       cp $< $@
+       $(MIPS_STRIP) -s $@
+
+# MIPS Compiler generated class compilation
+ifdef DO_JAVASOURCE
+
+build/%.java: build/%.mips build/org/xwt/mips/JavaSourceCompiler.class $(tasks)/unpack_bcel 
+       $(JAVA) -cp $(CLASSPATH) org.xwt.mips.Compiler -outformat javasource $(compiler_flags) $($(notdir $*)_COMPILERFLAGS) $(subst /,.,$*) $< > build/$*.java
+
+build/%.class: build/%.java build/org/xwt/mips/Runtime.class
+       $(JAVAC) $(JAVAC_NODEBUG_FLAGS) -classpath build -d build $<
+else
+
+build/%.class: build/%.mips build/org/xwt/mips/ClassFileCompiler.class $(tasks)/unpack_bcel 
+       $(JAVA) -cp $(CLASSPATH) org.xwt.mips.Compiler -outformat class -outfile $@ $(compiler_flags) $($(notdir $*)_COMPILERFLAGS) $(subst /,.,$*) $<
+
+
+endif
+
+# General Java Class compilation
+build/%.class: src/%.java
+       $(JAVAC) -classpath build -d build $<
+
+clean:
+       rm -rf build/tests build/org/xwt/mips *.jar build/mips2java$(EXE_EXT)
+
+#
+# env.sh
+#
+env.sh: Makefile $(tasks)/full_toolchain build/org/xwt/mips/Compiler.class $(tasks)/unpack_bcel 
+       @rm -f "$@~"
+       @echo 'PATH="$(mips2java_root)/build:$(mips2java_root)/upstream/install/bin:$$PATH"; export PATH' >> $@~
+       @echo 'CC=mips-unknown-elf-gcc; export CC' >> $@~
+       @echo 'CXX=mips-unknown-elf-g++; export CXX' >> $@~
+       @echo 'AS=mips-unknown-elf-as; export AS' >> $@~
+       @echo 'LD=mips-unknown-elf-ar; export LD' >> $@~
+       @echo 'RANLIB=mips-unknown-elf-ranlib; export RANLIB' >> $@~
+       @echo 'CFLAGS="$(mips_optflags)"; export CFLAGS' >> $@~
+       @echo 'CXXFLAGS="$(mips_optflags)"; export CXXFLAGS' >> $@~
+       @echo 'LDFLAGS="$(MIPS_LDFLAGS)"; export LDFLAGS' >> $@~
+       @echo 'CLASSPATH=$(mips2java_root)/build:$(mips2java_root)/upstream/build/bcel/bcel-5.1.jar:.; export CLASSPATH' >> $@~
+       @mv "$@~" "$@"
+       @echo "$@ created successfully"
+
+#
+# Runtime.jar
+#
+
+runtime_util_classes = SeekableData SeekableByteArray SeekableFile SeekableInputStream
+runtime_classes = Runtime Registers UsermodeConstants  $(runtime_util_classes:%=util/%)
+unixruntime_classes = $(runtime_classes) UnixRuntime
+
+runtime.jar: $(runtime_classes:%=build/org/xwt/mips/%.class)
+       cd build && jar cf ../$@ $(runtime_classes:%=org/xwt/mips/%*.class)
+
+unixruntime.jar: $(unixruntime_classes:%=build/org/xwt/mips/%.class)
+       cd build && jar cf ../$@ $(unixruntime_classes:%=org/xwt/mips/%*.class)
+
+
+
+#
+# Tests
+# These are simply here for convenience. They aren't required 
+# to build or run mips2java
+#
+
+build/tests/Env.class: build/org/xwt/mips/Runtime.class build/org/xwt/mips/Interpreter.class
+
+# Generic Hello Worldish test
+test: build/tests/Test.class
+       $(JAVA) -cp build tests.Test "arg 1" "arg 2" "arg 3"
+inttest: build/tests/Test.mips build/org/xwt/mips/Interpreter.class
+       $(JAVA) -cp build org.xwt.mips.Interpreter build/tests/Test.mips "arg 1" "arg 2" "arg 3"
+cxxtest: build/tests/CXXTest.class
+       $(JAVA) -cp build tests.CXXTest
+
+# CallTest
+build/tests/CallTest.class: build/tests/Test.class
+calltest: build/tests/CallTest.class
+       $(JAVA) -cp build tests.CallTest `date|perl -pe 's/\D+/ /g;'` `id -u`
+
+# FDTest
+build/tests/FDTest.class: build/tests/Test.class
+fdtest: build/tests/FDTest.class
+       $(JAVA) -cp build tests.FDTest
+
+
+# Simple
+Simple_LDFLAGS = -nostdlib
+simpletest: build/tests/Simple.class
+       $(JAVA) -cp build tests.Simple
+
+# Paranoia
+Paranoia_CFLAGS = "-Wno-error"
+Paranoia_LDFLAGS = -lm
+paranoiatest: build/tests/Paranoia.class
+       $(JAVA) -cp build tests.Paranoia
+
+#
+# Freetype Stuff
+#
+FreeType_CFLAGS = -Iupstream/build/freetype/include
+FreeType_LDFLAGS =  -Lupstream/build/freetype/objs -lfreetype
+
+FreeTypeDemoHelper_CFLAGS = $(FreeType_CFLAGS)
+FreeTypeDemoHelper_LDFLAGS = $(FreeType_LDFLAGS)
+build/tests/FreeTypeDemoHelper.o: $(mips_objects) $(tasks)/build_freetype
+build/tests/FreeTypeDemoHelper.mips: 
+build/tests/FreeTypeDemo.class: build/tests/FreeTypeDemoHelper.class
+
+FTBench_CFLAGS =  $(FreeType_CFLAGS)
+FTBench_LDFLAGS = $(FreeType_LDFLAGS)
+build/tests/FTBench.o: $(tasks)/build_freetype
+
+#
+# MSPack Stuff
+#
+MSPackHelper_CFLAGS = -Iupstream/build/libmspack/mspack
+MSPackHelper_LDFLAGS = -Lupstream/build/libmspack/mspack -lmspack
+build/tests/MSPackHelper.o: $(mips_objects) $(tasks)/build_libmspack
+build/tests/MSPack.class: build/tests/MSPackHelper.class
+
+MSPackBench_CFLAGS = -Iupstream/build/libmspack/mspack
+MSPackBench_LDFLAGS = -Lupstream/build/libmspack/mspack -lmspack
+build/tests/MSPackBench.o: $(tasks)/build_libmspack
+
+#
+# Echo
+#
+build/tests/Echo.class: build/tests/EchoHelper.class
+
+#
+# Libjpeg
+#
+DJpeg_COMPILERFLAGS = -o onepage,pagesize=8m
+build/tests/DJpeg.mips: $(mips_objects) $(tasks)/build_libjpeg
+       @mkdir -p `dirname $@`
+       cp upstream/build/libjpeg/djpeg $@
+
+#
+# Busybox
+#
+BusyBox_COMPILERFLAGS = -o unixruntime
+build/tests/BusyBox.mips: $(mips_object) $(tasks)/build_busybox
+       @mkdir -p `dirname $@`
+       cp upstream/build/busybox/busybox $@
+
+busyboxtest: build/tests/BusyBox.class
+       $(JAVA) -cp build tests.BusyBox ash
+
+#
+# Boehm GC
+#
+build/tests/GCTest.mips: $(mips_objects) $(tasks)/build_boehmgc
+       @mkdir -p `dirname $@`
+       cp upstream/build/boehmgc/gctest $@
+
+boehmgctest: build/tests/Env.class build/tests/GCTest.class
+       $(JAVA) -cp build tests.Env GC_PRINT_STATS=1  tests.GCTest
+
+
+#
+# Speed tests
+#
+
+build/tests/SpeedTest.class: build/org/xwt/mips/Runtime.class
+
+tmp/thebride_1280.jpg:
+       @mkdir -p tmp
+       cd tmp && wget http://www.kill-bill.com/images/wallpaper/thebride_1280.jpg
+
+oldspeedtest: build/tests/DJpeg.class tmp/thebride_1280.jpg
+       bash -c "time $(JAVA) -cp build tests.DJpeg -targa -outfile tmp/thebride_1280.tga tmp/thebride_1280.jpg"
+       @echo "e90f6b915aee2fc0d2eb9fc60ace6203  tmp/thebride_1280.tga" | md5sum -c && echo "MD5 is OK"
+
+speedtest: build/tests/SpeedTest.class build/tests/DJpeg.class build/tests/FTBench.class tmp/thebride_1280.jpg build/tests/MSPackBench.class
+       @echo "Running DJpeg test..."
+       @$(JAVA) -cp build tests.SpeedTest tests.DJpeg 10 -targa -outfile tmp/thebride_1280.tga tmp/thebride_1280.jpg
+       @if [ -e tmp/mspack/Comic.TTF ]; then \
+               echo "Running FTBench test..."; \
+               $(JAVA) -cp build tests.SpeedTest tests.FTBench 10 tmp/mspack/Comic.TTF tmp/mspack/Comic.TTF.render; \
+       else \
+               echo "Run \"make check\" to get Arial.TTF for the FTBench test"; \
+       fi
+       @if [ -e tmp/mspack/comic32.exe ]; then \
+               echo "Running MSPackBench test..."; \
+               cd tmp/mspack && $(JAVA) -cp ../../build tests.SpeedTest tests.MSPackBench 10 *32.exe; \
+       else \
+               echo "Run \"make check\" to get the MS True Type fonts for the MSPackBench test"; \
+       fi
+
+intspeed: build/tests/DJpeg.mips  build/org/xwt/mips/Interpreter.class tmp/thebride_1280.jpg
+       time $(JAVA) -cp build org.xwt.mips.Interpreter build/tests/DJpeg.mips -targa  -outfile tmp/thebride_1280.tga tmp/thebride_1280.jpg
+       @echo "e90f6b915aee2fc0d2eb9fc60ace6203  tmp/thebride_1280.tga" | md5sum -c && echo "MD5 is OK"
+
+#
+# Verification checks
+#
+
+check: $(patsubst %,build/tests/%.class, FTBench MSPackBench DJpeg GCTest) tmp/thebride_1280.jpg
+       @/bin/bash ./src/tests/check.sh running_from_make
+
+compiletests: $(patsubst %,build/tests/%.class,FTBench MSPackBench DJpeg Test FreeTypeDemoHelper MSPackHelper EchoHelper BusyBox GCTest Fork)
+       @true
+
diff --git a/doc/COPYING b/doc/COPYING
new file mode 100644 (file)
index 0000000..5b6e7c6
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/doc/ChangeLog b/doc/ChangeLog
new file mode 100644 (file)
index 0000000..e3eaaaf
--- /dev/null
@@ -0,0 +1,59 @@
+January 11, 2003
+    * [brian] Added Unistd.h as an interface so we can use its constants in
+              Runtime
+    * [brian] -o lessconstants option to compiler to emit all constants as
+              an addition of a field value and a small constant. This
+              prevents the classfile constant pool from overflowing on large
+              applications. This has a small performance impact. 
+    * [brian] Added stubs for the rmdir syscall and a minimal implementation
+              of sysconf
+    * [brian] Emit data segments as a series of <32k strings to avoid
+              hitting classfile limits
+January 10, 2003
+    * [brian] The compiler now outputs data segments as Strings rather than
+              huge int arrays.
+    * [brian] Cleaned up Makefile and upstream/Makefile to separate the 
+              required mips2java stuff from the tests. Ideally the tests
+              should be completelly separate from the main makefile but
+              keeping them integrated allows for better dependency checking
+              and faster builds.
+January 8, 2003
+    * Much thanks goes to Mohan Embar for discovering and fixing most
+      of the issues below.
+    * [brian] Updated Makefile to allow bulding with gcj
+              (make JAVAC="gcj -C" JAVA="gij")
+    * [brian] Updated Runtime.java to silently ignore SecurityExceptions
+              thrown from System.getProperty()
+    * [brian] Compiler now uses a PrintWriter for output rather than
+              PrintStream and properly closes the file on exit
+    * [brian] Made the htojava script a bourne shell script rather than a
+              perl script to remove the dependency on perl.
+December 29, 2003
+    * [brian] Changed build process to use -ffunction-sections, 
+              -fdata-sections, and --gc-sections
+    * [brian] Update support.s to use function sections
+    * [brian] Make the interpreter report the pc/sourceline of 
+              exceptions.
+    * [brian] Remove stdio calls from FreeTypeHelper
+    * [brian] Added gcc patch to fix -fdata-sections bug
+    * [brian] Added freetype patch to avoid stdio
+December 2, 2003
+    * [brian] Cleaned up a bunch of //FEATUREs and //FIXMEs. No major
+              changes, just cleanup.
+November 30, 2003
+    * [brian] Added crude support for O_APPEND and O_TRUNC
+
+November 29, 2003
+    * [brian] Moved all sources under org/xwt/mips - modified Makefiles
+              accordingly.
+    * [brian] Added org.xwt.mips.util tree containing SeekableData, 
+              SeekableByteArray, SeekableFile, and SeekableInputStream. 
+    * [brian] Made ELF.java use SeekableData rather than RandomAccessFile
+    * [brian] Made Runtime.java use org.xwt.mips.util.Seekable* for most
+              file operations.
+    * [brian] Added construtors to Interpreter.java that accept an InputStream
+              or SeekableData.
+    * [brian] Added support for the /dev/fd/n namespace and /dev/{null,zero}
+    * [brian] Added test/FDTest.java example and updated tests/Test.c
+    * [brian] Fixed absolute pathame bug on Win32
+    
\ No newline at end of file
diff --git a/src/org/xwt/mips/ClassFileCompiler.java b/src/org/xwt/mips/ClassFileCompiler.java
new file mode 100644 (file)
index 0000000..6619777
--- /dev/null
@@ -0,0 +1,2160 @@
+package org.xwt.mips;
+
+import java.io.*;
+import org.xwt.mips.util.*;
+
+import org.apache.bcel.generic.*;
+
+// FEATURE: Use BCEL to do peephole optimization
+// FEATURE: Special mode to support single-precision only - regs are floats not ints
+
+/* FEATURE: Span large binaries across several classfiles
+ * We should be able to do this with no performance penalty
+ * Every method in the inner classes is static and takes the main class as an arg
+ * This makes them look just like methods in the main class because arg1 gets loaded into
+ * local register 0
+ */
+
+/* FEATURE: smarter with local regs
+ * Be even smarter with the use of local registers. We need to only load fields into
+ * local regs when they are actually used and only write to fields if the regs could have
+ * changed. This should allow us to put more regs in local vars. Right now putting all used 
+ * regs local vars makes code like this slower.
+ * 
+ * void work(int a, int b) {
+ *    if(a == b) {
+ *       fast path
+ *       return;
+ *    }
+ *    real work
+ * }
+ * Because all the regs used in "real work" are loaded/restored even for fast path
+ */
+
+
+public class ClassFileCompiler extends Compiler implements org.apache.bcel.Constants  {    
+    /** The stream to write the compiled output to */
+    private OutputStream os;
+    private PrintStream warn = System.err;
+    
+    private ClassGen cl;
+    private ConstantPoolGen cp;
+    private InstructionList clinitExtras = new InstructionList();
+    private InstructionList initExtras = new InstructionList();
+    private InstructionFactory fac; 
+    
+    // Handy wrappers around the BCEL functions
+    private InstructionList insnList;
+    private void selectMethod(MethodGen m) { insnList = m.getInstructionList();    }
+    private void selectList(InstructionList l) { insnList = l; }
+    private InstructionHandle a(Instruction i) { return insnList.append(i); }
+    private BranchHandle a(BranchInstruction i) { return insnList.append(i); }
+    private InstructionHandle a(InstructionList l) { return insnList.append(l); }
+    private InstructionHandle a(CompoundInstruction c) { return insnList.append(c); }
+    
+    // This works around a bug in InstructionList
+    // FEATURE: fix this in bcel, send them a patch, etc
+    private static class FixedInstructionList extends InstructionList {
+        public void move(InstructionHandle start, InstructionHandle end, InstructionHandle target) {
+            InstructionHandle extra = target != null && target == getEnd() ? append(InstructionConstants.NOP) : null;
+            super.move(start,end,target);
+            if(extra != null) try { delete(extra); } catch (TargetLostException e) { /* won't happen */ }
+        }
+    }
+    
+    private MethodGen newMethod(int flags, Type ret, Type[] args, String name) {
+        return new MethodGen(flags,ret,args,null,name,fullClassName,new FixedInstructionList(),cp);
+    }
+    
+    public ClassFileCompiler(String path, String className, OutputStream os) throws IOException { this(new SeekableFile(path),className,os); }
+    public ClassFileCompiler(SeekableData binary, String className, OutputStream os) throws IOException {
+        super(binary,className);
+        this.os = os;
+    }
+    
+    public void setWarnWriter(PrintStream warn) { this.warn = warn; }
+        
+    protected void _go() throws Exn, IOException {
+        if(lessConstants) throw new Exn("ClassFileCompiler doesn't support -o lessconstants");
+        if(!pruneCases) throw new Exn("-o prunecases MUST be enabled for ClassFileCompiler");
+
+        // Class
+        cl = new ClassGen(fullClassName,runtimeClass,source,ACC_SUPER|ACC_PUBLIC,null);
+        cp = cl.getConstantPool();
+        fac = new InstructionFactory(cl,cp);
+        
+        // Fields
+        cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"pc",cp).getField());
+        for(int i=1;i<32;i++)
+            cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"r"+i,cp).getField());
+        for(int i=0;i<32;i++)
+            cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"f"+i,cp).getField());
+
+        cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"hi",cp).getField());
+        cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"lo",cp).getField());
+        cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"fcsr",cp).getField());
+        
+        if(onePage) {
+            cl.addField(new FieldGen(ACC_PRIVATE|ACC_FINAL,new ArrayType(Type.INT,1),"page",cp).getField());
+
+            selectList(initExtras);
+            a(InstructionConstants.ALOAD_0);
+            a(InstructionConstants.DUP);
+            a(fac.createFieldAccess(fullClassName,"readPages",new ArrayType(Type.INT, 2), GETFIELD));
+            pushConst(0);
+            a(InstructionConstants.AALOAD);
+            a(fac.createFieldAccess(fullClassName,"page",new ArrayType(Type.INT,1), PUTFIELD));
+        }
+        
+        if(supportCall)
+            cl.addField(new FieldGen(ACC_PRIVATE|ACC_STATIC|ACC_FINAL,Type.getType("L"+hashClass.replace('.','/')+";"),"symbols",cp).getField()); 
+        
+        int highestAddr = 0;
+        
+        for(int i=0;i<elf.sheaders.length;i++) {
+            ELF.SHeader sheader = elf.sheaders[i];
+            String name = sheader.name;
+            // if this section doesn't get loaded into our address space don't worry about it
+            if(sheader.addr == 0x0) continue;
+            
+            highestAddr = Math.max(highestAddr, sheader.addr + sheader.size);
+            
+            if(name.equals(".text"))
+                emitText(sheader.addr, new DataInputStream(sheader.getInputStream()),sheader.size);
+            else if(name.equals(".data") || name.equals(".sdata") || name.equals(".rodata") || name.equals(".ctors") || name.equals(".dtors"))
+                emitData(sheader.addr, new DataInputStream(sheader.getInputStream()), sheader.size,name.equals(".rodata")); 
+            else if(name.equals(".bss") || name.equals(".sbss"))                
+                emitBSS(sheader.addr,sheader.size);
+            else
+                throw new Exn("Unknown segment: " + name);
+        }
+        
+        ELF.SHeader text = elf.sectionWithName(".text");
+        
+        // Trampoline
+        MethodGen tramp = newMethod(ACC_PRIVATE,Type.VOID, Type.NO_ARGS, "trampoline");
+        tramp.addException("org.xwt.mips.Runtime$ExecutionException");
+        selectMethod(tramp);
+        
+        InstructionHandle start = a(InstructionConstants.ALOAD_0);
+        a(fac.createFieldAccess(fullClassName,"state",Type.INT, GETFIELD));
+        pushConst(Runtime.RUNNING);
+        BranchInstruction stateCheck =  InstructionFactory.createBranchInstruction(IF_ICMPNE,null);
+        a(stateCheck);
+        a(InstructionConstants.ALOAD_0);
+        a(InstructionConstants.ALOAD_0);
+        a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD));
+        pushConst(methodShift);
+        a(InstructionConstants.IUSHR);
+        
+        int beg = text.addr >>> methodShift;
+        int end = ((text.addr + text.size) >>> methodShift) + 1;
+
+        // This data is redundant but BCEL wants it
+        int[] matches = new int[end-beg];
+        for(int i=beg;i<end;i++)  matches[i-beg] = i;
+        TABLESWITCH ts = new TABLESWITCH(matches,new InstructionHandle[matches.length],null);
+        a(ts);
+        for(int n=beg;n<end;n++){
+            InstructionHandle h = a(fac.createInvoke(fullClassName,"run_"+toHex(n<<methodShift),Type.VOID,Type.NO_ARGS,INVOKESPECIAL));
+            a(InstructionFactory.createBranchInstruction(GOTO,start));
+            ts.setTarget(n-beg,h);
+        }
+        
+        ts.setTarget(a(InstructionConstants.POP)); // default case
+        a(fac.createNew("org.xwt.mips.Runtime$ExecutionException"));
+        a(InstructionConstants.DUP);
+        a(fac.createNew("java.lang.StringBuffer"));
+        a(InstructionConstants.DUP);
+        a(new PUSH(cp,"Jumped to invalid address in trampoline (r2: "));
+        a(fac.createInvoke("java.lang.StringBuffer","<init>",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL));
+        a(InstructionConstants.ALOAD_0);
+        a(fac.createFieldAccess(fullClassName,"r2",Type.INT, GETFIELD));
+        a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.INT},INVOKEVIRTUAL));
+        a(new PUSH(cp," pc:"));
+        a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.STRING},INVOKEVIRTUAL));
+        a(InstructionConstants.ALOAD_0);
+        a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD));
+        a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.INT},INVOKEVIRTUAL));
+        a(new PUSH(cp,')'));
+        a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.CHAR},INVOKEVIRTUAL));
+        a(fac.createInvoke("java.lang.StringBuffer","toString",Type.STRING,Type.NO_ARGS,INVOKEVIRTUAL));
+        a(fac.createInvoke("org.xwt.mips.Runtime$ExecutionException","<init>",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL));
+        a(InstructionConstants.ATHROW);
+        
+        stateCheck.setTarget(a(InstructionConstants.RETURN));
+        
+        tramp.setMaxStack();
+        tramp.setMaxLocals();
+        try {
+            cl.addMethod(tramp.getMethod());
+        } catch(ClassGenException e) {
+            e.printStackTrace(warn);
+            throw new Exn("Generation of the trampoline method failed. Try increasing maxInsnPerMethod");
+        }
+        
+        MethodGen init = newMethod(ACC_PUBLIC,Type.VOID, Type.NO_ARGS, "<init>");
+        selectMethod(init);
+        // Constructor
+        a(InstructionConstants.ALOAD_0);
+        pushConst(pageSize);
+        pushConst(totalPages);
+        pushConst(fastMem ? 0 : 1);
+        a(fac.createInvoke(runtimeClass,"<init>",Type.VOID,new Type[]{Type.INT,Type.INT,Type.BOOLEAN},INVOKESPECIAL));
+        a(InstructionConstants.ALOAD_0);
+        pushConst(gp.addr);
+        a(fac.createFieldAccess(fullClassName,"gp",Type.INT, PUTFIELD));
+        
+        a(InstructionConstants.ALOAD_0);
+        pushConst(elf.header.entry);
+        a(fac.createFieldAccess(fullClassName,"entryPoint",Type.INT, PUTFIELD));
+        
+        a(InstructionConstants.ALOAD_0);
+        pushConst(onePage ? ((highestAddr+4095)&~4095) : ((highestAddr+pageSize-1)&~(pageSize-1)));
+        a(fac.createFieldAccess(fullClassName,"brkAddr",Type.INT, PUTFIELD));
+        
+        if(userInfo != null) {
+            a(InstructionConstants.ALOAD_0);
+            pushConst(userInfo.addr);
+            a(fac.createFieldAccess(fullClassName,"userInfoBase",Type.INT, PUTFIELD));
+            a(InstructionConstants.ALOAD_0);
+            pushConst(userInfo.size);
+            a(fac.createFieldAccess(fullClassName,"userInfoSize",Type.INT, PUTFIELD));
+        }
+        a(initExtras);
+        a(InstructionConstants.ALOAD_0);
+        pushConst(Runtime.INITIALIZED);
+        a(fac.createFieldAccess(fullClassName,"state",Type.INT, PUTFIELD));
+        a(InstructionConstants.RETURN);
+        init.setMaxLocals();
+        init.setMaxStack();
+        cl.addMethod(init.getMethod());
+        
+        MethodGen clinit = newMethod(ACC_PRIVATE|ACC_STATIC,Type.VOID, Type.NO_ARGS, "<clinit>");
+        selectMethod(clinit);
+        a(clinitExtras);
+        
+        if(supportCall) {
+            a(fac.createNew(hashClass));
+            a(InstructionConstants.DUP);
+            a(InstructionConstants.DUP);
+            a(fac.createInvoke(hashClass,"<init>",Type.VOID,Type.NO_ARGS,INVOKESPECIAL));
+            a(fac.createFieldAccess(fullClassName,"symbols",Type.getType("L"+hashClass.replace('.','/')+";"), PUTSTATIC));
+            ELF.Symbol[] symbols = elf.getSymtab().symbols;
+            for(int i=0;i<symbols.length;i++) {
+                ELF.Symbol s = symbols[i];
+                if(s.type == ELF.Symbol.STT_FUNC && s.binding == ELF.Symbol.STB_GLOBAL && (s.name.equals("_call_helper") || !s.name.startsWith("_"))) {
+                    a(InstructionConstants.DUP);
+                    a(new PUSH(cp,s.name));
+                    a(fac.createNew("java.lang.Integer"));
+                    a(InstructionConstants.DUP);
+                    a(new PUSH(cp,s.addr));
+                    a(fac.createInvoke("java.lang.Integer","<init>",Type.VOID,new Type[]{Type.INT},INVOKESPECIAL));
+                    a(fac.createInvoke(hashClass,"put",Type.OBJECT,new Type[]{Type.OBJECT,Type.OBJECT},INVOKEVIRTUAL));
+                    a(InstructionConstants.POP);
+                }
+            }
+            a(InstructionConstants.POP);
+        }
+        
+        a(InstructionConstants.RETURN);
+        clinit.setMaxLocals();
+        clinit.setMaxStack();
+        cl.addMethod(clinit.getMethod());
+        
+        if(supportCall) {
+            MethodGen lookupSymbol = newMethod(ACC_PROTECTED,Type.INT,new Type[]{Type.STRING},"lookupSymbol");
+            selectMethod(lookupSymbol);
+            a(fac.createFieldAccess(fullClassName,"symbols",Type.getType("L"+hashClass.replace('.','/')+";"), GETSTATIC));
+            a(InstructionConstants.ALOAD_1);
+            a(fac.createInvoke(hashClass,"get",Type.OBJECT,new Type[]{Type.OBJECT},INVOKEVIRTUAL));
+            a(InstructionConstants.DUP);
+            BranchHandle bh = a(InstructionFactory.createBranchInstruction(IFNULL,null));
+            a(fac.createCheckCast(new ObjectType("java.lang.Integer")));
+            a(fac.createInvoke("java.lang.Integer","intValue",Type.INT,Type.NO_ARGS,INVOKEVIRTUAL));
+            a(InstructionConstants.IRETURN);
+            bh.setTarget(a(InstructionConstants.ICONST_M1));
+            a(InstructionConstants.IRETURN);     
+            lookupSymbol.setMaxLocals();
+            lookupSymbol.setMaxStack();
+            cl.addMethod(lookupSymbol.getMethod());
+        }
+        
+        MethodGen setCPUState = newMethod(ACC_PROTECTED,Type.VOID,new Type[]{Type.getType("Lorg/xwt/mips/Runtime$CPUState;")},"setCPUState");
+        selectMethod(setCPUState);
+        a(InstructionConstants.ALOAD_1);
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","r",new ArrayType(Type.INT,1),GETFIELD));
+        a(InstructionConstants.ASTORE_2);
+        for(int i=1;i<32;i++) {
+            a(InstructionConstants.ALOAD_0);
+            a(InstructionConstants.ALOAD_2);
+            pushConst(i);
+            a(InstructionConstants.IALOAD);
+            a(fac.createFieldAccess(fullClassName,"r"+i,Type.INT, PUTFIELD));
+        }
+        a(InstructionConstants.ALOAD_1);
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","f",new ArrayType(Type.INT,1),GETFIELD));
+        a(InstructionConstants.ASTORE_2);
+        for(int i=0;i<32;i++) {
+            a(InstructionConstants.ALOAD_0);
+            a(InstructionConstants.ALOAD_2);
+            pushConst(i);
+            a(InstructionConstants.IALOAD);
+            a(fac.createFieldAccess(fullClassName,"f"+i,Type.INT, PUTFIELD));
+        }
+        a(InstructionConstants.ALOAD_0);
+        a(InstructionConstants.ALOAD_1);
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","hi",Type.INT,GETFIELD));
+        a(fac.createFieldAccess(fullClassName,"hi",Type.INT, PUTFIELD));
+        a(InstructionConstants.ALOAD_0);
+        a(InstructionConstants.ALOAD_1);
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","lo",Type.INT,GETFIELD));
+        a(fac.createFieldAccess(fullClassName,"lo",Type.INT, PUTFIELD));
+        a(InstructionConstants.ALOAD_0);
+        a(InstructionConstants.ALOAD_1);
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","fcsr",Type.INT,GETFIELD));
+        a(fac.createFieldAccess(fullClassName,"fcsr",Type.INT, PUTFIELD));
+        a(InstructionConstants.ALOAD_0);
+        a(InstructionConstants.ALOAD_1);
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","pc",Type.INT,GETFIELD));
+        a(fac.createFieldAccess(fullClassName,"pc",Type.INT, PUTFIELD));
+        a(InstructionConstants.RETURN);
+        setCPUState.setMaxLocals();
+        setCPUState.setMaxStack();
+        cl.addMethod(setCPUState.getMethod());
+        
+        MethodGen getCPUState = newMethod(ACC_PROTECTED,Type.getType("Lorg/xwt/mips/Runtime$CPUState;"),Type.NO_ARGS,"getCPUState");
+        selectMethod(getCPUState);
+        a(fac.createNew("org.xwt.mips.Runtime$CPUState"));
+        a(InstructionConstants.DUP);
+        a(fac.createInvoke("org.xwt.mips.Runtime$CPUState","<init>",Type.VOID,Type.NO_ARGS,INVOKESPECIAL));
+        a(InstructionConstants.ASTORE_1);
+        
+        a(InstructionConstants.ALOAD_1);
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","r",new ArrayType(Type.INT,1),GETFIELD));
+        a(InstructionConstants.ASTORE_2);
+        for(int i=1;i<32;i++) {
+            a(InstructionConstants.ALOAD_2);
+            pushConst(i);
+            a(InstructionConstants.ALOAD_0);
+            a(fac.createFieldAccess(fullClassName,"r"+i,Type.INT, GETFIELD));
+            a(InstructionConstants.IASTORE);
+        }
+        
+        a(InstructionConstants.ALOAD_1);
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","f",new ArrayType(Type.INT,1),GETFIELD));
+        a(InstructionConstants.ASTORE_2);
+        for(int i=0;i<32;i++) {
+            a(InstructionConstants.ALOAD_2);
+            pushConst(i);
+            a(InstructionConstants.ALOAD_0);
+            a(fac.createFieldAccess(fullClassName,"f"+i,Type.INT, GETFIELD));
+            a(InstructionConstants.IASTORE);
+        }
+        a(InstructionConstants.ALOAD_1);
+        a(InstructionConstants.ALOAD_0);
+        a(fac.createFieldAccess(fullClassName,"hi",Type.INT, GETFIELD));
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","hi",Type.INT,PUTFIELD));
+        a(InstructionConstants.ALOAD_1);
+        a(InstructionConstants.ALOAD_0);
+        a(fac.createFieldAccess(fullClassName,"lo",Type.INT, GETFIELD));
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","lo",Type.INT,PUTFIELD));
+        a(InstructionConstants.ALOAD_1);
+        a(InstructionConstants.ALOAD_0);
+        a(fac.createFieldAccess(fullClassName,"fcsr",Type.INT, GETFIELD));
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","fcsr",Type.INT,PUTFIELD));
+        a(InstructionConstants.ALOAD_1);
+        a(InstructionConstants.ALOAD_0);
+        a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD));
+        a(fac.createFieldAccess("org.xwt.mips.Runtime$CPUState","pc",Type.INT,PUTFIELD));
+        
+        a(InstructionConstants.ALOAD_1);
+        a(InstructionConstants.ARETURN);
+        getCPUState.setMaxLocals();
+        getCPUState.setMaxStack();
+        cl.addMethod(getCPUState.getMethod());
+
+
+        MethodGen execute = newMethod(ACC_PROTECTED,Type.VOID,Type.NO_ARGS,"_execute");
+        selectMethod(execute);
+        a(InstructionConstants.ALOAD_0);
+        a(fac.createInvoke(fullClassName,"trampoline",Type.VOID,Type.NO_ARGS,INVOKESPECIAL));
+        a(InstructionConstants.RETURN);
+        execute.setMaxLocals();
+        execute.setMaxStack();
+        cl.addMethod(execute.getMethod());
+        
+        
+        MethodGen main = newMethod(ACC_STATIC|ACC_PUBLIC,Type.VOID,new Type[]{new ArrayType(Type.STRING,1)},"main");
+        selectMethod(main);
+        a(fac.createNew(fullClassName));
+        a(InstructionConstants.DUP);
+        a(fac.createInvoke(fullClassName,"<init>",Type.VOID,Type.NO_ARGS,INVOKESPECIAL));
+        a(new PUSH(cp,fullClassName));
+        a(InstructionConstants.ALOAD_0);
+        a(fac.createInvoke(fullClassName,"run",Type.INT,new Type[]{Type.STRING,new ArrayType(Type.STRING,1)},INVOKEVIRTUAL));
+        a(fac.createInvoke("java.lang.System","exit",Type.VOID,new Type[]{Type.INT},INVOKESTATIC));
+        a(InstructionConstants.RETURN);
+        main.setMaxLocals();
+        main.setMaxStack();
+        cl.addMethod(main.getMethod());
+        
+        cl.getJavaClass().dump(os);
+    }
+        
+    private static int initDataCount;
+    private void emitData(int addr, DataInputStream dis, int size, boolean readOnly) throws Exn,IOException {
+        if((addr&3)!=0 || (size&3)!=0) throw new Exn("Data section on weird boundaries");
+        int last = addr + size;
+        while(addr < last) {
+            int segSize = Math.min(size,28000); // must be a multiple of 56
+            StringBuffer sb = new StringBuffer();
+            for(int i=0;i<segSize;i+=7) {
+                long l = 0;
+                for(int j=0;j<7;j++) {
+                    l <<= 8;
+                    byte b = (i+j < size) ? dis.readByte() : 1;
+                    l |= (b & 0xffL);
+                }
+                for(int j=0;j<8;j++)
+                    sb.append((char) ((l>>>(7*(7-j)))&0x7f));
+            }
+            String fieldname =  "_data" + (++initDataCount);
+            cl.addField(new FieldGen(ACC_PRIVATE|ACC_STATIC|ACC_FINAL,new ArrayType(Type.INT,1),fieldname,cp).getField());
+            
+            selectList(clinitExtras);
+            a(new PUSH(cp,sb.toString()));
+            a(new PUSH(cp,segSize/4));
+            a(fac.createInvoke("org.xwt.mips.Runtime","decodeData",new ArrayType(Type.INT,1),new Type[]{Type.STRING,Type.INT},INVOKESTATIC));
+            a(fac.createPutStatic(fullClassName,fieldname,new ArrayType(Type.INT,1)));
+
+            selectList(initExtras);
+            a(InstructionConstants.ALOAD_0);
+            a(fac.createGetStatic(fullClassName,fieldname,new ArrayType(Type.INT,1)));
+            a(new PUSH(cp,addr));
+            a(new PUSH(cp,readOnly));
+            a(fac.createInvoke(fullClassName,"initPages",Type.VOID,new Type[]{new ArrayType(Type.INT,1),Type.INT,Type.BOOLEAN},INVOKEVIRTUAL));
+            
+            addr += segSize;
+            size -= segSize;
+        }
+        dis.close();
+    }
+    
+    private void emitBSS(int addr, int size) throws Exn {
+        if((addr&3)!=0) throw new Exn("BSS section on weird boundaries");
+        size = (size+3)&~3;
+        int count = size/4;
+        selectList(initExtras);
+        a(InstructionConstants.ALOAD_0);
+        a(new PUSH(cp,addr));
+        a(new PUSH(cp,count));
+        a(fac.createInvoke(fullClassName,"clearPages",Type.VOID,new Type[]{Type.INT,Type.INT},INVOKEVIRTUAL));
+    }
+    
+    // method state info
+    private boolean textDone;
+    private int startOfMethod = 0;
+    private int endOfMethod = 0;
+    private boolean unreachable = false;
+    private InstructionHandle[] jumpHandles;
+    private InstructionHandle defaultHandle;
+    private InstructionHandle returnHandle;
+    private InstructionHandle realStart;
+    private MethodGen curMethod;
+    
+    private boolean jumpable(int addr) { return jumpableAddresses.contains(new Integer(addr)); }
+    
+    private void emitText(int addr, DataInputStream dis, int size) throws Exn,IOException {
+        if(textDone) throw new Exn("Multiple text segments");
+        textDone = true;
+        
+        if((addr&3)!=0 || (size&3)!=0) throw new Exn("Section on weird boundaries");
+        int count = size/4;
+        int insn,nextInsn=-1;
+        boolean skipNext = true;
+        
+        for(int i=0;i<count;i++,addr+=4) {
+            insn = skipNext ? dis.readInt() : nextInsn;
+            nextInsn = (i == count-1) ? -1 : dis.readInt();
+            if(addr >= endOfMethod) { endMethod(addr); startMethod(addr); }
+            if(jumpHandles[(addr-startOfMethod)/4] != null) {
+                // Move the fake jump target to the current location
+                insnList.move(jumpHandles[(addr-startOfMethod)/4],insnList.getEnd());
+                unreachable = false;
+            } else if(unreachable) {
+                continue;
+            }
+            try {
+                skipNext = emitInstruction(addr,insn,nextInsn);
+            } catch(RuntimeException e) {
+                warn.println("Exception at " + toHex(addr));
+                throw e;
+            }
+            if(skipNext) { addr+=4; i++; }
+        }
+        endMethod(0);
+        dis.close();
+    }
+    
+    private void startMethod(int first) {
+        startOfMethod = first & methodMask;
+        endOfMethod = startOfMethod + maxBytesPerMethod;
+        curMethod = newMethod(ACC_PRIVATE,Type.VOID,Type.NO_ARGS,"run_" + toHex(startOfMethod));
+        selectMethod(curMethod);
+        
+        int[] buf = new int[maxBytesPerMethod/4];
+        jumpHandles = new InstructionHandle[maxBytesPerMethod/4];
+        int n=0;
+        for(int addr=first;addr<endOfMethod;addr+=4) {
+            if(jumpable(addr)) {
+                buf[n++] = addr;
+                // append NOPs for GOTO jumps (these will be moved to the correct location later)
+                jumpHandles[(addr-startOfMethod)/4] = a(InstructionConstants.NOP);
+            }
+        }
+        
+        // append NOP for default case (throw exn) (this will be moved later)
+        defaultHandle = a(InstructionConstants.NOP);
+        returnHandle = a(InstructionConstants.NOP);
+        
+        int[] matches = new int[n];
+        System.arraycopy(buf,0,matches,0,n);
+        InstructionHandle[] targets = new InstructionHandle[n];
+        for(int i=0;i<matches.length;i++)
+            targets[i] = jumpHandles[(matches[i]-startOfMethod)/4];
+        
+        
+        // First instruction of the actual method - everything above this should be removed
+        // before we get to the end
+        realStart = a(InstructionConstants.NOP);
+        
+        if(onePage) {
+            a(InstructionConstants.ALOAD_0);
+            a(fac.createFieldAccess(fullClassName,"page",new ArrayType(Type.INT,1), GETFIELD));
+            a(InstructionConstants.ASTORE_2);
+        } else {
+            a(InstructionConstants.ALOAD_0);
+            a(fac.createFieldAccess(fullClassName,"readPages",new ArrayType(Type.INT,2), GETFIELD));
+            a(InstructionConstants.ASTORE_2);
+            a(InstructionConstants.ALOAD_0);
+            a(fac.createFieldAccess(fullClassName,"writePages",new ArrayType(Type.INT,2), GETFIELD));
+            a(InstructionFactory.createStore(Type.OBJECT,3));
+        }
+        
+        LOOKUPSWITCH initialSwitch = new LOOKUPSWITCH(matches,targets,defaultHandle);
+        a(InstructionConstants.ALOAD_0);
+        a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD));
+        a(initialSwitch);     
+    }
+    
+    private void endMethod(int firstAddrOfNext) {
+        if(startOfMethod == 0) return;
+        
+        if(!unreachable) {
+            preSetPC();
+            pushConst(firstAddrOfNext);
+            setPC();
+            // mark the start of the next method as jumpable
+            jumpableAddresses.add(new Integer(firstAddrOfNext));
+        }
+        
+        insnList.move(returnHandle,insnList.getEnd());
+        fixupRegs();
+        a(InstructionConstants.RETURN);
+        
+        // move the default jump target (lookupswitch) to before the throw
+        insnList.move(defaultHandle,insnList.getEnd());
+        if(debugCompiler) {
+            a(fac.createNew("org.xwt.mips.Runtime$ExecutionException"));
+            a(InstructionConstants.DUP);
+            a(fac.createNew("java.lang.StringBuffer"));
+            a(InstructionConstants.DUP);
+            a(new PUSH(cp,"Jumped to invalid address: "));
+            a(fac.createInvoke("java.lang.StringBuffer","<init>",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL));
+            a(InstructionConstants.ALOAD_0);
+            a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD));
+            a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.INT},INVOKEVIRTUAL));
+            a(fac.createInvoke("java.lang.StringBuffer","toString",Type.STRING,Type.NO_ARGS,INVOKEVIRTUAL));
+            a(fac.createInvoke("org.xwt.mips.Runtime$ExecutionException","<init>",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL));
+            a(InstructionConstants.ATHROW);
+        } else {
+            a(fac.createNew("org.xwt.mips.Runtime$ExecutionException"));
+            a(InstructionConstants.DUP);
+            a(new PUSH(cp,"Jumped to invalid address"));
+            a(fac.createInvoke("org.xwt.mips.Runtime$ExecutionException","<init>",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL));
+            a(InstructionConstants.ATHROW);
+        }
+
+        if(insnList.getStart() != realStart) {
+            System.err.println(insnList);
+            throw new Error("A jumpHandle wasn't moved into place");
+        }
+        
+        curMethod.removeNOPs();
+        curMethod.setMaxLocals();
+        curMethod.setMaxStack();
+        
+        cl.addMethod(curMethod.getMethod());
+        
+        endOfMethod = startOfMethod = 0;
+    }
+
+
+    private void leaveMethod() {
+        a(InstructionFactory.createBranchInstruction(GOTO,returnHandle));
+    }
+
+    private void branch(int pc, int target) {
+        if((pc&methodMask) == (target&methodMask)) {
+            a(InstructionFactory.createBranchInstruction(GOTO,jumpHandles[(target-startOfMethod)/4]));
+        } else {
+            preSetPC();
+            pushConst(target);
+            setPC();
+            leaveMethod();
+        }
+    }
+    
+    // This assumes everything needed by ifInsn is already on the stack
+    private boolean doIfInstruction(short op, int pc, int target, int nextInsn) throws Exn {
+        emitInstruction(-1,nextInsn,-1); // delay slot
+        BranchHandle h;
+        IfInstruction ifInsn = (IfInstruction) InstructionFactory.createBranchInstruction(op,null);
+        if((target&methodMask) == (pc&methodMask)) {
+            h = a(ifInsn);
+            h.setTarget(jumpHandles[(target-startOfMethod)/4]);
+        } else {
+            h = a(ifInsn.negate());
+            branch(pc,target);
+            h.setTarget(a(InstructionConstants.NOP));
+        }
+        if(!jumpable(pc+4)) return true; // done - skip it
+        
+        //System.err.println("Delay slot is jumpable - This code is untested + " + toHex(nextInsn));
+        if(pc+4==endOfMethod) {
+            // the delay slot is at the start of the next method
+            jumpableAddresses.add(new Integer(pc+8)); // make the 2nd insn of the next method jumpable
+            branch(pc,pc+8); // jump over it
+            //System.err.println("delay slot: " + toHex(pc+8));
+            unreachable = true;
+            return false; // we still need to output it
+        } else {
+            //System.err.println("jumped over delay slot: " + toHex(pc+4));
+            // add another copy and jump over
+            h = a(InstructionFactory.createBranchInstruction(GOTO,null));
+            insnList.move(jumpHandles[(pc+4-startOfMethod)/4],insnList.getEnd());
+            emitInstruction(-1,nextInsn,-1); // delay slot
+            h.setTarget(a(InstructionConstants.NOP));
+            return true;
+        }
+    }
+    
+    private boolean emitInstruction(int pc, int insn, int nextInsn) throws Exn {
+        if(insn == -1) throw new Exn("insn is -1");
+        
+        int op = (insn >>> 26) & 0xff;                 // bits 26-31
+        int rs = (insn >>> 21) & 0x1f;                 // bits 21-25
+        int rt = (insn >>> 16) & 0x1f;                 // bits 16-20 
+        int ft = (insn >>> 16) & 0x1f;
+        int rd = (insn >>> 11) & 0x1f;                 // bits 11-15
+        int fs = (insn >>> 11) & 0x1f;
+        int shamt = (insn >>> 6) & 0x1f;               // bits 6-10
+        int fd = (insn >>> 6) & 0x1f;
+        int subcode = insn & 0x3f;                     // bits 0-5 
+        int breakCode = (insn >>> 6) & 0xfffff;         // bits 6-20
+
+        int jumpTarget = (insn & 0x03ffffff);          // bits 0-25
+        int unsignedImmediate = insn & 0xffff;
+        int signedImmediate = (insn << 16) >> 16;
+        int branchTarget = signedImmediate;
+
+        // temporaries
+        BranchHandle b1,b2;
+        
+        switch(op) {
+        case 0: {
+            switch(subcode) {
+            case 0: // SLL
+                if(insn == 0) break; 
+                preSetReg(R+rd);
+                pushRegWZ(R+rt);
+                pushConst(shamt);
+                a(InstructionConstants.ISHL);
+                setReg();
+                break;
+            case 2: // SRL
+                preSetReg(R+rd);
+                pushRegWZ(R+rt);
+                pushConst(shamt);
+                a(InstructionConstants.IUSHR);
+                setReg();
+                break;
+            case 3: // SRA
+                preSetReg(R+rd);
+                pushRegWZ(R+rt);
+                pushConst(shamt);
+                a(InstructionConstants.ISHR);        
+                setReg();
+                break;
+            case 4: // SLLV
+                preSetReg(R+rd);
+                pushRegWZ(R+rt);
+                pushRegWZ(R+rs);
+                a(InstructionConstants.ISHL);
+                setReg();
+                break;
+            case 6: // SRLV
+                preSetReg(R+rd);
+                pushRegWZ(R+rt);
+                pushRegWZ(R+rs);
+                a(InstructionConstants.IUSHR);
+                setReg();
+                break;
+            case 7: // SRAV
+                preSetReg(R+rd);
+                pushRegWZ(R+rt);
+                pushRegWZ(R+rs);
+                a(InstructionConstants.ISHR);
+                setReg();
+                break;
+            case 8: // JR
+                if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+                emitInstruction(-1,nextInsn,-1);
+                preSetPC();
+                pushRegWZ(R+rs);
+                setPC();
+                leaveMethod();
+                unreachable = true;
+                break;
+            case 9: // JALR
+                if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+                emitInstruction(-1,nextInsn,-1);
+                preSetPC();
+                pushRegWZ(R+rs);
+                setPC();
+                
+                preSetReg(R+RA);
+                pushConst(pc+8);
+                setReg();
+                leaveMethod();
+                unreachable = true;
+                break;
+            case 12: // SYSCALL
+                preSetPC();
+                pushConst(pc);
+                setPC();
+                
+                restoreChangedRegs();
+                
+                preSetReg(R+V0);
+                a(InstructionConstants.ALOAD_0);
+                pushRegZ(R+V0);
+                pushRegZ(R+A0);
+                pushRegZ(R+A1);
+                pushRegZ(R+A2);
+                pushRegZ(R+A3);
+                a(fac.createInvoke(fullClassName,"syscall",Type.INT,new Type[]{Type.INT,Type.INT,Type.INT,Type.INT,Type.INT},INVOKEVIRTUAL));
+                setReg();
+                
+                a(InstructionConstants.ALOAD_0);
+                a(fac.createFieldAccess(fullClassName,"state",Type.INT, GETFIELD));
+                pushConst(Runtime.RUNNING);
+                b1 = a(InstructionFactory.createBranchInstruction(IF_ICMPEQ,null));
+                preSetPC();
+                pushConst(pc+4);
+                setPC();
+                leaveMethod();
+                b1.setTarget(a(InstructionConstants.NOP));
+                
+                break;
+            case 13: // BREAK
+                a(fac.createNew("org.xwt.mips.Runtime$ExecutionException"));
+                a(InstructionConstants.DUP);
+                a(new PUSH(cp,"BREAK Code " + toHex(breakCode)));
+                a(fac.createInvoke("org.xwt.mips.Runtime$ExecutionException","<init>",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL));
+                a(InstructionConstants.ATHROW);
+                unreachable = true;
+                break;
+            case 16: // MFHI
+                preSetReg(R+rd);
+                pushReg(HI);
+                setReg();
+                break;
+            case 17: // MTHI
+                preSetReg(HI);
+                pushRegZ(R+rs);
+                setReg();
+                break;
+            case 18: // MFLO
+                preSetReg(R+rd);
+                pushReg(LO);
+                setReg();
+                break;
+            case 19: // MTLO
+                preSetReg(LO);
+                pushRegZ(R+rs);
+                setReg();
+                break;
+            case 24: // MULT
+                pushRegWZ(R+rs);
+                a(InstructionConstants.I2L);
+                pushRegWZ(R+rt);
+                a(InstructionConstants.I2L);
+                a(InstructionConstants.LMUL);
+                a(InstructionConstants.DUP2);
+                
+                a(InstructionConstants.L2I);
+                if(preSetReg(LO))
+                    a(InstructionConstants.SWAP);
+                setReg();
+                
+                pushConst(32);
+                a(InstructionConstants.LUSHR);
+                a(InstructionConstants.L2I);
+                if(preSetReg(HI))
+                    a(InstructionConstants.SWAP);
+                setReg();
+                
+                break;
+            case 25: // MULTU
+                pushRegWZ(R+rs);
+                a(InstructionConstants.I2L);
+                pushConst(0xffffffffL);
+                a(InstructionConstants.LAND);
+                pushRegWZ(R+rt);
+                a(InstructionConstants.I2L);
+                pushConst(0xffffffffL);
+                a(InstructionConstants.LAND);
+                a(InstructionConstants.LMUL);
+                a(InstructionConstants.DUP2);
+                
+                a(InstructionConstants.L2I);
+                if(preSetReg(LO))
+                    a(InstructionConstants.SWAP);
+                setReg();
+                
+                pushConst(32);
+                a(InstructionConstants.LUSHR);
+                a(InstructionConstants.L2I);
+                if(preSetReg(HI))
+                    a(InstructionConstants.SWAP);
+                setReg();
+                
+                break;
+            case 26: // DIV
+                pushRegWZ(R+rs);
+                pushRegWZ(R+rt);
+                a(InstructionConstants.DUP2);
+                
+                a(InstructionConstants.IDIV);
+                if(preSetReg(LO))
+                    a(InstructionConstants.SWAP);
+                setReg();
+                
+                a(InstructionConstants.IREM);
+                if(preSetReg(HI))
+                    a(InstructionConstants.SWAP);
+                setReg();
+                
+                break;
+            case 27: { // DIVU
+                pushRegWZ(R+rt);
+                a(InstructionConstants.DUP);
+                setTmp();
+                b1 = a(InstructionFactory.createBranchInstruction(IFEQ,null));
+                
+                pushRegWZ(R+rs);
+                a(InstructionConstants.I2L);
+                pushConst(0xffffffffL);
+                a(InstructionConstants.LAND);
+                a(InstructionConstants.DUP2);
+                pushTmp();
+                a(InstructionConstants.I2L);
+                pushConst(0xffffffffL);
+                
+                a(InstructionConstants.LAND);
+                a(InstructionConstants.DUP2_X2);
+                a(InstructionConstants.LDIV);
+                
+                a(InstructionConstants.L2I);
+                if(preSetReg(LO))
+                    a(InstructionConstants.SWAP);
+                setReg();
+                
+                a(InstructionConstants.LREM);
+                a(InstructionConstants.L2I);
+                if(preSetReg(HI))
+                    a(InstructionConstants.SWAP);
+                setReg();
+                
+                b1.setTarget(a(InstructionConstants.NOP));
+                
+                break;
+            }
+            case 32: // ADD
+                throw new Exn("ADD (add with oveflow trap) not suported");
+            case 33: // ADDU
+                   preSetReg(R+rd);
+                if(rt != 0 && rs != 0) {
+                    pushReg(R+rs);
+                    pushReg(R+rt);
+                    a(InstructionConstants.IADD);
+                } else if(rs != 0) {
+                    pushReg(R+rs);
+                } else {
+                    pushRegZ(R+rt);
+                }
+                setReg();
+                break;
+            case 34: // SUB
+                throw new Exn("SUB (add with oveflow trap) not suported");
+            case 35: // SUBU
+                preSetReg(R+rd);
+                if(rt != 0 && rs != 0) {
+                    pushReg(R+rs);
+                    pushReg(R+rt);
+                    a(InstructionConstants.ISUB);
+                } else if(rt != 0) {
+                    pushReg(R+rt);
+                    a(InstructionConstants.INEG);
+                } else {
+                    pushRegZ(R+rs);
+                }
+                setReg();                
+                break;
+            case 36: // AND
+                preSetReg(R+rd);
+                pushRegWZ(R+rs);
+                pushRegWZ(R+rt);
+                a(InstructionConstants.IAND);
+                setReg();
+                break;
+            case 37: // OR
+                preSetReg(R+rd);
+                pushRegWZ(R+rs);
+                pushRegWZ(R+rt);
+                a(InstructionConstants.IOR);
+                setReg();
+                break;
+            case 38: // XOR
+                preSetReg(R+rd);
+                pushRegWZ(R+rs);
+                pushRegWZ(R+rt);
+                a(InstructionConstants.IXOR);
+                setReg();
+                break;
+            case 39: // NOR
+                preSetReg(R+rd);
+                if(rs != 0 || rt != 0) {
+                    if(rs != 0 && rt != 0) {
+                        pushReg(R+rs);
+                        pushReg(R+rt);
+                        a(InstructionConstants.IOR);
+                    } else if(rs != 0) {
+                        pushReg(R+rs);
+                    } else {
+                        pushReg(R+rt);
+                    }
+                    a(InstructionConstants.ICONST_M1);
+                    a(InstructionConstants.IXOR);
+                } else {
+                    pushConst(-1);
+                }
+                setReg();
+                break;
+            case 42: // SLT
+                preSetReg(R+rd);
+                if(rs != rt) {
+                    pushRegZ(R+rs);
+                    pushRegZ(R+rt);
+                    b1 = a(InstructionFactory.createBranchInstruction(IF_ICMPLT,null));
+                    a(InstructionConstants.ICONST_0);
+                    b2 = a(InstructionFactory.createBranchInstruction(GOTO,null));
+                    b1.setTarget(a(InstructionConstants.ICONST_1));
+                    b2.setTarget(a(InstructionConstants.NOP));
+                } else {
+                    pushConst(0);
+                }
+                setReg();
+                break;
+            case 43: // SLTU
+                preSetReg(R+rd);
+                if(rs != rt) {
+                    if(rs != 0) {
+                        pushReg(R+rs);
+                        a(InstructionConstants.I2L);
+                        pushConst(0xffffffffL);
+                        a(InstructionConstants.LAND);
+                        pushReg(R+rt);
+                        a(InstructionConstants.I2L);
+                        pushConst(0xffffffffL);
+                        a(InstructionConstants.LAND);
+                        a(InstructionConstants.LCMP);
+                        b1 = a(InstructionFactory.createBranchInstruction(IFLT,null));
+                    } else {
+                        pushReg(R+rt);
+                        b1 = a(InstructionFactory.createBranchInstruction(IFNE,null));
+                    }
+                    a(InstructionConstants.ICONST_0);
+                    b2 = a(InstructionFactory.createBranchInstruction(GOTO,null));
+                    b1.setTarget(a(InstructionConstants.ICONST_1));
+                    b2.setTarget(a(InstructionConstants.NOP));
+                } else {
+                    pushConst(0);
+                }
+                setReg();
+                break;
+            default:
+                throw new RuntimeException("Illegal instruction 0/" + subcode);
+            }
+            break;
+        }
+        case 1: {
+            switch(rt) {
+            case 0: // BLTZ
+                if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+                pushRegWZ(R+rs);
+                return doIfInstruction(IFLT,pc,pc+branchTarget*4+4,nextInsn);
+            case 1: // BGEZ
+                if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+                pushRegWZ(R+rs);
+                return doIfInstruction(IFGE,pc,pc+branchTarget*4+4,nextInsn);
+            case 16: // BLTZAL
+                if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+                pushRegWZ(R+rs);
+                b1 = a(InstructionFactory.createBranchInstruction(IFGE,null));
+                emitInstruction(-1,nextInsn,-1);
+                preSetReg(R+RA);
+                pushConst(pc+8);
+                setReg();
+                branch(pc,pc+branchTarget*4+4);
+                b1.setTarget(a(InstructionConstants.NOP));
+                break;
+            case 17: // BGEZAL
+                if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+                b1 = null;
+                if(rs != 0) { // r0 is always >= 0
+                    pushRegWZ(R+rs);
+                    b1 = a(InstructionFactory.createBranchInstruction(IFLT,null));
+                }
+                emitInstruction(-1,nextInsn,-1);
+                preSetReg(R+RA);
+                pushConst(pc+8);
+                setReg();
+                branch(pc,pc+branchTarget*4+4);
+                if(b1 != null) b1.setTarget(a(InstructionConstants.NOP));
+                if(b1 == null) unreachable = true;
+                break;
+            default:
+                throw new RuntimeException("Illegal Instruction 1/" + rt);
+            }
+            break;
+        }
+        case 2: { // J
+            if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+            emitInstruction(-1,nextInsn,-1);
+            branch(pc,(pc&0xf0000000)|(jumpTarget << 2));
+            unreachable = true;
+            break;
+        }
+        case 3: { // JAL
+            if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+            int target = (pc&0xf0000000)|(jumpTarget << 2);
+            emitInstruction(-1,nextInsn,-1);
+            if(optimizedMemcpy && (target == memcpy || target == memset)) {
+                a(InstructionConstants.ALOAD_0);
+                pushRegZ(R+4);
+                pushRegZ(R+5);
+                pushRegZ(R+6);
+                a(fac.createInvoke(fullClassName,target==memcpy ? "memcpy" : "memset", Type.VOID, new Type[]{Type.INT,Type.INT,Type.INT},INVOKEVIRTUAL));
+                preSetReg(R+2);
+                pushReg(R+4);
+                setReg();
+                branch(pc,pc+8);
+            } else {
+                preSetReg(R+RA);
+                pushConst(pc+8);
+                setReg();
+                branch(pc, target);
+            }
+            unreachable = true;
+            break;
+        }
+        case 4: // BEQ
+            if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+            if(rs == rt) {
+                emitInstruction(-1,nextInsn,-1);
+                branch(pc,pc+branchTarget*4+4);
+                unreachable = true;
+            } else if(rs == 0 || rt == 0) {
+                pushReg(rt == 0 ? R+rs : R+rt);
+                return doIfInstruction(IFEQ,pc,pc+branchTarget*4+4,nextInsn);
+            } else {
+                pushReg(R+rs);
+                pushReg(R+rt);
+                return doIfInstruction(IF_ICMPEQ,pc,pc+branchTarget*4+4,nextInsn);
+            }
+            break;
+        case 5: // BNE       
+            if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+            pushRegWZ(R+rs);
+            if(rt == 0) {
+                return doIfInstruction(IFNE,pc,pc+branchTarget*4+4,nextInsn);
+            } else {
+                pushReg(R+rt);
+                return doIfInstruction(IF_ICMPNE,pc,pc+branchTarget*4+4,nextInsn);
+            }
+        case 6: //BLEZ
+            if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+            pushRegWZ(R+rs);
+            return doIfInstruction(IFLE,pc,pc+branchTarget*4+4,nextInsn);
+        case 7: //BGTZ
+            if(pc == -1) throw new Exn("pc modifying insn in delay slot");
+            pushRegWZ(R+rs);
+            return doIfInstruction(IFGT,pc,pc+branchTarget*4+4,nextInsn);
+        case 8: // ADDI
+            throw new Exn("ADDI (add immediate with oveflow trap) not suported");
+        case 9: // ADDIU
+            preSetReg(R+rt);
+            addiu(rs,signedImmediate);
+            setReg();            
+            break;
+        case 10: // SLTI
+            preSetReg(R+rt);
+            pushRegWZ(R+rs);
+            pushConst(signedImmediate);
+            b1 = a(InstructionFactory.createBranchInstruction(IF_ICMPLT,null));
+            a(InstructionConstants.ICONST_0);
+            b2 = a(InstructionFactory.createBranchInstruction(GOTO,null));
+            b1.setTarget(a(InstructionConstants.ICONST_1));
+            b2.setTarget(a(InstructionConstants.NOP));
+            setReg();
+            break;
+        case 11: // SLTIU
+            preSetReg(R+rt);
+            pushRegWZ(R+rs);
+            a(InstructionConstants.I2L);
+            pushConst(0xffffffffL);
+            a(InstructionConstants.LAND);
+            pushConst((long)unsignedImmediate);
+            a(InstructionConstants.LCMP);
+            
+            b1 = a(InstructionFactory.createBranchInstruction(IFLT,null));
+            a(InstructionConstants.ICONST_0);
+            b2 = a(InstructionFactory.createBranchInstruction(GOTO,null));
+            b1.setTarget(a(InstructionConstants.ICONST_1));
+            b2.setTarget(a(InstructionConstants.NOP));
+            
+            setReg();
+            break;            
+        case 12: // ANDI
+            preSetReg(R+rt);
+            pushRegWZ(R+rs);
+            pushConst(unsignedImmediate);
+            a(InstructionConstants.IAND);
+            setReg();
+            break;
+        case 13: // ORI
+            preSetReg(R+rt);
+            if(rs != 0 && unsignedImmediate != 0) {
+                pushReg(R+rs);
+                pushConst(unsignedImmediate);
+                a(InstructionConstants.IOR);
+            } else if(rs != 0){
+                pushReg(R+rs);
+            } else {
+                pushConst(unsignedImmediate);
+            }
+            setReg();
+            break;
+        case 14: // XORI
+            preSetReg(R+rt);
+            pushRegWZ(R+rs);
+            pushConst(unsignedImmediate);
+            a(InstructionConstants.IXOR);
+            setReg();
+            break;
+        case 15: // LUI
+            preSetReg(R+rt);
+            pushConst(unsignedImmediate << 16);
+            setReg();
+            break;
+        case 16:
+            throw new Exn("TLB/Exception support not implemented");
+        case 17: { // FPU
+            switch(rs) {
+            case 0: // MFC.1
+                preSetReg(R+rt);
+                pushReg(F+rd);
+                setReg();
+                break;
+            case 2: // CFC.1
+                if(fs != 31) throw new Exn("FCR " + fs + " unavailable");
+                preSetReg(R+rt);
+                pushReg(FCSR);
+                setReg();
+                break;
+            case 4: // MTC.1
+                preSetReg(F+rd);
+                if(rt != 0)
+                    pushReg(R+rt);
+                else
+                    pushConst(0);
+                setReg();
+                break;
+            case 6: // CTC.1
+                if(fs != 31) throw new Exn("FCR " + fs + " unavailable");
+                preSetReg(FCSR);
+                pushReg(R+rt);
+                setReg();
+                break;
+            case 8: {// BC1F, BC1T
+                pushReg(FCSR);
+                pushConst(0x800000);
+                a(InstructionConstants.IAND);
+                return doIfInstruction(((insn>>>16)&1) == 0 ? IFEQ : IFNE,pc,pc+branchTarget*4+4,nextInsn);
+            }
+            case 16:
+            case 17: 
+            { // Single/Double math
+                boolean d = rs == 17;
+                switch(subcode) {
+                case 0: // ADD.X
+                    preSetDouble(F+fd,d);
+                    pushDouble(F+fs,d);
+                    pushDouble(F+ft,d);
+                    a(d ? InstructionConstants.DADD : InstructionConstants.FADD);
+                    setDouble(d);
+                    break;
+                case 1: // SUB.X
+                    preSetDouble(F+fd,d);
+                    pushDouble(F+fs,d);
+                    pushDouble(F+ft,d);
+                    a(d ? InstructionConstants.DSUB : InstructionConstants.FSUB);
+                    setDouble(d);                    
+                    break;
+                case 2: // MUL.X
+                    preSetDouble(F+fd,d);
+                    pushDouble(F+fs,d);
+                    pushDouble(F+ft,d);
+                    a(d ? InstructionConstants.DMUL : InstructionConstants.FMUL);
+                    setDouble(d);                    
+                    break;
+                case 3: // DIV.X
+                    preSetDouble(F+fd,d);
+                    pushDouble(F+fs,d);
+                    pushDouble(F+ft,d);
+                    a(d ? InstructionConstants.DDIV : InstructionConstants.FDIV);
+                    setDouble(d);                    
+                    break;
+                case 5: // ABS.X
+                    preSetDouble(F+fd,d);
+                    // NOTE: We can't use fneg/dneg here since they'll turn +0.0 into -0.0
+                    
+                    pushDouble(F+fs,d);
+                    a(d ? InstructionConstants.DUP2 : InstructionConstants.DUP);
+                    a(d ? InstructionConstants.DCONST_0 : InstructionConstants.FCONST_0);
+                    a(d ? InstructionConstants.DCMPG : InstructionConstants.FCMPG);
+                    
+                    b1 = a(InstructionFactory.createBranchInstruction(IFGT,null));
+                    a(d ? InstructionConstants.DCONST_0 : InstructionConstants.FCONST_0);
+                    if(d) {
+                        a(InstructionConstants.DUP2_X2);
+                        a(InstructionConstants.POP2);
+                    } else {
+                        a(InstructionConstants.POP);
+                    }
+                    a(InstructionConstants.DSUB);
+                    
+                    b1.setTarget(setDouble(d));
+                    
+                    break;
+                case 6: // MOV.X
+                    preSetReg(F+fd);
+                    pushReg(F+fs);
+                    setReg();
+                    
+                    preSetReg(F+fd+1);
+                    pushReg(F+fs+1);
+                    setReg();
+                    
+                    break;
+                case 7: // NEG.X
+                    preSetDouble(F+fd,d);
+                    pushDouble(F+fs,d);
+                    a(d ? InstructionConstants.DNEG : InstructionConstants.FNEG);
+                    setDouble(d);                    
+                    break;
+                case 32: // CVT.S.X
+                    preSetFloat(F+fd);
+                    pushDouble(F+fd,d);
+                    if(d) a(InstructionConstants.D2F);
+                    setFloat();
+                    break;
+                case 33: // CVT.D.X
+                    preSetDouble(F+fd);
+                    pushDouble(F+fd,d);
+                    if(!d) a(InstructionConstants.F2D);
+                    setDouble();
+                    break;
+                case 36: { // CVT.W.D
+                    int[] matches = new int[4];
+                    for(int i=0;i<4;i++) matches[i] = i;
+                    
+                    TABLESWITCH ts = new  TABLESWITCH(matches,new InstructionHandle[4], null);
+                    
+                    preSetReg(F+fd);
+                    pushDouble(F+fs,d);
+                    pushReg(FCSR);
+                    a(InstructionConstants.ICONST_3);
+                    a(InstructionConstants.IAND);
+                    a(ts);
+                    
+                    // Round towards plus infinity
+                    ts.setTarget(2,a(InstructionConstants.NOP));
+                    if(!d) a(InstructionConstants.F2D); // Ugh.. java.lang.Math doesn't have a float ceil/floor
+                    a(fac.createInvoke("java.lang.Math","ceil",Type.DOUBLE,new Type[]{Type.DOUBLE},INVOKESTATIC));
+                    if(!d) a(InstructionConstants.D2F);
+                    b1 = a(InstructionFactory.createBranchInstruction(GOTO,null));
+                    
+                    // Round to nearest
+                    ts.setTarget(0,d ? pushConst(0.5d) : pushConst(0.5f));
+                    a(d ? InstructionConstants.DADD : InstructionConstants.FADD);
+                    // fall through
+                    
+                    // Round towards minus infinity
+                    ts.setTarget(3,a(InstructionConstants.NOP));
+                    if(!d) a(InstructionConstants.F2D);
+                    a(fac.createInvoke("java.lang.Math","floor",Type.DOUBLE,new Type[]{Type.DOUBLE},INVOKESTATIC));
+                    if(!d) a(InstructionConstants.D2F);
+                    
+                    InstructionHandle h = a(d ? InstructionConstants.D2I : InstructionConstants.F2I);
+                    setReg();
+                    
+                    ts.setTarget(1,h);
+                    ts.setTarget(h);
+                    b1.setTarget(h);
+                                        
+                    break;
+                }
+                case 50: // C.EQ.D
+                case 60: // C.LT.D
+                case 62: // C.LE.D
+                    preSetReg(FCSR);
+                    pushReg(FCSR);
+                    pushConst(~0x800000);
+                    a(InstructionConstants.IAND);
+                    pushDouble(F+fs,d);
+                    pushDouble(F+ft,d);
+                    a(d ? InstructionConstants.DCMPG : InstructionConstants.FCMPG);
+                    switch(subcode) {
+                        case 50: b1 = a(InstructionFactory.createBranchInstruction(IFEQ,null)); break;
+                        case 60: b1 = a(InstructionFactory.createBranchInstruction(IFLT,null)); break;
+                        case 62: b1 = a(InstructionFactory.createBranchInstruction(IFLE,null)); break;
+                        default: b1 = null;
+                    }
+                    
+                    pushConst(0x000000);
+                    b2 = a(InstructionFactory.createBranchInstruction(GOTO,null));
+                    b1.setTarget(pushConst(0x800000));
+                    b2.setTarget(a(InstructionConstants.IOR));
+                    setReg();
+                    break;
+                default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode);
+                }
+                break;
+            }
+            case 20: { // Integer
+                switch(subcode) {
+                case 32: // CVT.S.W
+                    preSetFloat(F+fd);
+                    pushReg(F+fs);
+                    a(InstructionConstants.I2F);
+                    setFloat();
+                    break;
+                case 33: // CVT.D.W
+                    preSetDouble(F+fd);
+                    pushReg(F+fs);
+                    a(InstructionConstants.I2D);
+                    setDouble();
+                    break;
+                default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode);
+                }
+                break; 
+            }
+            default:
+                throw new Exn("Invalid Instruction 17/" + rs);
+            }
+            break;
+        }
+        case 18: case 19:
+            throw new Exn("coprocessor 2 and 3 instructions not available");
+        case 32: { // LB
+            preSetReg(R+rt);
+            addiu(R+rs,signedImmediate);
+            setTmp();
+            preMemRead();
+            pushTmp();
+            memRead(true);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IXOR);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IUSHR);
+            a(InstructionConstants.I2B);
+            setReg();
+            break; 
+        }
+        case 33: { // LH
+            preSetReg(R+rt);
+            addiu(R+rs,signedImmediate);
+            setTmp();
+            preMemRead();
+            pushTmp();
+            memRead(true);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IXOR);
+            a(InstructionConstants.ICONST_2);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IUSHR);
+            a(InstructionConstants.I2S);
+            setReg();            
+            break; 
+        }
+        case 34: { // LWL;
+            preSetReg(R+rt);
+            addiu(R+rs,signedImmediate);
+            setTmp(); // addr
+            
+            pushRegWZ(R+rt);
+            pushConst(0x00ffffff);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IXOR);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IUSHR);
+            a(InstructionConstants.IAND);
+            
+            preMemRead();
+            pushTmp();
+            memRead(true);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IOR);
+            
+            setReg();
+            
+            break;
+            
+        }
+        case 35: // LW
+            preSetReg(R+rt);
+            memRead(R+rs,signedImmediate);
+            setReg();
+            break;
+        case 36: { // LBU
+            preSetReg(R+rt);
+            addiu(R+rs,signedImmediate);
+            setTmp();
+            preMemRead();
+            pushTmp();
+            memRead(true);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IXOR);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IUSHR);
+            pushConst(0xff);
+            a(InstructionConstants.IAND);
+            setReg();
+            break; 
+        }
+        case 37: { // LHU
+            preSetReg(R+rt);
+            addiu(R+rs,signedImmediate);
+            setTmp();
+            preMemRead();
+            pushTmp();
+            memRead(true);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IXOR);
+            a(InstructionConstants.ICONST_2);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IUSHR);
+            
+            // chars are unsigend so this works
+            a(InstructionConstants.I2C);
+            setReg();
+            break; 
+        }
+        case 38: { // LWR            
+            preSetReg(R+rt);
+            addiu(R+rs,signedImmediate);
+            setTmp(); // addr
+            
+            pushRegWZ(R+rt);
+            pushConst(0xffffff00);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IAND);
+            
+            preMemRead();
+            pushTmp();
+            memRead(true);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IXOR);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IUSHR);
+            a(InstructionConstants.IOR);
+            
+            
+            setReg();
+            break;
+        }
+        case 40: { // SB            
+            addiu(R+rs,signedImmediate);
+            setTmp(); // addr
+            
+            // FEATURE: DO the preMemRead(true) thing for the rest of the S* instructions
+            preMemRead(true);
+            pushTmp();
+            memRead(true);
+            
+            pushConst(0xff000000);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IUSHR);
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IXOR);
+            a(InstructionConstants.IAND);
+            
+            if(rt != 0) {
+                pushReg(R+rt);
+                pushConst(0xff);
+                a(InstructionConstants.IAND);
+            } else {
+                pushConst(0);
+            }
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IXOR);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IOR);
+            
+            memWrite();
+            
+            break;
+        }
+        case 41: { // SH    
+            preMemWrite1();
+            
+            addiu(R+rs,signedImmediate);
+            
+            a(InstructionConstants.DUP);
+            setTmp(); // addr
+            
+            preMemWrite2(true);
+            
+            preMemRead();
+            pushTmp();
+            memRead(true);
+            
+            pushConst(0xffff);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_2);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IAND);
+            
+            if(rt != 0) {
+                pushReg(R+rt);
+                pushConst(0xffff);
+                a(InstructionConstants.IAND);
+            } else {
+                pushConst(0);
+            }
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IXOR);
+            a(InstructionConstants.ICONST_2);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IOR);
+            
+            memWrite();
+            
+            break;            
+        }
+        case 42: { // SWL
+            preMemWrite1();
+            
+            addiu(R+rs,signedImmediate);
+            a(InstructionConstants.DUP);
+            setTmp(); // addr
+
+            preMemWrite2(true);
+            
+            preMemRead();
+            pushTmp();
+            memRead(true);
+            
+            pushConst(0xffffff00);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IXOR);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IAND);
+            
+            pushRegWZ(R+rt);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IUSHR);
+            a(InstructionConstants.IOR);
+            
+            memWrite();
+            break;
+            
+        }
+        case 43: // SW
+            preMemWrite1();
+            preMemWrite2(R+rs,signedImmediate);
+            pushRegZ(R+rt);
+            memWrite();
+            break;
+        case 46: { // SWR
+            preMemWrite1();
+            
+            addiu(R+rs,signedImmediate);
+            a(InstructionConstants.DUP);
+            setTmp(); // addr
+            
+            preMemWrite2(true);
+            
+            preMemRead();
+            pushTmp();
+            memRead(true);
+            
+            pushConst(0x00ffffff);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IUSHR);
+            a(InstructionConstants.IAND);
+            
+            pushRegWZ(R+rt);
+            pushTmp();
+            
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IXOR);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.IAND);
+            a(InstructionConstants.ICONST_3);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.ISHL);
+            a(InstructionConstants.IOR);
+                    
+            memWrite();
+            break;
+        }
+        // FEATURE: This need to be atomic if we ever support threads (see SWC0/SC)
+        case 48: // LWC0/LL
+            preSetReg(R+rt);
+            memRead(R+rs,signedImmediate);
+            setReg();
+            break;
+            
+        case 49: // LWC1
+            preSetReg(F+rt);
+            memRead(R+rs,signedImmediate);
+            setReg();
+            break;
+        
+        /* FEATURE: This needs to fail (set rt to 0) if the memory location was modified
+         * between the LL and SC if we every support threads.
+         */
+        case 56: // SWC0/SC
+            preSetReg(R+rt);
+            preMemWrite1();
+            preMemWrite2(R+rs,signedImmediate);
+            pushReg(R+rt);
+            memWrite();
+            pushConst(1);
+            setReg();
+            break;
+            
+        case 57: // SWC1
+            preMemWrite1();
+            preMemWrite2(R+rs,signedImmediate);
+            pushReg(F+rt);
+            memWrite();
+            break;
+        default:
+            throw new Exn("Invalid Instruction: " + op + " at " + toHex(pc));
+        }
+        return false; 
+    }
+    
+    // Helper functions for emitText
+    
+    private static final int R = 0;
+    private static final int F = 32;
+    private static final int HI = 64;
+    private static final int LO = 65;
+    private static final int FCSR = 66;
+    private static final int REG_COUNT=67;
+        
+    private int[] regLocalMapping = new int[REG_COUNT];  
+    private int[] regLocalReadCount = new int[REG_COUNT];
+    private int[] regLocalWriteCount = new int[REG_COUNT];
+    private int nextAvailLocal; 
+    
+    private int getLocalForReg(int reg) {
+        if(regLocalMapping[reg] != 0) return regLocalMapping[reg];
+        if(nextAvailLocal == 0) nextAvailLocal = onePage ? 3 : 4;
+        regLocalMapping[reg] = nextAvailLocal++;
+        return regLocalMapping[reg];
+    }
+    
+    private void fixupRegs() {
+        InstructionHandle prev = realStart;
+        for(int i=0;i<REG_COUNT;i++) {
+            if(regLocalMapping[i] == 0) continue; 
+            
+            prev = insnList.append(prev,InstructionConstants.ALOAD_0);
+            prev = insnList.append(prev,fac.createFieldAccess(fullClassName,regField(i),Type.INT, GETFIELD));
+            prev = insnList.append(prev,InstructionFactory.createStore(Type.INT,regLocalMapping[i]));
+            
+            if(regLocalWriteCount[i] > 0) {
+                a(InstructionConstants.ALOAD_0);
+                a(InstructionFactory.createLoad(Type.INT,regLocalMapping[i]));
+                a(fac.createFieldAccess(fullClassName,regField(i),Type.INT, PUTFIELD));
+            }
+            
+            regLocalMapping[i] = regLocalReadCount[i] = regLocalWriteCount[i] = 0;
+        }
+        nextAvailLocal = 0;
+    }
+    
+    private void restoreChangedRegs() {
+        for(int i=0;i<REG_COUNT;i++) {
+            if(regLocalWriteCount[i] > 0) {
+                a(InstructionConstants.ALOAD_0);
+                a(InstructionFactory.createLoad(Type.INT,regLocalMapping[i]));
+                a(fac.createFieldAccess(fullClassName,regField(i),Type.INT, PUTFIELD));                
+            }
+        }
+    }
+    
+    private String regField(int reg) {
+        String field;
+        switch(reg) {
+            case HI: field = "hi"; break;
+            case LO: field = "lo"; break;
+            case FCSR: field = "fcsr"; break;
+            default:
+                if(reg > R && reg < R+32) field="r"+(reg-R);
+                else if(reg >= F && reg < F+32) field="f"+(reg-F);
+                else throw new IllegalArgumentException(""+reg);
+        }
+        return field;
+    }
+    
+    private boolean doLocal(int reg) { return reg == R+2 || reg == R+3 || reg == R+4 || reg == R+29; }
+    
+    private InstructionHandle pushRegWZ(int reg) {
+        if(reg == R+0) {
+            warn.println("Warning: Pushing r0!");
+            new Exception().printStackTrace(warn);
+        }
+        return pushRegZ(reg);
+    }
+    
+    private InstructionHandle pushRegZ(int reg) {
+        if(reg == R+0) return pushConst(0);
+        else return pushReg(reg);
+    }
+    
+    
+    private InstructionHandle pushReg(int reg) {
+        InstructionHandle h;
+        if(doLocal(reg)) {
+            regLocalReadCount[reg]++;
+            h = a(InstructionFactory.createLoad(Type.INT,getLocalForReg(reg)));
+        } else {
+            h = a(InstructionConstants.ALOAD_0);
+            a(fac.createFieldAccess(fullClassName,regField(reg),Type.INT, GETFIELD));
+        }
+        return h;
+    }
+    
+    private int preSetRegStackPos;
+    private int[] preSetRegStack = new int[8];
+    
+    // This can push ONE or ZERO words to the stack. If it pushed one it returns true
+    private boolean preSetReg(int reg) {
+        regField(reg); // just to check for validity
+        preSetRegStack[preSetRegStackPos] = reg;
+        preSetRegStackPos++;
+        if(doLocal(reg)) {
+            return false;
+        } else {
+            a(InstructionConstants.ALOAD_0);
+            return true;
+        }
+    }
+    
+    private InstructionHandle setReg() {
+        if(preSetRegStackPos==0) throw new RuntimeException("didn't do preSetReg");
+        preSetRegStackPos--;
+        int reg = preSetRegStack[preSetRegStackPos];
+        InstructionHandle h;
+        if(doLocal(reg)) {
+            h = a(InstructionFactory.createStore(Type.INT,getLocalForReg(reg)));
+            regLocalWriteCount[reg]++;
+        } else {
+            h = a(fac.createFieldAccess(fullClassName,regField(reg),Type.INT, PUTFIELD));
+        }
+        return h;
+    }
+    
+    private InstructionHandle preSetPC() { return a(InstructionConstants.ALOAD_0); }
+    private InstructionHandle setPC() { return a(fac.createFieldAccess(fullClassName,"pc",Type.INT, PUTFIELD)); }
+    
+    //unused - private InstructionHandle pushFloat(int reg) throws CompilationException { return pushDouble(reg,false); }
+    //unused - private InstructionHandle pushDouble(int reg) throws CompilationException { return pushDouble(reg,true); }
+    private InstructionHandle pushDouble(int reg, boolean d) throws Exn {
+        if(reg < F || reg >= F+32) throw new IllegalArgumentException(""+reg);
+        InstructionHandle h;
+        if(d) {
+            if(reg == F+31) throw new Exn("Tried to use a double in f31");
+            h = pushReg(reg+1);
+            a(InstructionConstants.I2L);
+            pushConst(32);
+            a(InstructionConstants.LSHL);
+            pushReg(reg);
+            a(InstructionConstants.I2L);
+            pushConst(0xffffffffL);
+            a(InstructionConstants.LAND);
+            a(InstructionConstants.LOR);
+            //p("invokestatic java/lang/Double/longBitsToDouble(J)D");
+            a(fac.createInvoke("java.lang.Double","longBitsToDouble",Type.DOUBLE,new Type[]{Type.LONG},INVOKESTATIC));
+        } else {
+            h = pushReg(reg);
+            a(fac.createInvoke("java.lang.Float","intBitsToFloat",Type.FLOAT,new Type[]{Type.INT},INVOKESTATIC));
+        }
+        return h;
+    }
+    
+    private void preSetFloat(int reg) { preSetDouble(reg,false); }
+    private void preSetDouble(int reg) { preSetDouble(reg,true); }
+    private void preSetDouble(int reg, boolean d) { preSetReg(reg); }
+    
+    private InstructionHandle setFloat() throws Exn { return setDouble(false); }
+    private InstructionHandle setDouble() throws Exn { return setDouble(true); }
+    private InstructionHandle setDouble(boolean d) throws Exn {
+        int reg = preSetRegStack[preSetRegStackPos-1];
+        if(reg < F || reg >= F+32) throw new IllegalArgumentException(""+reg);
+        //p("invokestatic java/lang/Double/doubleToLongBits(D)J");
+        InstructionHandle h;
+        if(d) {
+            if(reg == F+31) throw new Exn("Tried to use a double in f31");
+            h = a(fac.createInvoke("java.lang.Double","doubleToLongBits",Type.LONG,new Type[]{Type.DOUBLE},INVOKESTATIC));
+            a(InstructionConstants.DUP2);
+            pushConst(32);
+            a(InstructionConstants.LUSHR);
+            a(InstructionConstants.L2I);
+            if(preSetReg(reg+1))
+                a(InstructionConstants.SWAP);
+            setReg();
+            a(InstructionConstants.L2I);
+            setReg(); // preSetReg was already done for this by preSetDouble
+        } else {
+            h = a(fac.createInvoke("java.lang.Float","floatToRawIntBits",Type.INT,new Type[]{Type.FLOAT},INVOKESTATIC));
+            setReg();   
+        }
+        return h;
+    }
+        
+    private InstructionHandle pushConst(int n) {
+        if(n >= 0 && n <= 5) {
+            switch(n) {
+                case 0: return a(InstructionConstants.ICONST_0);
+                case 1: return a(InstructionConstants.ICONST_1);
+                case 2: return a(InstructionConstants.ICONST_2);
+                case 3: return a(InstructionConstants.ICONST_3);
+                case 4: return a(InstructionConstants.ICONST_4);
+                case 5: return a(InstructionConstants.ICONST_5);
+                default: return null;
+            }
+        } else if(n == -1) {
+            return a(InstructionConstants.ICONST_M1);
+        } else if(n >= -128 && n <= 127) {
+            return a(new BIPUSH((byte) n));
+        } else if(n >= -32768 && n <= 32767) {
+            return a(new SIPUSH((short) n));
+        } else {
+            return a(new PUSH(cp,n));
+        }
+    }
+    
+    private InstructionHandle pushConst(long l) { return a(new PUSH(cp,l)); }
+    private InstructionHandle pushConst(float f) { return a(new PUSH(cp,f)); }
+    private InstructionHandle pushConst(double d) { return a(new PUSH(cp,d)); }
+    
+    private void pushTmp() { a(InstructionConstants.ILOAD_1); }
+    private void setTmp() { a(InstructionConstants.ISTORE_1); }
+    
+    private void addiu(int reg, int offset) {
+        if(reg != R+0 && offset != 0) {
+            pushReg(reg);
+            pushConst(offset);
+            a(InstructionConstants.IADD);
+        } else if(reg != R+0) {
+            pushReg(reg);
+        } else {
+            pushConst(offset);
+        }        
+    }
+    private int memWriteStage;
+    private void preMemWrite1() {
+        if(memWriteStage!=0) throw new Error("pending preMemWrite1/2");
+        memWriteStage=1;
+        if(onePage)
+            a(InstructionConstants.ALOAD_2);
+        else if(fastMem)
+            a(InstructionFactory.createLoad(Type.OBJECT,3));
+        else
+            a(InstructionConstants.ALOAD_0);
+    }
+    
+    private void preMemWrite2(int reg, int offset) {
+        addiu(reg,offset);
+        preMemWrite2();
+    }
+    
+    private void preMemWrite2() { preMemWrite2(false); }
+    private void preMemWrite2(boolean addrInTmp) {
+        if(memWriteStage!=1) throw new Error("pending preMemWrite2 or no preMemWrite1");
+        memWriteStage=2;
+        
+        if(nullPointerCheck) {
+            a(InstructionConstants.DUP);
+            a(InstructionConstants.ALOAD_0);
+            a(InstructionConstants.SWAP);
+            a(fac.createInvoke(fullClassName,"nullPointerCheck",Type.VOID,new Type[]{Type.INT},INVOKEVIRTUAL));
+        }
+        
+        if(onePage) {
+            a(InstructionConstants.ICONST_2);
+            a(InstructionConstants.IUSHR);
+        } else if(fastMem) {
+            if(!addrInTmp)
+                a(InstructionConstants.DUP_X1);
+            pushConst(pageShift);
+            a(InstructionConstants.IUSHR);
+            a(InstructionConstants.AALOAD);
+            if(addrInTmp)
+                pushTmp();
+            else
+                a(InstructionConstants.SWAP);
+            a(InstructionConstants.ICONST_2);
+            a(InstructionConstants.IUSHR);
+            pushConst((pageSize>>2)-1);
+            a(InstructionConstants.IAND);            
+        }
+    }
+    
+    // pops an address and value off the stack, sets *addr to value
+    private void memWrite() {
+        if(memWriteStage!=2) throw new Error("didn't do preMemWrite1 or preMemWrite2");
+        memWriteStage=0;
+                
+        if(onePage) {
+            a(InstructionConstants.IASTORE);
+        } else if(fastMem) {
+            a(InstructionConstants.IASTORE);
+        } else {
+            a(fac.createInvoke(fullClassName,"unsafeMemWrite",Type.VOID,new Type[]{Type.INT,Type.INT},INVOKEVIRTUAL));
+        }
+        
+    }
+    
+    // reads the word at r[reg]+offset
+    private void memRead(int reg, int offset) {
+        preMemRead();
+        addiu(reg,offset);
+        memRead();
+    }
+    
+    private boolean didPreMemRead;
+    private boolean preMemReadDoPreWrite;
+    
+    private void preMemRead() { preMemRead(false); }
+    private void preMemRead(boolean preWrite) {
+        if(didPreMemRead) throw new Error("pending preMemRead");
+        didPreMemRead = true;
+        preMemReadDoPreWrite = preWrite;
+        if(onePage)
+            a(InstructionConstants.ALOAD_2);
+        else if(fastMem)
+            a(InstructionFactory.createLoad(Type.OBJECT,preWrite ? 3 : 2));
+        else
+            a(InstructionConstants.ALOAD_0);
+    }
+    // memRead pops an address off the stack, reads the value at that addr, and pushed the value
+    // preMemRead MUST be called BEFORE the addresses is pushed
+    private void memRead() { memRead(false); }
+    
+    private void memRead(boolean addrInTmp) {
+        if(!didPreMemRead) throw new Error("didn't do preMemRead");
+        didPreMemRead = false;
+        if(preMemReadDoPreWrite)
+            memWriteStage=2; 
+            
+        if(nullPointerCheck) {
+            a(InstructionConstants.DUP);
+            a(InstructionConstants.ALOAD_0);
+            a(InstructionConstants.SWAP);
+            a(fac.createInvoke(fullClassName,"nullPointerCheck",Type.VOID,new Type[]{Type.INT},INVOKEVIRTUAL));
+        }
+        
+        if(onePage) {
+            // p(target + "= page[(" + addr + ")>>>2];");
+            a(InstructionConstants.ICONST_2);
+            a(InstructionConstants.IUSHR);
+            if(preMemReadDoPreWrite)
+                a(InstructionConstants.DUP2);
+            a(InstructionConstants.IALOAD);
+        } else if(fastMem) {
+            //p(target  + " = readPages[("+addr+")>>>"+pageShift+"][(("+addr+")>>>2)&"+toHex((pageSize>>2)-1)+"];");
+            
+            if(!addrInTmp)
+                a(InstructionConstants.DUP_X1);
+            pushConst(pageShift);
+            a(InstructionConstants.IUSHR);
+            a(InstructionConstants.AALOAD);
+            if(addrInTmp)
+                pushTmp();
+            else
+                a(InstructionConstants.SWAP);
+            a(InstructionConstants.ICONST_2);
+            a(InstructionConstants.IUSHR);
+            pushConst((pageSize>>2)-1);
+            a(InstructionConstants.IAND);
+            if(preMemReadDoPreWrite)
+                a(InstructionConstants.DUP2);
+            a(InstructionConstants.IALOAD);
+            
+        } else {
+            if(preMemReadDoPreWrite)
+                a(InstructionConstants.DUP2);
+            a(fac.createInvoke(fullClassName,"unsafeMemWrite",Type.INT,new Type[]{Type.INT},INVOKEVIRTUAL));
+        }
+    }
+    
+    
+    // This might come in handy for something else
+    /*private boolean touchesReg(int insn, int reg) {
+        if((reg < R+0 || reg >= R+32) && reg != FCSR) throw new IllegalArgumentException(""+reg);
+        if(reg == R+0) return false; // r0 is never modified
+        int op = (insn >>> 26) & 0xff;                 // bits 26-31
+        int subcode = insn & 0x3f;                     // bits 0-5 
+        int rd = (insn >>> 11) & 0x1f;                 // bits 11-15
+        int rt = (insn >>> 16) & 0x1f;                 // bits 16-20 
+        int rs = (insn >>> 21) & 0x1f;                 // bits 21-25
+        
+        switch(op) {
+        case 0:
+            if(subcode >= 0 && subcode <= 7) return reg == R+rd; // Shift ops
+            if(subcode >= 32 && subcode <= 43) return reg == R+rd; // Other math ops 
+            if(subcode >= 24 && subcode <= 27) return reg == HI || reg == LO; // MULT/DIV
+            break;
+        case 13: return false; // BREAK
+        case 17:
+            switch(rs) {
+                case 0: return reg == R+rt; // MFC.1
+                case 2: return reg == R+rt; // CFC.1
+                case 4: return false; // MTC.1
+                case 6: return false; // CTC.1
+                case 16: // Single 
+                case 17: // Double
+                    if(subcode == 50 || subcode == 60 || subcode == 62) return reg == FCSR;
+                    return false; // everything else just touches f0-f31
+                case 20: return false; // Integer - just touches f0-f31
+            }
+            break;
+        default:
+            if(op >= 8 && op <= 15) return reg == R+rt; // XXXI instructions
+            if(op >= 40 && op <= 46) return false; // Memory WRITE ops
+            if(op == 49) return reg == F+rt; // LWC1
+            if(op == 57) return false; // SWC1
+            break;
+        }
+        warn.println("Unknown instruction in touchesReg()- assuming it modifies all regs " + op + " " + subcode);
+        new Exception().fillInStackTrace().printStackTrace(warn);
+        return true;
+    }*/
+}
diff --git a/src/org/xwt/mips/ClassLoader.java b/src/org/xwt/mips/ClassLoader.java
new file mode 100644 (file)
index 0000000..510d309
--- /dev/null
@@ -0,0 +1,44 @@
+package org.xwt.mips;
+
+import java.io.*;
+
+// FEATURE: This is just a quick hack, it is really ugly and broken
+
+public class ClassLoader extends java.lang.ClassLoader {
+    public Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
+        Class c;
+        if(name.startsWith("mips.")) {
+            String path = name.substring(5).replace('.','/') + ".mips";
+            try {
+                ByteArrayOutputStream bos = new ByteArrayOutputStream();
+                new ClassFileCompiler(path,name,bos).go();
+                bos.close();
+                byte[] buf = bos.toByteArray();
+                c = defineClass(name,buf,0,buf.length);
+            } catch(IOException e) {
+                throw new ClassNotFoundException(name);
+            } catch(Compiler.Exn e) {
+                throw new ClassNotFoundException(e.getMessage());
+            }
+        } else {
+            c = findSystemClass(name);
+        }
+            
+        if(c == null) throw new ClassNotFoundException(name);
+        if(resolve) resolveClass(c);
+        return c;
+    }
+    
+    public Class classFromBinary(String path) throws ClassNotFoundException {
+        if(!path.endsWith(".mips")) throw new IllegalArgumentException("isn't a .mips");
+        return loadClass("mips." + path.substring(0,path.length()-5).replace('/','.'));
+    }
+    
+    public Runtime runtimeFromBinary(String path) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+        return (Runtime) classFromBinary(path).newInstance();
+    }
+    
+    public static void main(String[] args) throws Exception {
+        System.exit(new ClassLoader().runtimeFromBinary(args[0]).run(args));
+    }
+}
diff --git a/src/org/xwt/mips/Compiler.java b/src/org/xwt/mips/Compiler.java
new file mode 100644 (file)
index 0000000..de457e7
--- /dev/null
@@ -0,0 +1,540 @@
+// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
+
+package org.xwt.mips;
+
+import java.util.*;
+import java.io.*;
+
+import org.xwt.mips.util.SeekableData;
+import org.xwt.mips.util.SeekableFile;
+
+public abstract class Compiler implements Registers {    
+    /** The ELF binary being read */
+    protected ELF elf;
+    
+    /** The name of the class beging generated */
+    protected final String fullClassName;
+    
+    /** The name of the binary this class is begin generated from */
+    protected String source = "unknown.mips.binary";
+    public void setSource(String source) { this.source = source; }
+        
+    /** Thrown when the compilation fails for some reason */
+    protected static class Exn extends Exception { public Exn(String s) { super(s); } }
+    
+    // Set this to true to enable fast memory access 
+    // When this is enabled a Java RuntimeException will be thrown when a page fault occures. When it is disabled
+    // a FaultException will be throw which is easier to catch and deal with, however. as the name implies, this is slower
+    protected boolean fastMem = true;
+    
+    // This MUST be a power of two. If it is not horrible things will happen
+    // NOTE: This value can be much higher without breaking the classfile 
+    // specs (around 1024) but Hotstop seems to do much better with smaller
+    // methods. 
+    protected int maxInsnPerMethod = 128;
+    
+    // non-configurable
+    protected int maxBytesPerMethod;
+    protected int methodMask;
+    protected int methodShift;
+    protected void maxInsnPerMethodInit() throws Exn {
+        if((maxInsnPerMethod&(maxInsnPerMethod-1)) != 0) throw new Exn("maxBytesPerMethod is not a power of two");
+        maxBytesPerMethod = maxInsnPerMethod*4;
+        methodMask = ~(maxBytesPerMethod-1);
+        while(maxBytesPerMethod>>>methodShift != 1) methodShift++;
+    }
+    
+    // True to try to determine which case statement are needed and only include them
+    protected boolean pruneCases = true;
+    
+    protected boolean assumeTailCalls = true;
+    
+    protected boolean optimizedMemcpy = true;
+    
+    // True to insert some code in the output to help diagnore compiler problems
+    protected boolean debugCompiler = false;
+    
+    // True to print various statistics about the compilation
+    protected boolean printStats = false;
+    
+    // True to generate runtime statistics that slow execution down significantly
+    protected boolean runtimeStats = false;
+    
+    protected boolean supportCall = true;
+    
+    protected boolean nullPointerCheck = false;
+    
+    protected String runtimeClass = "org.xwt.mips.Runtime";
+    
+    protected String hashClass = "java.util.Hashtable";
+    
+    protected boolean unixRuntime;
+    
+    protected boolean lessConstants = false;
+            
+    protected int pageSize = 4096;
+    protected int totalPages = 65536;
+    protected int pageShift;
+    protected boolean onePage;
+    
+    protected void pageSizeInit() throws Exn {
+        try {
+            Runtime.checkPageSize(pageSize,totalPages);
+        } catch(IllegalArgumentException e) {
+            throw new Exn(e.getMessage());
+        }
+        while(pageSize>>>pageShift != 1) pageShift++;
+    }
+    
+    /** The address of the memcpy function in the binary (used for optimizedMemcpy) */
+    protected int memcpy;
+
+    /** The address of the memset function in the binary (used for optimizedMemcpy) */
+    protected int memset;
+    
+    /** A set of all addresses that can be jumped too (only available if pruneCases == true) */
+    protected Set jumpableAddresses;
+    
+    /** Some important symbols */
+    ELF.Symbol userInfo, gp;
+    
+    private static void usage() {
+        System.err.println("Usage: java Compiler [-outfile output.java] [-o options] [-dumpoptions] <classname> <binary.mips>");
+        System.err.println("-o takes mount(8) like options and can be specified multiple times");
+        System.err.println("Available options:");
+        for(int i=0;i<options.length;i+=2)
+            System.err.print(options[i] + ": " + wrapAndIndent(options[i+1],18-2-options[i].length(),18,62));
+        System.exit(1);
+    }
+    
+    public static void main(String[] args) throws IOException {
+        String outfile = null;
+        String o = null;
+        String className = null;
+        String mipsBinaryFileName = null;
+        String outformat = null;
+        boolean dumpOptions = false;
+        int arg = 0;
+        while(args.length-arg > 0) {
+            if(args[arg].equals("-outfile")) {
+                arg++;
+                if(arg==args.length) usage();
+                outfile = args[arg];
+            } else if(args[arg].equals("-outformat")) {
+                arg++;
+                if(arg==args.length) usage();
+                outformat = args[arg];
+            } else if(args[arg].equals("-o")) {
+                arg++;
+                if(arg==args.length) usage();
+                if(o==null || o.length() == 0)
+                    o = args[arg];
+                else if(args[arg].length() != 0)
+                    o += "," + args[arg];
+            } else if(args[arg].equals("-dumpoptions")) {
+                dumpOptions = true;
+            } else if(className == null) {
+                className = args[arg];
+            } else if(mipsBinaryFileName == null) {
+                mipsBinaryFileName = args[arg];
+            } else {
+                usage();
+            }
+            arg++;
+        }
+        if(className == null || mipsBinaryFileName == null) usage();
+        
+        SeekableData mipsBinary = new SeekableFile(mipsBinaryFileName);
+        
+        Writer w = null;
+        OutputStream os = null;
+        Compiler comp = null;
+        if(outformat == null || outformat.equals("class")) {
+            if(outfile == null) {
+                System.err.println("Refusing to write a classfile to stdout - use -outfile foo.class");
+                System.exit(1);
+            }
+            os = new FileOutputStream(outfile);
+            comp = new ClassFileCompiler(mipsBinary,className,os);
+        } else if(outformat.equals("javasource") || outformat .equals("java")) {
+            w = outfile == null ? new OutputStreamWriter(System.out): new FileWriter(outfile);
+            comp = new JavaSourceCompiler(mipsBinary,className,w);
+        } else {
+            System.err.println("Unknown output format: " + outformat);
+            System.exit(1);
+        }
+        
+        comp.parseOptions(o);
+        comp.setSource(mipsBinaryFileName);
+        
+        if(dumpOptions) {
+            System.err.println("== Options ==");
+            for(int i=0;i<options.length;i+=2)
+                System.err.println(options[i] + ": " + comp.getOption(options[i]).get());
+            System.err.println("== End Options ==");
+        }
+            
+        try {
+            comp.go();
+        } catch(Exn e) {
+            System.err.println("Compiler Error: " + e.getMessage());
+            System.exit(1);
+        } finally {
+            if(w != null) w.close();
+            if(os != null) os.close();
+        }
+    }
+        
+    public Compiler(SeekableData binary, String fullClassName) throws IOException {
+        this.fullClassName = fullClassName;
+        elf = new ELF(binary);
+        
+        if(elf.header.type != ELF.ELFHeader.ET_EXEC) throw new IOException("Binary is not an executable");
+        if(elf.header.machine != ELF.ELFHeader.EM_MIPS) throw new IOException("Binary is not for the MIPS I Architecture");
+        if(elf.ident.data != ELF.ELFIdent.ELFDATA2MSB) throw new IOException("Binary is not big endian");
+    }
+
+    protected abstract void _go() throws Exn, IOException;
+    
+    private boolean used;
+    public void go() throws Exn, IOException {
+        if(used) throw new RuntimeException("Compiler instances are good for one shot only");
+        used = true;
+        
+        if(onePage && pageSize <= 4096) pageSize = 4*1024*1024;
+        if(nullPointerCheck && !fastMem) throw new Exn("fastMem must be enabled for nullPointerCheck to be of any use");
+        if(onePage && !fastMem) throw new Exn("fastMem must be enabled for onePage to be of any use");
+        if(totalPages == 1 && !onePage) throw new Exn("totalPages == 1 and onePage is not set");
+        if(onePage) totalPages = 1;
+
+        maxInsnPerMethodInit();
+        pageSizeInit();
+        
+        // Get a copy of the symbol table in the elf binary
+        ELF.Symtab symtab = elf.getSymtab();
+        if(symtab == null) throw new Exn("Binary has no symtab (did you strip it?)");
+        ELF.Symbol sym;
+        
+        // Check for some functions we can override
+        sym = symtab.getGlobalSymbol("memcpy");
+        memcpy = sym == null ? -1 : sym.addr;
+        
+        sym = symtab.getGlobalSymbol("memset");
+        memset = sym == null ? -1 : sym.addr;
+        
+        userInfo = symtab.getGlobalSymbol("user_info");
+        gp = symtab.getGlobalSymbol("_gp");
+        if(gp == null) throw new Exn("no _gp symbol (did you strip the binary?)");   
+        
+        if(pruneCases) {
+            // Find all possible branches
+            jumpableAddresses = new HashSet();
+            
+            jumpableAddresses.add(new Integer(elf.header.entry));
+            
+            ELF.SHeader text = elf.sectionWithName(".text");
+            if(text == null) throw new Exn("No .text segment");
+            
+            findBranchesInSymtab(symtab,jumpableAddresses);
+            
+            for(int i=0;i<elf.sheaders.length;i++) {
+                ELF.SHeader sheader = elf.sheaders[i];
+                String name = sheader.name;
+                // if this section doesn't get loaded into our address space don't worry about it
+                if(sheader.addr == 0x0) continue;
+                if(name.equals(".data") || name.equals(".sdata") || name.equals(".rodata") || name.equals(".ctors") || name.equals(".dtors"))
+                    findBranchesInData(new DataInputStream(sheader.getInputStream()),sheader.size,jumpableAddresses,text.addr,text.addr+text.size);
+            }
+            
+            findBranchesInText(text.addr,new DataInputStream(text.getInputStream()),text.size,jumpableAddresses);            
+        }
+
+        if(unixRuntime && runtimeClass.startsWith("org.xwt.mips.")) runtimeClass = "org.xwt.mips.UnixRuntime";
+        
+        for(int i=0;i<elf.sheaders.length;i++) {
+            String name = elf.sheaders[i].name;
+            if(elf.sheaders[i].addr != 0 && !(
+                name.equals(".text")|| name.equals(".data") || name.equals(".sdata") || name.equals(".rodata") ||
+                name.equals(".ctors") || name.equals(".dtors") || name.equals(".bss") || name.equals(".sbss")))
+                    throw new Exn("Unknown section: " + name);
+        }
+        _go();
+    }
+    
+    private void findBranchesInSymtab(ELF.Symtab symtab, Set jumps) {
+        ELF.Symbol[] symbols = symtab.symbols;
+        int n=0;
+        for(int i=0;i<symbols.length;i++) {
+            ELF.Symbol s = symbols[i];
+            if(s.type == ELF.Symbol.STT_FUNC) {
+                if(jumps.add(new Integer(s.addr))) {
+                    //System.err.println("Adding symbol from symtab: " + s.name + " at " + toHex(s.addr));
+                    n++;
+                }
+            }
+        }
+        if(printStats) System.err.println("Found " + n + " additional possible branch targets in Symtab");
+    }
+    
+    private void findBranchesInText(int base, DataInputStream dis, int size, Set jumps) throws IOException {
+        int count = size/4;
+        int pc = base;
+        int n=0;
+        int[] lui_val = new int[32];
+        int[] lui_pc = new int[32];
+        //Interpreter inter = new Interpreter(source);
+        
+        for(int i=0;i<count;i++,pc+=4) {
+            int insn = dis.readInt();
+            int op = (insn >>> 26) & 0xff; 
+            int rs = (insn >>> 21) & 0x1f;
+            int rt = (insn >>> 16) & 0x1f;
+            int signedImmediate = (insn << 16) >> 16;
+            int unsignedImmediate = insn & 0xffff;
+            int branchTarget = signedImmediate;
+            int jumpTarget = (insn & 0x03ffffff);
+            int subcode = insn & 0x3f;
+            
+            switch(op) {
+                case 0:
+                    switch(subcode) {
+                        case 9: // JALR
+                            if(jumps.add(new Integer(pc+8))) n++; // return address
+                            break;
+                        case 12: // SYSCALL
+                            if(jumps.add(new Integer(pc+4))) n++; 
+                            break;
+                    }
+                    break;
+                case 1:
+                    switch(rt) {
+                        case 16: // BLTZAL
+                        case 17: // BGTZAL
+                            if(jumps.add(new Integer(pc+8))) n++; // return address
+                            // fall through
+                        case 0: // BLTZ
+                        case 1: // BGEZ
+                            if(jumps.add(new Integer(pc+branchTarget*4+4))) n++;
+                            break;
+                    }
+                    break;
+                case 3: // JAL
+                    if(jumps.add(new Integer(pc+8))) n++; // return address
+                    // fall through
+                case 2: // J
+                    if(jumps.add(new Integer((pc&0xf0000000)|(jumpTarget << 2)))) n++;
+                    break;
+                case 4: // BEQ
+                case 5: // BNE
+                case 6: // BLEZ
+                case 7: // BGTZ
+                    if(jumps.add(new Integer(pc+branchTarget*4+4))) n++;
+                    break;
+                case 9: { // ADDIU
+                    if(pc - lui_pc[rs] <= 4*32) {
+                        int t = (lui_val[rs]<<16)+signedImmediate;
+                        if((t&3)==0 && t >= base && t < base+size) {
+                            if(jumps.add(new Integer(t))) {
+                                //System.err.println("Possible jump to " + toHex(t) + " (" + inter.sourceLine(t) + ") from " + toHex(pc) + " (" + inter.sourceLine(pc) + ")");
+                                n++;
+                            }
+                        }
+                        // we just blew it away
+                        if(rt == rs) lui_pc[rs] = 0;
+                    }
+                    break;
+                }
+                case 15: { // LUI
+                    lui_val[rt] = unsignedImmediate;
+                    lui_pc[rt] = pc;
+                    break;
+                }
+                    
+                case 17: // FPU Instructions
+                    switch(rs) {
+                        case 8: // BC1F, BC1T
+                            if(jumps.add(new Integer(pc+branchTarget*4+4))) n++;
+                            break;
+                    }
+                    break;
+            }
+        }
+        dis.close();
+        if(printStats) System.err.println("Found " + n + " additional possible branch targets in Text segment");
+    }
+    
+    private void findBranchesInData(DataInputStream dis, int size, Set jumps, int textStart, int textEnd) throws IOException {
+        int count = size/4;
+        int n=0;
+        for(int i=0;i<count;i++) {
+            int word = dis.readInt();
+            if((word&3)==0 && word >= textStart && word < textEnd) {
+                if(jumps.add(new Integer(word))) {
+                    //System.err.println("Added " + toHex(word) + " as possible branch target (fron data segment)");
+                    n++;
+                }
+            }
+        }
+        dis.close();
+        if(n>0 && printStats) System.err.println("Found " + n + " additional possible branch targets in Data segment");
+    }
+    
+    // Helper functions for pretty output
+    protected final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
+    protected final static String toHex8(int n) {
+        String s = Long.toString(n & 0xffffffffL, 16);
+        StringBuffer sb = new StringBuffer("0x");
+        for(int i=8-s.length();i>0;i--) sb.append('0');
+        sb.append(s);
+        return sb.toString();
+    }
+
+    protected final static String toOctal3(int n) {
+        char[] buf = new char[3];
+        for(int i=2;i>=0;i--) {
+            buf[i] = (char) ('0' + (n & 7));
+            n >>= 3;
+        }
+        return new String(buf);
+    }
+
+    // Option parsing
+    private class Option {
+        private java.lang.reflect.Field field;
+        public Option(String name) throws NoSuchFieldException { field = name==null ? null : Compiler.class.getDeclaredField(name); }
+        public void set(Object val) {
+            if(field == null) return;
+            try {
+                field.setAccessible(true);
+                field.set(Compiler.this,val);
+            } catch(IllegalAccessException e) {
+                System.err.println(e);
+            }
+        }
+        public Object get() {
+            if(field == null) return null;
+            try {
+                field.setAccessible(true);
+                return field.get(Compiler.this);
+            } catch(IllegalAccessException e) {
+                System.err.println(e); return null;
+            }
+        }
+        public Class getType() { return field == null ? null : field.getType(); }
+    }
+    
+    private static String[] options = {
+        "fastMem",          "Enable fast memory access - RuntimeExceptions will be thrown on faults",
+        "nullPointerCheck", "Enables checking at runtime for null pointer accessses (slows things down a bit, only applicable with fastMem)",
+        "maxInsnPerMethod", "Maximum number of MIPS instructions per java method (128 is optimal with Hotspot)",
+        "pruneCases",       "Remove unnecessary case 0xAABCCDD blocks from methods - may break some weird code",
+        "assumeTailCalls",  "Assume the JIT optimizes tail calls",
+        "optimizedMemcpy",  "Use an optimized java version of memcpy where possible",
+        "debugCompiler",    "Output information in the generated code for debugging the compiler - will slow down generated code significantly",
+        "printStats",       "Output some useful statistics about the compilation",
+        "runtimeStats",     "Keep track of some statistics at runtime in the generated code - will slow down generated code significantly",
+        "supportCall",      "Keep a stripped down version of the symbol table in the generated code to support the call() method",
+        "runtimeClass",     "Full classname of the Runtime class (default: Runtime) - use this is you put Runtime in a package",
+        "hashClass",        "Full classname of a Hashtable class (default: java.util.HashMap) - this must support get() and put()",
+        "unixRuntime",      "Use the UnixRuntime (has support for fork, wai, du, pipe, etc)",
+        "pageSize",         "The page size (must be a power of two)",
+        "totalPages",       "Total number of pages (total mem = pageSize*totalPages, must be a power of two)",
+        "onePage",          "One page hack (FIXME: document this better)",
+        "lessConstants",    "Use less constants at the cost of speed (FIXME: document this better)"
+    };
+        
+    private Option getOption(String name) {
+        name = name.toLowerCase();
+        try {
+            for(int i=0;i<options.length;i+=2)
+                if(options[i].toLowerCase().equals(name))
+                    return new Option(options[i]);
+            return null;
+        } catch(NoSuchFieldException e) {
+            return null;
+        }
+    }
+    
+    public void parseOptions(String opts) {
+        if(opts == null || opts.length() == 0) return;
+        StringTokenizer st = new StringTokenizer(opts,",");
+        while(st.hasMoreElements()) {
+            String tok = st.nextToken();
+            String key;
+            String val;
+            if(tok.indexOf("=") != -1) {
+                key = tok.substring(0,tok.indexOf("="));
+                val = tok.substring(tok.indexOf("=")+1);
+            } else if(tok.startsWith("no")) {
+                key = tok.substring(2);
+                val = "false";
+            } else {
+                key = tok;
+                val = "true";
+            }
+            Option opt = getOption(key);
+            if(opt == null) {
+                System.err.println("WARNING: No such option: " + key);
+                continue;
+            }
+            
+            if(opt.getType() == String.class)
+                opt.set(val);
+            else if(opt.getType() == Integer.TYPE)
+                try {
+                    opt.set(parseInt(val));
+                } catch(NumberFormatException e) {
+                    System.err.println("WARNING: " + val + " is not an integer");
+                }
+            else if(opt.getType() == Boolean.TYPE)
+                opt.set(new Boolean(val.toLowerCase().equals("true")||val.toLowerCase().equals("yes")));
+            else
+                throw new Error("Unknown type: " + opt.getType());
+        }
+    }
+        
+    private static Integer parseInt(String s) {
+        int mult = 1;
+        s = s.toLowerCase();
+        if(!s.startsWith("0x") && s.endsWith("m")) { s = s.substring(0,s.length()-1); mult = 1024*1024; }
+        else if(!s.startsWith("0x") && s.endsWith("k")) { s = s.substring(0,s.length()-1); mult = 1024; }
+        int n;
+        if(s.length() > 2 && s.startsWith("0x")) n = Integer.parseInt(s.substring(2),16);
+        else n = Integer.parseInt(s);
+        return new Integer(n*mult);
+    }
+    
+    private static String wrapAndIndent(String s, int firstindent, int indent, int width) {
+        StringTokenizer st = new StringTokenizer(s," ");
+        StringBuffer sb = new StringBuffer();
+        for(int i=0;i<firstindent;i++)
+            sb.append(' ');
+        int sofar = 0;
+        while(st.hasMoreTokens()) {
+            String tok = st.nextToken();
+            if(tok.length() + sofar + 1 > width && sofar > 0) {
+                sb.append('\n');
+                for(int i=0;i<indent;i++) sb.append(' ');
+                sofar = 0;
+            } else if(sofar > 0) {
+                sb.append(' ');
+                sofar++;
+            }
+            sb.append(tok);
+            sofar += tok.length();
+        }
+        sb.append('\n');
+        return sb.toString();
+    }
+    
+    // This ugliness is to work around a gcj static linking bug (Bug 12908)
+    // The best solution is to force gnu.java.locale.Calendar to be linked in but this'll do
+    protected static String dateTime() {
+        try {
+            return new Date().toString();
+        } catch(RuntimeException e) {
+            return "<unknown>";
+        }
+    }
+}
+
diff --git a/src/org/xwt/mips/ELF.java b/src/org/xwt/mips/ELF.java
new file mode 100644 (file)
index 0000000..18698f2
--- /dev/null
@@ -0,0 +1,381 @@
+package org.xwt.mips;
+
+import org.xwt.mips.util.*;
+import java.io.*;
+
+public class ELF {
+    private SeekableData data;
+    
+    public ELFIdent ident;
+    public ELFHeader header;
+    public PHeader[] pheaders;
+    public SHeader[] sheaders;
+    
+    private byte[] stringTable;
+    
+    private boolean sectionReaderActive;
+    
+    
+    private void readFully(byte[] buf) throws IOException {
+        int len = buf.length;
+        int pos = 0;
+        while(len > 0) {
+            int n = data.read(buf,pos,len);
+            if(n == -1) throw new IOException("EOF");
+            pos += n;
+            len -= n;
+        }
+    }
+    
+    private int readIntBE() throws IOException {
+        byte[] buf = new byte[4];
+        readFully(buf);
+        return ((buf[0]&0xff)<<24)|((buf[1]&0xff)<<16)|((buf[2]&0xff)<<8)|((buf[3]&0xff)<<0);
+    }
+    private int readInt() throws IOException {
+        int x = readIntBE();
+        if(ident!=null && ident.data == ELFIdent.ELFDATA2LSB) 
+            x = ((x<<24)&0xff000000) | ((x<<8)&0xff0000) | ((x>>>8)&0xff00) | ((x>>24)&0xff);
+        return x;
+    }
+    
+    private short readShortBE() throws IOException {
+        byte[] buf = new byte[2];
+        readFully(buf);
+        return (short)(((buf[0]&0xff)<<8)|((buf[1]&0xff)<<0));
+    }
+    private short readShort() throws IOException {
+        short x = readShortBE();
+        if(ident!=null && ident.data == ELFIdent.ELFDATA2LSB) 
+            x = (short)((((x<<8)&0xff00) | ((x>>8)&0xff))&0xffff);
+        return x;
+    }
+    
+    private byte readByte() throws IOException {
+        byte[] buf = new byte[1];
+        readFully(buf);
+        return buf[0];
+    }
+        
+    public class ELFIdent {
+        private static final int ELF_MAGIC = 0x7f454c46; // '\177', 'E', 'L', 'F'
+
+        public static final int ELFCLASSNONE = 0;
+        public static final int ELFCLASS32 = 1;
+        public static final int ELFCLASS64 = 2;
+        public byte klass;
+
+
+        public static final int ELFDATANONE = 0;
+        public static final int ELFDATA2LSB = 1;
+        public static final int ELFDATA2MSB = 2;        
+        public byte data;
+        public byte osabi;
+        public byte abiversion;
+                
+        ELFIdent() throws IOException {
+            if(readIntBE() != ELF_MAGIC) throw new ELFException("Bad Magic (is: " );
+            
+            klass = readByte();
+            if(klass != ELFCLASS32) throw new ELFException("org.xwt.mips.ELF does not suport 64-bit binaries");
+            
+            data = readByte();
+            if(data != ELFDATA2LSB && data != ELFDATA2MSB) throw new ELFException("Unknown byte order");
+            
+            readByte(); // version
+            osabi = readByte();
+            abiversion = readByte();
+            for(int i=0;i<7;i++) readByte(); // padding
+        }
+    }
+    
+    public class ELFHeader {
+        public static final short ET_EXEC = 2;
+        public short type;
+        
+        public static final short EM_MIPS = 8;
+        public short machine;
+        
+        public int version;
+        public int entry;
+        public int phoff;
+        public int shoff;
+        public int flags;
+        public short ehsize;
+        public short phentsize;
+        public short phnum;
+        public short shentsize;
+        public short shnum;
+        public short shstrndx;
+
+        ELFHeader() throws IOException {
+            type = readShort();
+            machine = readShort();
+            version = readInt();
+            if(version != 1) throw new ELFException("version != 1");
+            entry = readInt();
+            phoff = readInt();
+            shoff = readInt();
+            flags = readInt();
+            ehsize = readShort();
+            phentsize = readShort();
+            phnum = readShort();
+            shentsize = readShort();
+            shnum = readShort();
+            shstrndx = readShort();
+        }
+    }
+    
+    public class PHeader {
+        public int type;
+        public int offset;
+        public int vaddr;
+        public int paddr;
+        public int filesz;
+        public int memsz;
+        public int flags;
+        public int align;
+        
+        public static final int PF_X = 0x1;
+        public static final int PF_W = 0x2;
+        public static final int PF_R = 0x4;
+        
+        public static final int PT_LOAD = 1;
+        
+        PHeader() throws IOException {
+            type = readInt();
+            offset = readInt();
+            vaddr = readInt();
+            paddr = readInt();
+            filesz = readInt();
+            memsz = readInt();
+            flags = readInt();
+            align = readInt();
+            if(filesz > memsz) throw new ELFException("ELF inconsistency: filesz > memsz (" + toHex(filesz) + " > " + toHex(memsz) + ")");
+        }
+        
+        public boolean writable() { return (flags & PF_W) != 0; }
+        
+        public InputStream getInputStream() throws IOException {
+            return new BufferedInputStream(new SectionInputStream(
+                offset,offset+filesz));
+        }
+    }
+    
+    public class SHeader {
+        int nameidx;
+        public String name;
+        public int type;
+        public int flags;
+        public int addr;
+        public int offset;
+        public int size;
+        public int link;
+        public int info;
+        public int addralign;
+        public int entsize;
+        
+        public static final int SHT_SYMTAB = 2;
+        public static final int SHT_STRTAB = 3;
+        public static final int SHT_NOBITS = 8;
+        
+        SHeader() throws IOException {
+            nameidx = readInt();
+            type = readInt();
+            flags = readInt();
+            addr = readInt();
+            offset = readInt();
+            size = readInt();
+            link = readInt();
+            info = readInt();
+            addralign = readInt();
+            entsize = readInt();
+        }
+        
+        public InputStream getInputStream() throws IOException {
+            return new BufferedInputStream(new SectionInputStream(
+                offset, type == SHT_NOBITS ? 0 : offset+size));
+        }
+        
+        public boolean isText() { return name.equals(".text"); }
+        public boolean isData() { return name.equals(".data") || name.equals(".sdata") || name.equals(".rodata") || name.equals(".ctors") || name.equals(".dtors"); }
+        public boolean isBSS() { return name.equals(".bss") || name.equals(".sbss"); }
+    }
+    
+    public ELF(String file) throws IOException, ELFException { this(new SeekableFile(file,false)); }
+    public ELF(SeekableData data) throws IOException, ELFException {
+        this.data = data;
+        ident = new ELFIdent();
+        header = new ELFHeader();
+        pheaders = new PHeader[header.phnum];
+        for(int i=0;i<header.phnum;i++) {
+            data.seek(header.phoff+i*header.phentsize);
+            pheaders[i] = new PHeader();
+        }
+        sheaders = new SHeader[header.shnum];
+        for(int i=0;i<header.shnum;i++) {
+            data.seek(header.shoff+i*header.shentsize);
+            sheaders[i] = new SHeader();
+        }
+        if(header.shstrndx < 0 || header.shstrndx >= header.shnum) throw new ELFException("Bad shstrndx");
+        data.seek(sheaders[header.shstrndx].offset);
+        stringTable = new byte[sheaders[header.shstrndx].size];
+        readFully(stringTable);
+        
+        for(int i=0;i<header.shnum;i++) {
+            SHeader s = sheaders[i];
+            s.name = getString(s.nameidx);
+        }
+    }
+    
+    private String getString(int off) { return getString(off,stringTable); }
+    private String getString(int off,byte[] strtab) {
+        StringBuffer sb = new StringBuffer();
+        if(off < 0 || off >= strtab.length) return "<invalid strtab entry>";
+        while(off >= 0 && off < strtab.length && strtab[off] != 0) sb.append((char)strtab[off++]);
+        return sb.toString();
+    }
+    
+    public SHeader sectionWithName(String name) {
+        for(int i=0;i<sheaders.length;i++)
+            if(sheaders[i].name.equals(name))
+                return sheaders[i];
+        return null;
+    }
+    
+    public class ELFException extends IOException { ELFException(String s) { super(s); } }
+    
+    private class SectionInputStream extends InputStream {
+        private int pos;
+        private int maxpos;
+        SectionInputStream(int start, int end) throws IOException {
+            if(sectionReaderActive)
+                throw new IOException("Section reader already active");
+            sectionReaderActive = true;
+            pos = start;
+            data.seek(pos);
+            maxpos = end;
+        }
+        
+        private int bytesLeft() { return maxpos - pos; }
+        public int read() throws IOException {
+            byte[] buf = new byte[1];
+            return read(buf,0,1) == -1 ? -1 : (buf[0]&0xff);
+        }
+        public int read(byte[] b, int off, int len) throws IOException {
+            int n = data.read(b,off,Math.min(len,bytesLeft())); if(n > 0) pos += n; return n;
+        }
+        public void close() { sectionReaderActive = false; }
+    }
+    
+    private Symtab _symtab;
+    public Symtab getSymtab() throws IOException {
+        if(_symtab != null) return _symtab;
+        
+        if(sectionReaderActive) throw new ELFException("Can't read the symtab while a section reader is active");
+        
+        SHeader sh = sectionWithName(".symtab");
+        if(sh == null || sh.type != SHeader.SHT_SYMTAB) return null;
+        
+        SHeader sth = sectionWithName(".strtab");
+        if(sth == null || sth.type != SHeader.SHT_STRTAB) return null;
+        
+        byte[] strtab = new byte[sth.size];
+        DataInputStream dis = new DataInputStream(sth.getInputStream());
+        dis.readFully(strtab);
+        dis.close();
+        
+        return _symtab = new Symtab(sh.offset, sh.size,strtab);
+    }
+    
+    public class  Symtab {
+        public Symbol[] symbols;
+        
+        Symtab(int off, int size, byte[] strtab) throws IOException {
+            data.seek(off);
+            int count = size/16;
+            symbols = new Symbol[count];
+            for(int i=0;i<count;i++) symbols[i] = new Symbol(strtab);
+        }
+        
+        public Symbol getSymbol(String name) {
+            Symbol sym = null;
+            for(int i=0;i<symbols.length;i++) {
+                if(symbols[i].name.equals(name)) {
+                    if(sym == null)
+                        sym = symbols[i];
+                    else
+                        System.err.println("WARNING: Multiple symbol matches for " + name);
+                }
+            }
+            return sym;
+        }
+        
+        public Symbol getGlobalSymbol(String name) {
+            for(int i=0;i<symbols.length;i++) 
+                if(symbols[i].binding == Symbol.STB_GLOBAL && symbols[i].name.equals(name))
+                    return symbols[i];
+            return null;
+        }
+    }
+    
+    public class Symbol {
+        public String name;
+        public int addr;
+        public int size;
+        public byte info;
+        public byte type;
+        public byte binding;
+        public byte other;
+        public SHeader sheader;
+        
+        public final static int STT_FUNC = 2;
+        public final static int STB_GLOBAL = 1;
+        
+        Symbol(byte[] strtab) throws IOException {
+            name = getString(readInt(),strtab);
+            addr = readInt();
+            size = readInt();
+            info = readByte();
+            type = (byte)(info&0xf);
+            binding = (byte)(info>>4);
+            other = readByte();
+            // FEATURE: This should point to some other entry or something
+            readShort();
+        }
+    }
+    
+    private static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
+    
+    public static void main(String[] args) throws IOException {
+        ELF elf = new ELF(new SeekableInputStream(new FileInputStream(args[0])));
+        System.out.println("Type: " + toHex(elf.header.type));
+        System.out.println("Machine: " + toHex(elf.header.machine));
+        System.out.println("Entry: " + toHex(elf.header.entry));
+        for(int i=0;i<elf.pheaders.length;i++) {
+            ELF.PHeader ph = elf.pheaders[i];
+            System.out.println("PHeader " + toHex(i));
+            System.out.println("\tOffset: " + ph.offset);
+            System.out.println("\tVaddr: " + toHex(ph.vaddr));
+            System.out.println("\tFile Size: " + ph.filesz);
+            System.out.println("\tMem Size: " + ph.memsz);
+        }
+        for(int i=0;i<elf.sheaders.length;i++) {
+            ELF.SHeader sh = elf.sheaders[i];
+            System.out.println("SHeader " + toHex(i));
+            System.out.println("\tName: " + sh.name);
+            System.out.println("\tOffset: " + sh.offset);
+            System.out.println("\tAddr: " + toHex(sh.addr));
+            System.out.println("\tSize: " + sh.size);
+            System.out.println("\tType: " + toHex(sh.type));
+        }
+        Symtab symtab = elf.getSymtab();
+        if(symtab != null) {
+            System.out.println("Symbol table:");
+            for(int i=0;i<symtab.symbols.length;i++)
+                System.out.println("\t" + symtab.symbols[i].name + " -> " + toHex(symtab.symbols[i].addr));
+        } else {
+            System.out.println("Symbol table: None");
+        }
+    }
+}
diff --git a/src/org/xwt/mips/Interpreter.java b/src/org/xwt/mips/Interpreter.java
new file mode 100644 (file)
index 0000000..f95df92
--- /dev/null
@@ -0,0 +1,757 @@
+// Copyright 2003 Brian Alliet
+// Based on org.xwt.imp.MIPS by Adam Megacz
+// Portions Copyright 2003 Adam Megacz
+
+package org.xwt.mips;
+
+import org.xwt.mips.util.*;
+import java.io.*;
+
+public class Interpreter extends UnixRuntime {
+    // Registers
+    private int[] registers = new int[32];
+    private int hi,lo;
+    
+    // Floating Point Registers
+    private int[] fpregs = new int[32];
+    // 24-31 - unused
+    // 23 - conditional bit
+    // 18-22 - unused
+    // 12-17 - cause bits (unimplemented)
+    // 7-11  - enables bits (unimplemented)
+    // 2-6   - flags (unimplemented)
+    // 0-1   - rounding mode (only implemented for fixed point conversions)
+    private int fcsr;
+    
+    private int pc;
+    
+    // The filename if the binary we're running
+    public String image;
+    private ELF.Symtab symtab;
+    
+    // Register Operations
+    private final void setFC(boolean b) { fcsr = (fcsr&~0x800000) | (b ? 0x800000 : 0x000000); }
+    private final int roundingMode() { return fcsr & 3; /* bits 0-1 */ }
+    private final double getDouble(int r) {
+        return Double.longBitsToDouble(((fpregs[r+1]&0xffffffffL) << 32) | (fpregs[r]&0xffffffffL));
+    }
+    private final void setDouble(int r, double d) {
+        long l = Double.doubleToLongBits(d);
+        fpregs[r+1] = (int)(l >>> 32); fpregs[r] = (int)l;
+    }
+    private final float getFloat(int r) { return Float.intBitsToFloat(fpregs[r]); }
+    private final void setFloat(int r, float f) { fpregs[r] = Float.floatToRawIntBits(f); }
+    
+    protected void _execute() throws ExecutionException {
+        try {
+            runSome();
+        } catch(ExecutionException e) {
+            e.setLocation(toHex(pc) + ": " + sourceLine(pc));
+            throw e;
+        }
+    }
+    
+    // Main interpretor
+    // the return value is meaningless, its just to catch people typing "return" by accident
+    private final int runSome() throws FaultException,ExecutionException {
+        int[] r = registers;
+        int[] f = fpregs;
+        int pc = this.pc;
+        int nextPC = pc + 4;
+    try {
+    OUTER: for(;;) {
+        int insn;
+        try {
+            insn = readPages[pc>>>PAGE_SHIFT][(pc>>>2)&PAGE_WORDS-1];
+        } catch (RuntimeException e) {
+            insn = memRead(pc);
+        }
+
+        int op = (insn >>> 26) & 0xff;                 // bits 26-31
+        int rs = (insn >>> 21) & 0x1f;                 // bits 21-25
+        int rt = (insn >>> 16) & 0x1f;                 // bits 16-20 
+        int ft = (insn >>> 16) & 0x1f;
+        int rd = (insn >>> 11) & 0x1f;                 // bits 11-15
+        int fs = (insn >>> 11) & 0x1f;
+        int shamt = (insn >>> 6) & 0x1f;               // bits 6-10
+        int fd = (insn >>> 6) & 0x1f;
+        int subcode = insn & 0x3f;                     // bits 0-5  
+
+        int jumpTarget = (insn & 0x03ffffff);          // bits 0-25
+        int unsignedImmediate = insn & 0xffff;
+        int signedImmediate = (insn << 16) >> 16;
+        int branchTarget = signedImmediate;
+
+        int tmp, addr; // temporaries
+        
+        r[ZERO] = 0;
+    
+        switch(op) {
+            case 0: {
+                switch(subcode) {
+                    case 0: // SLL
+                        if(insn == 0) break;
+                        r[rd] = r[rt] << shamt;
+                        break;
+                    case 2: // SRL
+                        r[rd] = r[rt] >>> shamt;
+                        break;
+                    case 3: // SRA
+                        r[rd] = r[rt] >> shamt;
+                        break;
+                    case 4: // SLLV
+                        r[rd] = r[rt] << (r[rs]&0x1f);
+                        break;
+                    case 6: // SRLV
+                        r[rd] = r[rt] >>> (r[rs]&0x1f);
+                        break;
+                    case 7: // SRAV
+                        r[rd] = r[rt] >> (r[rs]&0x1f);
+                        break;
+                    case 8: // JR
+                        tmp = r[rs]; pc += 4; nextPC = tmp;
+                        continue OUTER;
+                    case 9: // JALR
+                        tmp = r[rs]; pc += 4; r[rd] = pc+4; nextPC = tmp;
+                        continue OUTER;
+                    case 12: // SYSCALL
+                        this.pc = pc;
+                        r[V0] = syscall(r[V0],r[A0],r[A1],r[A2],r[A3]);
+                        if(state != RUNNING) { this.pc = nextPC; break OUTER; }
+                        break;
+                    case 13: // BREAK
+                        throw new ExecutionException("Break");
+                    case 16: // MFHI
+                        r[rd] = hi;
+                        break;
+                    case 17: // MTHI
+                        hi = r[rs];
+                        break;
+                    case 18: // MFLO
+                        r[rd] = lo;
+                        break;
+                    case 19: // MTLO
+                        lo = r[rs];
+                        break;
+                    case 24: { // MULT
+                        long hilo = (long)(r[rs]) * ((long)r[rt]);
+                        hi = (int) (hilo >>> 32);
+                        lo = (int) hilo;
+                        break;
+                    }
+                    case 25: { // MULTU
+                        long hilo = (r[rs] & 0xffffffffL) * (r[rt] & 0xffffffffL);
+                        hi = (int) (hilo >>> 32);
+                        lo = (int) hilo;
+                        break;
+                    }
+                    case 26: // DIV
+                        hi = r[rs]%r[rt];
+                        lo = r[rs]/r[rt];
+                        break;
+                    case 27: // DIVU
+                        if(rt != 0) {
+                            hi = (int)((r[rs] & 0xffffffffL) % (r[rt] & 0xffffffffL));
+                            lo = (int)((r[rs] & 0xffffffffL) / (r[rt] & 0xffffffffL));
+                        }
+                        break;
+                    case 32: // ADD
+                        throw new ExecutionException("ADD (add with oveflow trap) not suported");
+                        /*This must trap on overflow
+                        r[rd] = r[rs] + r[rt];
+                        break;*/
+                    case 33: // ADDU
+                        r[rd] = r[rs] + r[rt];
+                        break;
+                    case 34: // SUB
+                        throw new ExecutionException("SUB (sub with oveflow trap) not suported");
+                        /*This must trap on overflow
+                        r[rd] = r[rs] - r[rt];
+                        break;*/
+                    case 35: // SUBU
+                        r[rd] = r[rs] - r[rt];
+                        break;
+                    case 36: // AND
+                        r[rd] = r[rs] & r[rt];
+                        break;
+                    case 37: // OR
+                        r[rd] = r[rs] | r[rt];
+                        break;
+                    case 38: // XOR
+                        r[rd] = r[rs] ^ r[rt];
+                        break;
+                    case 39: // NOR
+                        r[rd] = ~(r[rs] | r[rt]);
+                        break;
+                    case 42: // SLT
+                        r[rd] = r[rs] < r[rt] ? 1 : 0;
+                        break;
+                    case 43: // SLTU
+                        r[rd] = ((r[rs] & 0xffffffffL) < (r[rt] & 0xffffffffL)) ? 1 : 0;
+                        break;
+                    default:
+                        throw new ExecutionException("Illegal instruction 0/" + subcode);
+                }
+                break;
+            }
+            case 1: {
+                switch(rt) {
+                    case 0: // BLTZ
+                        if(r[rs] < 0) {
+                            pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;                   
+                            continue OUTER;
+                        }
+                        break;
+                    case 1: // BGEZ
+                        if(r[rs] >= 0) {
+                            pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
+                            continue OUTER;
+                        }
+                        break;
+                    case 16: // BLTZAL
+                        if(r[rs] < 0) {
+                            pc += 4; r[RA] = pc+4; tmp = pc + branchTarget*4; nextPC = tmp;
+                            continue OUTER;
+                        }
+                        break;
+                    case 17: // BGEZAL
+                        if(r[rs] >= 0) {
+                            pc += 4; r[RA] = pc+4; tmp = pc + branchTarget*4; nextPC = tmp;  
+                            continue OUTER;
+                        }
+                        break;
+                    default:
+                        throw new ExecutionException("Illegal Instruction");
+                }
+                break;
+            }
+            case 2: { // J
+                tmp = (pc&0xf0000000) | (jumpTarget << 2);
+                pc+=4; nextPC = tmp;
+                continue OUTER;
+            }
+            case 3: { // JAL
+                tmp = (pc&0xf0000000) | (jumpTarget << 2);
+                pc+=4; r[RA] = pc+4; nextPC = tmp;
+                continue OUTER;
+            }
+            case 4: // BEQ
+                if(r[rs] == r[rt]) {
+                    pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
+                    continue OUTER;
+                }
+                break;
+            case 5: // BNE                
+                if(r[rs] != r[rt]) {
+                    pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; 
+                    continue OUTER;
+                }
+                break;
+            case 6: //BLEZ
+                if(r[rs] <= 0) {
+                    pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
+                    continue OUTER;
+                }
+                break;
+            case 7: //BGTZ
+                if(r[rs] > 0) {
+                    pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
+                    continue OUTER;
+                }
+                break;
+            case 8: // ADDI
+                r[rt] = r[rs] + signedImmediate;
+                break;
+            case 9: // ADDIU
+                r[rt] = r[rs] + signedImmediate;
+                break;
+            case 10: // SLTI
+                r[rt] = r[rs] < signedImmediate ? 1 : 0;
+                break;
+            case 11: // SLTIU
+                r[rt] = (r[rs]&0xffffffffL) < (unsignedImmediate&0xffffffffL) ? 1 : 0;
+                break;
+            case 12: // ANDI
+                r[rt] = r[rs] & unsignedImmediate;
+                break;
+            case 13: // ORI
+                r[rt] = r[rs] | unsignedImmediate;
+                break;
+            case 14: // XORI
+                r[rt] = r[rs] ^ unsignedImmediate;
+                break;
+            case 15: // LUI
+                r[rt] = unsignedImmediate << 16;
+                break;
+            case 16:
+                throw new ExecutionException("TLB/Exception support not implemented");
+            case 17: { // FPU
+                boolean debug = false;
+                String line = debug ? sourceLine(pc) : "";
+                boolean debugon = debug && (line.indexOf("dtoa.c:51") >= 0 || line.indexOf("dtoa.c:52") >= 0 || line.indexOf("test.c") >= 0);
+                if(rs > 8 && debugon)
+                    System.out.println("               FP Op: " + op + "/" + rs + "/" + subcode + " " + line);
+                if(roundingMode() != 0 && rs != 6 /*CTC.1*/ && !((rs==16 || rs==17) && subcode == 36 /* CVT.W.Z */))
+                    throw new ExecutionException("Non-cvt.w.z operation attempted with roundingMode != round to nearest");
+                switch(rs) {
+                    case 0: // MFC.1
+                        r[rt] = f[rd];
+                        break;
+                    case 2: // CFC.1
+                        if(fs != 31) throw new ExecutionException("FCR " + fs + " unavailable");
+                        r[rt] = fcsr;
+                        break;
+                    case 4: // MTC.1
+                        f[rd] = r[rt];
+                        break;
+                    case 6: // CTC.1
+                        if(fs != 31) throw new ExecutionException("FCR " + fs + " unavailable");
+                        fcsr = r[rt];   
+                        break;
+                    case 8: // BC1F, BC1T
+                        if(((fcsr&0x800000)!=0) == (((insn>>>16)&1)!=0)) {
+                            pc += 4; tmp = pc + branchTarget*4; nextPC = tmp;
+                            continue OUTER;
+                        }
+                        break;
+                    case 16: {  // Single
+                        switch(subcode) {
+                            case 0: // ADD.S
+                                setFloat(fd,getFloat(fs)+getFloat(ft));
+                                break;
+                            case 1: // SUB.S
+                                setFloat(fd,getFloat(fs)-getFloat(ft));
+                                break;
+                            case 2: // MUL.S
+                                setFloat(fd,getFloat(fs)*getFloat(ft));
+                                break;
+                            case 3: // DIV.S
+                                setFloat(fd,getFloat(fs)/getFloat(ft));
+                                break;
+                            case 5: // ABS.S
+                                setFloat(fd,Math.abs(getFloat(fs)));
+                                break;
+                            case 6: // MOV.S
+                                f[fd] = f[fs];
+                                break;
+                            case 7: // NEG.S
+                                setFloat(fd,-getFloat(fs));
+                                break;
+                            case 33: // CVT.D.S
+                                setDouble(fd,getFloat(fs));
+                                break;
+                            case 36: // CVT.W.S
+                                switch(roundingMode()) {
+                                    case 0: f[fd] = (int)Math.floor(getFloat(fs)+0.5f); break; // Round to nearest
+                                    case 1: f[fd] = (int)getFloat(fs); break; // Round towards zero
+                                    case 2: f[fd] = (int)Math.ceil(getFloat(fs)); break; // Round towards plus infinity
+                                    case 3: f[fd] = (int)Math.floor(getFloat(fs)); break; // Round towards minus infinity
+                                }
+                                break;
+                            case 50: // C.EQ.S
+                                setFC(getFloat(fs) == getFloat(ft));
+                                break;
+                            case 60: // C.LT.S
+                                setFC(getFloat(fs) < getFloat(ft));
+                                break;
+                            default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc));
+                        }
+                        break;
+                    }
+                    case 17: { // Double
+                        switch(subcode) {
+                            case 0: // ADD.D
+                                setDouble(fd,getDouble(fs)+getDouble(ft));
+                                break;
+                            case 1: // SUB.D
+                                if(debugon) System.out.println("f" + fd + " = f" + fs + " (" + getDouble(fs) + ") - f" + ft + " (" + getDouble(ft) + ")");
+                                setDouble(fd,getDouble(fs)-getDouble(ft));
+                                break;
+                            case 2: // MUL.D
+                                if(debugon) System.out.println("f" + fd + " = f" + fs + " (" + getDouble(fs) + ") * f" + ft + " (" + getDouble(ft) + ")");
+                                setDouble(fd,getDouble(fs)*getDouble(ft));
+                                if(debugon) System.out.println("f" + fd + " = " + getDouble(fd));
+                                break;
+                            case 3: // DIV.D
+                                setDouble(fd,getDouble(fs)/getDouble(ft));
+                                break;
+                            case 5: // ABS.D
+                                setDouble(fd,Math.abs(getDouble(fs)));
+                                break;
+                            case 6: // MOV.D
+                                f[fd] = f[fs];
+                                f[fd+1] = f[fs+1];
+                                break;
+                            case 7: // NEG.D
+                                setDouble(fd,-getDouble(fs));
+                                break;
+                            case 32: // CVT.S.D
+                                setFloat(fd,(float)getDouble(fs));
+                                break;
+                            case 36: // CVT.W.D
+                                if(debugon) System.out.println("CVT.W.D rm: " + roundingMode() + " f" + fs + ":" + getDouble(fs));
+                                switch(roundingMode()) {
+                                    case 0: f[fd] = (int)Math.floor(getDouble(fs)+0.5); break; // Round to nearest
+                                    case 1: f[fd] = (int)getDouble(fs); break; // Round towards zero
+                                    case 2: f[fd] = (int)Math.ceil(getDouble(fs)); break; // Round towards plus infinity
+                                    case 3: f[fd] = (int)Math.floor(getDouble(fs)); break; // Round towards minus infinity
+                                }
+                                if(debugon) System.out.println("CVT.W.D: f" + fd + ":" + f[fd]);
+                                break;
+                            case 50: // C.EQ.D
+                                setFC(getDouble(fs) == getDouble(ft));
+                                break;
+                            case 60: // C.LT.D
+                                setFC(getDouble(fs) < getDouble(ft));
+                                break;
+                            case 62: // C.LE.D
+                                setFC(getDouble(fs) <= getDouble(ft));
+                                break;                                
+                            default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc));
+                        }
+                        break;
+                    }
+                    case 20: { // Integer
+                        switch(subcode) {
+                            case 33: // CVT.D.W
+                                setDouble(fd,f[fs]);
+                                break;
+                            default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc));
+                        }
+                        break;
+                    }
+                    default:
+                        throw new ExecutionException("Invalid Instruction 17/" + rs);
+                }
+                break;
+            }
+            case 18: case 19:
+                throw new ExecutionException("No coprocessor installed");
+            case 32: { // LB
+                addr = r[rs] + signedImmediate;
+                try {
+                    tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
+                } catch(RuntimeException e) {
+                    tmp = memRead(addr&~3);
+                }
+                switch(addr&3) {
+                    case 0: tmp = (tmp>>>24)&0xff; break;
+                    case 1: tmp = (tmp>>>16)&0xff; break;
+                    case 2: tmp = (tmp>>> 8)&0xff; break;
+                    case 3: tmp = (tmp>>> 0)&0xff; break;
+                }
+                if((tmp&0x80)!=0) tmp |= 0xffffff00; // sign extend
+                r[rt] = tmp;
+                break;
+            }
+            case 33: { // LH
+                addr = r[rs] + signedImmediate;
+                try {
+                    tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
+                } catch(RuntimeException e) {
+                    tmp = memRead(addr&~3);
+                }
+                switch(addr&2) {
+                    case 0: tmp = (tmp>>>16)&0xffff; break;
+                    case 2: tmp = (tmp>>> 0)&0xffff; break;
+                }
+                if((tmp&0x8000)!=0) tmp |= 0xffff0000; // sign extend
+                r[rt] = tmp;
+                break;              
+            }
+            case 34: { // LWL;
+                addr = r[rs] + signedImmediate;
+                try {
+                    tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
+                } catch(RuntimeException e) {
+                    tmp = memRead(addr&~3);
+                }
+                switch(addr&3) {
+                    case 0: r[rt] = (r[rt]&0x00000000)|(tmp<< 0); break;
+                    case 1: r[rt] = (r[rt]&0x000000ff)|(tmp<< 8); break;
+                    case 2: r[rt] = (r[rt]&0x0000ffff)|(tmp<<16); break;
+                    case 3: r[rt] = (r[rt]&0x00ffffff)|(tmp<<24); break;
+                }
+                break;
+            }
+            case 35: // LW
+                addr = r[rs] + signedImmediate;
+                try {
+                    r[rt] = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
+                } catch(RuntimeException e) {
+                    r[rt] = memRead(addr);
+                }
+                break;
+            case 36: { // LBU
+                addr = r[rs] + signedImmediate;
+                try {
+                    tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
+                } catch(RuntimeException e) {
+                    tmp = memRead(addr);
+                }
+                switch(addr&3) {
+                    case 0: r[rt] = (tmp>>>24)&0xff; break;
+                    case 1: r[rt] = (tmp>>>16)&0xff; break;
+                    case 2: r[rt] = (tmp>>> 8)&0xff; break;
+                    case 3: r[rt] = (tmp>>> 0)&0xff; break;
+                }
+                break;
+            }
+            case 37: { // LHU
+                addr = r[rs] + signedImmediate;
+                try {
+                    tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
+                } catch(RuntimeException e) {
+                    tmp = memRead(addr&~3);
+                }
+                switch(addr&2) {
+                    case 0: r[rt] = (tmp>>>16)&0xffff; break;
+                    case 2: r[rt] = (tmp>>> 0)&0xffff; break;
+                }
+                break;
+            }
+            case 38: { // LWR
+                addr = r[rs] + signedImmediate;
+                try {
+                    tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
+                } catch(RuntimeException e) {
+                    tmp = memRead(addr&~3);
+                }
+                switch(addr&3) {
+                    case 0: r[rt] = (r[rt]&0xffffff00)|(tmp>>>24); break;
+                    case 1: r[rt] = (r[rt]&0xffff0000)|(tmp>>>16); break;
+                    case 2: r[rt] = (r[rt]&0xff000000)|(tmp>>> 8); break;
+                    case 3: r[rt] = (r[rt]&0x00000000)|(tmp>>> 0); break;
+                }
+                break;
+            }
+            case 40: { // SB
+                addr = r[rs] + signedImmediate;
+                try {
+                    tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
+                } catch(RuntimeException e) {
+                    tmp = memRead(addr&~3);
+                }
+                switch(addr&3) {
+                    case 0: tmp = (tmp&0x00ffffff) | ((r[rt]&0xff)<<24); break;
+                    case 1: tmp = (tmp&0xff00ffff) | ((r[rt]&0xff)<<16); break;
+                    case 2: tmp = (tmp&0xffff00ff) | ((r[rt]&0xff)<< 8); break;
+                    case 3: tmp = (tmp&0xffffff00) | ((r[rt]&0xff)<< 0); break;
+                }
+                try {
+                    writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp;
+                } catch(RuntimeException e) {
+                    memWrite(addr&~3,tmp);
+                }
+                break;
+            }
+            case 41: { // SH
+                addr = r[rs] + signedImmediate;
+                try {
+                    tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
+                } catch(RuntimeException e) {
+                    tmp = memRead(addr&~3);
+                }
+                switch(addr&2) {
+                    case 0: tmp = (tmp&0x0000ffff) | ((r[rt]&0xffff)<<16); break;
+                    case 2: tmp = (tmp&0xffff0000) | ((r[rt]&0xffff)<< 0); break;
+                }
+                try {
+                    writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp;
+                } catch(RuntimeException e) {
+                    memWrite(addr&~3,tmp);
+                }
+                break;
+            }
+            case 42: { // SWL
+                addr = r[rs] + signedImmediate;
+                tmp = memRead(addr&~3);
+                switch(addr&3) {
+                    case 0: tmp=(tmp&0x00000000)|(r[rt]>>> 0); break;
+                    case 1: tmp=(tmp&0xff000000)|(r[rt]>>> 8); break;
+                    case 2: tmp=(tmp&0xffff0000)|(r[rt]>>>16); break;
+                    case 3: tmp=(tmp&0xffffff00)|(r[rt]>>>24); break;
+                }
+                try {
+                    writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp;
+                } catch(RuntimeException e) {
+                    memWrite(addr&~3,tmp);
+                }
+                break;
+            }
+            case 43: // SW
+                addr = r[rs] + signedImmediate;
+                try {
+                    writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = r[rt];
+                } catch(RuntimeException e) {
+                    memWrite(addr&~3,r[rt]);
+                }
+                break;
+            case 46: { // SWR
+                addr = r[rs] + signedImmediate;
+                tmp = memRead(addr&~3);
+                switch(addr&3) {
+                    case 0: tmp=(tmp&0x00ffffff)|(r[rt]<<24); break;
+                    case 1: tmp=(tmp&0x0000ffff)|(r[rt]<<16); break;
+                    case 2: tmp=(tmp&0x000000ff)|(r[rt]<< 8); break;
+                    case 3: tmp=(tmp&0x00000000)|(r[rt]<< 0); break;
+                }
+                memWrite(addr&~3,tmp);
+                break;
+            }
+            // FEATURE: Needs to be atomic w/ threads
+            case 48: // LWC0/LL
+                r[rt] = memRead(r[rs] + signedImmediate);
+                break;
+            case 49: // LWC1
+                f[rt] = memRead(r[rs] + signedImmediate);
+                break;
+            // FEATURE: Needs to be atomic w/ threads
+            case 56:
+                memWrite(r[rs] + signedImmediate,r[rt]);
+                r[rt] = 1;
+                break;
+            case 57: // SWC1
+                memWrite(r[rs] + signedImmediate,f[rt]);
+                break;
+            default:
+                throw new ExecutionException("Invalid Instruction: " + op);
+        }
+        pc = nextPC;
+        nextPC = pc + 4;
+    } // for(;;)
+    } catch(ExecutionException e) {
+        this.pc = pc;
+        throw e;
+    }
+        return 0;
+    }
+    
+    public int lookupSymbol(String name) {
+        ELF.Symbol sym = symtab.getGlobalSymbol(name);
+        return sym == null ? -1 : sym.addr;
+    }
+    
+    // Image loading function
+    private void loadImage(SeekableData data) throws IOException {
+        if(state != UNINITIALIZED) throw new IllegalStateException("loadImage called on initialized runtime");
+        
+        ELF elf = new ELF(data);
+        symtab = elf.getSymtab();
+        
+        if(elf.header.type != ELF.ELFHeader.ET_EXEC) throw new IOException("Binary is not an executable");
+        if(elf.header.machine != ELF.ELFHeader.EM_MIPS) throw new IOException("Binary is not for the MIPS I Architecture");
+        if(elf.ident.data != ELF.ELFIdent.ELFDATA2MSB) throw new IOException("Binary is not big endian");
+        
+        entryPoint = elf.header.entry;
+        
+        ELF.Symtab symtab = elf.getSymtab();
+        if(symtab == null) throw new IOException("No symtab in binary (did you strip it?)");
+        ELF.Symbol userInfo = symtab.getGlobalSymbol("user_info");
+        ELF.Symbol gpsym = symtab.getGlobalSymbol("_gp");
+        
+        if(gpsym == null) throw new IOException("NO _gp symbol!");
+        gp = gpsym.addr;
+        
+        if(userInfo != null) {
+            userInfoBase = userInfo.addr;
+            userInfoSize = userInfo.size;
+        }
+        
+        ELF.PHeader[] pheaders = elf.pheaders;
+        int brk = 0;
+        for(int i=0;i<pheaders.length;i++) {
+            ELF.PHeader ph = pheaders[i];
+            if(ph.type != ELF.PHeader.PT_LOAD) continue;
+            int memsize = ph.memsz;
+            int filesize = ph.filesz;
+            if(memsize == 0) continue;
+            if(memsize < 0) throw new IOException("pheader size too large");
+            int addr = ph.vaddr;
+            if(addr == 0x0) throw new IOException("pheader vaddr == 0x0");
+            brk = max(addr+memsize,brk);
+            
+            for(int j=0;j<memsize+PAGE_SIZE-1;j+=PAGE_SIZE) {
+                int page = (j+addr) >>> PAGE_SHIFT;
+                if(readPages[page] == null)
+                    readPages[page] = new int[PAGE_WORDS];
+                if(ph.writable()) writePages[page] = readPages[page];
+            }
+            if(filesize != 0) {
+                filesize = filesize & ~3;
+                DataInputStream dis = new DataInputStream(ph.getInputStream());
+                do {
+                    readPages[addr >>> PAGE_SHIFT][(addr >>> 2)&(PAGE_WORDS-1)] = dis.readInt();
+                    addr+=4;
+                    filesize-=4;
+                } while(filesize > 0);
+                dis.close();
+            }
+        }
+        brkAddr = (brk+PAGE_SIZE-1)&~(PAGE_SIZE-1);
+        state = INITIALIZED;
+    }
+    
+    protected void setCPUState(CPUState state) {
+        for(int i=1;i<32;i++) registers[i] = state.r[i];
+        for(int i=0;i<32;i++) fpregs[i] = state.f[i];
+        hi=state.hi; lo=state.lo; fcsr=state.fcsr;
+        pc=state.pc;
+    }
+    
+    protected CPUState getCPUState() {
+        CPUState state = new CPUState();
+        for(int i=1;i<32;i++) state.r[i] = registers[i];
+        for(int i=0;i<32;i++) state.f[i] = fpregs[i];
+        state.hi=hi; state.lo=lo; state.fcsr=fcsr;
+        state.pc=pc;
+        return state;
+    }
+    
+    // This is package private for fork() which does all kinds of ugly things behind the scenes
+    Interpreter() { super(4096,65536,true); }
+    public Interpreter(SeekableData data) throws IOException { this(); loadImage(data); }
+    public Interpreter(String filename) throws IOException {
+        this(new SeekableFile(filename,false));
+        image = filename;
+    }
+    public Interpreter(InputStream is) throws IOException { this(new SeekableInputStream(is)); }
+    
+    // Debug functions
+    // NOTE: This probably requires a jdk > 1.1, however, it is only used for debugging
+    private java.util.HashMap sourceLineCache;
+    public String sourceLine(int pc) {
+        final String addr2line = "mips-unknown-elf-addr2line";
+        String line = (String) (sourceLineCache == null ? null : sourceLineCache.get(new Integer(pc)));
+        if(line != null) return line;
+        if(image==null) return null;
+        try {
+            Process p = java.lang.Runtime.getRuntime().exec(new String[]{addr2line,"-e",image,toHex(pc)});
+            line = new BufferedReader(new InputStreamReader(p.getInputStream())).readLine();
+            if(line == null) return null;
+            while(line.startsWith("../")) line = line.substring(3);
+            if(sourceLineCache == null) sourceLineCache = new java.util.HashMap();
+            sourceLineCache.put(new Integer(pc),line);
+            return line;
+        } catch(IOException e) {
+            return null;
+        }
+    }
+    
+    public class DebugShutdownHook implements Runnable {
+        public void run() {
+            int pc = Interpreter.this.pc;
+            if(getState() == RUNNING)
+                System.err.print("\nCPU Executing " + toHex(pc) + ": " + sourceLine(pc) + "\n");
+        }
+    }
+
+    public static void main(String[] argv) throws Exception {
+        String image = argv[0];
+        Interpreter emu = new Interpreter(image);
+        java.lang.Runtime.getRuntime().addShutdownHook(new Thread(emu.new DebugShutdownHook()));
+        int status = emu.run(argv);
+        System.err.println("Exit status: " + status);
+        System.exit(status);
+    }
+}
diff --git a/src/org/xwt/mips/JavaSourceCompiler.java b/src/org/xwt/mips/JavaSourceCompiler.java
new file mode 100644 (file)
index 0000000..5bf7e5d
--- /dev/null
@@ -0,0 +1,933 @@
+package org.xwt.mips;
+
+import java.util.*;
+import java.io.*;
+import org.xwt.mips.util.SeekableData;
+
+public class JavaSourceCompiler extends Compiler {
+    /** Stores the "case r XXX: ... run_YYYY();" blocks generated by the emitText method/ */
+    private StringBuffer runs = new StringBuffer();
+    /** Stores the "initData" and "cleadData" calls generated by the emitData and emitBSS methods */
+    private StringBuffer inits = new StringBuffer();
+    /** Stores lines to go in the class scope */
+    private StringBuffer classLevel = new StringBuffer();
+    
+    /** The stream to write the compiled output to */
+    private PrintWriter out;
+
+    /** Prints a blank line to the output stream */
+    private void p() { out.println(); }
+    /** prints the given string (indented by <i>indent</i>*4 spaces) to the output stream */ 
+    private void p(String s) { out.println(indents[indent] + s); }
+    private void pblock(StringBuffer sb) { out.print(sb.toString()); }
+    
+    /** Used by the p() method to add indentation */
+    private int indent;
+    
+    private static String indents[] = new String[16];
+    static { String s=""; for(int i=0;i<indents.length;i++,s=s+"    ") indents[i] = s; }
+    
+    public JavaSourceCompiler(SeekableData binary, String className, Writer w)  throws IOException {
+        super(binary,className);
+        out = new PrintWriter(w);
+    }
+    
+    protected void _go() throws Exn, IOException {
+        String packageName;
+        String className;
+        if (fullClassName.indexOf('.') != -1) {
+            packageName = fullClassName.substring(0, fullClassName.lastIndexOf('.'));
+            className = fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
+        } else {
+            className = fullClassName;
+            packageName = null;
+        }
+        
+        p("/* This file was generated from " + source + " by Mips2Java on " + dateTime() + " */");
+        if (packageName != null) p("package " + packageName + ";");
+        if(runtimeStats) p("import java.util.*;");
+        p();
+        p("public class " + className + " extends " + runtimeClass + " {");
+        indent++;
+        
+        p("/* program counter */");
+        p("private int pc = 0;");
+        if(debugCompiler)
+            p("private int lastPC = 0;");
+        p();
+        p("/* General Purpose registers */");
+        p("private final static int r0 = 0;");
+        p("private int      r1,  r2,  r3,  r4,  r5,  r6,  r7,");
+        p("            r8,  r9,  r10, r11, r12, r13, r14, r15,");
+        p("            r16, r17, r18, r19, r20, r21, r22, r23,");
+        p("            r24, r25, r26, r27, r28, r29, r30, r31,");
+        p("            hi = 0, lo = 0;");
+        p("/* FP registers */");
+        p("private int f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,");
+        p("            f8,  f9,  f10, f11, f12, f13, f14, f15,");
+        p("            f16, f17, f18, f19, f20, f21, f22, f23,");
+        p("            f24, f25, f26, f27, f28, f29, f30, f31;");
+        p("/* FP Control Register */");
+        p("private int fcsr = 0;");
+        p();
+        
+        if(onePage) p("private final int[] page = readPages[0];");
+                
+        // Generate main body functions (run_XXXX() blocks, _data[] arrays, etc) 
+        int highestAddr = 0;
+        
+        for(int i=0;i<elf.sheaders.length;i++) {
+            ELF.SHeader sheader = elf.sheaders[i];
+            String name = sheader.name;
+            // if this section doesn't get loaded into our address space don't worry about it
+            if(sheader.addr == 0x0) continue;
+            
+            highestAddr = Math.max(highestAddr, sheader.addr + sheader.size);
+            
+            if(name.equals(".text"))
+                emitText(sheader.addr, new DataInputStream(sheader.getInputStream()),sheader.size);
+            else if(name.equals(".data") || name.equals(".sdata") || name.equals(".rodata") || name.equals(".ctors") || name.equals(".dtors"))
+                emitData(sheader.addr, new DataInputStream(sheader.getInputStream()), sheader.size,name.equals(".rodata")); 
+            else if(name.equals(".bss") || name.equals(".sbss"))                
+                emitBSS(sheader.addr,sheader.size);
+            else
+                throw new Exn("Unknown segment: " + name);
+        }
+        p();
+        
+        pblock(classLevel);
+        p();
+        
+        // Trampoline (dispatch calls to the appropriate run_XXX() methods
+        p("private final void trampoline() throws ExecutionException {");
+        indent++;
+        p("while(state == RUNNING) {");
+        indent++;
+        p("switch(pc>>>" + methodShift+ ") {");
+        indent++;
+        pblock(runs);
+        p("default: throw new ExecutionException(\"invalid address 0x\" + Long.toString(this.pc&0xffffffffL,16) + \": r2: \" + r2);");
+        indent--; p("}");
+        indent--; p("}");
+        indent--; p("}");
+        p();
+        
+        // Constructor
+        p("public " + className + "() {");
+        indent++;
+        p("super(" + pageSize + "," + totalPages + "," + (fastMem?"false":"true") + ");");
+        p("entryPoint = " + toHex(elf.header.entry) + ";");
+        if(userInfo != null) {
+            p("userInfoBase=" + toHex(userInfo.addr) + ";");
+            p("userInfoSize=" + userInfo.size + ";");
+        }
+        p("gp = " + toHex(gp.addr) + ";");
+        if(onePage)
+            p("brkAddr = " + toHex((highestAddr+4095)&~4095) + ";");
+        else
+            p("brkAddr = " + toHex((highestAddr+pageSize-1)&~(pageSize-1)) + ";");
+        pblock(inits);
+        p("state = INITIALIZED;");
+        indent--;
+        p("}");
+        p();
+        
+        // main() function
+        p("public static void main(String[] args) throws Exception {");
+        indent++;
+        p("" + className + " me = new " + className + "();");
+        p("int status = me.run(\"" + fullClassName + "\",args);");
+        if(runtimeStats) p("me.printStats();");
+        p("System.exit(status);");
+        indent--;
+        p("}");
+        p();
+        
+        // Runtime abstract methods
+        p("protected void _execute() throws ExecutionException { trampoline(); }");
+        p();
+        
+        p("protected void setCPUState(CPUState state) {");
+        indent++;
+        for(int i=1;i<32;i++) p("r" + i + "=state.r[" + i + "];");
+        for(int i=0;i<32;i++) p("f" + i + "=state.f[" + i + "];");
+        p("hi=state.hi; lo=state.lo; fcsr=state.fcsr;");
+        p("pc=state.pc;");
+        indent--;
+        p("}");
+        p("protected CPUState getCPUState() {");
+        indent++;
+        p("CPUState state = new CPUState();");
+        for(int i=1;i<32;i++) p("state.r[" + i + "]=r" + i+ ";");
+        for(int i=0;i<32;i++) p("state.f[" + i + "]=f" + i +";");
+        p("state.hi=hi; state.lo=lo; state.fcsr=fcsr;");
+        p("state.pc=pc;");
+        p("return state;");
+        indent--;
+        p("}");
+        p();
+        
+        if(supportCall) {
+            p("private static final " + hashClass + " symbols = new " + hashClass + "();");
+            p("static {");
+            indent++;
+            ELF.Symbol[] symbols = elf.getSymtab().symbols;
+            for(int i=0;i<symbols.length;i++) {
+                ELF.Symbol s = symbols[i];
+                if(s.type == ELF.Symbol.STT_FUNC && s.binding == ELF.Symbol.STB_GLOBAL && (s.name.equals("_call_helper") || !s.name.startsWith("_")))
+                    p("symbols.put(\"" + s.name + "\",new Integer(" + toHex(s.addr) + "));");
+            }
+            indent--;
+            p("}");
+            p("public int lookupSymbol(String symbol) { Integer i = (Integer) symbols.get(symbol); return i==null ? -1 : i.intValue(); }");
+            p();
+        }
+        
+        // Runtime stats
+        if(runtimeStats) {
+            p("private HashMap counters = new HashMap();");
+            p("private void inc(String k) { Long i = (Long)counters.get(k); counters.put(k,new Long(i==null ? 1 : i.longValue() + 1)); }");
+            p("private void printStats() {");
+            p(" Iterator i = new TreeSet(counters.keySet()).iterator();");
+            p(" while(i.hasNext()) { Object o = i.next(); System.err.println(\"\" + o + \": \" + counters.get(o)); }");
+            p("}");
+            p();
+        }
+        
+        indent--;
+        p("}");
+    }
+    
+    private int startOfMethod = 0;
+    private int endOfMethod = 0;
+    
+    private void startMethod(int addr) {
+        addr &= ~(maxBytesPerMethod-1);
+        startOfMethod = addr;
+        endOfMethod = addr + maxBytesPerMethod;
+        String methodName = "run_" + Long.toString(addr & 0xffffffffL, 16);
+        runs.append(indents[4] + "case " + toHex(addr>>>methodShift) + ": " + methodName + "(); break; \n");
+        p("private final void " + methodName + "() throws ExecutionException { /"+"* " + toHex(addr) + " - " + toHex(endOfMethod) + " *" + "/");
+        indent++;
+        p("int addr, tmp;");
+        p("for(;;) {");
+        indent++;
+        p("switch(pc) {");
+        indent++;
+    }
+    
+    private void endMethod() { endMethod(endOfMethod); }
+    private void endMethod(int lastAddr) {
+        if(startOfMethod == 0) return;
+        // FEATURE: We should be able to use if(!unreachable) here (i think)
+        // This isn't strictly necessary; its just here to work around unreachable code errors
+        p("case " + toHex(lastAddr) + ":");
+        indent++;
+        p("pc=" + constant(lastAddr) + ";");
+        leaveMethod();
+        indent--;
+        if(debugCompiler)
+            p("default: throw new ExecutionException(\"invalid address 0x\" + Long.toString(pc&0xffffffffL,16)  + \" (got here from 0x\" + Long.toString(lastPC&0xffffffffL,16)+\")\");");
+        else
+            p("default: throw new ExecutionException(\"invalid address 0x\" + Long.toString(pc&0xffffffffL,16));");
+        indent--;
+        p("}"); // end switch
+        p("/* NOT REACHED */");
+        indent--;
+        p("}"); // end for
+        indent--;
+        p("}"); // end method
+        endOfMethod = startOfMethod = 0;
+    }
+    
+    private HashMap relativeAddrs = new HashMap();  
+    private String constant(int target) {
+        if(target >= 4096 && lessConstants) {
+            int n = target & ~1023;
+            String var = "N_" + toHex8(n);
+            if(relativeAddrs.get(new Integer(n)) == null) {
+                relativeAddrs.put(new Integer(n),Boolean.TRUE);
+                classLevel.append(indents[1] + "private static int " + var + " = " + toHex(n) + ";\n");
+            }
+            return "(" + var + " + " + toHex(target - n) + ")";
+        } else {
+            return toHex(target);
+        }
+    }
+    
+    private void branch(int pc, int target) {
+        if(debugCompiler) p("lastPC = " + toHex(pc) + ";");
+        p("pc=" + constant(target) + ";");
+        if(target == 0)
+            p("throw new ExecutionException(\"Branch to addr 0x0\");");
+        else if((pc&methodMask) == (target&methodMask))
+            p("continue;");
+        else if(assumeTailCalls)
+            p("run_" +  Long.toString((target&methodMask)&0xffffffffL, 16) + "(); return;");
+        else
+            leaveMethod();
+    }
+    
+    private void leaveMethod() {
+        p("return;");
+    }
+    
+    private boolean textDone;
+    private void emitText(int addr, DataInputStream dis, int size) throws Exn,IOException {
+        if(textDone) throw new Exn("Multiple text segments");
+        textDone = true;
+        
+        if((addr&3)!=0 || (size&3)!=0) throw new Exn("Section on weird boundaries");
+        int count = size/4;
+        int nextInsn = dis.readInt();
+        if(nextInsn == -1) throw new Error("Actually read -1 at " + toHex(addr));
+        int insn;
+        
+        for(int i=0;i<count;i++,addr+=4) {
+            insn = nextInsn;
+            nextInsn = (i == count-1) ? -1 : dis.readInt();
+            if(addr >= endOfMethod) { endMethod(); startMethod(addr); }
+            if(jumpableAddresses==null || addr == startOfMethod || jumpableAddresses.contains(new Integer(addr))) {
+                p("case " + toHex(addr) + ":");
+                unreachable = false;
+            } else if(unreachable) {
+                continue;
+            } else if(debugCompiler) {
+                p("/" + "* pc = " + toHex(addr) + "*" + "/");
+            }
+            indent++;
+            emitInstruction(addr,insn,nextInsn);
+            indent--;
+        }
+        endMethod(addr);
+        p();
+        dis.close();
+    }
+    
+    private int initDataCount = 0;
+    private void emitData(int addr, DataInputStream dis, int size, boolean readOnly) throws Exn,IOException {
+        if((addr&3)!=0 || (size&3)!=0) throw new Exn("Data section on weird boundaries");
+        int last = addr + size;
+        while(addr < last) {
+            int segSize = Math.min(size,28000); // must be a multiple of 56
+            StringBuffer sb = new StringBuffer();
+            for(int i=0;i<segSize;i+=7) {
+                long l = 0;
+                for(int j=0;j<7;j++) {
+                    l <<= 8;
+                    byte b = (i+j < size) ? dis.readByte() : 1;
+                    l |= (b & 0xffL);
+                }
+                for(int j=0;j<8;j++) {
+                    char c = (char) ((l>>>(7*(7-j)))&0x7f);
+                    if(c=='\n') sb.append("\\n"); 
+                    else if(c=='\r') sb.append("\\r");
+                    else if(c=='\\') sb.append("\\\\");
+                    else if(c=='"') sb.append("\\\"");
+                    else if(c >= 32 && c <= 126) sb.append(c);
+                    else sb.append("\\" +  toOctal3(c));
+                }
+            }
+            String varname =  "_data" + (++initDataCount);
+            p("private static final int[] " + varname + " = decodeData(\"" + sb.toString() + "\"," + toHex(segSize/4) + ");");
+            inits.append(indents[2] + "initPages(" + varname +"," + toHex(addr) + "," + (readOnly?"true":"false") + ");\n");
+            addr += segSize;
+            size -= segSize;
+        }
+        dis.close();
+    }
+
+    private void emitBSS(int addr, int size) throws Exn {
+        if((addr&3)!=0) throw new Exn("BSS section on weird boundaries");
+        size = (size+3)&~3;
+        int count = size/4;
+        inits.append(indents[2] + "clearPages(" + toHex(addr) + "," + toHex(count) + ");\n");
+    }
+
+    // True if the current code path is unreachable (any instruction with a case statement is reachable)
+    private boolean unreachable = false;
+    
+    private void emitInstruction(int pc, int insn, int nextInsn) throws IOException,Exn {
+        if(insn == -1) throw new Error("insn is -1");
+        
+        int op = (insn >>> 26) & 0xff;                 // bits 26-31
+        int rs = (insn >>> 21) & 0x1f;                 // bits 21-25
+        int rt = (insn >>> 16) & 0x1f;                 // bits 16-20 
+        int ft = (insn >>> 16) & 0x1f;
+        int rd = (insn >>> 11) & 0x1f;                 // bits 11-15
+        int fs = (insn >>> 11) & 0x1f;
+        int shamt = (insn >>> 6) & 0x1f;               // bits 6-10
+        int fd = (insn >>> 6) & 0x1f;
+        int subcode = insn & 0x3f;                     // bits 0-5  
+
+        int jumpTarget = (insn & 0x03ffffff);          // bits 0-25
+        int unsignedImmediate = insn & 0xffff;
+        int signedImmediate = (insn << 16) >> 16;
+        int branchTarget = signedImmediate;
+
+        int tmp; // temporaries
+        
+        //if(pc%64==0) p("System.err.println(\"Executing: " + toHex(pc) + "\");");
+        //p("/" + "*" + (pc == -1 ? "Delay Slot"  : toHex(pc)) + " *" + "/ ");
+        if(pc==-1) p("/" + "* Next insn is delay slot *" + "/ ");
+        
+        if(runtimeStats && op != 0) p("inc(\"opcode: " + op + "\");");
+        switch(op) {
+            case 0: {
+                if(runtimeStats && insn != 0) p("inc(\"opcode: 0/" + subcode + "\");");
+                switch(subcode) {
+                    case 0: // SLL
+                        if(insn != 0) 
+                            p( "r"+rd+" = r"+rt+" << "+shamt+";");
+                        break;
+                    case 2: // SRL
+                        p( "r"+rd+" = r"+rt+" >>> "+shamt+";");
+                        break;
+                    case 3: // SRA
+                        p( "r"+rd+" = r"+rt+" >> "+shamt+";");
+                        break;
+                    case 4: // SLLV
+                        p( "r"+rd+" = r"+rt+" << (r"+rs+"&0x1f);");
+                        break;
+                    case 6: // SRLV
+                        p( "r"+rd+" = r"+rt+" >>> (r"+rs+"&0x1f);");
+                        break;
+                    case 7: // SRAV
+                        p( "r"+rd+" = r"+rt+" >> (r"+rs+"&0x1f);");
+                        break;
+                    case 8: // JR
+                        if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                        emitInstruction(-1,nextInsn,-1);
+                        if(debugCompiler) p("lastPC = " + toHex(pc) + ";");
+                        p("pc=r" + rs + ";");
+                        leaveMethod();
+                        unreachable = true;
+                        break;
+                    case 9: // JALR
+                        if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                        emitInstruction(-1,nextInsn,-1);
+                        if(debugCompiler) p("lastPC = " + toHex(pc) + ";");
+                        p("pc=r" + rs + ";");
+                        p("r" + RA + "=" + constant(pc+8 /*skip this insn and delay slot*/) + ";");
+                        leaveMethod();
+                        unreachable = true;
+                        break;
+                    case 12: // SYSCALL
+                        p("pc = " + toHex(pc) + ";");
+                        p( "r"+V0+" = syscall(r"+V0+",r"+A0+",r"+A1+",r"+A2+",r"+A3+");");
+                        p("if (state != RUNNING) {");
+                            indent++;
+                            p("pc = " + toHex(pc+4) + ";");
+                            leaveMethod();
+                            indent--;
+                        p("}");
+                        break;
+                    case 13: // BREAK
+                        p( "throw new ExecutionException(\"Break\");");
+                        break;
+                    case 16: // MFHI
+                        p( "r"+rd+" = hi;");
+                        break;
+                    case 17: // MTHI
+                        p( "hi = r"+rs+";");
+                        break;
+                    case 18: // MFLO
+                        p( "r"+rd+" = lo;");
+                        break;
+                    case 19: // MTLO
+                        p( "lo = r"+rs+";");
+                        break;
+                    case 24: // MULT
+                        p( "{ long hilo = (long)(r"+rs+") * ((long)r"+rt+"); " +
+                             "hi = (int) (hilo >>> 32); " +
+                             "lo = (int) hilo; }");
+                        break;
+                    case 25: // MULTU
+                        p( "{ long hilo = (r"+rs+" & 0xffffffffL) * (r"+rt+" & 0xffffffffL); " +
+                             "hi = (int) (hilo >>> 32); " +
+                             "lo = (int) hilo; } ");
+                        break;
+                    case 26: // DIV
+                        p( "hi = r"+rs+"%r"+rt+"; lo = r"+rs+"/r"+rt+";");
+                        break;
+                    case 27: // DIVU
+                        p("if(r"+rt+"!=0) {");
+                        p( "hi = (int)((r"+rs+" & 0xffffffffL) % (r"+rt+" & 0xffffffffL)); " +
+                             "lo = (int)((r"+rs+" & 0xffffffffL) / (r"+rt+" & 0xffffffffL));");
+                        p("}");
+                        break;
+                    case 32: // ADD
+                         throw new Exn("ADD (add with oveflow trap) not suported");
+                        /*This must trap on overflow
+                        p( "r"+rd+" = r"+rs+" + r"+rt+";");
+                        break;*/
+                    case 33: // ADDU
+                        p( "r"+rd+" = r"+rs+" + r"+rt+";");
+                        break;
+                    case 34: // SUB
+                         throw new Exn("SUB (add with oveflow trap) not suported");
+                        /*This must trap on overflow
+                        p( "r"+rd+" = r"+rs+" - r"+rt+";");
+                        break;*/
+                    case 35: // SUBU
+                        p( "r"+rd+" = r"+rs+" - r"+rt+";");
+                        break;
+                    case 36: // AND
+                        p( "r"+rd+" = r"+rs+" & r"+rt+";");
+                        break;
+                    case 37: // OR
+                        p( "r"+rd+" = r"+rs+" | r"+rt+";");
+                        break;
+                    case 38: // XOR
+                        p( "r"+rd+" = r"+rs+" ^ r"+rt+";");
+                        break;
+                    case 39: // NOR
+                        p( "r"+rd+" = ~(r"+rs+" | r"+rt+");");
+                        break;
+                    case 42: // SLT
+                        p( "r"+rd+" = r"+rs+" < r"+rt+" ? 1 : 0;");
+                        break;
+                    case 43: // SLTU
+                        p( "r"+rd+" = ((r"+rs+" & 0xffffffffL) < (r"+rt+" & 0xffffffffL)) ? 1 : 0;");
+                        break;
+                    default:
+                        throw new RuntimeException("Illegal instruction 0/" + subcode);
+                }
+                break;
+            }
+            case 1: {
+                switch(rt) {
+                    case 0: // BLTZ
+                        if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                        p("if(r" + rs + " < 0) {");
+                            indent++;
+                            emitInstruction(-1,nextInsn,-1);
+                            branch(pc,pc+branchTarget*4+4);
+                            indent--;
+                        p("}");
+                        break;
+                    case 1: // BGEZ
+                        if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                        p("if(r" + rs + " >= 0) {");
+                            indent++;
+                            emitInstruction(-1,nextInsn,-1);
+                            branch(pc,pc+branchTarget*4+4);
+                            indent--;
+                        p("}");
+                        break;
+                    case 16: // BLTZAL
+                        if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                        p("if(r" + rs + " < 0) {");
+                            indent++;
+                            emitInstruction(-1,nextInsn,-1);
+                            p("r" + RA + "=" + constant(pc+8 /*skip this insn and delay slot*/) + ";");
+                            branch(pc,pc+branchTarget*4+4);
+                            indent--;
+                        p("}");
+                        break;
+                    case 17: // BGEZAL
+                        if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                        p("if(r" + rs + " >= 0) {");
+                            indent++;
+                            emitInstruction(-1,nextInsn,-1);
+                            p("r" + RA + "=" + constant(pc+8 /*skip this insn and delay slot*/) + ";");
+                            branch(pc,pc+branchTarget*4+4);
+                            indent--;
+                        p("}");
+                        break;
+                    default:
+                        throw new RuntimeException("Illegal Instruction 1/" + rt);
+                }
+                break;
+            }
+            case 2: { // J
+                if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                emitInstruction(-1,nextInsn,-1);
+                branch(pc,(pc&0xf0000000)|(jumpTarget << 2));
+                unreachable = true;
+                break;
+            }
+            case 3: { // JAL
+                if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                int target = (pc&0xf0000000)|(jumpTarget << 2);
+                emitInstruction(-1,nextInsn,-1);
+                if(optimizedMemcpy && (target == memcpy || target == memset)) {
+                    if(target == memcpy)
+                        p("memcpy(r4,r5,r6);");
+                    else if(target == memset)
+                        p("memset(r4,r5,r6);");
+                    p("r2 = r4;");
+                    branch(pc,pc+8);
+                } else {
+                    p("r" + RA + "=" + constant(pc+8 /*skip this insn and delay slot*/) + ";");
+                    branch(pc, target);
+                }
+                unreachable = true;
+                break;
+            }
+            case 4: // BEQ
+                if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                p("if(r" + rs + " == r" + rt + ") {");
+                    indent++;
+                    emitInstruction(-1,nextInsn,-1);
+                    branch(pc,pc+branchTarget*4+4);
+                    indent--;
+                p("}");
+                break;
+            case 5: // BNE       
+                if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                p("if(r" + rs + " != r" + rt + ") {");
+                    indent++;
+                    emitInstruction(-1,nextInsn,-1);
+                    branch(pc,pc+branchTarget*4+4);
+                    indent--;
+                p("}");
+                break;
+            case 6: //BLEZ
+                if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                p("if(r" + rs + " <= 0) {");
+                    indent++;
+                    emitInstruction(-1,nextInsn,-1);
+                    branch(pc,pc+branchTarget*4+4);
+                    indent--;
+                p("}");
+                break;
+            case 7: //BGTZ
+                if(pc == -1) throw new Error("pc modifying insn in delay slot");
+                p("if(r" + rs + " > 0) {");
+                    indent++;
+                    emitInstruction(-1,nextInsn,-1);
+                    branch(pc,pc+branchTarget*4+4);
+                    indent--;
+                p("}");
+                break;
+            case 8: // ADDI
+                p( "r"+rt+" = r"+rs+" + "+signedImmediate +";");
+                break;
+            case 9: // ADDIU
+                p( "r"+rt+" = r"+rs+" + "+signedImmediate+";");
+                break;
+            case 10: // SLTI
+                p( "r"+rt+" = r"+rs+" < "+signedImmediate+" ? 1 : 0;");
+                break;
+            case 11: // SLTIU
+                p( "r"+rt+" = (r"+rs+"&0xffffffffL) < ("+unsignedImmediate+"&0xffffffffL) ? 1 : 0;");
+                break;
+            case 12: // ANDI
+                p( "r"+rt+" = r"+rs+" & "+unsignedImmediate+";");
+                break;
+            case 13: // ORI
+                p( "r"+rt+" = r"+rs+" | "+unsignedImmediate+";");
+                break;
+            case 14: // XORI
+                p( "r"+rt+" = r"+rs+" ^ "+unsignedImmediate+";");
+                break;
+            case 15: // LUI
+                p( "r"+rt+" = "+unsignedImmediate+" << 16;");
+                break;
+            case 16:
+                throw new Exn("TLB/Exception support not implemented");
+            case 17: { // FPU
+                switch(rs) {
+                    case 0: // MFC.1
+                        p( "r"+rt+" = f"+rd+";");
+                        break;
+                    case 2: // CFC.1
+                        if(fs != 31) throw new Exn("FCR " + fs + " unavailable");
+                        p( "r"+rt+" = fcsr;");
+                        break;
+                    case 4: // MTC.1
+                        p( "f"+rd+" = r"+rt+";");
+                        break;
+                    case 6: // CTC.1
+                        if(fs != 31) throw new Exn("FCR " + fs + " unavailable");
+                        p( "fcsr = r"+rt+";");
+                        break;
+                    case 8: {// BC1F, BC1T
+                        tmp = (insn>>>16)&1;
+                        p("if(((fcsr&0x800000)!=0) == (" + tmp + "!=0)) {");
+                            indent++;
+                            emitInstruction(-1,nextInsn,-1);
+                            branch(pc,pc+branchTarget*4+4);
+                            indent--;
+                        p("}");
+                        break;
+                    }
+                    case 16: {  // Single 
+                        switch(subcode) {
+                            case 0: // ADD.S
+                                p(setFloat(fd,getFloat(fs)+"+"+getFloat(ft)));
+                                break;
+                            case 1: // SUB.S
+                                p(setFloat(fd,getFloat(fs)+"-"+getFloat(ft)));
+                                break;
+                            case 2: // MUL.S
+                                p(setFloat(fd,getFloat(fs)+"*"+getFloat(ft)));
+                                break;
+                            case 3: // DIV.S
+                                p(setFloat(fd,getFloat(fs)+"/"+getFloat(ft)));
+                                break;
+                            case 5: // ABS.S
+                                p(setFloat(fd,"Math.abs("+getFloat(fs)+")"));
+                                break;
+                            case 6: // MOV.S
+                                p("f"+fd+" = f"+fs+"; // MOV.S");
+                                break;
+                            case 7: // NEG.S
+                                p(setFloat(fd,"-"+getFloat(fs)));
+                                break;
+                            case 33: // CVT.D.S
+                                p(setDouble(fd,"(float)"+getFloat(fs)));
+                                break;
+                            case 36: // CVT.W.D
+                                p("switch(fcsr & 3) {");
+                                    indent++;
+                                    p("case 0: f"+fd+" = (int)Math.floor("+getFloat(fs)+"+0.5); break; // Round to nearest");
+                                    p("case 1: f"+fd+" = (int)"+getFloat(fs)+"; break; // Round towards zero");
+                                    p("case 2: f"+fd+" = (int)Math.ceil("+getFloat(fs)+"); break; // Round towards plus infinity");
+                                    p("case 3: f"+fd+" = (int)Math.floor("+getFloat(fs)+"); break; // Round towards minus infinity");
+                                    indent--;
+                                p("}");
+                                break;
+                            case 50: // C.EQ.S
+                                p("fcsr = (fcsr&~0x800000) | (("+getFloat(fs)+"=="+getFloat(ft)+") ? 0x800000 : 0x000000);");
+                                break;
+                            case 60: // C.LT.S
+                                p("fcsr = (fcsr&~0x800000) | (("+getFloat(fs)+"<"+getFloat(ft)+") ? 0x800000 : 0x000000);");
+                                break;
+                            case 62: // C.LE.S
+                                p("fcsr = (fcsr&~0x800000) | (("+getFloat(fs)+"<="+getFloat(ft)+") ? 0x800000 : 0x000000);");
+                                break;                                
+                            default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode);
+                        }
+                        break;
+                    }
+                    case 17: { // Double
+                        switch(subcode) {
+                            case 0: // ADD.D
+                                p(setDouble(fd,getDouble(fs)+"+"+getDouble(ft)));
+                                break;
+                            case 1: // SUB.D
+                                p(setDouble(fd,getDouble(fs)+"-"+getDouble(ft)));
+                                break;
+                            case 2: // MUL.D
+                                p(setDouble(fd,getDouble(fs)+"*"+getDouble(ft)));
+                                break;
+                            case 3: // DIV.D
+                                p(setDouble(fd,getDouble(fs)+"/"+getDouble(ft)));
+                                break;
+                            case 5: // ABS.D
+                                p(setDouble(fd,"Math.abs("+getDouble(fs)+")"));
+                                break;
+                            case 6: // MOV.D
+                                p("f"+fd+" = f"+fs+";");
+                                p("f"+(fd+1)+" = f"+(fs+1)+";");
+                                break;
+                            case 7: // NEG.D
+                                p(setDouble(fd,"-"+getDouble(fs)));
+                                break;
+                            case 32: // CVT.S.D
+                                p(setFloat(fd,"(float)"+getDouble(fs)));
+                                break;
+                            case 36: // CVT.W.D
+                                p("switch(fcsr & 3) {");
+                                    indent++;
+                                    p("case 0: f"+fd+" = (int)Math.floor("+getDouble(fs)+"+0.5); break; // Round to nearest");
+                                    p("case 1: f"+fd+" = (int)"+getDouble(fs)+"; break; // Round towards zero");
+                                    p("case 2: f"+fd+" = (int)Math.ceil("+getDouble(fs)+"); break; // Round towards plus infinity");
+                                    p("case 3: f"+fd+" = (int)Math.floor("+getDouble(fs)+"); break; // Round towards minus infinity");
+                                    indent--;
+                                p("}");
+                                break;
+                            case 50: // C.EQ.D
+                                p("fcsr = (fcsr&~0x800000) | (("+getDouble(fs)+"=="+getDouble(ft)+") ? 0x800000 : 0x000000);");                                
+                                break;
+                            case 60: // C.LT.D
+                                p("fcsr = (fcsr&~0x800000) | (("+getDouble(fs)+"<"+getDouble(ft)+") ? 0x800000 : 0x000000);");                                
+                                break;
+                            case 62: // C.LE.D
+                                p("fcsr = (fcsr&~0x800000) | (("+getDouble(fs)+"<="+getDouble(ft)+") ? 0x800000 : 0x000000);");                                
+                                break;                                
+                            default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode);
+                        }
+                        break;
+                    }
+                    case 20: { // Integer
+                        switch(subcode) {
+                            case 32: // CVT.S.W
+                                p(" // CVS.S.W");
+                                p(setFloat(fd,"((float)f"+fs+")"));
+                                break;
+                            case 33: // CVT.D.W
+                                p(setDouble(fd,"((double)f"+fs+")"));
+                                break;
+                            default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode);
+                        }
+                        break; 
+                    }
+                    default:
+                        throw new Exn("Invalid Instruction 17/" + rs);
+                }
+                break;
+            }
+            case 18: case 19:
+                throw new Exn("coprocessor 2 and 3 instructions not available");
+            case 32: { // LB
+                if(runtimeStats) p("inc(\"LB\");");
+                p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr","tmp");
+                p("tmp = (tmp>>>(((~addr)&3)<<3)) & 0xff;");
+                p("if((tmp&0x80)!=0) tmp |= 0xffffff00; /* sign extend */");
+                p("r"+rt+" = tmp;");
+                break; 
+            }
+            case 33: { // LH
+                if(runtimeStats) p("inc(\"LH\");");
+                p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr","tmp");
+                p("tmp = (tmp>>>(((~addr)&2)<<3)) & 0xffff;");
+                p("if((tmp&0x8000)!=0) tmp |= 0xffff0000; /* sign extend */");
+                p("r"+rt+" = tmp;");
+                break; 
+            }
+            case 34: { // LWL;
+                p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr","tmp");
+                p("r" + rt + " = (r"+rt+"&(0x00ffffff>>>(((~addr)&3)<<3)))|(tmp<<((addr&3)<<3));");
+                break;
+                /*p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr&~3","tmp");
+                p("switch(addr&3) {");
+                indent++;
+                p("case 0: r"+rt+" = (r"+rt+"&0x00000000)|(tmp<< 0); break;");
+                p("case 1: r"+rt+" = (r"+rt+"&0x000000ff)|(tmp<< 8); break;");
+                p("case 2: r"+rt+" = (r"+rt+"&0x0000ffff)|(tmp<<16); break;");
+                p("case 3: r"+rt+" = (r"+rt+"&0x00ffffff)|(tmp<<24); break;");
+                indent--;
+                p("}");
+                break;*/
+            }
+            case 35: // LW
+                if(runtimeStats) p("inc(\"LW\");");
+                memRead("r" + rs +"+"+signedImmediate,"r"+rt);
+                break;
+            case 36: { // LBU
+                p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr","tmp");
+                p("tmp = (tmp>>>(((~addr)&3)<<3)) & 0xff;");
+                p("r"+rt+" = tmp;");
+                break; 
+            }
+            case 37: { // LHU
+                p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr","tmp");
+                p("tmp = (tmp>>>(((~addr)&2)<<3)) & 0xffff;");
+                p("r"+rt+" = tmp;");
+                break; 
+            }
+            case 38: { // LWR
+                p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr","tmp");
+                p("r" + rt + " = (r"+rt+"&(0xffffff00<<((addr&3)<<3)))|(tmp>>>(((~addr)&3)<<3));");
+                break;
+                
+                /*p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr&~3","tmp");
+                p("switch(addr&3) {");
+                indent++;
+                p("case 0: r"+rt+" = (r"+rt+"&0xffffff00)|(tmp>>>24); break;");
+                p("case 1: r"+rt+" = (r"+rt+"&0xffff0000)|(tmp>>>16); break;");
+                p("case 2: r"+rt+" = (r"+rt+"&0xff000000)|(tmp>>> 8); break;");
+                p("case 3: r"+rt+" = (r"+rt+"&0x00000000)|(tmp>>> 0); break;");
+                indent--;
+                p("}");
+                break;*/
+                
+            }
+            case 40: { // SB
+                if(runtimeStats) p("inc(\"SB\");");
+                p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr","tmp");
+                p("tmp = (tmp&~(0xff000000>>>((addr&3)<<3)))|((r"+rt+"&0xff)<<(((~addr)&3)<<3));");
+                memWrite("addr","tmp");
+                break;
+            }
+            case 41: { // SH
+                if(runtimeStats) p("inc(\"SH\");");
+                p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr","tmp");
+                p("tmp = (tmp&(0xffff<<((addr&2)<<3)))|((r" + rt + "&0xffff)<<(((~addr)&2)<<3));");
+                memWrite("addr","tmp");
+                break;
+            }
+            case 42: { // SWL
+                p(" // SWL");
+                p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr","tmp");
+                p("tmp = (tmp&(0xffffff00<<(((~addr)&3)<<3)))|(r"+rt+">>>((addr&3)<<3));");
+                memWrite("addr","tmp");
+                break;
+            }
+            case 43: // SW
+                if(runtimeStats) p("inc(\"SW\");");
+                memWrite("r"+rs+"+"+signedImmediate,"r" + rt);
+                break;
+            case 46: { // SWR
+                p(" // SWR");
+                p("addr=r" + rs +"+"+signedImmediate + ";");
+                memRead("addr","tmp");
+                p("tmp = (tmp&(0x00ffffff>>>((addr&3)<<3)))|(r"+rt+"<<(((~addr)&3)<<3));");
+                memWrite("addr","tmp");
+                break;
+            }
+            // FEATURE: Need to be atomic if threads
+            case 48: // LWC0/LL
+                memRead("r"+rs+"+"+signedImmediate,"r"+rt);
+                break;
+            case 49: // LWC1
+                memRead("r"+rs+"+"+signedImmediate,"f"+rt);
+                break;
+            // FEATURE: Needs to be atomic if threads
+            case 56: // SWC1/SC
+                memWrite("r"+rs+"+"+signedImmediate,"r"+rt);
+                p("r" + rt + "=1;");
+                break;
+            case 57: // SWC1
+                memWrite("r"+rs+"+"+signedImmediate,"f"+rt);
+                break;
+            default:
+                throw new Exn("Invalid Instruction: " + op + " at " + toHex(pc));
+        }
+    }
+    
+    // Helper functions for emitText
+    // NOTE: memWrite and memRead MUST discard the last two bits of addr
+    private void memWrite(String addr, String target) {
+        if(nullPointerCheck) p("nullPointerCheck(" + addr + ");");
+        if(onePage)
+            p("page[(" + addr + ")>>>2] = " + target + ";");
+        else if(fastMem)
+            p("writePages[("+addr+")>>>"+pageShift+"][(("+addr+")>>>2)&"+toHex((pageSize>>2)-1)+"] = " + target + ";");
+        else
+            p("unsafeMemWrite(" + addr + "," + target + ");");
+    }
+    private void memRead(String addr, String target) {
+        if(nullPointerCheck) p("nullPointerCheck(" + addr + ");");
+        if(onePage)
+            p(target + "= page[(" + addr + ")>>>2];");
+        else if(fastMem)
+            p(target  + " = readPages[("+addr+")>>>"+pageShift+"][(("+addr+")>>>2)&"+toHex((pageSize>>2)-1)+"];");
+        else
+            p(target + " = unsafeMemRead(" + addr + ");");
+    }
+    private static String getFloat(int r) { return "(Float.intBitsToFloat(f"+r+"))"; }
+    private static String getDouble(int r) {
+        return "(Double.longBitsToDouble(((f"+(r+1)+"&0xffffffffL) << 32) | (f"+r+"&0xffffffffL)))";
+    }
+    private static String setFloat(int r, String expr) { return "f"+r+"=Float.floatToRawIntBits("+expr+");"; }
+    private static String setDouble(int r, String expr) {
+        return "{ long l = Double.doubleToLongBits("+expr+"); "+
+            "f"+(r+1)+" = (int)(l >>> 32); f"+r+" = (int)l; }";
+    }
+}
+    
\ No newline at end of file
diff --git a/src/org/xwt/mips/Registers.java b/src/org/xwt/mips/Registers.java
new file mode 100644 (file)
index 0000000..14b2825
--- /dev/null
@@ -0,0 +1,42 @@
+package org.xwt.mips;
+
+interface Registers {
+    // Register Names
+    public final static int ZERO = 0; // Immutable, hardwired to 0
+    public final static int AT = 1;  // Reserved for assembler
+    public final static int K0 = 26; // Reserved for kernel 
+    public final static int K1 = 27; // Reserved for kernel 
+    public final static int GP = 28; // Global pointer (the middle of .sdata/.sbss)
+    public final static int SP = 29; // Stack pointer
+    public final static int FP = 30; // Frame Pointer
+    public final static int RA = 31; // Return Address
+    
+    // Return values (caller saved)
+    public final static int V0 = 2;
+    public final static int V1 = 3;
+    // Argument Registers (caller saved)
+    public final static int A0 = 4; 
+    public final static int A1 = 5;
+    public final static int A2 = 6;
+    public final static int A3 = 7;
+    // Temporaries (caller saved)
+    public final static int T0 = 8;
+    public final static int T1 = 9;
+    public final static int T2 = 10;
+    public final static int T3 = 11;
+    public final static int T4 = 12;
+    public final static int T5 = 13;
+    public final static int T6 = 14;
+    public final static int T7 = 15;
+    public final static int T8 = 24;
+    public final static int T9 = 25;
+    // Saved (callee saved)
+    public final static int S0 = 16;
+    public final static int S1 = 17;
+    public final static int S2 = 18;
+    public final static int S3 = 19;
+    public final static int S4 = 20;
+    public final static int S5 = 21;
+    public final static int S6 = 22;
+    public final static int S7 = 23;
+}
diff --git a/src/org/xwt/mips/Runtime.java b/src/org/xwt/mips/Runtime.java
new file mode 100644 (file)
index 0000000..6a5c4b6
--- /dev/null
@@ -0,0 +1,1256 @@
+// Copyright 2003 Brian Alliet
+// Based on org.xwt.imp.MIPS by Adam Megacz
+// Portions Copyright 2003 Adam Megacz
+
+package org.xwt.mips;
+
+import org.xwt.mips.util.*;
+import java.io.*;
+import java.util.Arrays;
+
+// FEATURE: Look over the public API, make sure we're exposing a bare minimum
+// (we might make this an interface in the future)
+
+public abstract class Runtime implements UsermodeConstants,Registers {
+    /** Pages are 4k in size */
+    protected final int PAGE_SIZE;
+    protected final int PAGE_WORDS;
+    protected final int PAGE_SHIFT;
+    protected final int TOTAL_PAGES;
+    /** This is the upper limit of the pages allocated by the sbrk() syscall. */
+    protected final int BRK_LIMIT;
+    protected final int STACK_BOTTOM;
+
+    /** This is the maximum size of command line arguments */
+    public final static int ARGS_MAX = 1024*1024;
+    
+    /** True if we allow empty pages (_emptyPage) to exist in memory.
+       Empty pages are pages which are allocated by the program but do not contain any
+       data yet (they are all 0s). If empty pages are allowed subclasses must always
+       access main memory with the memRead and memWrite functions */
+    private final boolean allowEmptyPages;
+    /** the "empty page" */
+    private final static int[] _emptyPage = new int[0];
+    
+    protected final static boolean isEmptyPage(int[] page) { return page == _emptyPage; }
+    
+    /** Returns a new empty page (_emptyPage is empty pages are enabled or a new zero'd page) */
+    private final int[] emptyPage() { return allowEmptyPages ? _emptyPage : new int[PAGE_WORDS]; }
+    
+    /** Readable main memory pages */
+    protected final int[][] readPages;
+    /** Writable main memory pages.
+        If the page is writable writePages[x] == readPages[x]; if not writePages[x] == null. */
+    protected final int[][] writePages;
+    
+    /** The current break between the heap and unallocated memory */
+    protected int brkAddr;
+        
+    /** The program's entry point */
+    protected int entryPoint;
+
+    /** The location of the _user_info block (or 0 is there is none) */
+    protected int userInfoBase;
+    protected int userInfoSize;
+    
+    /** The location of the global pointer */
+    protected int gp;
+    
+    /** When the process started */
+    private long startTime;
+    
+    /** State constant: There is no program loaded in memory */
+    public final static int UNINITIALIZED = 0; 
+    /**  Text/Data loaded in memory  */
+    public final static int INITIALIZED = 1;
+    /** Program is executing instructions */
+    public final static int RUNNING = 2;
+    /** Prgram has been started but is paused */
+    public final static int PAUSED = 3;
+    /** Program is executing a callJava() method */
+    public final static int CALLJAVA = 4;
+    /** Program has exited (it cannot currently be restarted) */
+    public final static int DONE = 5;
+        
+    /** The current state (UNINITIALIZED, INITIALIZED, RUNNING, PAUSED, or DONE) */
+    protected int state = UNINITIALIZED;
+    /** @see Runtime#state state */
+    public final int getState() { return state; }
+    
+    /** The exit status if the process (only valid if state==DONE) 
+        @see Runtime#state */
+    protected int exitStatus;
+    public ExecutionException exitException;
+    
+    /** Maximum number of open file descriptors */
+    final static int OPEN_MAX = 256;
+    /** Table containing all open file descriptors. (Entries are null if the fd is not in use */
+    FD[] fds  = new FD[OPEN_MAX];
+        
+    /** Temporary buffer for read/write operations */
+    private byte[] _byteBuf = null;
+    /** Max size of temporary buffer
+        @see Runtime#_byteBuf */
+    private final static int MAX_CHUNK = 15*1024*1024;
+        
+    /** Subclasses should actually execute program in this method. They should continue 
+        executing until state != RUNNING. Only syscall() can modify state. It is safe 
+        to only check the state attribute after a call to syscall() */
+    protected abstract void _execute() throws ExecutionException;
+    
+    /** Subclasses should return the address of the symbol <i>symbol</i> or -1 it it doesn't exits in this method 
+        This method is only required if the call() function is used */
+    protected int lookupSymbol(String symbol) { return -1; }
+    
+    /** Subclasses should returns a CPUState object representing the cpu state */
+    protected abstract CPUState getCPUState();
+    
+    /** Subclasses should set the CPUState to the state held in <i>state</i> */
+    protected abstract void setCPUState(CPUState state);
+
+    static void checkPageSize(int pageSize, int totalPages) throws IllegalArgumentException {
+        if(pageSize < 256) throw new IllegalArgumentException("pageSize too small");
+        if((pageSize&(pageSize-1)) != 0) throw new IllegalArgumentException("pageSize must be a power of two");
+        if((totalPages&(totalPages-1)) != 0) throw new IllegalArgumentException("totalPages must be a power of two");
+        if(totalPages != 1 && totalPages < 256) throw new IllegalArgumentException("totalPages too small");
+        if(totalPages * pageSize < 4*1024*1024) throw new IllegalArgumentException("total memory too small (" + totalPages + "*" + pageSize + ")");
+    }
+    
+    protected Runtime(int pageSize, int totalPages, boolean allowEmptyPages) {
+        this.allowEmptyPages = allowEmptyPages;
+        
+        checkPageSize(pageSize,totalPages);
+        
+        PAGE_SIZE = pageSize;
+        PAGE_WORDS = pageSize>>>2;
+        int pageShift = 0;
+        while(pageSize>>>pageShift != 1) pageShift++;
+        PAGE_SHIFT = pageShift;
+        
+        TOTAL_PAGES = totalPages;
+        
+        readPages = new int[TOTAL_PAGES][];
+        writePages = new int[TOTAL_PAGES][];
+        
+        if(TOTAL_PAGES == 1) {
+            readPages[0] = writePages[0] = new int[PAGE_WORDS];
+            BRK_LIMIT = STACK_BOTTOM = 0;
+        } else {
+            int stackPages = max(TOTAL_PAGES>>>8,(1024*1024)>>>PAGE_SHIFT);
+            STACK_BOTTOM = (TOTAL_PAGES - stackPages) * PAGE_SIZE;
+            // leave some unmapped pages between the stack and the heap
+            BRK_LIMIT = STACK_BOTTOM - 4*PAGE_SIZE;
+        
+            for(int i=0;i<stackPages;i++)
+                readPages[TOTAL_PAGES-1-i] = writePages[TOTAL_PAGES-1-i] = emptyPage();
+        }
+        
+        addFD(new StdinFD(System.in));
+        addFD(new StdoutFD(System.out));
+        addFD(new StdoutFD(System.err));
+    }
+    
+    /** Copy everything from <i>src</i> to <i>addr</i> initializing uninitialized pages if required. 
+       Newly initalized pages will be marked read-only if <i>ro</i> is set */
+    protected final void initPages(int[] src, int addr, boolean ro) {
+        for(int i=0;i<src.length;) {
+            int page = addr >>> PAGE_SHIFT;
+            int start = (addr&(PAGE_SIZE-1))>>2;
+            int elements = min(PAGE_WORDS-start,src.length-i);
+            if(readPages[page]==null) {
+                initPage(page,ro);
+            } else if(!ro) {
+                if(writePages[page] == null) writePages[page] = readPages[page];
+            }
+            System.arraycopy(src,i,readPages[page],start,elements);
+            i += elements;
+            addr += elements*4;
+        }
+    }
+    
+    /** Initialize <i>words</i> of pages starting at <i>addr</i> to 0 */
+    protected final void clearPages(int addr, int words) {
+        for(int i=0;i<words;) {
+            int page = addr >>> PAGE_SHIFT;
+            int start = (addr&(PAGE_SIZE-1))>>2;
+            int elements = min(PAGE_WORDS-start,words-i);
+            if(readPages[page]==null) {
+                readPages[page] = writePages[page] = emptyPage();
+            } else {
+                if(writePages[page] == null) writePages[page] = readPages[page];
+                for(int j=start;j<start+elements;j++) writePages[page][j] = 0;
+            }
+            i += elements;
+            addr += elements*4;
+        }
+    }
+    
+    /** Copies <i>length</i> bytes from the processes memory space starting at
+        <i>addr</i> INTO a java byte array <i>a</i> */
+    public final void copyin(int addr, byte[] buf, int count) throws ReadFaultException {
+        int x=0;
+        if((addr&3)!=0) {
+            int word = memRead(addr&~3);
+            switch(addr&3) {
+                case 1: buf[x++] = (byte)((word>>>16)&0xff); if(--count==0) break;
+                case 2: buf[x++] = (byte)((word>>> 8)&0xff); if(--count==0) break;
+                case 3: buf[x++] = (byte)((word>>> 0)&0xff); if(--count==0) break;
+            }
+            addr = (addr&~3)+4;
+        }
+        if((count&~3) != 0) {
+            int c = count>>>2;
+            int a = addr>>>2;
+            while(c != 0) {
+                int[] page = readPages[a >>> (PAGE_SHIFT-2)];
+                if(page == null) throw new ReadFaultException(a<<2);
+                int index = a&(PAGE_WORDS-1);
+                int n = min(c,PAGE_WORDS-index);
+                if(page != _emptyPage) {
+                    for(int i=0;i<n;i++,x+=4) {
+                        int word = page[index+i];
+                        buf[x+0] = (byte)((word>>>24)&0xff); buf[x+1] = (byte)((word>>>16)&0xff);
+                        buf[x+2] = (byte)((word>>> 8)&0xff); buf[x+3] = (byte)((word>>> 0)&0xff);                        
+                    }
+                }
+                a += n; c -=n;
+            }
+            addr = a<<2; count &=3;
+        }
+        if(count != 0) {
+            int word = memRead(addr);
+            switch(count) {
+                case 3: buf[x+2] = (byte)((word>>>8)&0xff);
+                case 2: buf[x+1] = (byte)((word>>>16)&0xff);
+                case 1: buf[x+0] = (byte)((word>>>24)&0xff);
+            }
+        }
+    }
+    
+    /** Copies <i>length</i> bytes OUT OF the java array <i>a</i> into the processes memory
+        space at <i>addr</i> */
+    public final void copyout(byte[] buf, int addr, int count) throws FaultException {
+        int x=0;
+        if((addr&3)!=0) {
+            int word = memRead(addr&~3);
+            switch(addr&3) {
+                case 1: word = (word&0xff00ffff)|((buf[x++]&0xff)<<16); if(--count==0) break;
+                case 2: word = (word&0xffff00ff)|((buf[x++]&0xff)<< 8); if(--count==0) break;
+                case 3: word = (word&0xffffff00)|((buf[x++]&0xff)<< 0); if(--count==0) break;
+            }
+            memWrite(addr&~3,word);
+            addr += x;
+        }
+        if((count&~3) != 0) {
+            int c = count>>>2;
+            int a = addr>>>2;
+            while(c != 0) {
+                int[] page = writePages[a >>> (PAGE_SHIFT-2)];
+                if(page == null) throw new WriteFaultException(a<<2);
+                if(page == _emptyPage) page = initPage(a >>> (PAGE_SHIFT-2));
+                int index = a&(PAGE_WORDS-1);
+                int n = min(c,PAGE_WORDS-index);
+                for(int i=0;i<n;i++,x+=4)
+                    page[index+i] = ((buf[x+0]&0xff)<<24)|((buf[x+1]&0xff)<<16)|((buf[x+2]&0xff)<<8)|((buf[x+3]&0xff)<<0);
+                a += n; c -=n;
+            }
+            addr = a<<2; count&=3;
+        }
+        if(count != 0) {
+            int word = memRead(addr);
+            switch(count) {
+                case 1: word = (word&0x00ffffff)|((buf[x+0]&0xff)<<24); break;
+                case 2: word = (word&0x0000ffff)|((buf[x+0]&0xff)<<24)|((buf[x+1]&0xff)<<16); break;
+                case 3: word = (word&0x000000ff)|((buf[x+0]&0xff)<<24)|((buf[x+1]&0xff)<<16)|((buf[x+2]&0xff)<<8); break;
+            }
+            memWrite(addr,word);
+        }
+    }
+    
+    public final void memcpy(int dst, int src, int count) throws FaultException {
+        if((dst&3) == 0 && (src&3)==0) {
+            if((count&~3) != 0) {
+                int c = count>>2;
+                int s = src>>>2;
+                int d = dst>>>2;
+                while(c != 0) {
+                    int[] srcPage = readPages[s>>>(PAGE_SHIFT-2)];
+                    if(srcPage == null) throw new ReadFaultException(s<<2);
+                    int[] dstPage = writePages[d>>>(PAGE_SHIFT-2)];
+                    if(dstPage == null) throw new WriteFaultException(d<<2);
+                    int srcIndex = (s&(PAGE_WORDS-1));
+                    int dstIndex = (d&(PAGE_WORDS-1));
+                    int n = min(c,PAGE_WORDS-max(srcIndex,dstIndex));
+                    if(srcPage != _emptyPage) {
+                        if(dstPage == _emptyPage) dstPage = initPage(d>>>(PAGE_SHIFT-2));
+                        System.arraycopy(srcPage,srcIndex,dstPage,dstIndex,n);
+                    } else if(srcPage == _emptyPage && dstPage != _emptyPage) {
+                        Arrays.fill(dstPage,dstIndex,dstIndex+n,0);
+                    }
+                    s += n; d += n; c -= n;
+                }
+                src = s<<2; dst = d<<2; count&=3;
+            }
+            if(count != 0) {
+                int word1 = memRead(src);
+                int word2 = memRead(dst);
+                switch(count) {
+                    case 1: memWrite(dst,(word1&0xff000000)|(word2&0x00ffffff)); break;
+                    case 2: memWrite(dst,(word1&0xffff0000)|(word2&0x0000ffff)); break;
+                    case 3: memWrite(dst,(word1&0xffffff00)|(word2&0x000000ff)); break;
+                }
+            }
+        } else {
+            while(count > 0) {
+                int n = min(count,MAX_CHUNK);
+                byte[] buf = byteBuf(n);
+                copyin(src,buf,n);
+                copyout(buf,dst,n);
+                count -= n; src += n; dst += n;
+            }
+        }
+    }
+    
+    public final void memset(int addr, int ch, int count) throws FaultException {
+        int fourBytes = ((ch&0xff)<<24)|((ch&0xff)<<16)|((ch&0xff)<<8)|((ch&0xff)<<0);
+        if((addr&3)!=0) {
+            int word = memRead(addr&~3);
+            switch(addr&3) {
+                case 1: word = (word&0xff00ffff)|((ch&0xff)<<16); if(--count==0) break;
+                case 2: word = (word&0xffff00ff)|((ch&0xff)<< 8); if(--count==0) break;
+                case 3: word = (word&0xffffff00)|((ch&0xff)<< 0); if(--count==0) break;
+            }
+            memWrite(addr&~3,word);
+            addr = (addr&~3)+4;
+        }
+        if((count&~3) != 0) {
+            int c = count>>2;
+            int a = addr>>>2;
+            while(c != 0) {
+                int[] page = readPages[a>>>(PAGE_SHIFT-2)];
+                if(page == null) throw new WriteFaultException(a<<2);
+                int index = (a&(PAGE_WORDS-1));
+                int n = min(c,PAGE_WORDS-index);
+                if(page != _emptyPage || ch != 0) {
+                    if(page == _emptyPage) page = initPage(a>>>(PAGE_SHIFT-2));
+                    Arrays.fill(page,index,index+n,fourBytes);
+                }
+                a += n; c -= n;
+            }
+            addr = a<<2; count&=3;
+        }
+        if(count != 0) {
+            int word = memRead(addr);
+            switch(count) {
+                case 1: word = (word&0x00ffffff)|(fourBytes&0xff000000); break;
+                case 2: word = (word&0x0000ffff)|(fourBytes&0xffff0000); break;
+                case 3: word = (word&0x000000ff)|(fourBytes&0xffffff00); break;
+            }
+            memWrite(addr,word);
+        }
+    }
+    
+    /** Read a word from the processes memory at <i>addr</i> */
+    public final int memRead(int addr) throws ReadFaultException  {
+        if((addr & 3) != 0) throw new ReadFaultException(addr);
+        return unsafeMemRead(addr);
+    }
+       
+    protected final int unsafeMemRead(int addr) throws ReadFaultException {
+        int page = addr >>> PAGE_SHIFT;
+        int entry = (addr >>> 2) & (PAGE_WORDS-1);
+        try {
+            return readPages[page][entry];
+        } catch(ArrayIndexOutOfBoundsException e) {
+            if(page < 0) throw e; // should never happen
+            if(page >= readPages.length) throw new ReadFaultException(addr);
+            if(readPages[page] != _emptyPage) throw e; // should never happen
+            initPage(page);
+            return 0;
+        } catch(NullPointerException e) {
+            throw new ReadFaultException(addr);
+        }
+    }
+    
+    /** Writes a word to the processes memory at <i>addr</i> */
+    public final void memWrite(int addr, int value) throws WriteFaultException  {
+        if((addr & 3) != 0) throw new WriteFaultException(addr);
+        unsafeMemWrite(addr,value);
+    }
+    
+    protected final void unsafeMemWrite(int addr, int value) throws WriteFaultException {
+        int page = addr >>> PAGE_SHIFT;
+        int entry = (addr>>>2)&(PAGE_WORDS-1);
+        try {
+            writePages[page][entry] = value;
+        } catch(ArrayIndexOutOfBoundsException e) {
+            if(page < 0) throw e;// should never happen
+            if(page >= writePages.length) throw new WriteFaultException(addr);
+            if(readPages[page] != _emptyPage) throw e; // should never happen
+            initPage(page);
+            writePages[page][entry] = value;
+        } catch(NullPointerException e) {
+            throw new WriteFaultException(addr);
+        }
+    }
+    
+    /** Created a new non-empty writable page at page number <i>page</i> */
+    private final int[] initPage(int page) { return initPage(page,false); }
+    /** Created a new non-empty page at page number <i>page</i>. If <i>ro</i> is set the page will be read-only */
+    private final int[] initPage(int page, boolean ro) {
+        int[] buf = new int[PAGE_WORDS];
+        writePages[page] = ro ? null : buf;
+        readPages[page] = buf;
+        return buf;
+    }
+    
+    /** Returns the exit status of the process. (only valid if state == DONE) 
+        @see Runtime#state */
+    public final int exitStatus() {
+        if(state != DONE) throw new IllegalStateException("exitStatus() called in an inappropriate state");
+        return exitStatus;
+    }
+        
+    private int addStringArray(String[] strings, int topAddr) {
+        int count = strings.length;
+        int total = 0; /* null last table entry  */
+        for(int i=0;i<count;i++) total += strings[i].length() + 1;
+        if(total >= ARGS_MAX) throw new IllegalArgumentException("arguments/environ too big");
+        total += (count+1)*4;
+        int start = (topAddr - total)&~3;
+        int addr = start + (count+1)*4;
+        int[] table = new int[count+1];
+        try {
+            for(int i=0;i<count;i++) {
+                byte[] a = getBytes(strings[i]);
+                table[i] = addr;
+                copyout(a,addr,a.length);
+                memset(addr+a.length,0,1);
+                addr += a.length + 1;
+            }
+            addr=start;
+            for(int i=0;i<count+1;i++) {
+                memWrite(addr,table[i]);
+                addr += 4;
+            }
+        } catch(FaultException e) {
+            // should never happen
+            throw new Error(e);
+        }
+        return start;
+    }
+    
+    protected String[] createEnv(String[] extra) { if(extra == null) extra = new String[0]; return extra; }
+    
+    /** Sets word number <i>index</i> in the _user_info table to <i>word</i>
+     * The user_info table is a chunk of memory in the program's memory defined by the
+     * symbol "user_info". The compiler/interpreter automatically determine the size
+     * and location of the user_info table from the ELF symbol table. setUserInfo and
+     * getUserInfo are used to modify the words in the user_info table. */
+    public void setUserInfo(int index, int word) {
+        if(index < 0 || index >= userInfoSize/4) throw new IndexOutOfBoundsException("setUserInfo called with index >= " + (userInfoSize/4));
+        try {
+            memWrite(userInfoBase+index*4,word);
+        } catch(FaultException e) { throw new Error("should never happen: " + e); }
+    }
+    
+    /** Returns the word in the _user_info table entry <i>index</i>
+        @see Runtime#setUserInfo(int,int) setUserInfo */
+    public int getUserInfo(int index) {
+        if(index < 0 || index >= userInfoSize/4) throw new IndexOutOfBoundsException("setUserInfo called with index >= " + (userInfoSize/4));
+        try {
+            return memRead(userInfoBase+index*4);
+        } catch(FaultException e) { throw new Error("should never happen: " + e); }
+    }
+    
+    /** Calls _execute() (subclass's execute()) and catches exceptions */
+    private void __execute() {
+        try {
+            _execute();
+        } catch(FaultException e) {
+            e.printStackTrace();
+            sys_exit(128+11); // SIGSEGV
+            exitException = e;
+        } catch(ExecutionException e) {
+            e.printStackTrace();
+            System.err.println(e);
+            sys_exit(128+4); // SIGILL
+            exitException = e;
+        }
+    }
+    
+    /** Executes the process until the PAUSE syscall is invoked or the process exits. Returns true if the process exited. */
+    public final boolean execute()  {
+        if(state != PAUSED) throw new IllegalStateException("execute() called in inappropriate state");
+        if(startTime == 0) startTime = System.currentTimeMillis();
+        state = RUNNING;
+        __execute();
+        if(state != PAUSED && state != DONE) throw new IllegalStateException("execute() ended up in an inappropriate state (" + state + ")");
+        return state == DONE;
+    }
+    
+    public final int run() { return run(null); }
+    public final int run(String argv0, String[] rest) {
+        String[] args = new String[rest.length+1];
+        System.arraycopy(rest,0,args,1,rest.length);
+        args[0] = argv0;
+        return run(args);
+    }
+    public final int run(String[] args) { return run(args,null); }
+    
+    /** Runs the process until it exits and returns the exit status.
+        If the process executes the PAUSE syscall execution will be paused for 500ms and a warning will be displayed */
+    public final int run(String[] args, String[] env) {
+        start(args,env);
+        for(;;) {
+            if(execute()) break;
+            System.err.println("WARNING: Pause requested while executing run()");
+            try { Thread.sleep(500); } catch(InterruptedException e) { /* noop */ }
+        }
+        return exitStatus();
+    }
+
+    public final void start() { start(null); }
+    public final void start(String[] args) { start(args,null); }
+    
+    /** Initializes the process and prepairs it to be executed with execute() */
+    public final void start(String[] args, String[] environ)  {
+        int sp, argsAddr, envAddr;
+        if(state != INITIALIZED) throw new IllegalStateException("start() called in inappropriate state");
+
+        if(args == null) args = new String[]{getClass().getName()};
+        
+        sp = TOTAL_PAGES*PAGE_SIZE-512;
+        sp = argsAddr = addStringArray(args,sp);
+        sp = envAddr = addStringArray(createEnv(environ),sp);
+        sp &= ~15;
+        
+        CPUState cpuState = new CPUState();
+        cpuState.r[A0] = argsAddr;
+        cpuState.r[A1] = envAddr;
+        cpuState.r[SP] = sp;
+        cpuState.r[RA] = 0xdeadbeef;
+        cpuState.r[GP] = gp;
+        cpuState.pc = entryPoint;
+        setCPUState(cpuState);
+                
+        state = PAUSED;
+        
+        _start();
+    }
+    
+    /** Hook for subclasses to do their own startup */
+    protected void _start() { /* noop */ }
+    
+    public final int call(String sym) throws CallException { return call(sym,0,0,0,0,0,0,0); }
+    public final int call(String sym, int a0) throws CallException  { return call(sym,a0,0,0,0,0,0,0); }
+    public final int call(String sym, int a0, int a1) throws CallException  { return call(sym,a0,a1,0,0,0,0,0); }
+    public final int call(String sym, int a0, int a1, int a2) throws CallException  { return call(sym,a0,a1,a2,0,0,0,0); }
+    public final int call(String sym, int a0, int a1, int a2, int a3) throws CallException  { return call(sym,a0,a1,a2,a3,0,0,0); }
+    public final int call(String sym, int a0, int a1, int a2, int a3, int a4) throws CallException  { return call(sym,a0,a1,a2,a3,a4,0,0); }
+    public final int call(String sym, int a0, int a1, int a2, int a3, int a4, int a5) throws CallException  { return call(sym,a0,a1,a2,a3,a4,a5,0); }
+    
+    /** Calls a function in the process with the given arguments */
+    public final int call(String sym, int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws CallException {
+        int func = lookupSymbol(sym);
+        if(func == -1) throw new CallException(sym + " not found");
+        int helper = lookupSymbol("_call_helper");
+        if(helper == -1) throw new CallException("_call_helper not found");
+        return call(helper,func,a0,a1,a2,a3,a4,a5,a6);
+    }
+    
+    /** Executes the code at <i>addr</i> in the process setting A0-A3 and S0-S3 to the given arguments
+        and returns the contents of V1 when the the pause syscall is invoked */
+    public final int call(int addr, int a0, int a1, int a2, int a3, int s0, int s1, int s2, int s3) {
+        if(state != PAUSED && state != CALLJAVA) throw new IllegalStateException("call() called in inappropriate state");
+        int oldState = state;
+        CPUState saved = getCPUState();
+        CPUState cpustate = new CPUState();
+        cpustate.r[SP] = saved.r[SP]&~15;
+        cpustate.r[RA] = 0xdeadbeef;
+        cpustate.r[A0] = a0;
+        cpustate.r[A1] = a1;
+        cpustate.r[A2] = a2;
+        cpustate.r[A3] = a3;
+        cpustate.r[S0] = s0;
+        cpustate.r[S1] = s1;
+        cpustate.r[S2] = s2;
+        cpustate.r[S3] = s3;
+        cpustate.r[GP] = gp;
+        cpustate.pc = addr;
+        
+        state = RUNNING;
+
+        setCPUState(cpustate);
+        __execute();
+        cpustate = getCPUState();
+        setCPUState(saved);
+
+        if(state != PAUSED)
+            System.out.println("WARNING: Process exit()ed while servicing a call() request");
+        else
+            state = oldState;
+        
+        return cpustate.r[V1];
+    }
+    
+    // FEATURE: This is ugly - we should have some kind of way  to specify a callback rather than requiring subclassing
+    protected int callJava(int a, int b, int c, int d) {
+        System.err.println("WARNING: Default implementation of callJava() called with args " + toHex(a) + "," + toHex(b) + "," + toHex(c) + "," + toHex(d));
+        return 0;
+    }
+    
+    /** Determines if the process can access <i>fileName</i>. The default implementation simply logs 
+        the request and allows it */
+    protected boolean allowFileAccess(String fileName, boolean write) {
+        //System.err.println("Allowing " + (write?"write":"read-only") + " access to " + fileName);
+        return true;
+    }
+    
+    /** Allocated an entry in the FileDescriptor table for <i>fd</i> and returns the number.
+        Returns -1 if the table is full. This can be used by subclasses to use custom file
+        descriptors */
+    public int addFD(FD fd) {
+        int i;
+        for(i=0;i<OPEN_MAX;i++) if(fds[i] == null) break;
+        if(i==OPEN_MAX) return -1;
+        fds[i] = fd;
+        return i;
+    }
+
+    /** Closes file descriptor <i>fdn</i> and removes it from the file descriptor table */
+    public boolean closeFD(int fdn) {
+        if(fdn < 0 || fdn >= OPEN_MAX) return false;
+        if(fds[fdn] == null) return false;
+        fds[fdn].close();
+        fds[fdn] = null;        
+        return true;
+    }
+
+    // FEATURE: These should be pulled in from UsermodeConstants but fcntl.h is hard to parse
+    public static final int RD_ONLY = 0;
+    public static final int WR_ONLY = 1;
+    public static final int RDWR = 2;
+    
+    public static final int O_CREAT = 0x0200;
+    public static final int O_EXCL = 0x0800;
+    public static final int O_APPEND = 0x0008;
+    public static final int O_TRUNC = 0x0400;
+    public static final int O_NONBLOCK = 0x4000;
+    
+    // FEATURE: Lots of duplicate code between this and UnixRuntime.HostFS.open()
+    protected FD open(String path, int flags, int mode) throws IOException {
+        final File f = new File(path);
+        // NOTE: createNewFile is a Java2 function
+        if((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT))
+            if(!f.createNewFile()) throw new ErrnoException(EEXIST);
+        if(!f.exists() && (flags&O_CREAT) == 0) return null;
+        if(f.isDirectory()) return null;
+        final SeekableFile sf = new SeekableFile(path,mode!=RD_ONLY);
+        if((flags&O_TRUNC)!=0) sf.setLength(0);
+        return new SeekableFD(sf,flags) {
+            protected FStat _fstat() { return new HostFStat(f) {
+                public int size() {
+                    try { return sf.length(); } catch(IOException e) { return 0; }
+                }
+            };}
+        };
+    }
+    
+    /** The open syscall */
+    private int sys_open(int addr, int flags, int mode) {
+        if((flags & O_NONBLOCK) != 0) {
+            System.err.println("WARNING: O_NONBLOCK not supported");
+            return -EOPNOTSUPP;
+        }
+
+        try {
+            FD fd = open(cstring(addr),flags,mode);
+            if(fd == null) return -ENOENT;
+            int fdn = addFD(fd);
+            if(fdn == -1) {
+                fd.close();
+                return -ENFILE;
+            }
+            return fdn;
+        }
+        catch(ErrnoException e) { return -e.errno; }
+        catch(FileNotFoundException e) {
+            if(e.getMessage() != null && e.getMessage().indexOf("Permission denied") >= 0) return -EACCES;
+            return -ENOENT;
+        }
+        catch(IOException e) { return -EIO; }
+        catch(FaultException e) { return -EFAULT; }
+    }
+
+    /** The write syscall */
+    private int sys_write(int fdn, int addr, int count) {
+        count = Math.min(count,MAX_CHUNK);
+        if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD;
+        if(fds[fdn] == null || !fds[fdn].writable()) return -EBADFD;
+        try {
+            byte[] buf = byteBuf(count);
+            copyin(addr,buf,count);
+            return fds[fdn].write(buf,0,count);
+        } catch(FaultException e) {
+            System.err.println(e);
+            return -EFAULT;
+        } catch(IOException e) {
+            // FEATURE: We should support signals and send a SIGPIPE
+            if(e.getMessage().equals("Pipe closed")) return sys_exit(128+13);
+            System.err.println(e);
+            return -EIO;
+        }
+    }
+
+    /** The read syscall */
+    private int sys_read(int fdn, int addr, int count) {
+        count = Math.min(count,MAX_CHUNK);
+        if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD;
+        if(fds[fdn] == null || !fds[fdn].readable()) return -EBADFD;
+        try {
+            byte[] buf = byteBuf(count);
+            int n = fds[fdn].read(buf,0,count);
+            copyout(buf,addr,n);
+            return n;
+        } catch(FaultException e) {
+            System.err.println(e);
+            return -EFAULT;
+        } catch(IOException e) {
+            System.err.println(e);
+            return -EIO;
+        }
+    }
+    
+    /** The close syscall */
+    private int sys_close(int fdn) {
+        return closeFD(fdn) ? 0 : -EBADFD;
+    }
+
+    
+    /** The seek syscall */
+    private int sys_lseek(int fdn, int offset, int whence) {
+        if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD;
+        if(fds[fdn] == null) return -EBADFD;
+        if(whence != SEEK_SET && whence !=  SEEK_CUR && whence !=  SEEK_END) return -EINVAL;
+        try {
+            int n = fds[fdn].seek(offset,whence);
+            return n < 0 ? -ESPIPE : n;
+        } catch(IOException e) {
+            return -ESPIPE;
+        }
+    }
+    
+    /** The stat/fstat syscall helper */
+    int stat(FStat fs, int addr) {
+        try {
+            memWrite(addr+0,(fs.dev()<<16)|(fs.inode()&0xffff)); // st_dev (top 16), // st_ino (bottom 16)
+            memWrite(addr+4,((fs.type()&0xf000))|(fs.mode()&0xfff)); // st_mode
+            memWrite(addr+8,1<<16); // st_nlink (top 16) // st_uid (bottom 16)
+            memWrite(addr+12,0); // st_gid (top 16) // st_rdev (bottom 16)
+            memWrite(addr+16,fs.size()); // st_size
+            memWrite(addr+20,fs.atime()); // st_atime
+            // memWrite(addr+24,0) // st_spare1
+            memWrite(addr+28,fs.mtime()); // st_mtime
+            // memWrite(addr+32,0) // st_spare2
+            memWrite(addr+36,fs.ctime()); // st_ctime
+            // memWrite(addr+40,0) // st_spare3
+            memWrite(addr+44,fs.blksize()); // st_bklsize;
+            memWrite(addr+48,fs.blocks()); // st_blocks
+            // memWrite(addr+52,0) // st_spare4[0]
+            // memWrite(addr+56,0) // st_spare4[1]
+        } catch(FaultException e) {
+            System.err.println(e);
+            return -EFAULT;
+        }
+        return 0;
+    }
+    
+    /** The fstat syscall */
+    private int sys_fstat(int fdn, int addr) {
+        if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD;
+        if(fds[fdn] == null) return -EBADFD;
+        return stat(fds[fdn].fstat(),addr);
+    }
+    
+    /*
+    struct timeval {
+    long tv_sec;
+    long tv_usec;
+    };
+    */
+    private int sys_gettimeofday(int timevalAddr, int timezoneAddr) {
+        long now = System.currentTimeMillis();
+        int tv_sec = (int)(now / 1000);
+        int tv_usec = (int)((now%1000)*1000);
+        try {
+            memWrite(timevalAddr+0,tv_sec);
+            memWrite(timevalAddr+4,tv_usec);
+            return 0;
+        } catch(FaultException e) {
+            return -EFAULT;
+        }
+    }
+    
+    private int sys_sleep(int sec) {
+        if(sec < 0) sec = Integer.MAX_VALUE;
+        try {
+            Thread.sleep((long)sec*1000);
+            return 0;
+        } catch(InterruptedException e) {
+            return -1;
+        }
+    }
+    
+    /*
+      #define _CLOCKS_PER_SEC_ 1000
+      #define    _CLOCK_T_    unsigned long
+    struct tms {
+      clock_t   tms_utime;
+      clock_t   tms_stime;
+      clock_t   tms_cutime;    
+      clock_t   tms_cstime;
+    };*/
+   
+    private int sys_times(int tms) {
+        long now = System.currentTimeMillis();
+        int userTime = (int)((now - startTime)/16);
+        int sysTime = (int)((now - startTime)/16);
+        
+        try {
+            if(tms!=0) {
+                memWrite(tms+0,userTime);
+                memWrite(tms+4,sysTime);
+                memWrite(tms+8,userTime);
+                memWrite(tms+12,sysTime);
+            }
+        } catch(FaultException e) {
+            return -EFAULT;
+        }
+        return (int)now;
+    }
+    
+    private int sys_sysconf(int n) {
+        switch(n) {
+            case _SC_CLK_TCK: return 1000;
+            default:
+                System.err.println("WARNING: Attempted to use unknown sysconf key: " + n);
+                return -EINVAL;
+        }
+    }
+    
+    /** The sbrk syscall. This can also be used by subclasses to allocate memory.
+        <i>incr</i> is how much to increase the break by */
+    public int sbrk(int incr) {
+        if(incr < 0) return -ENOMEM;
+        if(incr==0) return brkAddr;
+        incr = (incr+3)&~3;
+        int oldBrk = brkAddr;
+        int newBrk = oldBrk + incr;
+        if(TOTAL_PAGES == 1) {
+            CPUState state = getCPUState();
+            if(newBrk >= state.r[SP] - 65536) {
+                System.err.println("WARNING: brk too close to stack pointer");
+                return -ENOMEM;
+            }
+        } else if(newBrk >= BRK_LIMIT) {
+            System.err.println("WARNING: Hit BRK_LIMIT");
+            return -ENOMEM;
+        }
+        if(TOTAL_PAGES != 1) {
+            try {
+                for(int i=(oldBrk+PAGE_SIZE-1)>>>PAGE_SHIFT;i<((newBrk+PAGE_SIZE-1)>>>PAGE_SHIFT);i++)
+                    readPages[i] = writePages[i] = emptyPage();
+            } catch(OutOfMemoryError e) {
+                System.err.println("WARNING: Caught OOM Exception in sbrk: " + e);
+                return -ENOMEM;
+            }
+        }
+        brkAddr = newBrk;
+        return oldBrk;
+    }
+
+    /** The getpid syscall */
+    private int sys_getpid() { return getPid(); }
+    protected int getPid() { return 1; }
+    
+    private int sys_calljava(int a, int b, int c, int d) {
+        if(state != RUNNING) throw new IllegalStateException("wound up calling sys_calljava while not in RUNNING");
+        state = CALLJAVA;
+        int ret = callJava(a,b,c,d);
+        state = RUNNING;
+        return ret;
+    }
+        
+    private int sys_pause() {
+        state = PAUSED;
+        return 0;
+    }
+    
+    private int sys_getpagesize() { return TOTAL_PAGES == 1 ? 4096 : PAGE_SIZE; }
+    
+    private int sys_isatty(int fdn) {
+        if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD;
+        if(fds[fdn] == null) return -EBADFD;
+        return fds[fdn].isatty() ? 1 : 0;
+    }
+
+    
+    /** Hook for subclasses to do something when the process exits (MUST set state = DONE) */
+    protected void _exit() { state = DONE; }
+    private int sys_exit(int status) {
+        exitStatus = status;
+        for(int i=0;i<fds.length;i++) if(fds[i] != null) sys_close(i);
+        _exit();
+        return 0;
+    }
+       
+    private int sys_fcntl(int fdn, int cmd, int arg) {
+        final int F_DUPFD = 0;
+        final int F_GETFL = 3;
+        int i;
+            
+        if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD;
+        if(fds[fdn] == null) return -EBADFD;
+        FD fd = fds[fdn];
+        
+        switch(cmd) {
+            case F_DUPFD:
+                if(arg < 0 || arg >= OPEN_MAX) return -EINVAL;
+                for(i=arg;i<OPEN_MAX;i++) if(fds[i]==null) break;
+                if(i==OPEN_MAX) return -EMFILE;
+                fds[i] = fd.dup();
+                return 0;
+            case F_GETFL:
+                int flags = 0;
+                if(fd.writable() && fd.readable())  flags = 2;
+                else if(fd.writable()) flags = 1;
+                return flags;
+            default:
+                System.err.println("WARNING: Unknown fcntl command: " + cmd);
+                return -ENOSYS;
+        }
+    }
+            
+    /** The syscall dispatcher.
+        The should be called by subclasses when the syscall instruction is invoked.
+        <i>syscall</i> should be the contents of V0 and <i>a</i>, <i>b</i>, <i>c</i>, and <i>d</i> should be 
+        the contenst of A0, A1, A2, and A3. The call MAY change the state
+        @see Runtime#state state */
+    protected int syscall(int syscall, int a, int b, int c, int d) {
+        switch(syscall) {
+            case SYS_null: return 0;
+            case SYS_exit: return sys_exit(a);
+            case SYS_pause: return sys_pause();
+            case SYS_write: return sys_write(a,b,c);
+            case SYS_fstat: return sys_fstat(a,b);
+            case SYS_sbrk: return sbrk(a);
+            case SYS_open: return sys_open(a,b,c);
+            case SYS_close: return sys_close(a);
+            case SYS_read: return sys_read(a,b,c);
+            case SYS_lseek: return sys_lseek(a,b,c);
+            case SYS_getpid: return sys_getpid();
+            case SYS_calljava: return sys_calljava(a,b,c,d);
+            case SYS_gettimeofday: return sys_gettimeofday(a,b);
+            case SYS_sleep: return sys_sleep(a);
+            case SYS_times: return sys_times(a);
+            case SYS_getpagesize: return sys_getpagesize();
+            case SYS_isatty: return sys_isatty(a);
+            case SYS_fcntl: return sys_fcntl(a,b,c);
+            case SYS_sysconf: return sys_sysconf(a);
+
+            case SYS_kill:
+            case SYS_fork:
+            case SYS_pipe:
+            case SYS_dup2:
+            case SYS_waitpid:
+            case SYS_stat:
+            case SYS_mkdir:
+            case SYS_getcwd:
+            case SYS_chdir:
+                System.err.println("Attempted to use a UnixRuntime syscall in Runtime (" + syscall + ")");
+                return -ENOSYS;
+            default:
+                System.err.println("Attempted to use unknown syscall: " + syscall);
+                return -ENOSYS;
+        }
+    }
+    
+    public int xmalloc(int size) { int p=malloc(size); if(p==0) throw new RuntimeException("malloc() failed"); return p; }
+    public int xrealloc(int addr,int newsize) { int p=realloc(addr,newsize); if(p==0) throw new RuntimeException("realloc() failed"); return p; }
+    public int realloc(int addr, int newsize) { try { return call("realloc",addr,newsize); } catch(CallException e) { return 0; } }
+    public int malloc(int size) { try { return call("malloc",size); } catch(CallException e) { return 0; } }
+    public void free(int p) { try { if(p!=0) call("free",p); } catch(CallException e) { /*noop*/ } }
+    
+    /** Helper function to create a cstring in main memory */
+    public int strdup(String s) {
+        byte[] a;
+        if(s == null) s = "(null)";
+        byte[] a2 = getBytes(s);
+        a = new byte[a2.length+1];
+        System.arraycopy(a2,0,a,0,a2.length);
+        int addr = malloc(a.length);
+        if(addr == 0) return 0;
+        try {
+            copyout(a,addr,a.length);
+        } catch(FaultException e) {
+            free(addr);
+            return 0;
+        }
+        return addr;
+    }
+    
+    /** Helper function to read a cstring from main memory */
+    public String cstring(int addr) throws ReadFaultException {
+        StringBuffer sb = new StringBuffer();
+        for(;;) {
+            int word = memRead(addr&~3);
+            switch(addr&3) {
+                case 0: if(((word>>>24)&0xff)==0) return sb.toString(); sb.append((char)((word>>>24)&0xff)); addr++;
+                case 1: if(((word>>>16)&0xff)==0) return sb.toString(); sb.append((char)((word>>>16)&0xff)); addr++;
+                case 2: if(((word>>> 8)&0xff)==0) return sb.toString(); sb.append((char)((word>>> 8)&0xff)); addr++;
+                case 3: if(((word>>> 0)&0xff)==0) return sb.toString(); sb.append((char)((word>>> 0)&0xff)); addr++;
+            }
+        }
+    }
+    
+    /** File Descriptor class */
+    public static abstract class FD {
+        private int refCount = 1;
+    
+        /** returns true if the fd is readable */
+        public boolean readable() { return false; }
+        /** returns true if the fd is writable */
+        public boolean writable() { return false; }
+        
+        /** Read some bytes. Should return the number of bytes read, 0 on EOF, or throw an IOException on error */
+        public int read(byte[] a, int off, int length) throws IOException { throw new IOException("no definition"); }
+        /** Write. Should return the number of bytes written or throw an IOException on error */
+        public int write(byte[] a, int off, int length) throws IOException { throw new IOException("no definition"); }
+
+        /** Seek in the filedescriptor. Whence is SEEK_SET, SEEK_CUR, or SEEK_END. Should return -1 on error or the new position. */
+        public int seek(int n, int whence)  throws IOException  { return -1; }
+        
+        /** Should return true if this is a tty */
+        public boolean isatty() { return false; }
+        
+        private FStat cachedFStat = null;
+        public final FStat fstat() {
+            if(cachedFStat == null) cachedFStat = _fstat(); 
+            return cachedFStat;
+        }
+        
+        protected abstract FStat _fstat();
+        
+        /** Closes the fd */
+        public final void close() { if(--refCount==0) _close(); }
+        protected void _close() { /* noop*/ }
+        
+        FD dup() { refCount++; return this; }
+    }
+        
+    /** FileDescriptor class for normal files */
+    public abstract static class SeekableFD extends FD {
+        private final int flags;
+        private final SeekableData data;
+        public boolean readable() { return (flags&3) != WR_ONLY; }
+        public boolean writable() { return (flags&3) != RD_ONLY; }
+        
+        SeekableFD(SeekableData data, int flags) { this.data = data; this.flags = flags; }
+        
+        protected abstract FStat _fstat();
+
+        public int seek(int n, int whence) throws IOException {
+            switch(whence) {
+                case SEEK_SET: break;
+                case SEEK_CUR: n += data.pos(); break;
+                case SEEK_END: n += data.length(); break;
+                default: return -1;
+            }
+            data.seek(n);
+            return n;
+        }
+        
+        public int write(byte[] a, int off, int length) throws IOException {
+            // NOTE: There is race condition here but we can't fix it in pure java
+            if((flags&O_APPEND) != 0) seek(0,SEEK_END);
+            return data.write(a,off,length);
+        }
+        
+        public int read(byte[] a, int off, int length) throws IOException {
+            int n = data.read(a,off,length);
+            return n < 0 ? 0 : n;
+        }
+        
+        protected void _close() { try { data.close(); } catch(IOException e) { /*ignore*/ } }        
+    }
+    
+    public static class OutputStreamFD extends FD {
+        private OutputStream os;
+        public boolean writable() { return true; }
+        public OutputStreamFD(OutputStream os) { this.os = os; }
+        public int write(byte[] a, int off, int length) throws IOException { os.write(a,off,length); return length; }
+        public void _close() { try { os.close(); } catch(IOException e) { /*ignore*/ }  }
+        public FStat _fstat() { return new FStat(); }
+    }
+    
+    public static class InputStreamFD extends FD {
+        private InputStream is;
+        public boolean readable() { return true; }
+        public InputStreamFD(InputStream is) { this.is = is; }
+        public int read(byte[] a, int off, int length) throws IOException { int n = is.read(a,off,length); return n < 0 ? 0 : n; }
+        public void _close() { try { is.close(); } catch(IOException e) { /*ignore*/ } }
+        public FStat _fstat() { return new FStat(); }
+    }
+    
+    protected static class StdinFD extends InputStreamFD {
+        public StdinFD(InputStream is) { super(is); }
+        public void _close() { /* noop */ }
+        public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; }
+        public boolean isatty() { return true; }
+    }
+    protected static class StdoutFD extends OutputStreamFD {
+        public StdoutFD(OutputStream os) { super(os); }
+        public void _close() { /* noop */ }
+        public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; }
+        public boolean isatty() { return true; }
+    }
+    
+    public static class FStat {
+        public static final int S_IFIFO = 0010000;
+        public static final int S_IFCHR = 0020000;
+        public static final int S_IFDIR = 0040000;
+        public static final int S_IFREG = 0100000;
+        
+        public int dev() { return -1; }
+        // FEATURE: inode numbers are calculated inconsistently throught the runtime
+        public int inode() { return hashCode() & 0xfffff; }
+        public int mode() { return 0; }
+        public int type() { return S_IFIFO; }
+        public int nlink() { return 0; }
+        public int uid() { return 0; }
+        public int gid() { return 0; }
+        public int size() { return 0; }
+        public int atime() { return 0; }
+        public int mtime() { return 0; }
+        public int ctime() { return 0; }
+        public int blksize() { return 512; }
+        public int blocks() { return (size()+blksize()-1)/blksize(); }        
+    }
+    
+    protected static class HostFStat extends FStat {
+        private final File f;
+        private final boolean executable; 
+        public HostFStat(File f) {
+            this.f = f;
+            String name = f.getName();
+            // FEATURE: This is ugly.. maybe we should do a file(1) type check
+            executable = name.endsWith(".mips") || name.endsWith(".sh");
+        }
+        public int dev() { return 1; }
+        public int inode() { return f.getName().hashCode() & 0xffff; }
+        public int type() { return f.isDirectory() ? S_IFDIR : S_IFREG; }
+        public int nlink() { return 1; }
+        public int mode() {
+            int mode = 0;
+            boolean canread = f.canRead();
+            if(canread && (executable || f.isDirectory())) mode |= 0111;
+            if(canread) mode |= 0444;
+            if(f.canWrite()) mode |= 0222;
+            return mode;
+        }
+        public int size() { return (int) f.length(); }
+        public int mtime() { return (int)(f.lastModified()/1000); }
+    }
+    
+    // Exceptions
+    public class ReadFaultException extends FaultException {
+        public ReadFaultException(int addr) { super(addr); }
+    }
+    public class WriteFaultException extends FaultException {
+        public WriteFaultException(int addr) { super(addr); }
+    }
+    public abstract class FaultException extends ExecutionException {
+        public int addr;
+        public FaultException(int addr) { super("fault at: " + toHex(addr)); this.addr = addr; }
+    }
+    public static class ExecutionException extends Exception {
+        private String message = "(null)";
+        private String location = "(unknown)";
+        public ExecutionException() { /* noop */ }
+        public ExecutionException(String s) { if(s != null) message = s; }
+        void setLocation(String s) { location = s == null ? "(unknown)" : s; }
+        public final String getMessage() { return message + " at " + location; }
+    }
+    public static class CallException extends Exception {
+        public CallException(String s) { super(s); }
+    }
+    
+    protected static class ErrnoException extends IOException {
+        public int errno;
+        public ErrnoException(int errno) { super("Errno: " + errno); this.errno = errno; }
+    }
+    
+    // CPU State
+    protected static class CPUState {
+        public CPUState() { /* noop */ }
+        /* GPRs */
+        public int[] r = new int[32];
+        /* Floating point regs */
+        public int[] f = new int[32];
+        public int hi, lo;
+        public int fcsr;
+        public int pc;
+    }
+    
+    // Null pointer check helper function
+    protected final void nullPointerCheck(int addr) throws ExecutionException {
+        if(TOTAL_PAGES==1 ? addr < 65536 : (addr>>>PAGE_SHIFT) < 16)
+            throw new ExecutionException("Attempted to dereference a null pointer " + toHex(addr));
+    }
+    
+    // Utility functions
+    private byte[] byteBuf(int size) {
+        if(_byteBuf==null) _byteBuf = new byte[size];
+        else if(_byteBuf.length < size)
+            _byteBuf = new byte[min(max(_byteBuf.length*2,size),MAX_CHUNK)];
+        return _byteBuf;
+    }
+    
+    protected static String getSystemProperty(String key) {
+        try {
+            return System.getProperty(key);
+        } catch(SecurityException e) {
+            return null;
+        }
+    }
+    
+    /** Decode an packed string.. FEATURE: document this better */
+    protected static final int[] decodeData(String s, int words) {
+        if(s.length() % 8 != 0) throw new IllegalArgumentException("string length must be a multiple of 8");
+        if((s.length() / 8) * 7 < words*4) throw new IllegalArgumentException("string isn't big enough");
+        int[] buf = new int[words];
+        int prev = 0, left=0;
+        for(int i=0,n=0;n<words;i+=8) {
+            long l = 0;
+            for(int j=0;j<8;j++) { l <<= 7; l |= s.charAt(i+j) & 0x7f; }
+            if(left > 0) buf[n++] = prev | (int)(l>>>(56-left));
+            if(n < words) buf[n++] = (int) (l >>> (24-left));
+            left = (left + 8) & 0x1f;
+            prev = (int)(l << left);
+        }
+        return buf;
+    }
+    
+    protected static byte[] getBytes(String s) {
+        try {
+            return s.getBytes("ISO-8859-1");
+        } catch(UnsupportedEncodingException e) {
+            return null; // should never happen
+        }
+    }
+    
+    protected final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
+    protected final static int min(int a, int b) { return a < b ? a : b; }
+    protected final static int max(int a, int b) { return a > b ? a : b; }
+}
diff --git a/src/org/xwt/mips/UnixRuntime.java b/src/org/xwt/mips/UnixRuntime.java
new file mode 100644 (file)
index 0000000..8572ab9
--- /dev/null
@@ -0,0 +1,620 @@
+package org.xwt.mips;
+
+import org.xwt.mips.util.*;
+import java.io.*;
+import java.util.*;
+
+public abstract class UnixRuntime extends Runtime {
+    /** The pid of this "process" */
+    private int pid;
+    private int ppid;
+    protected int getPid() { return pid; }
+    
+    /** processes filesystem */
+    private FS fs;
+    public FS getFS() { return fs; }
+    public void setFS(FS fs) {
+        if(state >= RUNNING) throw new IllegalStateException("Can't change fs while process is running");
+        this.fs = fs;
+    }
+    
+    /** proceses current working directory */
+    private String cwd;
+    
+    /* Static stuff */
+    // FEATURE: Most of this is O(n) or worse - fix it
+    private final Object waitNotification = new Object();
+    private final static int MAX_TASKS = 256;
+    private final static UnixRuntime[] tasks = new UnixRuntime[MAX_TASKS];
+    private static int addTask(UnixRuntime rt) {
+        synchronized(tasks) {
+            for(int i=1;i<MAX_TASKS;i++) {
+                if(tasks[i] == null) {
+                    tasks[i] = rt;
+                    rt.pid = i;
+                    return i;
+                }
+            }
+            return -1;
+        }
+    }
+    private static void removeTask(UnixRuntime rt) {
+        synchronized(tasks) {
+            for(int i=1;i<MAX_TASKS;i++)
+                if(tasks[i] == rt) { tasks[i] = null; break; }
+        }
+    }
+    
+    public UnixRuntime(int pageSize, int totalPages, boolean allowEmptyPages) {
+        super(pageSize,totalPages,allowEmptyPages);
+        
+        HostFS root = new HostFS();
+        fs = new UnixOverlayFS(root);
+        
+        String dir = root.hostCWD();
+        try {
+            chdir(dir == null ? "/" : dir);
+        } catch(FileNotFoundException e) {
+            e.printStackTrace();
+            cwd = "/";
+        }
+    }
+    
+    private static String posixTZ() {
+        StringBuffer sb = new StringBuffer();
+        TimeZone zone = TimeZone.getDefault();
+        int off = zone.getRawOffset() / 1000;
+        sb.append(zone.getDisplayName(false,TimeZone.SHORT));
+        if(off > 0) sb.append("-");
+        else off = -off;
+        sb.append(off/3600); off = off%3600;
+        if(off > 0) sb.append(":").append(off/60); off=off%60;
+        if(off > 0) sb.append(":").append(off);
+        if(zone.useDaylightTime())
+            sb.append(zone.getDisplayName(true,TimeZone.SHORT));
+        return sb.toString();
+    }
+    
+    private static boolean envHas(String key,String[] environ) {
+        for(int i=0;i<environ.length;i++)
+            if(environ[i]!=null && environ[i].startsWith(key + "=")) return true;
+        return false;
+    }
+    
+    protected String[] createEnv(String[] extra) {
+        String[] defaults = new String[5];
+        int n=0;
+        if(extra == null) extra = new String[0];
+        if(!envHas("USER",extra) && getSystemProperty("user.name") != null)
+            defaults[n++] = "USER=" + getSystemProperty("user.name");
+        if(!envHas("HOME",extra) && getSystemProperty("user.name") != null)
+            defaults[n++] = "HOME=" + getSystemProperty("user.home");
+        if(!envHas("SHELL",extra)) defaults[n++] = "SHELL=/bin/sh";
+        if(!envHas("TERM",extra))  defaults[n++] = "TERM=vt100";
+        if(!envHas("TZ",extra))    defaults[n++] = "TZ=" + posixTZ();
+        String[] env = new String[extra.length+n];
+        for(int i=0;i<n;i++) env[i] = defaults[i];
+        for(int i=0;i<extra.length;i++) env[n++] = extra[i];
+        return env;
+    }
+    
+    protected void _start() {
+        if(addTask(this) < 0) throw new Error("Task list full");
+    }
+    
+    protected void _exit() {
+        synchronized(tasks) {
+            if(ppid == 0) removeTask(this);
+            for(int i=0;i<MAX_TASKS;i++) {
+                if(tasks[i] != null && tasks[i].ppid == pid) {
+                    if(tasks[i].state == DONE) removeTask(tasks[i]);
+                    else tasks[i].ppid = 0;
+                }
+            }
+            state = DONE;
+            if(ppid != 0) synchronized(tasks[ppid].waitNotification) { tasks[ppid].waitNotification.notify(); }
+        }
+    }
+
+    protected int syscall(int syscall, int a, int b, int c, int d) {
+        switch(syscall) {
+            case SYS_kill: return sys_kill(a,b);
+            case SYS_fork: return sys_fork();
+            case SYS_pipe: return sys_pipe(a);
+            case SYS_dup2: return sys_dup2(a,b);
+            case SYS_waitpid: return sys_waitpid(a,b,c);
+            case SYS_stat: return sys_stat(a,b);
+            case SYS_mkdir: return sys_mkdir(a,b);
+            case SYS_getcwd: return sys_getcwd(a,b);
+            case SYS_chdir: return sys_chdir(a);
+
+            default: return super.syscall(syscall,a,b,c,d);
+        }
+    }
+    
+    protected FD open(String path, int flags, int mode) throws IOException { return fs.open(cleanupPath(path),flags,mode); }
+
+    // FEATURE: Allow simple, broken signal delivery to other processes 
+    // (check if a signal was delivered before and after syscalls)
+    // FEATURE: Implement raise() in terms of call("raise",...) - kinda cheap, but it keeps the complexity in newlib
+    /** The kill syscall.
+       SIGSTOP, SIGTSTO, SIGTTIN, and SIGTTOUT pause the process.
+       SIGCONT, SIGCHLD, SIGIO, and SIGWINCH are ignored.
+       Anything else terminates the process. */
+    private int sys_kill(int pid, int signal) {
+        // This will only be called by raise() in newlib to invoke the default handler
+        // We don't have to worry about actually delivering the signal
+        if(pid != pid) return -ESRCH;
+        if(signal < 0 || signal >= 32) return -EINVAL;
+        switch(signal) {
+            case 0: return 0;
+            case 17: // SIGSTOP
+            case 18: // SIGTSTP
+            case 21: // SIGTTIN
+            case 22: // SIGTTOU
+                state = PAUSED;
+                break;
+            case 19: // SIGCONT
+            case 20: // SIGCHLD
+            case 23: // SIGIO
+            case 28: // SIGWINCH
+                break;
+            default: {
+                String msg = "Terminating on signal: " + signal + "\n";
+                exitStatus = 1;
+                state = DONE;
+                if(fds[2]==null) {
+                    System.out.print(msg);
+                } else {
+                    try {
+                        byte[] b = getBytes(msg); 
+                        fds[2].write(b,0,b.length);
+                    }
+                    catch(IOException e) { /* ignore */ }
+                }
+            }
+        }
+        return 0;
+    }
+
+    private int sys_waitpid(int pid, int statusAddr, int options) {
+        final int WNOHANG = 1;
+        if((options & ~(WNOHANG)) != 0) return -EINVAL;
+        if(pid !=-1 && (pid <= 0 || pid >= MAX_TASKS)) return -ECHILD;
+        for(;;) {
+            synchronized(tasks) {
+                UnixRuntime task = null;
+                if(pid == -1) {
+                    for(int i=0;i<MAX_TASKS;i++) {
+                        if(tasks[i] != null && tasks[i].ppid == this.pid && tasks[i].state == DONE) {
+                            task = tasks[i];
+                            break;
+                        }
+                    }
+                } else if(tasks[pid] != null && tasks[pid].ppid == this.pid && tasks[pid].state == DONE) {
+                    task = tasks[pid];
+                }
+                
+                if(task != null) {
+                    removeTask(task);
+                    try {
+                        if(statusAddr!=0) memWrite(statusAddr,task.exitStatus()<<8);
+                    } catch(FaultException e) {
+                        return -EFAULT;
+                    }
+
+                    return task.pid;
+                }
+            }
+            if((options&WNOHANG)!=0) return 0;
+            synchronized(waitNotification) {
+                try { waitNotification.wait(); } catch(InterruptedException e) { throw new Error(e); }
+            }
+        }
+    }
+    
+    // Great ugliness lies within.....
+    private int sys_fork() {
+        CPUState state = getCPUState();
+        int sp = state.r[SP];
+        final UnixRuntime r;
+        try {
+            r = (UnixRuntime) getClass().newInstance();
+        } catch(Exception e) {
+            System.err.println(e);
+            return -ENOMEM;
+        }
+        int child_pid = addTask(r);
+        if(child_pid < 0) return -ENOMEM;
+        
+        r.ppid = pid;
+        r.brkAddr = brkAddr;
+        r.fds = new FD[OPEN_MAX];
+        for(int i=0;i<OPEN_MAX;i++) if(fds[i] != null) r.fds[i] = fds[i].dup();
+        r.cwd = cwd;
+        r.fs = fs;
+        for(int i=0;i<TOTAL_PAGES;i++) {
+            if(readPages[i] == null) continue;
+            if(isEmptyPage(writePages[i])) {
+                r.readPages[i] = r.writePages[i] = writePages[i];
+            } else if(writePages[i] != null) {
+                r.readPages[i] = r.writePages[i] = new int[PAGE_WORDS];
+                if(STACK_BOTTOM == 0 || i*PAGE_SIZE < STACK_BOTTOM || i*PAGE_SIZE >= sp-PAGE_SIZE*2)
+                    System.arraycopy(writePages[i],0,r.writePages[i],0,PAGE_WORDS);
+            } else {
+                r.readPages[i] = r.readPages[i];
+            }
+        }
+        state.r[V0] = 0;
+        state.pc += 4;
+        r.setCPUState(state);
+        r.state = PAUSED;
+        
+        new Thread() {
+            public void run() {
+                try {
+                    while(!r.execute());
+                } catch(Exception e) {
+                    System.err.println("Forked process threw exception: ");
+                    e.printStackTrace();
+                }
+            }
+        }.start();
+        
+        return child_pid;        
+    }
+            
+    private int sys_pipe(int addr) {
+        PipedOutputStream writerStream = new PipedOutputStream();
+        PipedInputStream readerStream;
+        try {
+             readerStream = new PipedInputStream(writerStream);
+        } catch(IOException e) {
+            return -EIO;
+        }
+        FD reader = new InputStreamFD(readerStream);
+        FD writer = new OutputStreamFD(writerStream);
+        int fd1 = addFD(reader);
+        if(fd1 < 0) return -ENFILE;
+        int fd2 = addFD(writer);
+        if(fd2 < 0) { closeFD(fd1); return -ENFILE; }
+        try {
+            memWrite(addr,fd1);
+            memWrite(addr+4,fd2);
+        } catch(FaultException e) {
+            closeFD(fd1);
+            closeFD(fd2);
+            return -EFAULT;
+        }
+        return 0;
+    }
+    
+    private int sys_dup2(int oldd, int newd) {
+        if(oldd == newd) return 0;
+        if(oldd < 0 || oldd >= OPEN_MAX) return -EBADFD;
+        if(newd < 0 || newd >= OPEN_MAX) return -EBADFD;
+        if(fds[oldd] == null) return -EBADFD;
+        if(fds[newd] != null) fds[newd].close();
+        fds[newd] = fds[oldd].dup();
+        return 0;
+    }
+    
+    private int sys_stat(int cstring, int addr) {
+        try {
+            String path = cleanupPath(cstring(cstring));
+            return stat(fs.stat(path),addr);
+        }
+        catch(ErrnoException e) { return -e.errno; }
+        catch(FileNotFoundException e) {
+            if(e.getMessage() != null && e.getMessage().indexOf("Permission denied") >= 0) return -EACCES;
+            return -ENOENT;
+        }
+        catch(IOException e) { return -EIO; }
+        catch(FaultException e) { return -EFAULT; }
+    }
+    
+    
+    private int sys_mkdir(int cstring, int mode) {
+        try {
+            fs.mkdir(cleanupPath(cstring(cstring)));
+            return 0;
+        }
+        catch(ErrnoException e) { return -e.errno; }
+        catch(FileNotFoundException e) { return -ENOENT; }
+        catch(IOException e) { return -EIO; }
+        catch(FaultException e) { return -EFAULT; }
+    }
+   
+    
+    private int sys_getcwd(int addr, int size) {
+        byte[] b = getBytes(cwd);
+        if(size == 0) return -EINVAL;
+        if(size < b.length+1) return -ERANGE;
+        if(!new File(cwd).exists()) return -ENOENT;
+        try {
+            copyout(b,addr,b.length);
+            memset(addr+b.length+1,0,1);
+            return addr;
+        } catch(FaultException e) {
+            return -EFAULT;
+        }
+    }
+    
+    private int sys_chdir(int addr) {
+        try {
+            String path = cleanupPath(cstring(addr));
+            System.err.println("Chdir: " + cstring(addr) + " -> " + path + " pwd: " + cwd);
+            if(fs.stat(path).type() != FStat.S_IFDIR) return -ENOTDIR;
+            cwd = path;
+            System.err.println("Now: " + cwd);
+            return 0;
+        }
+        catch(ErrnoException e) { return -e.errno; }
+        catch(FileNotFoundException e) { return -ENOENT; }
+        catch(IOException e) { return -EIO; }
+        catch(FaultException e) { return -EFAULT; }
+    }
+
+    public void chdir(String dir) throws FileNotFoundException {
+        if(state >= RUNNING) throw new IllegalStateException("Can't chdir while process is running");
+        try {
+            dir = cleanupPath(dir);
+            if(fs.stat(dir).type() != FStat.S_IFDIR) throw new FileNotFoundException();
+        } catch(IOException e) {
+            throw new FileNotFoundException();
+        }
+        cwd = dir;
+    }
+        
+    public abstract static class FS {
+        public FD open(String path, int flags, int mode) throws IOException { throw new FileNotFoundException(); }
+        public FStat stat(String path) throws IOException { throw new FileNotFoundException(); }
+        public void mkdir(String path) throws IOException { throw new ErrnoException(ENOTDIR); }
+        
+        public static FD directoryFD(String[] files, int hashCode) throws IOException {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            DataOutputStream dos = new DataOutputStream(bos);
+            for(int i=0;i<files.length;i++) {
+                byte[] b = getBytes(files[i]);
+                int inode = (files[i].hashCode() ^ hashCode) & 0xfffff;
+                dos.writeInt(inode);
+                dos.writeInt(b.length);
+                dos.write(b,0,b.length);
+            }
+            final byte[] data = bos.toByteArray();
+            return new SeekableFD(new SeekableByteArray(data,false),RD_ONLY) {
+                protected FStat _fstat() { return  new FStat() {
+                    public int length() { return data.length; }
+                    public int type() { return S_IFDIR; }
+                }; }
+            };
+        }
+    }
+        
+    public static void main(String[] args) throws Exception {
+        UnixRuntime rt = new Interpreter();
+        rt.cwd = getSystemProperty("user.dir");
+        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+        String line;
+        while((line = br.readLine()) != null) {
+            System.out.println("[" + rt.cleanupPath(line) + "]");
+        }
+    }
+    
+    
+    private static boolean needsCleanup(String path) {
+        if(path.indexOf("//") != -1) return true;
+        if(path.indexOf('.') != -1) {
+            if(path.length() == 1) return true;
+            if(path.equals("..")) return true;
+            if(path.startsWith("./")  || path.indexOf("/./")  != -1 || path.endsWith("/."))  return true;
+            if(path.startsWith("../") || path.indexOf("/../") != -1 || path.endsWith("/..")) return true;
+        }
+        return false;
+    }
+    
+    // FIXME: This is probably still buggy
+    // FEATURE: Remove some of the "should never happen checks"
+    protected String cleanupPath(String p) throws ErrnoException {
+        if(p.length() == 0) throw new ErrnoException(ENOENT);
+        if(needsCleanup(p)) {
+            char[] in = p.toCharArray();
+            char[] out;
+            int outp ;
+            if(in[0] == '/') {
+                out = new char[in.length];
+                outp = 0;
+            } else {
+                out = new char[cwd.length() + in.length + 1];
+                outp = cwd.length();
+                for(int i=0;i<outp;i++) out[i] = cwd.charAt(i);
+                if(outp == 0 || out[0] != '/') throw new Error("should never happen");
+            }
+            int inLength = in.length;
+            int inp = 0;
+            while(inp<inLength) {
+                if(inp == 0 || in[inp] == '/') {
+                    while(inp < inLength && in[inp] == '/') inp++;
+                    if(inp == inLength) break;
+                    if(in[inp] == '.') {
+                        if(inp+1 == inLength) break;
+                        if(in[inp+1] == '.' && (inp+2 == inLength || in[inp+2] == '/')) {
+                            inp+=2;
+                            if(outp == 0) continue;
+                            do { outp--; } while(outp > 0 && out[outp] != '/');
+                        } else if(in[inp+1] == '/') {
+                            inp++;
+                        } else {
+                            out[outp++] = '/';
+                        }
+                    } else {
+                        out[outp++] = '/';
+                        out[outp++] = in[inp++];
+                    }
+                } else {
+                    out[outp++] = in[inp++];
+                }
+            }
+            if(outp == 0) out[outp++] = '/';
+            return new String(out,0,outp);
+        } else {
+            if(p.startsWith("/")) return p;
+            StringBuffer sb = new StringBuffer(cwd);
+            if(!cwd.equals("/")) sb.append('/');
+            return sb.append(p).toString();
+        }
+    }
+    
+    // FEATURE: Probably should make this more general - support mountpoints, etc
+    public class UnixOverlayFS extends FS {
+        private final FS root;
+        private final FS dev = new DevFS();
+        public UnixOverlayFS(FS root) {
+            this.root = root;
+        }
+        private String devPath(String path) {
+            if(path.startsWith("/dev")) {
+                if(path.length() == 4) return "/";
+                if(path.charAt(4) == '/') return path.substring(4);
+            }
+            return null;
+        }
+        public FD open(String path, int flags, int mode) throws IOException{
+            String dp = devPath(path);
+            return dp == null ? root.open(path,flags,mode) : dev.open(dp,flags,mode);
+        }
+        public FStat stat(String path) throws IOException {
+            String dp = devPath(path);
+            return dp == null ? root.stat(path) : dev.stat(dp);
+        }
+        public void mkdir(String path) throws IOException {
+            String dp = devPath(path);
+            if(dp == null) root.mkdir(path);
+            else dev.mkdir(dp);
+        }
+    }
+    
+    // FIXME: This is totally broken on non-unix hosts - need to do some kind of cygwin type mapping
+    public static class HostFS extends FS {
+        public static String fixPath(String path) throws FileNotFoundException {
+            return path;
+        }
+        
+        public String hostCWD() {
+            return getSystemProperty("user.dir");
+        }
+        
+        // FEATURE: This shares a lot with Runtime.open
+        public FD open(String path, int flags, int mode) throws IOException {
+            path = fixPath(path);
+            final File f = new File(path);
+            // NOTE: createNewFile is a Java2 function
+            if((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT))
+                if(!f.createNewFile()) throw new ErrnoException(EEXIST);
+            if(!f.exists() && (flags&O_CREAT) == 0) return null;
+            if(f.isDirectory()) {
+                if((flags&3)!=RD_ONLY) throw new ErrnoException(EACCES);
+                return directoryFD(f.list(),path.hashCode());
+            }
+            final SeekableFile sf = new SeekableFile(path,(flags&3)!=RD_ONLY);
+            if((flags&O_TRUNC)!=0) sf.setLength(0);
+            return new SeekableFD(sf,mode) {
+                protected FStat _fstat() { return new HostFStat(f) {
+                    public int size() {
+                        try { return sf.length(); } catch(IOException e) { return 0; }
+                    }
+                };}
+            };
+        }
+        
+        public FStat stat(String path) throws FileNotFoundException {
+            File f = new File(fixPath(path));
+            if(!f.exists()) throw new FileNotFoundException();
+            return new HostFStat(f);
+        }
+        
+        public void mkdir(String path) throws IOException {
+            File f = new File(fixPath(path));
+            if(f.exists() && f.isDirectory()) throw new ErrnoException(EEXIST);
+            if(f.exists()) throw new ErrnoException(ENOTDIR);
+            File parent = f.getParentFile();
+            if(parent!=null && (!parent.exists() || !parent.isDirectory())) throw new ErrnoException(ENOTDIR);
+            if(!f.mkdir()) throw new ErrnoException(EIO);            
+        }
+    }
+    
+    private static class DevFStat extends FStat {
+        public int dev() { return 1; }
+        public int mode() { return 0666; }
+        public int type() { return S_IFCHR; }
+        public int nlink() { return 1; }
+    }
+    private static FD devZeroFD = new FD() {
+        public boolean readable() { return true; }
+        public boolean writable() { return true; }
+        public int read(byte[] a, int off, int length) { Arrays.fill(a,off,off+length,(byte)0); return length; }
+        public int write(byte[] a, int off, int length) { return length; }
+        public int seek(int n, int whence) { return 0; }
+        public FStat _fstat() { return new DevFStat(); }
+    };
+    private static FD devNullFD = new FD() {
+        public boolean readable() { return true; }
+        public boolean writable() { return true; }
+        public int read(byte[] a, int off, int length) { return 0; }
+        public int write(byte[] a, int off, int length) { return length; }
+        public int seek(int n, int whence) { return 0; }
+        public FStat _fstat() { return new DevFStat(); }
+    };    
+    
+    public class DevFS extends FS {
+        public FD open(String path, int mode, int flags) throws IOException {
+            if(path.equals("/null")) return devNullFD;
+            if(path.equals("/zero")) return devZeroFD;
+            if(path.startsWith("/fd/")) {
+                int n;
+                try {
+                    n = Integer.parseInt(path.substring(4));
+                } catch(NumberFormatException e) {
+                    throw new FileNotFoundException();
+                }
+                if(n < 0 || n >= OPEN_MAX) throw new FileNotFoundException();
+                if(fds[n] == null) throw new FileNotFoundException();
+                return fds[n].dup();
+            }
+            if(path.equals("/fd")) {
+                int count=0;
+                for(int i=0;i<OPEN_MAX;i++) if(fds[i] != null) count++; 
+                String[] files = new String[count];
+                count = 0;
+                for(int i=0;i<OPEN_MAX;i++) if(fds[i] != null) files[count++] = Integer.toString(i);
+                return directoryFD(files,hashCode());
+            }
+            if(path.equals("/")) {
+                String[] files = { "null", "zero", "fd" };
+                return directoryFD(files,hashCode());
+            }
+            throw new FileNotFoundException();
+        }
+        
+        public FStat stat(String path) throws IOException {
+            if(path.equals("/null")) return devNullFD.fstat();
+            if(path.equals("/zero")) return devZeroFD.fstat();            
+            if(path.startsWith("/fd/")) {
+                int n;
+                try {
+                    n = Integer.parseInt(path.substring(4));
+                } catch(NumberFormatException e) {
+                    throw new FileNotFoundException();
+                }
+                if(n < 0 || n >= OPEN_MAX) throw new FileNotFoundException();
+                if(fds[n] == null) throw new FileNotFoundException();
+                return fds[n].fstat();
+            }
+            if(path.equals("/fd")) return new FStat() { public int type() { return S_IFDIR; } public int mode() { return 0444; }};
+            if(path.equals("/")) return new FStat() { public int type() { return S_IFDIR; } public int mode() { return 0444; }};
+            throw new FileNotFoundException();
+        }
+        
+        public void mkdir(String path) throws IOException { throw new ErrnoException(EACCES); }
+    }
+}
diff --git a/src/org/xwt/mips/crt0.c b/src/org/xwt/mips/crt0.c
new file mode 100644 (file)
index 0000000..a85cdbc
--- /dev/null
@@ -0,0 +1,31 @@
+#include <stddef.h>
+
+extern int _gp[];
+
+extern int main(int argc, char **argv, char **envp);
+extern void exit(int status);
+extern int atexit(void (*f)());
+
+/* For constuctors/destructors */
+extern void _init();
+extern void _fini();
+
+char **environ;
+    
+void _start(char **argv, char **environ_) {
+    int argc;
+    
+    environ = environ_;
+    
+    /* Call global constructors */
+    _init();
+    
+    /* Register _fini() to be called on exit */
+    atexit(_fini);
+    
+    /* Count the arguments */
+    for(argc=0;argv[argc];argc++);
+        
+    /* Call main and exit */
+    exit(main(argc,argv,environ));
+}
diff --git a/src/org/xwt/mips/linker.ld b/src/org/xwt/mips/linker.ld
new file mode 100644 (file)
index 0000000..c12be88
--- /dev/null
@@ -0,0 +1,60 @@
+ENTRY(_start)
+INPUT(support.o support_aux.o)
+GROUP(-lc -lgcc)
+/*GROUP(-lgcc)*/
+__DYNAMIC  =  0;
+
+SECTIONS {
+  . = 0x10000;
+  .text : {
+    KEEP(*(.init))
+    KEEP(*(.fini))
+    KEEP(*(.text))
+    *(.text.*) 
+    *(.gnu.linkonce.t*)
+  }
+
+  _etext = .;
+
+  .ctors :
+  {
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  
+  .dtors :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+
+  . = ALIGN(4k);
+
+  .rodata : {
+    *(.rodata*) *(.gnu.linkonce.r*)
+    *(.gcc_except_table)
+    KEEP(*(.eh_frame)) KEEP(*(.jcr))
+  }
+
+  .data : {
+    *(.data*) *(.gnu.linkonce.d*)
+  }
+
+  . = ALIGN(16);
+   _gp = . + 0x8000;
+  .sdata : {
+    *(.rosdata*) *(.sdata*) *(.gnu.linkonce.s*)
+  }
+  .sbss : {
+    *(.sbss*) *(.scommon*)
+  }
+  .bss : {
+    *(.bss*) *(.gnu.linkonce.b*) *(COMMON) 
+  }
+
+  _end = .;
+}
diff --git a/src/org/xwt/mips/support.s b/src/org/xwt/mips/support.s
new file mode 100644 (file)
index 0000000..b7781d5
--- /dev/null
@@ -0,0 +1,122 @@
+#include "syscalls.h"
+
+#define zero $0
+#define v0 $2
+#define v1 $3
+#define a0 $4
+#define a1 $5
+#define a2 $6
+#define a3 $7
+#define t0 $8
+#define t1 $9
+#define ra $31
+
+/* We intentionally don't take advantage of delay slots because
+   the compiler removes them anyway */
+
+.set noreorder;
+
+#define SYSCALL(name) SYSCALL2(name,SYS_##name)
+#define SYSCALL2(name,number)  \
+    .section .text.name,"ax",@progbits; \
+    .align 2;       \
+    .globl name;    \
+    .ent name;      \
+name:               \
+    li v0, number;  \
+    syscall;        \
+    j ra;           \
+    nop;            \
+    .end name;
+
+#define SYSCALL_R(name)        \
+    .section .text._##name##_r,"ax",@progbits; \
+    .align 2;                  \
+    .globl _##name##_r;        \
+    .ent _##name##_r;          \
+_##name##_r:                   \
+    li v0, SYS_##name;         \
+    move t0, a0;               \
+    move a0, a1;               \
+    move a1, a2;               \
+    move a2, a3;               \
+    syscall;                   \
+    addu t1,v0,255;            \
+    sltu t1,t1,255;            \
+    bne t1,zero,$L##name##_errno;\
+    nop;                       \
+    j ra;                      \
+    nop;                       \
+$L##name##_errno:              \
+    move a0, t0;               \
+    move a1, v0;               \
+    j _syscall_set_errno;      \
+    nop;                       \
+    .end _##name##_r;
+
+
+    .align   2
+    .globl   _call_helper
+    .ent     _call_helper
+_call_helper:
+    subu $sp,$sp,32
+    
+    /* addr */
+    move $2,$4
+    
+    /* args 1-4 */
+    move $4,$5 
+    move $5,$6
+    move $6,$7
+    move $7,$16
+    
+    /* args 5 and 6 */
+    sw $17,16($sp)
+    sw $18,20($sp)
+    
+    /* call the func */
+    jal $31,$2
+    nop
+    
+    move $3,$2
+    li $2,SYS_pause
+    syscall
+    
+    /* shouldn't get here */
+    li $2,SYS_exit
+    li $3,1
+    syscall
+    
+    .end _call_helper
+
+SYSCALL2(_exit,SYS_exit)
+SYSCALL2(_pause,SYS_pause)
+SYSCALL_R(open)
+SYSCALL_R(close)
+SYSCALL_R(read)
+SYSCALL_R(write)
+SYSCALL_R(sbrk)
+SYSCALL_R(fstat)
+SYSCALL(isatty)
+SYSCALL_R(lseek)
+SYSCALL_R(kill)
+SYSCALL_R(getpid)
+SYSCALL2(_call_java,SYS_calljava)
+SYSCALL_R(stat)
+SYSCALL_R(gettimeofday)
+SYSCALL(sleep)
+SYSCALL_R(times)
+SYSCALL_R(mkdir)
+SYSCALL(getpagesize)
+SYSCALL_R(unlink)
+SYSCALL_R(utime)
+SYSCALL_R(chdir)
+SYSCALL_R(pipe)
+SYSCALL_R(dup2)
+SYSCALL_R(fork)
+SYSCALL_R(waitpid)
+SYSCALL_R(getcwd)
+SYSCALL_R(execve)
+SYSCALL_R(fcntl)
+SYSCALL_R(rmdir)
+SYSCALL_R(sysconf)
diff --git a/src/org/xwt/mips/support_aux.c b/src/org/xwt/mips/support_aux.c
new file mode 100644 (file)
index 0000000..9800e4a
--- /dev/null
@@ -0,0 +1,124 @@
+#include <sys/stat.h>
+#include <sys/dirent.h>
+#include <sys/types.h>
+#include <utime.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int _syscall_set_errno(struct _reent *ptr, int err) {
+    ptr->_errno = -err;
+    return -1;
+}
+
+extern int _stat_r(struct _reent *ptr, const char *path, struct stat *sb);
+int _lstat_r(struct _reent *ptr, const char *path, struct stat *sb) {
+    return _stat_r(ptr,path,sb);
+}
+
+uid_t getuid() { return 0; }
+gid_t getgid() { return 0; }
+uid_t geteuid() { return 0; }
+gid_t getegid() { return 0; }
+int getgroups(int gidsetlen, gid_t *gidset) {
+    if(gidsetlen) *gidset = 0;
+    return 1;
+}
+mode_t umask(mode_t new) { return 0022; }
+
+static int syscall_nosys(struct _reent *ptr) {
+    ptr->_errno = ENOSYS;
+    return -1;
+}
+
+int _access_r(struct _reent *ptr, const char *pathname, int mode) {
+    struct stat statbuf;
+    if(_stat_r(ptr,pathname,&statbuf) < 0) return -1;
+    return 0;
+}
+
+/* FIXME: These should be in newlib */
+int access(const char *pathname, int mode) { return _access_r(_REENT,pathname,mode); }
+extern int _rmdir_r(struct _reent *ptr, const char *pathname);
+int rmdir(const char *pathname) { return _rmdir_r(_REENT,pathname); }
+extern long _sysconf_r(struct _reent *ptr, int n);
+long sysconf(int n) { return _sysconf_r(_REENT,n); }
+
+#define SYSCALL_NOSYS_R(name) int _##name##_r(struct _reent *ptr) { return syscall_nosys(ptr); }
+
+SYSCALL_NOSYS_R(link)
+SYSCALL_NOSYS_R(symlink)
+SYSCALL_NOSYS_R(readlink)
+SYSCALL_NOSYS_R(chown)
+SYSCALL_NOSYS_R(fchown)
+SYSCALL_NOSYS_R(chmod)
+SYSCALL_NOSYS_R(fchmod)
+
+static int read_fully(int fd, void *buf, size_t size) {
+    int n;
+    while(size) {
+        n = read(fd,buf,size);
+        if(n <= 0) return -1;
+        size -= n;
+        buf += n;
+    }
+    return 0;
+}
+
+DIR *opendir(const char *path) {
+    struct stat sb;
+    int fd;
+    DIR *dir;
+    
+    fd = open(path,O_RDONLY);
+    if(fd < 0) return NULL;
+    
+    if(fstat(fd,&sb) < 0 || !S_ISDIR(sb.st_mode)) {
+        close(fd);
+        errno = ENOTDIR;
+        return NULL;
+    }
+    
+    dir = malloc(sizeof(*dir));
+    if(dir == NULL) {
+        close(fd);
+        errno = ENOMEM;
+        return NULL;
+    }
+    dir->dd_fd = fd;
+    dir->dd_pos = 0;
+    return dir;
+}
+
+static int readdir_r(DIR *dir,struct dirent *entry, struct dirent **result) {
+    struct {
+        int inode;
+        int name_len;
+    } h;
+    if(dir->dd_fd < 0) return -1;
+again:
+    if(read_fully(dir->dd_fd,&h,sizeof(h)) < 0) goto fail;
+    if(h.name_len < 0 || h.name_len >= sizeof(entry->d_name)-1) goto fail;
+    
+    entry->d_ino = h.inode;
+    if(read_fully(dir->dd_fd,entry->d_name,h.name_len) < 0) goto fail;
+    
+    entry->d_name[h.name_len] = '\0';
+    dir->dd_pos += h.name_len + 8;
+    
+    if(result) *result = entry;
+    return 0;
+fail:
+    if(result) *result = NULL; 
+    return -1;    
+}
+
+struct dirent *readdir(DIR *dir) { return readdir_r(dir,&dir->ent,NULL) == 0 ? &dir->ent : NULL; }
+
+int closedir(DIR *dir) {
+    close(dir->dd_fd);
+    free(dir);
+    return 0;
+}
diff --git a/src/org/xwt/mips/syscalls.h b/src/org/xwt/mips/syscalls.h
new file mode 100644 (file)
index 0000000..5a1edf3
--- /dev/null
@@ -0,0 +1,32 @@
+#define SYS_null 0
+#define SYS_exit 1
+#define SYS_pause 2
+#define SYS_open 3
+#define SYS_close 4
+#define SYS_read 5
+#define SYS_write 6
+#define SYS_sbrk 7
+#define SYS_fstat 8
+#define SYS_isatty 9
+#define SYS_lseek 10
+#define SYS_kill 11
+#define SYS_getpid 12
+#define SYS_calljava 13
+#define SYS_stat 14
+#define SYS_gettimeofday 15
+#define SYS_sleep 16
+#define SYS_times 17
+#define SYS_mkdir 18
+#define SYS_getpagesize 19
+#define SYS_unlink 20
+#define SYS_utime 21
+#define SYS_chdir 22
+#define SYS_pipe 23
+#define SYS_dup2 24
+#define SYS_fork 25
+#define SYS_waitpid 26
+#define SYS_getcwd 27
+#define SYS_execve 28
+#define SYS_fcntl 29
+#define SYS_rmdir 30
+#define SYS_sysconf 31
diff --git a/src/org/xwt/mips/util/SeekableByteArray.java b/src/org/xwt/mips/util/SeekableByteArray.java
new file mode 100644 (file)
index 0000000..807dd68
--- /dev/null
@@ -0,0 +1,37 @@
+package org.xwt.mips.util;
+
+import java.io.IOException;
+
+public class SeekableByteArray implements SeekableData {
+    protected byte[] data;
+    protected int pos;
+    private final boolean writable;
+    
+    public SeekableByteArray(byte[] data, boolean writable) {
+        this.data = data;
+        this.pos = 0;
+        this.writable = writable;
+    }
+    
+    public int read(byte[] buf, int off, int len) {
+        len = Math.min(len,data.length-pos);
+        if(len <= 0) return -1;
+        System.arraycopy(data,pos,buf,off,len);
+        pos += len;
+        return len;
+    }
+    
+    public int write(byte[] buf, int off, int len) throws IOException {
+        if(!writable) throw new IOException("read-only data");
+        len = Math.min(len,data.length-pos);
+        if(len <= 0) throw new IOException("no space");
+        System.arraycopy(buf,off,data,pos,len);        
+        pos += len;
+        return len;
+    }
+    
+    public int length() { return data.length; }
+    public int pos() { return pos; }
+    public void seek(int pos) { this.pos = pos; }
+    public void close() { /*noop*/ }
+}
diff --git a/src/org/xwt/mips/util/SeekableData.java b/src/org/xwt/mips/util/SeekableData.java
new file mode 100644 (file)
index 0000000..2603aba
--- /dev/null
@@ -0,0 +1,12 @@
+package org.xwt.mips.util;
+
+import java.io.IOException;
+
+public interface SeekableData { 
+    public int read(byte[] buf, int offset, int length) throws IOException;
+    public int write(byte[] buf, int offset, int length) throws IOException;
+    public int length() throws IOException;
+    public void seek(int pos) throws IOException;
+    public void close() throws IOException;
+    public int pos() throws IOException;
+}
diff --git a/src/org/xwt/mips/util/SeekableFile.java b/src/org/xwt/mips/util/SeekableFile.java
new file mode 100644 (file)
index 0000000..168d43a
--- /dev/null
@@ -0,0 +1,24 @@
+package org.xwt.mips.util;
+
+import java.io.*;
+
+public class SeekableFile implements SeekableData {
+    private final RandomAccessFile raf;
+    
+    public SeekableFile(String fileName) throws IOException { this(fileName,false); }
+    public SeekableFile(String fileName, boolean writable) throws IOException { this(new File(fileName),writable); }    
+    
+    public SeekableFile(File file, boolean writable) throws IOException {
+        raf = new RandomAccessFile(file,writable ? "rw" : "r");
+    }
+    
+    // NOTE: RandomAccessFile.setLength() is a Java2 function
+    public void setLength(int n) throws IOException { raf.setLength(n); }
+    
+    public int read(byte[] buf, int offset, int length) throws IOException { return raf.read(buf,offset,length); }
+    public int write(byte[] buf, int offset, int length) throws IOException { raf.write(buf,offset,length); return length; }
+    public void seek(int pos) throws IOException{ raf.seek(pos); }
+    public int pos()  throws IOException { return (int) raf.getFilePointer(); }
+    public int length() throws IOException { return (int)raf.length(); }
+    public void close() throws IOException { raf.close(); }
+}
diff --git a/src/org/xwt/mips/util/SeekableInputStream.java b/src/org/xwt/mips/util/SeekableInputStream.java
new file mode 100644 (file)
index 0000000..1dc0b0d
--- /dev/null
@@ -0,0 +1,48 @@
+package org.xwt.mips.util;
+
+import java.io.*;
+
+public class SeekableInputStream implements SeekableData {
+    private byte[] buffer = new byte[4096];
+    private int bytesRead = 0;
+    private boolean eof = false;
+    private int pos;
+    private InputStream is;
+    
+    public SeekableInputStream(InputStream is) { this.is = is; }
+    
+    public int read(byte[] outbuf, int off, int len) throws IOException {
+        if(pos >= bytesRead && !eof) readTo(pos + 1);
+        len = Math.min(len,bytesRead-pos);
+        if(len <= 0) return -1;
+        System.arraycopy(buffer,pos,outbuf,off,len);
+        pos += len;
+        return len;
+    }
+    
+    private void readTo(int target) throws IOException {
+        if(target >= buffer.length) {
+            byte[] buf2 = new byte[Math.max(buffer.length+Math.min(buffer.length,65536),target)];
+            System.arraycopy(buffer,0,buf2,0,bytesRead);
+            buffer = buf2;
+        }
+        while(bytesRead < target) {
+            int n = is.read(buffer,bytesRead,buffer.length-bytesRead);
+            if(n == -1) {
+                eof = true;
+                break;
+            }
+            bytesRead += n;
+        }
+    }
+    
+    public int length() throws IOException {
+        while(!eof) readTo(bytesRead+4096);
+        return bytesRead;
+    }
+        
+    public int write(byte[] buf, int off, int len) throws IOException { throw new IOException("read-only"); }
+    public void seek(int pos) { this.pos = pos; }
+    public int pos() { return pos; }
+    public void close() throws IOException { is.close(); }
+}
diff --git a/src/tests/CXXTest.cc b/src/tests/CXXTest.cc
new file mode 100644 (file)
index 0000000..21b3972
--- /dev/null
@@ -0,0 +1,54 @@
+#include <iostream>
+
+using namespace std;
+
+class Test {
+public:
+    Test();
+    ~Test();
+    void sayhi();
+};
+
+class Exn {
+public:
+    Exn() { }
+};
+    
+
+Test test;
+
+int main(int argc,char *argv[]) {
+    printf("Name: %p\n",typeid(const char*).name());
+    printf("Name: %s\n",typeid(const char*).name());
+    printf("Is pointer: %d\n",typeid(const char*).__is_pointer_p ());
+    printf("Name: %p\n",typeid(int).name());
+    printf("Name: %s\n",typeid(int).name());
+    printf("Is pointer: %d\n",typeid(int).__is_pointer_p ());
+    
+    try {
+        test.sayhi();
+    } catch(char *e) {
+        printf("sayhi threw: %s\n",e);
+    } catch(const char *e) {
+        printf("sayhi threw: const char *:%s\n",e);
+    } catch(int n) {
+        printf("sayhi threw: %d\n",n);
+    }
+    return 0;
+}
+
+Test::Test() {
+    cout << "Test's constructor" << endl;
+}
+
+Test::~Test() {
+    cout << "Test's destructor" << endl;
+}
+
+void Test::sayhi() {
+    static char exn[] = "Non-const!";
+    cout << "Hello, World from Test" << endl;
+    cout << "Now throwing an exception" << endl;
+    throw "Hello, Exception Handling!";
+    //throw exn;
+}
diff --git a/src/tests/CallTest.java b/src/tests/CallTest.java
new file mode 100644 (file)
index 0000000..0e56a5f
--- /dev/null
@@ -0,0 +1,66 @@
+package tests;
+
+import org.xwt.mips.Runtime;
+import org.xwt.mips.Interpreter;
+import java.io.*;
+import java.util.*;
+
+public class CallTest {
+    public static void main(String[] args) throws Exception {
+        int a1 = args.length > 0 ? Integer.parseInt(args[0]) : 0;
+        int a2 = args.length > 1 ? Integer.parseInt(args[1]) : 0;
+        int a3 = args.length > 2 ? Integer.parseInt(args[2]) : 0;
+        int a4 = args.length > 3 ? Integer.parseInt(args[3]) : 0;
+        int a5 = args.length > 4 ? Integer.parseInt(args[4]) : 0;
+        int a6 = args.length > 5 ? Integer.parseInt(args[5]) : 0;
+        
+        System.out.println("Version is: " + System.getProperty("os.version"));
+        Runtime rt;
+        if(a1 == 99) // yeah.. this is ugly
+            rt = new Interpreter("build/tests/Test.mips");
+        else
+            rt = new Test() {
+                protected int callJava(int a, int b, int c, int d) {
+                    switch(a) {
+                        case 1: return strdup("OS: " + System.getProperty("os.name"));
+                        case 2: return strdup(System.getProperty("os.version"));
+                        case 3: return strdup(new Date().toString());
+                        case 4: return allocFDEnt(new OutputStreamFD(new CustomOS()));
+                        case 5:
+                            System.out.println("In callJava() in Java"); 
+                            try { call("backinmips"); } catch(CallException e) { }
+                            System.out.println("Back in callJava() in Java");
+                            return 0;
+                        default: return super.callJava(a,b,c,d);
+                    }
+                }
+            };
+        System.out.println("Runtime: " + rt);
+        
+        rt.start(new String[]{"Test","calltest"});
+        rt.execute();
+        
+        System.out.println("== Start of CallTest ==");
+        System.out.println("Back in java... calling callme()");
+        int ret = rt.call("callme",a1,a2,a3,a4,a5,a6);
+        System.out.println("callme returned: " + ret);
+        
+        int addr = rt.strdup("Hello, World from java");
+        rt.call("echo",addr,4);
+        rt.free(addr);
+        System.out.println("== End of CallTest ==");
+        
+        rt.execute();
+        System.exit(rt.exitStatus());
+    }
+    
+    private static class CustomOS extends OutputStream {
+        public CustomOS() { }
+        public void write(int b) {  byte[] a = new byte[1]; a[0] = (byte)(b&0xff); write(a,0,1); }
+        public void write(byte[] b, int off, int len) {
+            int len2 = len;
+            while(b[len2-1]=='\n') len2--;
+            System.out.println("This just in from MIPS: " + new String(b,off,len2));
+        }
+    }
+}
diff --git a/src/tests/Echo.java b/src/tests/Echo.java
new file mode 100644 (file)
index 0000000..47f8046
--- /dev/null
@@ -0,0 +1,35 @@
+package tests;
+
+import java.net.*;
+
+import org.xwt.mips.Runtime;
+
+public class Echo {
+    private static final int PORT = 2000;
+    public static void main(String[] args) throws Exception {
+        ServerSocket sock = new ServerSocket(PORT);
+        System.err.println("Listening on " + PORT);
+        for(;;) new Client(sock.accept()).go();
+    }
+    
+    private static class Client implements Runnable {
+        private Socket sock;
+        public Client(Socket sock) { this.sock = sock; }
+        public void go() { new Thread(this).start(); }
+        public void run() {
+            try {
+                Runtime task = new EchoHelper();
+                int status = task.run(
+                    new String[]{"EchoHelper"},
+                    null,
+                    new Runtime.InputStreamFD(sock.getInputStream()),
+                    new Runtime.OutputStreamFD(sock.getOutputStream()),
+                    null
+                );
+                System.err.println("Exit status: " + status);
+            } catch(Exception e) {
+                System.err.println(e);
+            }
+        }
+    }
+}
diff --git a/src/tests/EchoHelper.c b/src/tests/EchoHelper.c
new file mode 100644 (file)
index 0000000..f1cf1a4
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <string.h>
+
+int main() {
+    char buf[1024];
+    char *p;
+    printf("Hello! Welcome to EchoHelper.c\n");
+    while(fgets(buf,sizeof(buf),stdin) != NULL) {
+        for(p=buf;*p && *p!='\n' && *p!='\r';p++);
+        *p = '\0';
+        fprintf(stdout,"You said: %s\n",buf);
+        fprintf(stderr,"They said: %s\n",buf);
+        if(strcmp(buf,"exit")==0) break;
+    }
+    return 0;
+}
diff --git a/src/tests/Env.java b/src/tests/Env.java
new file mode 100644 (file)
index 0000000..59048b5
--- /dev/null
@@ -0,0 +1,32 @@
+package tests;
+
+import org.xwt.mips.Runtime;
+import org.xwt.mips.Interpreter;
+
+class Env {
+    public static void main(String[] args) throws Exception {
+        int n = 0;
+        while(n < args.length && args[n].indexOf("=") != -1) n++;
+
+        if(n==args.length) {
+            System.err.println("Usage: Env [name=value ...] classname [args ...]");
+            System.exit(1);
+        }
+        
+        String[] env = new String[n];
+        String[] appArgs = new String[args.length-n-1];
+        for(int i=0;i<n;i++) env[i] = args[i];
+        String className = args[n];
+        for(int i=n+1;i<args.length;i++) appArgs[i-n-1] = args[i];
+        
+        Runtime rt;
+        if(className.endsWith(".mips")) {
+            rt = new Interpreter(className);
+        } else {
+            Class c = Class.forName(className);
+            if(!Runtime.class.isAssignableFrom(c)) { System.err.println(className + " isn't a MIPS compiled class"); System.exit(1); }
+            rt = (Runtime) c.newInstance();
+        }
+        System.exit(rt.run(appArgs,env));
+    }
+}
diff --git a/src/tests/FDTest.java b/src/tests/FDTest.java
new file mode 100644 (file)
index 0000000..52c70db
--- /dev/null
@@ -0,0 +1,15 @@
+package tests;
+
+import org.xwt.mips.Runtime;
+
+public class FDTest {
+    public static void main(String[] args) throws Exception {
+        Runtime rt = new Test();
+        int fd = rt.allocFDEnt(new Runtime.SeekableInputStreamFD(System.in));
+        int status = rt.run(new String[]{"test","fdtest","/dev/fd/" + fd});
+        System.err.println("Exit status: " + status);
+    }
+}
+
+        
\ No newline at end of file
diff --git a/src/tests/FTBench.c b/src/tests/FTBench.c
new file mode 100644 (file)
index 0000000..9bb6dac
--- /dev/null
@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <freetype/freetype.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define FT_Check(expr) do { \
+    if((expr) != 0) { \
+        fprintf(stderr,#expr " failed\n"); \
+        exit(EXIT_FAILURE); \
+    } \
+} while(0)
+
+#define BMP_WIDTH 800
+#define BMP_HEIGHT 600
+
+static char buf[BMP_WIDTH*BMP_HEIGHT];
+
+int main(int argc, char **argv) {
+    char *ttf;
+    char *out;
+    FT_Library library;
+    FT_Face face;
+    FT_GlyphSlot glyph;
+    int num_glyphs;
+    int c;
+    int glyph_index;
+    int loc_x;
+    int loc_y;
+    int glyph_width;
+    int glyph_height;
+    int i,j;
+    int fd;
+    char *p;
+    int n,count;
+    char *glyph_buf;
+    int pixel_size;
+    
+    if(argc < 3) {
+        fprintf(stderr,"Usage: %s ttf bmp\n",argv[0]);
+        exit(1);
+    }
+    
+    ttf = argv[1];
+    out = argv[2];
+    
+    memset(buf,'\377',BMP_WIDTH*BMP_HEIGHT);
+    
+    FT_Check(FT_Init_FreeType(&library));
+    FT_Check(FT_New_Face(library,ttf,0,&face));
+    
+    loc_y = loc_x = 0;
+    for(pixel_size=8;pixel_size<48;pixel_size+=4) {
+        FT_Check(FT_Set_Pixel_Sizes(face,0,pixel_size));
+        for(c=32;c<127;c++) {
+            glyph_index = FT_Get_Char_Index(face,c);
+            FT_Check(FT_Load_Glyph(face,glyph_index,FT_LOAD_DEFAULT));
+            FT_Check(FT_Render_Glyph(face->glyph, ft_render_mode_normal));
+            glyph = face->glyph;
+            glyph_width = glyph->bitmap.width;
+            glyph_height = glyph->bitmap.rows;
+            glyph_buf = glyph->bitmap.buffer;
+            if(loc_x + glyph_width + glyph->bitmap_left >= BMP_WIDTH) {
+                loc_x = 0;
+                loc_y += pixel_size;
+                if(loc_y >= BMP_HEIGHT-pixel_size) goto done;
+            }
+            
+            for(i=0;i<glyph_height;i++)
+                for(j=0;j<glyph_width;j++)
+                    buf[(loc_y+i)*BMP_WIDTH+loc_x+j] &= (~glyph_buf[i*glyph_width+j]);
+            loc_x += face->glyph->advance.x/64;
+        }
+    }
+done:
+    
+    if((fd = open(out,O_CREAT|O_WRONLY,0644)) < 0) {
+        perror("open");
+        exit(1);
+    }
+    p = buf;
+    count = BMP_WIDTH*BMP_HEIGHT;
+    
+    while(count) {
+        n = write(fd,p,count);
+        if(n < 0) {
+            perror("write");
+            exit(1);
+        }
+        count -=n;
+        p += n;
+    }
+    close(fd);
+    
+    return 0;
+}
diff --git a/src/tests/Fork.c b/src/tests/Fork.c
new file mode 100644 (file)
index 0000000..088ebaf
--- /dev/null
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+
+int main() {
+    fprintf(stderr,"In the main process (pid: %d), about to fork\n",getpid());
+    pid_t pid = fork();
+    int status;
+    int i;
+    
+    switch(pid) {
+        case -1: perror("fork"); break;
+        case 0: 
+            fprintf(stderr,"In the forked process (pid: %d), sleeping for 2 sec\n",getpid());
+            sleep(2);
+            fprintf(stderr,"Child done sleeping... exiting\n");
+            _exit(0);
+            break;
+        default:
+            fprintf(stderr,"In the main process (child is: %d) waiting for child\n",pid);
+            if(waitpid(pid,&status,0) < 0)
+                perror("waitpid");
+            else
+                fprintf(stderr,"Child process exited (status: %d)\n",status);
+    }
+    pid = fork();
+    if(pid==0) {
+        fprintf(stderr,"1st fork (pid: %d)\n",getpid());
+        if(fork()==0) {
+            fprintf(stderr,"2nd fork (pid: %d).. sleeping\n",getpid());
+            sleep(5);
+            fprintf(stderr,"2nd fork exiting\n");
+            _exit(0);
+        }
+        _exit(0);
+    } else  {
+        waitpid(pid,NULL,0);
+        fprintf(stderr,"1st  fork terminated\n");
+    }
+    fprintf(stderr,"Sleeping for a bit\n");
+    sleep(10);
+    fprintf(stderr,"Next few pids should be sequential\n");
+    for(i=0;i<10;i++) {
+        if(fork() == 0) {
+            fprintf(stderr,"I am a child %d\n",getpid());
+            sleep(i%4);
+            _exit(0);
+        }
+    }
+    for(i=0;i<10;i++) fprintf(stderr,"Waited on %d\n",waitpid(-1,NULL,0));
+    
+    return 0;
+}
diff --git a/src/tests/FreeTypeDemo.java b/src/tests/FreeTypeDemo.java
new file mode 100644 (file)
index 0000000..0ac84cd
--- /dev/null
@@ -0,0 +1,170 @@
+package tests;
+
+import org.xwt.mips.Runtime;
+import org.xwt.mips.Interpreter;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.event.*;
+import java.io.*;
+
+public class FreeTypeDemo {
+    private JFrame frame;
+    private static final int OURWIDTH=640;
+    private static final int OURHEIGHT=256;
+    private static final int BASELINE=160;
+    private byte[] render = new byte[OURWIDTH*OURHEIGHT];
+    private int size = 72;
+    private StringBuffer sb = new StringBuffer();
+    private View view;
+    private Image image;
+    
+    private Runnable renderThread;
+    private String theText;
+    private boolean renderNeeded;
+    
+    private String name;
+    private Runtime rt;
+    
+    int renderAddr;
+    int stringAddr;
+    int stringSize;
+    
+    public static void main(String[] argv) throws Exception {
+        new FreeTypeDemo(argv);
+    }
+    
+    public FreeTypeDemo(String[] argv) throws Exception {
+        if(argv.length >= 2 && argv[1].startsWith("int")) {
+            name = "Interpreter";
+            rt = new Interpreter("build/FreeTypeDemoHelper.mips");
+        } else {
+            rt = new FreeTypeDemoHelper();
+            name = "Compiler";
+        }
+        
+        rt.start(new String[]{ "freetype.mips"});
+        if(rt.execute()) throw new Error("freetype.mips exited");
+
+        byte[] font = InputStreamToByteArray.convert(new FileInputStream(argv[0]));
+        int fontAddr = rt.malloc(font.length);
+        if(fontAddr == 0) throw new Error("malloc() failed");
+        rt.copyout(font,fontAddr,font.length);
+        
+        rt.setUserInfo(0,fontAddr);
+        rt.setUserInfo(1,font.length);
+
+        renderAddr = rt.malloc(OURWIDTH*OURHEIGHT);
+        if(renderAddr == 0) throw new Error("malloc() failed");
+        
+        if(rt.execute()) throw new Error("freetype.mips exited (" + rt.getUserInfo(1) +")");
+
+        createImage();
+        
+        frame = new JFrame("FreeTypeDemo - " + name);
+        frame.setSize(OURWIDTH,OURHEIGHT);
+        view = new View();
+        frame.getContentPane().add(view,BorderLayout.CENTER);
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        frame.show();
+        view.requestFocus();
+        renderThread = new Runnable() {
+            public void run() {
+                try {
+                    for(;;) {
+                         synchronized(this) { while(!renderNeeded) wait(); renderNeeded = false; }
+                        renderText(theText==null ? "" : theText);
+                    }
+                } catch(Exception e) { throw new Error(e); }
+            }
+        };
+        new Thread(renderThread).start();
+        keyPress('\n');
+    }
+   
+    private static ColorModel cmodel = new DirectColorModel(8, 0xff,0xff,0xff);
+    private void createImage() {
+        for(int i=0;i<OURHEIGHT;i++)
+            for(int j=0;j<OURWIDTH;j++)
+                render[i*OURWIDTH+j] = (byte)((~(render[i*OURWIDTH+j]&0xff))&0xff);
+        image = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(OURWIDTH, OURHEIGHT, cmodel, render, 0, OURWIDTH));
+        MediaTracker mediatracker = new MediaTracker(new Canvas());
+        mediatracker.addImage(image, 1);
+        try { mediatracker.waitForAll(); } catch (InterruptedException e) { }
+        mediatracker.removeImage(image);
+    }
+    private void renderText(String s) {
+        try {
+            byte[] b = (s+"\0").getBytes("UTF-16BE");
+            if(stringSize < b.length) {
+                System.err.println("reallocing the string space");
+                if(stringAddr != 0) rt.free(stringAddr);
+                stringAddr = rt.malloc(b.length*2);
+                if(stringAddr == 0) throw new Error("malloc failed");
+                stringSize = b.length*2;
+            }
+            rt.copyout(b,stringAddr,b.length);
+            long start = System.currentTimeMillis();
+            if(rt.call("render",stringAddr,size,renderAddr,OURWIDTH,OURHEIGHT,BASELINE)==0) throw new Error("render() failed");
+            System.out.println(name + ": Render of: " + s + " took " + (System.currentTimeMillis()-start) + " ms");
+            rt.copyin(renderAddr,render,render.length);
+            createImage();
+            view.repaint();
+        } catch(Exception e) {
+            throw new Error(e);
+        }
+    }
+    
+    private void keyPress(char c) {
+        if(c == '\n' || c == '\r') {
+            sb.setLength(0);
+            theText = "Press any key";
+        } else if(c == '+' || c == '-') {
+            size += (c=='+'?1:-1) * 8;
+            System.out.println("New size: " + size);
+        } else {
+            sb.append(c);
+            theText = sb.toString();
+        }
+        synchronized(renderThread) { renderNeeded = true; renderThread.notify(); }
+    }
+                
+    public class View extends JComponent {
+        public void paintComponent(Graphics g) {
+            g.drawImage(image,0,0,OURWIDTH,OURHEIGHT,0,0,OURWIDTH,OURHEIGHT,null);
+        }
+        public View() {
+            addKeyListener(new KeyAdapter() {
+                public void keyTyped(KeyEvent e) {
+                    keyPress(e.getKeyChar());
+                }
+            });
+            setPreferredSize(new Dimension(OURWIDTH,OURHEIGHT));
+        }
+    }
+    private static class InputStreamToByteArray {
+
+        /** scratch space for isToByteArray() */
+        private static byte[] workspace = new byte[16 * 1024];
+        /** Trivial method to completely read an InputStream */
+        public static synchronized byte[] convert(InputStream is) throws IOException {
+            int pos = 0;
+            while (true) {
+                int numread = is.read(workspace, pos, workspace.length - pos);
+                if (numread == -1) break;
+                else if (pos + numread < workspace.length) pos += numread;
+                else {
+                    pos += numread;
+                    byte[] temp = new byte[workspace.length * 2];
+                    System.arraycopy(workspace, 0, temp, 0, workspace.length);
+                    workspace = temp;
+                }
+            }
+            byte[] ret = new byte[pos];
+            System.arraycopy(workspace, 0, ret, 0, pos);
+            return ret;
+        }
+    }
+}
+
diff --git a/src/tests/FreeTypeDemoHelper.c b/src/tests/FreeTypeDemoHelper.c
new file mode 100644 (file)
index 0000000..cfae8ff
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
+
+#include <unistd.h>
+#include <freetype/freetype.h>
+
+FT_Library  library;   /* handle to library     */
+FT_Face     face;      /* handle to face object */
+
+#define FT_Check(expr,err) do { \
+    if((expr) != 0) { \
+        errprint(#expr " failed\n"); \
+            return err; \
+    } \
+} while(0)
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+static int errprint(const char *s) {
+    int l = strlen(s);
+    int n;
+    while(l) {
+        n = write(STDERR_FILENO,s,l);
+        if(n < 0) return n;
+        l -= n;
+        s += n;
+    }
+    return 0;
+}
+        
+void draw(FT_GlyphSlot glyph,int x, char *buf, int buf_width, int buf_height, int baseline) {
+    int y = max(baseline - glyph->bitmap_top,0);
+    int rows = glyph->bitmap.rows;
+    int width = glyph->bitmap.width;
+    int i,j;
+    x = x + glyph->bitmap_left;
+    if(x + width >= buf_width) return;
+    if(y + rows >= buf_height) return;
+    //if(buf == NULL) fprintf(stderr,"ABout to dereference %p\n",buf);
+    for(i=0;i<rows;i++)
+        for(j=0;j<width;j++)
+            buf[(i+y)*buf_width+x+j] |= glyph->bitmap.buffer[i*width+j];
+}
+
+/* Prevent --gc-sections from blowing this away */
+int render(short *s, int size, char *buf, int buf_width, int buf_height, int baseline)  __attribute__((section(".text")));
+int render(short *s, int size, char *buf, int buf_width, int buf_height, int baseline) {
+    int glyph_index;
+    int x = 0;
+    FT_Check(FT_Set_Pixel_Sizes(face,0,size),0);
+    memset(buf,'\0',buf_width*buf_height);
+    //fprintf(stderr,"Rendering %d pt %c... at %p (%dx%d)\n",size,*s,buf,buf_width,buf_height);
+    while(*s) {
+        glyph_index = FT_Get_Char_Index(face,*s);
+        FT_Check(FT_Load_Glyph(face,glyph_index,FT_LOAD_DEFAULT),0);
+        FT_Check(FT_Render_Glyph(face->glyph,FT_RENDER_MODE_NORMAL/*256color antialiased*/),0);
+        draw(face->glyph,x,buf,buf_width,buf_height,baseline);
+        x += face->glyph->advance.x/64;
+        s++;
+    }
+    return 1;
+}
+
+char * user_info[2];
+extern void _pause();
+
+int main(int argc,char** argv) {
+    char *fontdata;
+    int fontsize;
+
+    _pause();
+    
+    fontdata = user_info[0];
+    fontsize = (int)user_info[1];
+    
+    //fprintf(stderr,"Initializng freetype with a %d byte font at %p\n", fontsize, fontdata);
+    
+    FT_Check(FT_Init_FreeType(&library),EXIT_FAILURE);
+    FT_Check(FT_New_Memory_Face(library, fontdata,fontsize, 0, &face),EXIT_FAILURE);
+    
+    errprint("Freetype initialized\n");
+    _pause();
+    errprint("Unpaused\n");
+    
+    /* not reached */
+    return EXIT_FAILURE;
+}
diff --git a/src/tests/Hello.c b/src/tests/Hello.c
new file mode 100644 (file)
index 0000000..d7189ae
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main() {
+    puts("Hello, World");
+    return 0;
+}
diff --git a/src/tests/MSPack.java b/src/tests/MSPack.java
new file mode 100644 (file)
index 0000000..198b7aa
--- /dev/null
@@ -0,0 +1,106 @@
+package tests;
+
+import org.xwt.mips.Runtime;
+import java.io.*;
+
+public class MSPack {
+    private String[] fileNames;
+    private int[] lengths;
+    private byte[][] data;
+        
+    public static class MSPackException extends IOException { public MSPackException(String s) { super(s); } }
+    
+    public MSPack(InputStream cabIS) throws IOException {
+        byte[] cab = InputStreamToByteArray.convert(cabIS);        
+        try {
+            //Interpreter vm = new Interpreter("mspack.mips");
+            MSPackHelper vm = new MSPackHelper();
+        
+            int cabAddr = vm.sbrk(cab.length);
+            if(cabAddr < 0) throw new MSPackException("sbrk failed");
+        
+            vm.copyout(cab,cabAddr,cab.length);
+        
+            vm.setUserInfo(0,cabAddr);
+            vm.setUserInfo(1,cab.length);
+        
+            int status = vm.run(new String[]{ "mspack.mips"} );
+            if(status != 0) throw new MSPackException("mspack.mips failed (" + status + ")");
+            
+            /*static struct {
+                char *filename;
+                char *data;
+                int length;
+            } output_table[MAX_MEMBERS+1]; */
+
+            int filesTable = vm.getUserInfo(2);
+            int count=0;
+            while(vm.memRead(filesTable+count*12) != 0) count++;
+            
+            fileNames = new String[count];
+            data = new byte[count][];
+            lengths = new int[count];
+            
+            for(int i=0,addr=filesTable;i<count;i++,addr+=12) {
+                int length = vm.memRead(addr+8);
+                data[i] = new byte[length];
+                lengths[i] = length;
+                fileNames[i] = vm.cstring(vm.memRead(addr));
+                System.out.println("" + fileNames[i]);
+                vm.copyin(vm.memRead(addr+4),data[i],length);
+            }
+        } catch(Runtime.ExecutionException e) {
+            e.printStackTrace();
+            throw new MSPackException("mspack.mips crashed");
+        }
+    }
+    
+    public String[] getFileNames() { return fileNames; }
+    public int[] getLengths() { return lengths; }
+    public InputStream getInputStream(int index) { return new ByteArrayInputStream(data[index]); }
+    public InputStream getInputStream(String fileName) {
+        for(int i=0;i<fileNames.length;i++) {
+            if(fileName.equalsIgnoreCase(fileNames[i])) return getInputStream(i);
+        }
+        return null;
+    }
+    
+    public static void main(String[] args) throws IOException {
+        MSPack pack = new MSPack(new FileInputStream(args[0]));
+        String[] files = pack.getFileNames();
+        for(int i=0;i<files.length;i++)
+            System.out.println(i + ": " + files[i] + ": " + pack.getLengths()[i]);
+        System.out.println("Writing " + files[files.length-1]);
+        InputStream is = pack.getInputStream(files.length-1);
+        OutputStream os = new FileOutputStream(files[files.length-1]);
+        int n;
+        byte[] buf = new byte[4096];
+        while((n = is.read(buf)) != -1) os.write(buf,0,n);
+        os.close();
+        is.close();
+    }
+    private static class InputStreamToByteArray {
+
+        /** scratch space for isToByteArray() */
+        private static byte[] workspace = new byte[16 * 1024];
+        /** Trivial method to completely read an InputStream */
+        public static synchronized byte[] convert(InputStream is) throws IOException {
+            int pos = 0;
+            while (true) {
+                int numread = is.read(workspace, pos, workspace.length - pos);
+                if (numread == -1) break;
+                else if (pos + numread < workspace.length) pos += numread;
+                else {
+                    pos += numread;
+                    byte[] temp = new byte[workspace.length * 2];
+                    System.arraycopy(workspace, 0, temp, 0, workspace.length);
+                    workspace = temp;
+                }
+            }
+            byte[] ret = new byte[pos];
+            System.arraycopy(workspace, 0, ret, 0, pos);
+            return ret;
+        }
+    }
+}
+
diff --git a/src/tests/MSPackBench.c b/src/tests/MSPackBench.c
new file mode 100644 (file)
index 0000000..2966c6f
--- /dev/null
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/fcntl.h>
+
+#include "mspack.h"
+
+int main(int argc, char **argv) {
+    struct mscab_decompressor *decomp;
+    struct mscabd_cabinet *cab;
+    struct mscabd_file *file;
+    int i;
+    
+    if(argc < 2) {
+        fprintf(stderr,"Usage: %s cab\n",argv[0]);
+        exit(1);
+    }
+    
+    
+    decomp = mspack_create_cab_decompressor(NULL);
+    if(!decomp) exit(1);
+    
+    for(i=1;i<argc;i++) {
+        cab = decomp->search(decomp,argv[i]);
+        if(!cab) exit(2);
+    
+        for(file = cab->files;file;file=file->next)
+            decomp->extract(decomp,file,file->filename);
+         
+        decomp->close(decomp,cab);
+    }
+    mspack_destroy_cab_decompressor(decomp);
+
+    return 0;
+}
diff --git a/src/tests/MSPackHelper.c b/src/tests/MSPackHelper.c
new file mode 100644 (file)
index 0000000..ddbcfcf
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+UserInfo:
+    On start:
+        0: Addr of CAB/EXE
+        1: Length of CAB/EXE
+    On Edit:
+        2: Addr of output_table array
+
+Exit codes:
+    0: Success
+    1: Internal Error
+    2: Invalid CAB
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/fcntl.h>
+
+#include "mspack.h"
+
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX_MEMBERS 64
+
+char *xstrdup(const char *s) {
+    char *ret = strdup(s);
+    if(ret == NULL) exit(1);
+    return ret;
+}
+
+typedef struct {
+    char *addr;
+    int pos;
+    int size;
+    int length;
+    int writable;
+} mem_buf_t;
+
+static mem_buf_t *cab_mem_buf = NULL;
+
+static void mem_buf_grow(mem_buf_t *buf,size_t newsize) {
+    size_t new_len;
+    char *p;
+    if(buf->length < 0) exit(1); 
+    if(newsize <= buf->length) return;
+    new_len = MAX(buf->length ? buf->length*2 : 65536,newsize);
+    p = realloc(buf->addr,new_len);
+    if(p == NULL) exit(1);
+    buf->addr = p;
+    buf->length = new_len;
+}
+
+static struct {
+    char *filename;
+    mem_buf_t buf;
+} write_buf_table[MAX_MEMBERS];
+
+static struct {
+    char *filename;
+    char *data;
+    int length;
+} output_table[MAX_MEMBERS+1];
+
+static struct mspack_file *my_open(struct mspack_system *sys, char *filename, int mode) {
+    mem_buf_t *buf = NULL;
+    int i;
+    if(strcmp(filename,"/dev/cab")==0) {    
+        if(mode != MSPACK_SYS_OPEN_READ) return NULL;
+        buf = cab_mem_buf;
+    } else {
+        if(mode != MSPACK_SYS_OPEN_WRITE) return NULL;
+        
+        for(i=0;i<MAX_MEMBERS;i++) {
+            if(write_buf_table[i].filename == NULL) {
+                printf("%s in %d\n",filename,i);
+                write_buf_table[i].filename = xstrdup(filename);
+                buf = &write_buf_table[i].buf;
+                buf->writable = 1;
+                break;
+            }
+        }
+    }
+    
+    return (struct mspack_file *) buf;
+}
+
+static void my_close(struct mspack_file *buf_) {
+    mem_buf_t *buf = (mem_buf_t*) buf_;
+    /* NO OP */
+}
+
+static int my_read(struct mspack_file *buf_, void *out, int count) {
+    mem_buf_t *buf = (mem_buf_t*) buf_;
+    count = MIN(buf->size - buf->pos, count);
+    memcpy(out,buf->addr + buf->pos,count);
+    buf->pos += count;
+    return count;
+}
+
+static int my_write(struct mspack_file *buf_, void *in, int count) {
+    mem_buf_t *buf = (mem_buf_t*) buf_;
+    if(!buf->writable) return -1;
+    if(buf->length < buf->pos + count) mem_buf_grow(buf,buf->pos + count);
+    memcpy(buf->addr+buf->pos,in,count);
+    buf->pos += count;
+    buf->size = MAX(buf->size,buf->pos);
+    return count;
+}
+
+static int my_seek(struct mspack_file *buf_, off_t off, int mode) {
+    mem_buf_t *buf = (mem_buf_t*) buf_;
+    int newpos;
+    switch(mode) {
+        case MSPACK_SYS_SEEK_START: newpos = off; break;
+        case MSPACK_SYS_SEEK_CUR: newpos = buf->pos + off; break;
+        case MSPACK_SYS_SEEK_END: newpos = buf->size - off; break;
+        default: return -1;
+    }
+    if(newpos < 0) return -1;
+    if(newpos > buf->size) {
+        if(!buf->writable) return -1;
+        if(newpos > buf->length)
+            mem_buf_grow(buf,newpos);
+    }
+    buf->pos = newpos;
+    return 0;
+}
+
+static off_t my_tell(struct mspack_file *buf_) {
+    mem_buf_t *buf = (mem_buf_t*) buf_;
+    return buf ? buf->pos : 0;
+}
+
+static void my_message(struct mspack_file *file, char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  vfprintf(stderr, format, ap);
+  va_end(ap);
+  fputc((int) '\n', stderr);
+  fflush(stderr);
+}
+
+static void *my_alloc(struct mspack_system *sys, size_t size) { return malloc(size); }
+static void my_free(void *p) { free(p); }
+static void my_copy(void *src, void *dest, size_t bytes) { memcpy(dest, src, bytes); }
+
+static struct mspack_system my_system =  {
+    &my_open,
+    &my_close,
+    &my_read, 
+    &my_write,
+    &my_seek,
+    &my_tell,
+    &my_message,
+    &my_alloc,
+    &my_free,
+    &my_copy,
+    NULL
+};
+
+char *user_info[4];
+
+int main(int argc, char **argv) {
+    struct mscab_decompressor *decomp;
+    struct mscabd_cabinet *cab;
+    struct mscabd_file *file;
+        mem_buf_t mem_buf;
+        size_t size = (size_t)user_info[1];
+        int i;
+        
+        mem_buf.addr = user_info[0];
+        mem_buf.pos = mem_buf.writable = 0;
+        mem_buf.length = -1;
+        mem_buf.size = size;
+        
+        cab_mem_buf = &mem_buf;
+                
+    decomp = mspack_create_cab_decompressor(&my_system);
+    if(!decomp) exit(1);
+    
+    cab = decomp->search(decomp,"/dev/cab");
+    if(!cab) exit(2);
+    
+        for(file = cab->files;file;file=file->next)
+            decomp->extract(decomp,file,file->filename);
+        
+    decomp->close(decomp,cab);
+    mspack_destroy_cab_decompressor(decomp);
+        
+    printf("Success!\n");
+    
+        for(i=0;i<MAX_MEMBERS && write_buf_table[i].filename;i++) {
+            output_table[i].filename = write_buf_table[i].filename;
+            output_table[i].data = write_buf_table[i].buf.addr;
+            output_table[i].length = write_buf_table[i].buf.size;
+        }
+        
+        user_info[2] = (char*) output_table;
+        
+        /*
+        if(output_table[0].filename) {
+            printf("%s in 0\n",write_buf_table[0].filename);
+            fp = fopen(output_table[0].filename,"wb");
+            if(fp) {
+                fwrite(output_table[0].data,1,output_table[0].length,fp);
+                fclose(fp);
+                printf("Wrote: %s\n",output_table[0].filename);
+            }
+        }
+        */
+        
+    return 0;
+}
diff --git a/src/tests/Paranoia.c b/src/tests/Paranoia.c
new file mode 100644 (file)
index 0000000..1d3d55c
--- /dev/null
@@ -0,0 +1,2247 @@
+/*     A C version of Kahan's Floating Point Test "Paranoia"
+
+                       Thos Sumner, UCSF, Feb. 1985
+                       David Gay, BTL, Jan. 1986
+
+       This is a rewrite from the Pascal version by
+
+                       B. A. Wichmann, 18 Jan. 1985
+
+       (and does NOT exhibit good C programming style).
+
+       Adjusted to use Standard C headers 19 Jan. 1992 (dmg);
+       compile with -DKR_headers or insert
+#define KR_headers
+       at the beginning if you have an old-style C compiler.
+
+(C) Apr 19 1983 in BASIC version by:
+       Professor W. M. Kahan,
+       567 Evans Hall
+       Electrical Engineering & Computer Science Dept.
+       University of California
+       Berkeley, California 94720
+       USA
+
+converted to Pascal by:
+       B. A. Wichmann
+       National Physical Laboratory
+       Teddington Middx
+       TW11 OLW
+       UK
+
+converted to C by:
+
+       David M. Gay            and     Thos Sumner
+       AT&T Bell Labs                  Computer Center, Rm. U-76
+       600 Mountain Avenue             University of California
+       Murray Hill, NJ 07974           San Francisco, CA 94143
+       USA                             USA
+
+with simultaneous corrections to the Pascal source (reflected
+in the Pascal source available over netlib).
+[A couple of bug fixes from dgh = sun!dhough incorporated 31 July 1986.]
+
+Reports of results on various systems from all the versions
+of Paranoia are being collected by Richard Karpinski at the
+same address as Thos Sumner.  This includes sample outputs,
+bug reports, and criticisms.
+
+You may copy this program freely if you acknowledge its source.
+Comments on the Pascal version to NPL, please.
+
+
+The C version catches signals from floating-point exceptions.
+If signal(SIGFPE,...) is unavailable in your environment, you may
+#define NOSIGNAL to comment out the invocations of signal.
+
+This source file is too big for some C compilers, but may be split
+into pieces.  Comments containing "SPLIT" suggest convenient places
+for this splitting.  At the end of these comments is an "ed script"
+(for the UNIX(tm) editor ed) that will do this splitting.
+
+By #defining Single when you compile this source, you may obtain
+a single-precision C version of Paranoia.
+
+
+The following is from the introductory commentary from Wichmann's work:
+
+The BASIC program of Kahan is written in Microsoft BASIC using many
+facilities which have no exact analogy in Pascal.  The Pascal
+version below cannot therefore be exactly the same.  Rather than be
+a minimal transcription of the BASIC program, the Pascal coding
+follows the conventional style of block-structured languages.  Hence
+the Pascal version could be useful in producing versions in other
+structured languages.
+
+Rather than use identifiers of minimal length (which therefore have
+little mnemonic significance), the Pascal version uses meaningful
+identifiers as follows [Note: A few changes have been made for C]:
+
+
+BASIC   C               BASIC   C               BASIC   C               
+
+   A                       J                       S    StickyBit
+   A1   AInverse           J0   NoErrors           T
+   B    Radix                    [Failure]         T0   Underflow
+   B1   BInverse           J1   NoErrors           T2   ThirtyTwo
+   B2   RadixD2                  [SeriousDefect]   T5   OneAndHalf
+   B9   BMinusU2           J2   NoErrors           T7   TwentySeven
+   C                             [Defect]          T8   TwoForty
+   C1   CInverse           J3   NoErrors           U    OneUlp
+   D                             [Flaw]            U0   UnderflowThreshold
+   D4   FourD              K    PageNo             U1
+   E0                      L    Milestone          U2
+   E1                      M                       V
+   E2   Exp2               N                       V0
+   E3                      N1                      V8
+   E5   MinSqEr            O    Zero               V9
+   E6   SqEr               O1   One                W
+   E7   MaxSqEr            O2   Two                X
+   E8                      O3   Three              X1
+   E9                      O4   Four               X8
+   F1   MinusOne           O5   Five               X9   Random1
+   F2   Half               O8   Eight              Y
+   F3   Third              O9   Nine               Y1
+   F6                      P    Precision          Y2
+   F9                      Q                       Y9   Random2
+   G1   GMult              Q8                      Z
+   G2   GDiv               Q9                      Z0   PseudoZero
+   G3   GAddSub            R                       Z1
+   H                       R1   RMult              Z2
+   H1   HInverse           R2   RDiv               Z9
+   I                       R3   RAddSub
+   IO   NoTrials           R4   RSqrt
+   I3   IEEE               R9   Random9
+
+   SqRWrng
+
+All the variables in BASIC are true variables and in consequence,
+the program is more difficult to follow since the "constants" must
+be determined (the glossary is very helpful).  The Pascal version
+uses Real constants, but checks are added to ensure that the values
+are correctly converted by the compiler.
+
+The major textual change to the Pascal version apart from the
+identifiersis that named procedures are used, inserting parameters
+wherehelpful.  New procedures are also introduced.  The
+correspondence is as follows:
+
+
+BASIC       Pascal
+lines 
+
+  90- 140   Pause
+ 170- 250   Instructions
+ 380- 460   Heading
+ 480- 670   Characteristics
+ 690- 870   History
+2940-2950   Random
+3710-3740   NewD
+4040-4080   DoesYequalX
+4090-4110   PrintIfNPositive
+4640-4850   TestPartialUnderflow
+
+=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+
+Below is an "ed script" that splits para.c into 10 files
+of the form part[1-8].c, subs.c, and msgs.c, plus a header
+file, paranoia.h, that these files require.
+
+r paranoia.c
+$
+?SPLIT
+ .d
++d
+-,$w msgs.c
+-,$d
+?SPLIT
+ .d
++d
+-,$w subs.c
+-,$d
+?part8
++d
+?include
+ .,$w part8.c
+ .,$d
+-d
+?part7
++d
+?include
+ .,$w part7.c
+ .,$d
+-d
+?part6
++d
+?include
+ .,$w part6.c
+ .,$d
+-d
+?part5
++d
+?include
+ .,$w part5.c
+ .,$d
+-d
+?part4
++d
+?include
+ .,$w part4.c
+ .,$d
+-d
+?part3
++d
+?include
+ .,$w part3.c
+ .,$d
+-d
+?part2
++d
+?include
+ .,$w part2.c
+ .,$d
+?SPLIT
+ .d
+1,/^#include/-1d
+1,$w part1.c
+/Computed constants/,$d
+1,$s/^int/extern &/
+1,$s/^FLOAT/extern &/
+1,$s/^char/extern &/
+1,$s! = .*!;!
+/^Guard/,/^Round/s/^/extern /
+/^jmp_buf/s/^/extern /
+/^Sig_type/s/^/extern /
+s/$/\
+extern void sigfpe(INT);/
+w paranoia.h
+q
+
+*/
+
+#include <stdio.h>
+#ifndef NOSIGNAL
+#include <signal.h>
+#endif
+#include <setjmp.h>
+
+#ifdef Single
+#define FLOAT float
+#define FABS(x) (float)fabs((double)(x))
+#define FLOOR(x) (float)floor((double)(x))
+#define LOG(x) (float)log((double)(x))
+#define POW(x,y) (float)pow((double)(x),(double)(y))
+#define SQRT(x) (float)sqrt((double)(x))
+#else
+#define FLOAT double
+#define FABS(x) fabs(x)
+#define FLOOR(x) floor(x)
+#define LOG(x) log(x)
+#define POW(x,y) pow(x,y)
+#define SQRT(x) sqrt(x)
+#endif
+
+jmp_buf ovfl_buf;
+#ifdef KR_headers
+#define VOID /* void */
+#define INT /* int */
+#define FP /* FLOAT */
+#define CHARP /* char * */
+#define CHARPP /* char ** */
+extern double fabs(), floor(), log(), pow(), sqrt();
+extern void exit();
+typedef void (*Sig_type)();
+FLOAT Sign(), Random();
+extern void BadCond();
+extern void SqXMinX();
+extern void TstCond();
+extern void notify();
+extern int read();
+#else
+#define VOID void
+#define INT int
+#define FP FLOAT
+#define CHARP char *
+#define CHARPP char **
+#ifdef __STDC__
+#include <stdlib.h>
+#include <math.h>
+#else
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern double fabs(double), floor(double), log(double);
+extern double pow(double,double), sqrt(double);
+extern void exit(INT);
+#ifdef __cplusplus
+       }
+#endif
+#endif
+typedef void (*Sig_type)(int);
+FLOAT Sign(FLOAT), Random(void);
+extern void BadCond(int, char*);
+extern void SqXMinX(int);
+extern void TstCond(int, int, char*);
+extern void notify(char*);
+extern int read(int, char*, int);
+#endif
+#undef V9
+extern void Characteristics(VOID);
+extern void Heading(VOID);
+extern void History(VOID);
+extern void Instructions(VOID);
+extern void IsYeqX(VOID);
+extern void NewD(VOID);
+extern void Pause(VOID);
+extern void PrintIfNPositive(VOID);
+extern void SR3750(VOID);
+extern void SR3980(VOID);
+extern void TstPtUf(VOID);
+
+Sig_type sigsave;
+
+#define KEYBOARD 0
+
+FLOAT Radix, BInvrse, RadixD2, BMinusU2;
+
+/*Small floating point constants.*/
+FLOAT Zero = 0.0;
+FLOAT Half = 0.5;
+FLOAT One = 1.0;
+FLOAT Two = 2.0;
+FLOAT Three = 3.0;
+FLOAT Four = 4.0;
+FLOAT Five = 5.0;
+FLOAT Eight = 8.0;
+FLOAT Nine = 9.0;
+FLOAT TwentySeven = 27.0;
+FLOAT ThirtyTwo = 32.0;
+FLOAT TwoForty = 240.0;
+FLOAT MinusOne = -1.0;
+FLOAT OneAndHalf = 1.5;
+/*Integer constants*/
+int NoTrials = 20; /*Number of tests for commutativity. */
+#define False 0
+#define True 1
+
+/* Definitions for declared types 
+       Guard == (Yes, No);
+       Rounding == (Chopped, Rounded, Other);
+       Message == packed array [1..40] of char;
+       Class == (Flaw, Defect, Serious, Failure);
+         */
+#define Yes 1
+#define No  0
+#define Chopped 2
+#define Rounded 1
+#define Other   0
+#define Flaw    3
+#define Defect  2
+#define Serious 1
+#define Failure 0
+typedef int Guard, Rounding, Class;
+typedef char Message;
+
+/* Declarations of Variables */
+int Indx;
+char ch[8];
+FLOAT AInvrse, A1;
+FLOAT C, CInvrse;
+FLOAT D, FourD;
+FLOAT E0, E1, Exp2, E3, MinSqEr;
+FLOAT SqEr, MaxSqEr, E9;
+FLOAT Third;
+FLOAT F6, F9;
+FLOAT H, HInvrse;
+int I;
+FLOAT StickyBit, J;
+FLOAT MyZero;
+FLOAT Precision;
+FLOAT Q, Q9;
+FLOAT R, Random9;
+FLOAT T, Underflow, S;
+FLOAT OneUlp, UfThold, U1, U2;
+FLOAT V, V0, V9;
+FLOAT W;
+FLOAT X, X1, X2, X8, Random1;
+FLOAT Y, Y1, Y2, Random2;
+FLOAT Z, PseudoZero, Z1, Z2, Z9;
+int ErrCnt[4];
+int fpecount;
+int Milestone;
+int PageNo;
+int M, N, N1;
+Guard GMult, GDiv, GAddSub;
+Rounding RMult, RDiv, RAddSub, RSqrt;
+int Break, Done, NotMonot, Monot, Anomaly, IEEE,
+               SqRWrng, UfNGrad;
+/* Computed constants. */
+/*U1  gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */
+/*U2  gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */
+
+/* floating point exception receiver */
+ void
+sigfpe(INT x)
+{
+       fpecount++;
+       printf("\n* * * FLOATING-POINT ERROR %d * * *\n", x);
+       fflush(stdout);
+       if (sigsave) {
+#ifndef NOSIGNAL
+               signal(SIGFPE, sigsave);
+#endif
+               sigsave = 0;
+               longjmp(ovfl_buf, 1);
+               }
+       exit(1);
+}
+
+main(VOID)
+{
+       /* First two assignments use integer right-hand sides. */
+       Zero = 0;
+       One = 1;
+       Two = One + One;
+       Three = Two + One;
+       Four = Three + One;
+       Five = Four + One;
+       Eight = Four + Four;
+       Nine = Three * Three;
+       TwentySeven = Nine * Three;
+       ThirtyTwo = Four * Eight;
+       TwoForty = Four * Five * Three * Four;
+       MinusOne = -One;
+       Half = One / Two;
+       OneAndHalf = One + Half;
+       ErrCnt[Failure] = 0;
+       ErrCnt[Serious] = 0;
+       ErrCnt[Defect] = 0;
+       ErrCnt[Flaw] = 0;
+       PageNo = 1;
+       /*=============================================*/
+       Milestone = 0;
+       /*=============================================*/
+#ifndef NOSIGNAL
+       signal(SIGFPE, sigfpe);
+#endif
+       Instructions();
+       Pause();
+       Heading();
+       Pause();
+       Characteristics();
+       Pause();
+       History();
+       Pause();
+       /*=============================================*/
+       Milestone = 7;
+       /*=============================================*/
+       printf("Program is now RUNNING tests on small integers:\n");
+       
+       TstCond (Failure, (Zero + Zero == Zero) && (One - One == Zero)
+                  && (One > Zero) && (One + One == Two),
+                       "0+0 != 0, 1-1 != 0, 1 <= 0, or 1+1 != 2");
+       Z = - Zero;
+       if (Z != 0.0) {
+               ErrCnt[Failure] = ErrCnt[Failure] + 1;
+               printf("Comparison alleges that -0.0 is Non-zero!\n");
+               U2 = 0.001;
+               Radix = 1;
+               TstPtUf();
+               }
+       TstCond (Failure, (Three == Two + One) && (Four == Three + One)
+                  && (Four + Two * (- Two) == Zero)
+                  && (Four - Three - One == Zero),
+                  "3 != 2+1, 4 != 3+1, 4+2*(-2) != 0, or 4-3-1 != 0");
+       TstCond (Failure, (MinusOne == (0 - One))
+                  && (MinusOne + One == Zero ) && (One + MinusOne == Zero)
+                  && (MinusOne + FABS(One) == Zero)
+                  && (MinusOne + MinusOne * MinusOne == Zero),
+                  "-1+1 != 0, (-1)+abs(1) != 0, or -1+(-1)*(-1) != 0");
+       TstCond (Failure, Half + MinusOne + Half == Zero,
+                 "1/2 + (-1) + 1/2 != 0");
+       /*=============================================*/
+       /*SPLIT
+       {
+               extern void part2(VOID), part3(VOID), part4(VOID),
+                       part5(VOID), part6(VOID), part7(VOID);
+               int part8(VOID);
+
+               part2();
+               part3();
+               part4();
+               part5();
+               part6();
+               part7();
+               return part8();
+               }
+       }
+#include "paranoia.h"
+void part2(VOID){
+*/
+       Milestone = 10;
+       /*=============================================*/
+       TstCond (Failure, (Nine == Three * Three)
+                  && (TwentySeven == Nine * Three) && (Eight == Four + Four)
+                  && (ThirtyTwo == Eight * Four)
+                  && (ThirtyTwo - TwentySeven - Four - One == Zero),
+                  "9 != 3*3, 27 != 9*3, 32 != 8*4, or 32-27-4-1 != 0");
+       TstCond (Failure, (Five == Four + One) &&
+                       (TwoForty == Four * Five * Three * Four)
+                  && (TwoForty / Three - Four * Four * Five == Zero)
+                  && ( TwoForty / Four - Five * Three * Four == Zero)
+                  && ( TwoForty / Five - Four * Three * Four == Zero),
+                 "5 != 4+1, 240/3 != 80, 240/4 != 60, or 240/5 != 48");
+       if (ErrCnt[Failure] == 0) {
+               printf("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n");
+               printf("\n");
+               }
+       printf("Searching for Radix and Precision.\n");
+       W = One;
+       do  {
+               W = W + W;
+               Y = W + One;
+               Z = Y - W;
+               Y = Z - One;
+               } while (MinusOne + FABS(Y) < Zero);
+       /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ...*/
+       Precision = Zero;
+       Y = One;
+       do  {
+               Radix = W + Y;
+               Y = Y + Y;
+               Radix = Radix - W;
+               } while ( Radix == Zero);
+       if (Radix < Two) Radix = One;
+       printf("Radix = %f .\n", Radix);
+       if (Radix != 1) {
+               W = One;
+               do  {
+                       Precision = Precision + One;
+                       W = W * Radix;
+                       Y = W + One;
+                       } while ((Y - W) == One);
+               }
+       /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1
+                                                     ...*/
+       U1 = One / W;
+       U2 = Radix * U1;
+       printf("Closest relative separation found is U1 = %.7e .\n\n", U1);
+       printf("Recalculating radix and precision\n ");
+       
+       /*save old values*/
+       E0 = Radix;
+       E1 = U1;
+       E9 = U2;
+       E3 = Precision;
+       
+       X = Four / Three;
+       Third = X - One;
+       F6 = Half - Third;
+       X = F6 + F6;
+       X = FABS(X - Third);
+       if (X < U2) X = U2;
+       
+       /*... now X = (unknown no.) ulps of 1+...*/
+       do  {
+               U2 = X;
+               Y = Half * U2 + ThirtyTwo * U2 * U2;
+               Y = One + Y;
+               X = Y - One;
+               } while ( ! ((U2 <= X) || (X <= Zero)));
+       
+       /*... now U2 == 1 ulp of 1 + ... */
+       X = Two / Three;
+       F6 = X - Half;
+       Third = F6 + F6;
+       X = Third - Half;
+       X = FABS(X + F6);
+       if (X < U1) X = U1;
+       
+       /*... now  X == (unknown no.) ulps of 1 -... */
+       do  {
+               U1 = X;
+               Y = Half * U1 + ThirtyTwo * U1 * U1;
+               Y = Half - Y;
+               X = Half + Y;
+               Y = Half - X;
+               X = Half + Y;
+               } while ( ! ((U1 <= X) || (X <= Zero)));
+       /*... now U1 == 1 ulp of 1 - ... */
+       if (U1 == E1) printf("confirms closest relative separation U1 .\n");
+       else printf("gets better closest relative separation U1 = %.7e .\n", U1);
+       W = One / U1;
+       F9 = (Half - U1) + Half;
+       Radix = FLOOR(0.01 + U2 / U1);
+       if (Radix == E0) printf("Radix confirmed.\n");
+       else printf("MYSTERY: recalculated Radix = %.7e .\n", Radix);
+       TstCond (Defect, Radix <= Eight + Eight,
+                  "Radix is too big: roundoff problems");
+       TstCond (Flaw, (Radix == Two) || (Radix == 10)
+                  || (Radix == One), "Radix is not as good as 2 or 10");
+       /*=============================================*/
+       Milestone = 20;
+       /*=============================================*/
+       TstCond (Failure, F9 - Half < Half,
+                  "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?");
+       X = F9;
+       I = 1;
+       Y = X - Half;
+       Z = Y - Half;
+       TstCond (Failure, (X != One)
+                  || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0");
+       X = One + U2;
+       I = 0;
+       /*=============================================*/
+       Milestone = 25;
+       /*=============================================*/
+       /*... BMinusU2 = nextafter(Radix, 0) */
+       BMinusU2 = Radix - One;
+       BMinusU2 = (BMinusU2 - U2) + One;
+       /* Purify Integers */
+       if (Radix != One)  {
+               X = - TwoForty * LOG(U1) / LOG(Radix);
+               Y = FLOOR(Half + X);
+               if (FABS(X - Y) * Four < One) X = Y;
+               Precision = X / TwoForty;
+               Y = FLOOR(Half + Precision);
+               if (FABS(Precision - Y) * TwoForty < Half) Precision = Y;
+               }
+       if ((Precision != FLOOR(Precision)) || (Radix == One)) {
+               printf("Precision cannot be characterized by an Integer number\n");
+               printf("of significant digits but, by itself, this is a minor flaw.\n");
+               }
+       if (Radix == One) 
+               printf("logarithmic encoding has precision characterized solely by U1.\n");
+       else printf("The number of significant digits of the Radix is %f .\n",
+                       Precision);
+       TstCond (Serious, U2 * Nine * Nine * TwoForty < One,
+                  "Precision worse than 5 decimal figures  ");
+       /*=============================================*/
+       Milestone = 30;
+       /*=============================================*/
+       /* Test for extra-precise subepressions */
+       X = FABS(((Four / Three - One) - One / Four) * Three - One / Four);
+       do  {
+               Z2 = X;
+               X = (One + (Half * Z2 + ThirtyTwo * Z2 * Z2)) - One;
+               } while ( ! ((Z2 <= X) || (X <= Zero)));
+       X = Y = Z = FABS((Three / Four - Two / Three) * Three - One / Four);
+       do  {
+               Z1 = Z;
+               Z = (One / Two - ((One / Two - (Half * Z1 + ThirtyTwo * Z1 * Z1))
+                       + One / Two)) + One / Two;
+               } while ( ! ((Z1 <= Z) || (Z <= Zero)));
+       do  {
+               do  {
+                       Y1 = Y;
+                       Y = (Half - ((Half - (Half * Y1 + ThirtyTwo * Y1 * Y1)) + Half
+                               )) + Half;
+                       } while ( ! ((Y1 <= Y) || (Y <= Zero)));
+               X1 = X;
+               X = ((Half * X1 + ThirtyTwo * X1 * X1) - F9) + F9;
+               } while ( ! ((X1 <= X) || (X <= Zero)));
+       if ((X1 != Y1) || (X1 != Z1)) {
+               BadCond(Serious, "Disagreements among the values X1, Y1, Z1,\n");
+               printf("respectively  %.7e,  %.7e,  %.7e,\n", X1, Y1, Z1);
+               printf("are symptoms of inconsistencies introduced\n");
+               printf("by extra-precise evaluation of arithmetic subexpressions.\n");
+               notify("Possibly some part of this");
+               if ((X1 == U1) || (Y1 == U1) || (Z1 == U1))  printf(
+                       "That feature is not tested further by this program.\n") ;
+               }
+       else  {
+               if ((Z1 != U1) || (Z2 != U2)) {
+                       if ((Z1 >= U1) || (Z2 >= U2)) {
+                               BadCond(Failure, "");
+                               notify("Precision");
+                               printf("\tU1 = %.7e, Z1 - U1 = %.7e\n",U1,Z1-U1);
+                               printf("\tU2 = %.7e, Z2 - U2 = %.7e\n",U2,Z2-U2);
+                               }
+                       else {
+                               if ((Z1 <= Zero) || (Z2 <= Zero)) {
+                                       printf("Because of unusual Radix = %f", Radix);
+                                       printf(", or exact rational arithmetic a result\n");
+                                       printf("Z1 = %.7e, or Z2 = %.7e ", Z1, Z2);
+                                       notify("of an\nextra-precision");
+                                       }
+                               if (Z1 != Z2 || Z1 > Zero) {
+                                       X = Z1 / U1;
+                                       Y = Z2 / U2;
+                                       if (Y > X) X = Y;
+                                       Q = - LOG(X);
+                                       printf("Some subexpressions appear to be calculated extra\n");
+                                       printf("precisely with about %g extra B-digits, i.e.\n",
+                                               (Q / LOG(Radix)));
+                                       printf("roughly %g extra significant decimals.\n",
+                                               Q / LOG(10.));
+                                       }
+                               printf("That feature is not tested further by this program.\n");
+                               }
+                       }
+               }
+       Pause();
+       /*=============================================*/
+       /*SPLIT
+       }
+#include "paranoia.h"
+void part3(VOID){
+*/
+       Milestone = 35;
+       /*=============================================*/
+       if (Radix >= Two) {
+               X = W / (Radix * Radix);
+               Y = X + One;
+               Z = Y - X;
+               T = Z + U2;
+               X = T - Z;
+               TstCond (Failure, X == U2,
+                       "Subtraction is not normalized X=Y,X+Z != Y+Z!");
+               if (X == U2) printf(
+                       "Subtraction appears to be normalized, as it should be.");
+               }
+       printf("\nChecking for guard digit in *, /, and -.\n");
+       Y = F9 * One;
+       Z = One * F9;
+       X = F9 - Half;
+       Y = (Y - Half) - X;
+       Z = (Z - Half) - X;
+       X = One + U2;
+       T = X * Radix;
+       R = Radix * X;
+       X = T - Radix;
+       X = X - Radix * U2;
+       T = R - Radix;
+       T = T - Radix * U2;
+       X = X * (Radix - One);
+       T = T * (Radix - One);
+       if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)) GMult = Yes;
+       else {
+               GMult = No;
+               TstCond (Serious, False,
+                       "* lacks a Guard Digit, so 1*X != X");
+               }
+       Z = Radix * U2;
+       X = One + Z;
+       Y = FABS((X + Z) - X * X) - U2;
+       X = One - U2;
+       Z = FABS((X - U2) - X * X) - U1;
+       TstCond (Failure, (Y <= Zero)
+                  && (Z <= Zero), "* gets too many final digits wrong.\n");
+       Y = One - U2;
+       X = One + U2;
+       Z = One / Y;
+       Y = Z - X;
+       X = One / Three;
+       Z = Three / Nine;
+       X = X - Z;
+       T = Nine / TwentySeven;
+       Z = Z - T;
+       TstCond(Defect, X == Zero && Y == Zero && Z == Zero,
+               "Division lacks a Guard Digit, so error can exceed 1 ulp\n\
+or  1/3  and  3/9  and  9/27 may disagree");
+       Y = F9 / One;
+       X = F9 - Half;
+       Y = (Y - Half) - X;
+       X = One + U2;
+       T = X / One;
+       X = T - X;
+       if ((X == Zero) && (Y == Zero) && (Z == Zero)) GDiv = Yes;
+       else {
+               GDiv = No;
+               TstCond (Serious, False,
+                       "Division lacks a Guard Digit, so X/1 != X");
+               }
+       X = One / (One + U2);
+       Y = X - Half - Half;
+       TstCond (Serious, Y < Zero,
+                  "Computed value of 1/1.000..1 >= 1");
+       X = One - U2;
+       Y = One + Radix * U2;
+       Z = X * Radix;
+       T = Y * Radix;
+       R = Z / Radix;
+       StickyBit = T / Radix;
+       X = R - X;
+       Y = StickyBit - Y;
+       TstCond (Failure, X == Zero && Y == Zero,
+                       "* and/or / gets too many last digits wrong");
+       Y = One - U1;
+       X = One - F9;
+       Y = One - Y;
+       T = Radix - U2;
+       Z = Radix - BMinusU2;
+       T = Radix - T;
+       if ((X == U1) && (Y == U1) && (Z == U2) && (T == U2)) GAddSub = Yes;
+       else {
+               GAddSub = No;
+               TstCond (Serious, False,
+                       "- lacks Guard Digit, so cancellation is obscured");
+               }
+       if (F9 != One && F9 - One >= Zero) {
+               BadCond(Serious, "comparison alleges  (1-U1) < 1  although\n");
+               printf("  subtraction yields  (1-U1) - 1 = 0 , thereby vitiating\n");
+               printf("  such precautions against division by zero as\n");
+               printf("  ...  if (X == 1.0) {.....} else {.../(X-1.0)...}\n");
+               }
+       if (GMult == Yes && GDiv == Yes && GAddSub == Yes) printf(
+               "     *, /, and - appear to have guard digits, as they should.\n");
+       /*=============================================*/
+       Milestone = 40;
+       /*=============================================*/
+       Pause();
+       printf("Checking rounding on multiply, divide and add/subtract.\n");
+       RMult = Other;
+       RDiv = Other;
+       RAddSub = Other;
+       RadixD2 = Radix / Two;
+       A1 = Two;
+       Done = False;
+       do  {
+               AInvrse = Radix;
+               do  {
+                       X = AInvrse;
+                       AInvrse = AInvrse / A1;
+                       } while ( ! (FLOOR(AInvrse) != AInvrse));
+               Done = (X == One) || (A1 > Three);
+               if (! Done) A1 = Nine + One;
+               } while ( ! (Done));
+       if (X == One) A1 = Radix;
+       AInvrse = One / A1;
+       X = A1;
+       Y = AInvrse;
+       Done = False;
+       do  {
+               Z = X * Y - Half;
+               TstCond (Failure, Z == Half,
+                       "X * (1/X) differs from 1");
+               Done = X == Radix;
+               X = Radix;
+               Y = One / X;
+               } while ( ! (Done));
+       Y2 = One + U2;
+       Y1 = One - U2;
+       X = OneAndHalf - U2;
+       Y = OneAndHalf + U2;
+       Z = (X - U2) * Y2;
+       T = Y * Y1;
+       Z = Z - X;
+       T = T - X;
+       X = X * Y2;
+       Y = (Y + U2) * Y1;
+       X = X - OneAndHalf;
+       Y = Y - OneAndHalf;
+       if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T <= Zero)) {
+               X = (OneAndHalf + U2) * Y2;
+               Y = OneAndHalf - U2 - U2;
+               Z = OneAndHalf + U2 + U2;
+               T = (OneAndHalf - U2) * Y1;
+               X = X - (Z + U2);
+               StickyBit = Y * Y1;
+               S = Z * Y2;
+               T = T - Y;
+               Y = (U2 - Y) + StickyBit;
+               Z = S - (Z + U2 + U2);
+               StickyBit = (Y2 + U2) * Y1;
+               Y1 = Y2 * Y1;
+               StickyBit = StickyBit - Y2;
+               Y1 = Y1 - Half;
+               if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
+                       && ( StickyBit == Zero) && (Y1 == Half)) {
+                       RMult = Rounded;
+                       printf("Multiplication appears to round correctly.\n");
+                       }
+               else    if ((X + U2 == Zero) && (Y < Zero) && (Z + U2 == Zero)
+                               && (T < Zero) && (StickyBit + U2 == Zero)
+                               && (Y1 < Half)) {
+                               RMult = Chopped;
+                               printf("Multiplication appears to chop.\n");
+                               }
+                       else printf("* is neither chopped nor correctly rounded.\n");
+               if ((RMult == Rounded) && (GMult == No)) notify("Multiplication");
+               }
+       else printf("* is neither chopped nor correctly rounded.\n");
+       /*=============================================*/
+       Milestone = 45;
+       /*=============================================*/
+       Y2 = One + U2;
+       Y1 = One - U2;
+       Z = OneAndHalf + U2 + U2;
+       X = Z / Y2;
+       T = OneAndHalf - U2 - U2;
+       Y = (T - U2) / Y1;
+       Z = (Z + U2) / Y2;
+       X = X - OneAndHalf;
+       Y = Y - T;
+       T = T / Y1;
+       Z = Z - (OneAndHalf + U2);
+       T = (U2 - OneAndHalf) + T;
+       if (! ((X > Zero) || (Y > Zero) || (Z > Zero) || (T > Zero))) {
+               X = OneAndHalf / Y2;
+               Y = OneAndHalf - U2;
+               Z = OneAndHalf + U2;
+               X = X - Y;
+               T = OneAndHalf / Y1;
+               Y = Y / Y1;
+               T = T - (Z + U2);
+               Y = Y - Z;
+               Z = Z / Y2;
+               Y1 = (Y2 + U2) / Y2;
+               Z = Z - OneAndHalf;
+               Y2 = Y1 - Y2;
+               Y1 = (F9 - U1) / F9;
+               if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
+                       && (Y2 == Zero) && (Y2 == Zero)
+                       && (Y1 - Half == F9 - Half )) {
+                       RDiv = Rounded;
+                       printf("Division appears to round correctly.\n");
+                       if (GDiv == No) notify("Division");
+                       }
+               else if ((X < Zero) && (Y < Zero) && (Z < Zero) && (T < Zero)
+                       && (Y2 < Zero) && (Y1 - Half < F9 - Half)) {
+                       RDiv = Chopped;
+                       printf("Division appears to chop.\n");
+                       }
+               }
+       if (RDiv == Other) printf("/ is neither chopped nor correctly rounded.\n");
+       BInvrse = One / Radix;
+       TstCond (Failure, (BInvrse * Radix - Half == Half),
+                  "Radix * ( 1 / Radix ) differs from 1");
+       /*=============================================*/
+       /*SPLIT
+       }
+#include "paranoia.h"
+void part4(VOID){
+*/
+       Milestone = 50;
+       /*=============================================*/
+       TstCond (Failure, ((F9 + U1) - Half == Half)
+                  && ((BMinusU2 + U2 ) - One == Radix - One),
+                  "Incomplete carry-propagation in Addition");
+       X = One - U1 * U1;
+       Y = One + U2 * (One - U2);
+       Z = F9 - Half;
+       X = (X - Half) - Z;
+       Y = Y - One;
+       if ((X == Zero) && (Y == Zero)) {
+               RAddSub = Chopped;
+               printf("Add/Subtract appears to be chopped.\n");
+               }
+       if (GAddSub == Yes) {
+               X = (Half + U2) * U2;
+               Y = (Half - U2) * U2;
+               X = One + X;
+               Y = One + Y;
+               X = (One + U2) - X;
+               Y = One - Y;
+               if ((X == Zero) && (Y == Zero)) {
+                       X = (Half + U2) * U1;
+                       Y = (Half - U2) * U1;
+                       X = One - X;
+                       Y = One - Y;
+                       X = F9 - X;
+                       Y = One - Y;
+                       if ((X == Zero) && (Y == Zero)) {
+                               RAddSub = Rounded;
+                               printf("Addition/Subtraction appears to round correctly.\n");
+                               if (GAddSub == No) notify("Add/Subtract");
+                               }
+                       else printf("Addition/Subtraction neither rounds nor chops.\n");
+                       }
+               else printf("Addition/Subtraction neither rounds nor chops.\n");
+               }
+       else printf("Addition/Subtraction neither rounds nor chops.\n");
+       S = One;
+       X = One + Half * (One + Half);
+       Y = (One + U2) * Half;
+       Z = X - Y;
+       T = Y - X;
+       StickyBit = Z + T;
+       if (StickyBit != Zero) {
+               S = Zero;
+               BadCond(Flaw, "(X - Y) + (Y - X) is non zero!\n");
+               }
+       StickyBit = Zero;
+       if ((GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes)
+               && (RMult == Rounded) && (RDiv == Rounded)
+               && (RAddSub == Rounded) && (FLOOR(RadixD2) == RadixD2)) {
+               printf("Checking for sticky bit.\n");
+               X = (Half + U1) * U2;
+               Y = Half * U2;
+               Z = One + Y;
+               T = One + X;
+               if ((Z - One <= Zero) && (T - One >= U2)) {
+                       Z = T + Y;
+                       Y = Z - X;
+                       if ((Z - T >= U2) && (Y - T == Zero)) {
+                               X = (Half + U1) * U1;
+                               Y = Half * U1;
+                               Z = One - Y;
+                               T = One - X;
+                               if ((Z - One == Zero) && (T - F9 == Zero)) {
+                                       Z = (Half - U1) * U1;
+                                       T = F9 - Z;
+                                       Q = F9 - Y;
+                                       if ((T - F9 == Zero) && (F9 - U1 - Q == Zero)) {
+                                               Z = (One + U2) * OneAndHalf;
+                                               T = (OneAndHalf + U2) - Z + U2;
+                                               X = One + Half / Radix;
+                                               Y = One + Radix * U2;
+                                               Z = X * Y;
+                                               if (T == Zero && X + Radix * U2 - Z == Zero) {
+                                                       if (Radix != Two) {
+                                                               X = Two + U2;
+                                                               Y = X / Two;
+                                                               if ((Y - One == Zero)) StickyBit = S;
+                                                               }
+                                                       else StickyBit = S;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       if (StickyBit == One) printf("Sticky bit apparently used correctly.\n");
+       else printf("Sticky bit used incorrectly or not at all.\n");
+       TstCond (Flaw, !(GMult == No || GDiv == No || GAddSub == No ||
+                       RMult == Other || RDiv == Other || RAddSub == Other),
+               "lack(s) of guard digits or failure(s) to correctly round or chop\n\
+(noted above) count as one flaw in the final tally below");
+       /*=============================================*/
+       Milestone = 60;
+       /*=============================================*/
+       printf("\n");
+       printf("Does Multiplication commute?  ");
+       printf("Testing on %d random pairs.\n", NoTrials);
+       Random9 = SQRT(3.0);
+       Random1 = Third;
+       I = 1;
+       do  {
+               X = Random();
+               Y = Random();
+               Z9 = Y * X;
+               Z = X * Y;
+               Z9 = Z - Z9;
+               I = I + 1;
+               } while ( ! ((I > NoTrials) || (Z9 != Zero)));
+       if (I == NoTrials) {
+               Random1 = One + Half / Three;
+               Random2 = (U2 + U1) + One;
+               Z = Random1 * Random2;
+               Y = Random2 * Random1;
+               Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half /
+                       Three) * ((U2 + U1) + One);
+               }
+       if (! ((I == NoTrials) || (Z9 == Zero)))
+               BadCond(Defect, "X * Y == Y * X trial fails.\n");
+       else printf("     No failures found in %d integer pairs.\n", NoTrials);
+       /*=============================================*/
+       Milestone = 70;
+       /*=============================================*/
+       printf("\nRunning test of square root(x).\n");
+       TstCond (Failure, (Zero == SQRT(Zero))
+                  && (- Zero == SQRT(- Zero))
+                  && (One == SQRT(One)), "Square root of 0.0, -0.0 or 1.0 wrong");
+       MinSqEr = Zero;
+       MaxSqEr = Zero;
+       J = Zero;
+       X = Radix;
+       OneUlp = U2;
+       SqXMinX (Serious);
+       X = BInvrse;
+       OneUlp = BInvrse * U1;
+       SqXMinX (Serious);
+       X = U1;
+       OneUlp = U1 * U1;
+       SqXMinX (Serious);
+       if (J != Zero) Pause();
+       printf("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials);
+       J = Zero;
+       X = Two;
+       Y = Radix;
+       if ((Radix != One)) do  {
+               X = Y;
+               Y = Radix * Y;
+               } while ( ! ((Y - X >= NoTrials)));
+       OneUlp = X * U2;
+       I = 1;
+       while (I <= NoTrials) {
+               X = X + One;
+               SqXMinX (Defect);
+               if (J > Zero) break;
+               I = I + 1;
+               }
+       printf("Test for sqrt monotonicity.\n");
+       I = - 1;
+       X = BMinusU2;
+       Y = Radix;
+       Z = Radix + Radix * U2;
+       NotMonot = False;
+       Monot = False;
+       while ( ! (NotMonot || Monot)) {
+               I = I + 1;
+               X = SQRT(X);
+               Q = SQRT(Y);
+               Z = SQRT(Z);
+               if ((X > Q) || (Q > Z)) NotMonot = True;
+               else {
+                       Q = FLOOR(Q + Half);
+                       if (!(I > 0 || Radix == Q * Q)) Monot = True;
+                       else if (I > 0) {
+                       if (I > 1) Monot = True;
+                       else {
+                               Y = Y * BInvrse;
+                               X = Y - U1;
+                               Z = Y + U1;
+                               }
+                       }
+                       else {
+                               Y = Q;
+                               X = Y - U2;
+                               Z = Y + U2;
+                               }
+                       }
+               }
+       if (Monot) printf("sqrt has passed a test for Monotonicity.\n");
+       else {
+               BadCond(Defect, "");
+               printf("sqrt(X) is non-monotonic for X near %.7e .\n", Y);
+               }
+       /*=============================================*/
+       /*SPLIT
+       }
+#include "paranoia.h"
+void part5(VOID){
+*/
+       Milestone = 80;
+       /*=============================================*/
+       MinSqEr = MinSqEr + Half;
+       MaxSqEr = MaxSqEr - Half;
+       Y = (SQRT(One + U2) - One) / U2;
+       SqEr = (Y - One) + U2 / Eight;
+       if (SqEr > MaxSqEr) MaxSqEr = SqEr;
+       SqEr = Y + U2 / Eight;
+       if (SqEr < MinSqEr) MinSqEr = SqEr;
+       Y = ((SQRT(F9) - U2) - (One - U2)) / U1;
+       SqEr = Y + U1 / Eight;
+       if (SqEr > MaxSqEr) MaxSqEr = SqEr;
+       SqEr = (Y + One) + U1 / Eight;
+       if (SqEr < MinSqEr) MinSqEr = SqEr;
+       OneUlp = U2;
+       X = OneUlp;
+       for( Indx = 1; Indx <= 3; ++Indx) {
+               Y = SQRT((X + U1 + X) + F9);
+               Y = ((Y - U2) - ((One - U2) + X)) / OneUlp;
+               Z = ((U1 - X) + F9) * Half * X * X / OneUlp;
+               SqEr = (Y + Half) + Z;
+               if (SqEr < MinSqEr) MinSqEr = SqEr;
+               SqEr = (Y - Half) + Z;
+               if (SqEr > MaxSqEr) MaxSqEr = SqEr;
+               if (((Indx == 1) || (Indx == 3))) 
+                       X = OneUlp * Sign (X) * FLOOR(Eight / (Nine * SQRT(OneUlp)));
+               else {
+                       OneUlp = U1;
+                       X = - OneUlp;
+                       }
+               }
+       /*=============================================*/
+       Milestone = 85;
+       /*=============================================*/
+       SqRWrng = False;
+       Anomaly = False;
+       RSqrt = Other; /* ~dgh */
+       if (Radix != One) {
+               printf("Testing whether sqrt is rounded or chopped.\n");
+               D = FLOOR(Half + POW(Radix, One + Precision - FLOOR(Precision)));
+       /* ... == Radix^(1 + fract) if (Precision == Integer + fract. */
+               X = D / Radix;
+               Y = D / A1;
+               if ((X != FLOOR(X)) || (Y != FLOOR(Y))) {
+                       Anomaly = True;
+                       }
+               else {
+                       X = Zero;
+                       Z2 = X;
+                       Y = One;
+                       Y2 = Y;
+                       Z1 = Radix - One;
+                       FourD = Four * D;
+                       do  {
+                               if (Y2 > Z2) {
+                                       Q = Radix;
+                                       Y1 = Y;
+                                       do  {
+                                               X1 = FABS(Q + FLOOR(Half - Q / Y1) * Y1);
+                                               Q = Y1;
+                                               Y1 = X1;
+                                               } while ( ! (X1 <= Zero));
+                                       if (Q <= One) {
+                                               Z2 = Y2;
+                                               Z = Y;
+                                               }
+                                       }
+                               Y = Y + Two;
+                               X = X + Eight;
+                               Y2 = Y2 + X;
+                               if (Y2 >= FourD) Y2 = Y2 - FourD;
+                               } while ( ! (Y >= D));
+                       X8 = FourD - Z2;
+                       Q = (X8 + Z * Z) / FourD;
+                       X8 = X8 / Eight;
+                       if (Q != FLOOR(Q)) Anomaly = True;
+                       else {
+                               Break = False;
+                               do  {
+                                       X = Z1 * Z;
+                                       X = X - FLOOR(X / Radix) * Radix;
+                                       if (X == One) 
+                                               Break = True;
+                                       else
+                                               Z1 = Z1 - One;
+                                       } while ( ! (Break || (Z1 <= Zero)));
+                               if ((Z1 <= Zero) && (! Break)) Anomaly = True;
+                               else {
+                                       if (Z1 > RadixD2) Z1 = Z1 - Radix;
+                                       do  {
+                                               NewD();
+                                               } while ( ! (U2 * D >= F9));
+                                       if (D * Radix - D != W - D) Anomaly = True;
+                                       else {
+                                               Z2 = D;
+                                               I = 0;
+                                               Y = D + (One + Z) * Half;
+                                               X = D + Z + Q;
+                                               SR3750();
+                                               Y = D + (One - Z) * Half + D;
+                                               X = D - Z + D;
+                                               X = X + Q + X;
+                                               SR3750();
+                                               NewD();
+                                               if (D - Z2 != W - Z2) Anomaly = True;
+                                               else {
+                                                       Y = (D - Z2) + (Z2 + (One - Z) * Half);
+                                                       X = (D - Z2) + (Z2 - Z + Q);
+                                                       SR3750();
+                                                       Y = (One + Z) * Half;
+                                                       X = Q;
+                                                       SR3750();
+                                                       if (I == 0) Anomaly = True;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               if ((I == 0) || Anomaly) {
+                       BadCond(Failure, "Anomalous arithmetic with Integer < ");
+                       printf("Radix^Precision = %.7e\n", W);
+                       printf(" fails test whether sqrt rounds or chops.\n");
+                       SqRWrng = True;
+                       }
+               }
+       if (! Anomaly) {
+               if (! ((MinSqEr < Zero) || (MaxSqEr > Zero))) {
+                       RSqrt = Rounded;
+                       printf("Square root appears to be correctly rounded.\n");
+                       }
+               else  {
+                       if ((MaxSqEr + U2 > U2 - Half) || (MinSqEr > Half)
+                               || (MinSqEr + Radix < Half)) SqRWrng = True;
+                       else {
+                               RSqrt = Chopped;
+                               printf("Square root appears to be chopped.\n");
+                               }
+                       }
+               }
+       if (SqRWrng) {
+               printf("Square root is neither chopped nor correctly rounded.\n");
+               printf("Observed errors run from %.7e ", MinSqEr - Half);
+               printf("to %.7e ulps.\n", Half + MaxSqEr);
+               TstCond (Serious, MaxSqEr - MinSqEr < Radix * Radix,
+                       "sqrt gets too many last digits wrong");
+               }
+       /*=============================================*/
+       Milestone = 90;
+       /*=============================================*/
+       Pause();
+       printf("Testing powers Z^i for small Integers Z and i.\n");
+       N = 0;
+       /* ... test powers of zero. */
+       I = 0;
+       Z = -Zero;
+       M = 3;
+       Break = False;
+       do  {
+               X = One;
+               SR3980();
+               if (I <= 10) {
+                       I = 1023;
+                       SR3980();
+                       }
+               if (Z == MinusOne) Break = True;
+               else {
+                       Z = MinusOne;
+                       /* .. if(-1)^N is invalid, replace MinusOne by One. */
+                       I = - 4;
+                       }
+               } while ( ! Break);
+       PrintIfNPositive();
+       N1 = N;
+       N = 0;
+       Z = A1;
+       M = (int)FLOOR(Two * LOG(W) / LOG(A1));
+       Break = False;
+       do  {
+               X = Z;
+               I = 1;
+               SR3980();
+               if (Z == AInvrse) Break = True;
+               else Z = AInvrse;
+               } while ( ! (Break));
+       /*=============================================*/
+               Milestone = 100;
+       /*=============================================*/
+       /*  Powers of Radix have been tested, */
+       /*         next try a few primes     */
+       M = NoTrials;
+       Z = Three;
+       do  {
+               X = Z;
+               I = 1;
+               SR3980();
+               do  {
+                       Z = Z + Two;
+                       } while ( Three * FLOOR(Z / Three) == Z );
+               } while ( Z < Eight * Three );
+       if (N > 0) {
+               printf("Errors like this may invalidate financial calculations\n");
+               printf("\tinvolving interest rates.\n");
+               }
+       PrintIfNPositive();
+       N += N1;
+       if (N == 0) printf("... no discrepancies found.\n");
+       if (N > 0) Pause();
+       else printf("\n");
+       /*=============================================*/
+       /*SPLIT
+       }
+#include "paranoia.h"
+void part6(VOID){
+*/
+       Milestone = 110;
+       /*=============================================*/
+       printf("Seeking Underflow thresholds UfThold and E0.\n");
+       D = U1;
+       if (Precision != FLOOR(Precision)) {
+               D = BInvrse;
+               X = Precision;
+               do  {
+                       D = D * BInvrse;
+                       X = X - One;
+                       } while ( X > Zero);
+               }
+       Y = One;
+       Z = D;
+       /* ... D is power of 1/Radix < 1. */
+       do  {
+               C = Y;
+               Y = Z;
+               Z = Y * Y;
+               } while ((Y > Z) && (Z + Z > Z));
+       Y = C;
+       Z = Y * D;
+       do  {
+               C = Y;
+               Y = Z;
+               Z = Y * D;
+               } while ((Y > Z) && (Z + Z > Z));
+       if (Radix < Two) HInvrse = Two;
+       else HInvrse = Radix;
+       H = One / HInvrse;
+       /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
+       CInvrse = One / C;
+       E0 = C;
+       Z = E0 * H;
+       /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
+       do  {
+               Y = E0;
+               E0 = Z;
+               Z = E0 * H;
+               } while ((E0 > Z) && (Z + Z > Z));
+       UfThold = E0;
+       E1 = Zero;
+       Q = Zero;
+       E9 = U2;
+       S = One + E9;
+       D = C * S;
+       if (D <= C) {
+               E9 = Radix * U2;
+               S = One + E9;
+               D = C * S;
+               if (D <= C) {
+                       BadCond(Failure, "multiplication gets too many last digits wrong.\n");
+                       Underflow = E0;
+                       Y1 = Zero;
+                       PseudoZero = Z;
+                       Pause();
+                       }
+               }
+       else {
+               Underflow = D;
+               PseudoZero = Underflow * H;
+               UfThold = Zero;
+               do  {
+                       Y1 = Underflow;
+                       Underflow = PseudoZero;
+                       if (E1 + E1 <= E1) {
+                               Y2 = Underflow * HInvrse;
+                               E1 = FABS(Y1 - Y2);
+                               Q = Y1;
+                               if ((UfThold == Zero) && (Y1 != Y2)) UfThold = Y1;
+                               }
+                       PseudoZero = PseudoZero * H;
+                       } while ((Underflow > PseudoZero)
+                               && (PseudoZero + PseudoZero > PseudoZero));
+               }
+       /* Comment line 4530 .. 4560 */
+       if (PseudoZero != Zero) {
+               printf("\n");
+               Z = PseudoZero;
+       /* ... Test PseudoZero for "phoney- zero" violates */
+       /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
+                  ... */
+               if (PseudoZero <= Zero) {
+                       BadCond(Failure, "Positive expressions can underflow to an\n");
+                       printf("allegedly negative value\n");
+                       printf("PseudoZero that prints out as: %g .\n", PseudoZero);
+                       X = - PseudoZero;
+                       if (X <= Zero) {
+                               printf("But -PseudoZero, which should be\n");
+                               printf("positive, isn't; it prints out as  %g .\n", X);
+                               }
+                       }
+               else {
+                       BadCond(Flaw, "Underflow can stick at an allegedly positive\n");
+                       printf("value PseudoZero that prints out as %g .\n", PseudoZero);
+                       }
+               TstPtUf();
+               }
+       /*=============================================*/
+       Milestone = 120;
+       /*=============================================*/
+       if (CInvrse * Y > CInvrse * Y1) {
+               S = H * S;
+               E0 = Underflow;
+               }
+       if (! ((E1 == Zero) || (E1 == E0))) {
+               BadCond(Defect, "");
+               if (E1 < E0) {
+                       printf("Products underflow at a higher");
+                       printf(" threshold than differences.\n");
+                       if (PseudoZero == Zero) 
+                       E0 = E1;
+                       }
+               else {
+                       printf("Difference underflows at a higher");
+                       printf(" threshold than products.\n");
+                       }
+               }
+       printf("Smallest strictly positive number found is E0 = %g .\n", E0);
+       Z = E0;
+       TstPtUf();
+       Underflow = E0;
+       if (N == 1) Underflow = Y;
+       I = 4;
+       if (E1 == Zero) I = 3;
+       if (UfThold == Zero) I = I - 2;
+       UfNGrad = True;
+       switch (I)  {
+               case    1:
+               UfThold = Underflow;
+               if ((CInvrse * Q) != ((CInvrse * Y) * S)) {
+                       UfThold = Y;
+                       BadCond(Failure, "Either accuracy deteriorates as numbers\n");
+                       printf("approach a threshold = %.17e\n", UfThold);;
+                       printf(" coming down from %.17e\n", C);
+                       printf(" or else multiplication gets too many last digits wrong.\n");
+                       }
+               Pause();
+               break;
+       
+               case    2:
+               BadCond(Failure, "Underflow confuses Comparison, which alleges that\n");
+               printf("Q == Y while denying that |Q - Y| == 0; these values\n");
+               printf("print out as Q = %.17e, Y = %.17e .\n", Q, Y2);
+               printf ("|Q - Y| = %.17e .\n" , FABS(Q - Y2));
+               UfThold = Q;
+               break;
+       
+               case    3:
+               X = X;
+               break;
+       
+               case    4:
+               if ((Q == UfThold) && (E1 == E0)
+                       && (FABS( UfThold - E1 / E9) <= E1)) {
+                       UfNGrad = False;
+                       printf("Underflow is gradual; it incurs Absolute Error =\n");
+                       printf("(roundoff in UfThold) < E0.\n");
+                       Y = E0 * CInvrse;
+                       Y = Y * (OneAndHalf + U2);
+                       X = CInvrse * (One + U2);
+                       Y = Y / X;
+                       IEEE = (Y == E0);
+                       }
+               }
+       if (UfNGrad) {
+               printf("\n");
+               sigsave = sigfpe;
+               if (setjmp(ovfl_buf)) {
+                       printf("Underflow / UfThold failed!\n");
+                       R = H + H;
+                       }
+               else R = SQRT(Underflow / UfThold);
+               sigsave = 0;
+               if (R <= H) {
+                       Z = R * UfThold;
+                       X = Z * (One + R * H * (One + H));
+                       }
+               else {
+                       Z = UfThold;
+                       X = Z * (One + H * H * (One + H));
+                       }
+               if (! ((X == Z) || (X - Z != Zero))) {
+                       BadCond(Flaw, "");
+                       printf("X = %.17e\n\tis not equal to Z = %.17e .\n", X, Z);
+                       Z9 = X - Z;
+                       printf("yet X - Z yields %.17e .\n", Z9);
+                       printf("    Should this NOT signal Underflow, ");
+                       printf("this is a SERIOUS DEFECT\nthat causes ");
+                       printf("confusion when innocent statements like\n");;
+                       printf("    if (X == Z)  ...  else");
+                       printf("  ... (f(X) - f(Z)) / (X - Z) ...\n");
+                       printf("encounter Division by Zero although actually\n");
+                       sigsave = sigfpe;
+                       if (setjmp(ovfl_buf)) printf("X / Z fails!\n");
+                       else printf("X / Z = 1 + %g .\n", (X / Z - Half) - Half);
+                       sigsave = 0;
+                       }
+               }
+       printf("The Underflow threshold is %.17e, %s\n", UfThold,
+                  " below which");
+       printf("calculation may suffer larger Relative error than ");
+       printf("merely roundoff.\n");
+       Y2 = U1 * U1;
+       Y = Y2 * Y2;
+       Y2 = Y * U1;
+       if (Y2 <= UfThold) {
+               if (Y > E0) {
+                       BadCond(Defect, "");
+                       I = 5;
+                       }
+               else {
+                       BadCond(Serious, "");
+                       I = 4;
+                       }
+               printf("Range is too narrow; U1^%d Underflows.\n", I);
+               }
+       /*=============================================*/
+       /*SPLIT
+       }
+#include "paranoia.h"
+void part7(VOID){
+*/
+       Milestone = 130;
+       /*=============================================*/
+       Y = - FLOOR(Half - TwoForty * LOG(UfThold) / LOG(HInvrse)) / TwoForty;
+       Y2 = Y + Y;
+       printf("Since underflow occurs below the threshold\n");
+       printf("UfThold = (%.17e) ^ (%.17e)\nonly underflow ", HInvrse, Y);
+       printf("should afflict the expression\n\t(%.17e) ^ (%.17e);\n",
+               HInvrse, Y2);
+       printf("actually calculating yields:");
+       if (setjmp(ovfl_buf)) {
+               sigsave = 0;
+               BadCond(Serious, "trap on underflow.\n");
+               }
+       else {
+               sigsave = sigfpe;
+               V9 = POW(HInvrse, Y2);
+               sigsave = 0;
+               printf(" %.17e .\n", V9);
+               if (! ((V9 >= Zero) && (V9 <= (Radix + Radix + E9) * UfThold))) {
+                       BadCond(Serious, "this is not between 0 and underflow\n");
+               printf("   threshold = %.17e .\n", UfThold);
+               }
+               else if (! (V9 > UfThold * (One + E9)))
+                       printf("This computed value is O.K.\n");
+               else {
+                       BadCond(Defect, "this is not between 0 and underflow\n");
+                       printf("   threshold = %.17e .\n", UfThold);
+                       }
+               }
+       /*=============================================*/
+       Milestone = 140;
+       /*=============================================*/
+       printf("\n");
+       /* ...calculate Exp2 == exp(2) == 7.389056099... */
+       X = Zero;
+       I = 2;
+       Y = Two * Three;
+       Q = Zero;
+       N = 0;
+       do  {
+               Z = X;
+               I = I + 1;
+               Y = Y / (I + I);
+               R = Y + Q;
+               X = Z + R;
+               Q = (Z - X) + R;
+               } while(X > Z);
+       Z = (OneAndHalf + One / Eight) + X / (OneAndHalf * ThirtyTwo);
+       X = Z * Z;
+       Exp2 = X * X;
+       X = F9;
+       Y = X - U1;
+       printf("Testing X^((X + 1) / (X - 1)) vs. exp(2) = %.17e as X -> 1.\n",
+               Exp2);
+       for(I = 1;;) {
+               Z = X - BInvrse;
+               Z = (X + One) / (Z - (One - BInvrse));
+               Q = POW(X, Z) - Exp2;
+               if (FABS(Q) > TwoForty * U2) {
+                       N = 1;
+                       V9 = (X - BInvrse) - (One - BInvrse);
+                       BadCond(Defect, "Calculated");
+                       printf(" %.17e for\n", POW(X,Z));
+                       printf("\t(1 + (%.17e) ^ (%.17e);\n", V9, Z);
+                       printf("\tdiffers from correct value by %.17e .\n", Q);
+                       printf("\tThis much error may spoil financial\n");
+                       printf("\tcalculations involving tiny interest rates.\n");
+                       break;
+                       }
+               else {
+                       Z = (Y - X) * Two + Y;
+                       X = Y;
+                       Y = Z;
+                       Z = One + (X - F9)*(X - F9);
+                       if (Z > One && I < NoTrials) I++;
+                       else  {
+                               if (X > One) {
+                                       if (N == 0)
+                                          printf("Accuracy seems adequate.\n");
+                                       break;
+                                       }
+                               else {
+                                       X = One + U2;
+                                       Y = U2 + U2;
+                                       Y += X;
+                                       I = 1;
+                                       }
+                               }
+                       }
+               }
+       /*=============================================*/
+       Milestone = 150;
+       /*=============================================*/
+       printf("Testing powers Z^Q at four nearly extreme values.\n");
+       N = 0;
+       Z = A1;
+       Q = FLOOR(Half - LOG(C) / LOG(A1));
+       Break = False;
+       do  {
+               X = CInvrse;
+               Y = POW(Z, Q);
+               IsYeqX();
+               Q = - Q;
+               X = C;
+               Y = POW(Z, Q);
+               IsYeqX();
+               if (Z < One) Break = True;
+               else Z = AInvrse;
+               } while ( ! (Break));
+       PrintIfNPositive();
+       if (N == 0) printf(" ... no discrepancies found.\n");
+       printf("\n");
+       
+       /*=============================================*/
+       Milestone = 160;
+       /*=============================================*/
+       Pause();
+       printf("Searching for Overflow threshold:\n");
+       printf("This may generate an error.\n");
+       Y = - CInvrse;
+       V9 = HInvrse * Y;
+       sigsave = sigfpe;
+       if (setjmp(ovfl_buf)) { I = 0; V9 = Y; goto overflow; }
+       do {
+               V = Y;
+               Y = V9;
+               V9 = HInvrse * Y;
+               } while(V9 < Y);
+       I = 1;
+overflow:
+       sigsave = 0;
+       Z = V9;
+       printf("Can `Z = -Y' overflow?\n");
+       printf("Trying it on Y = %.17e .\n", Y);
+       V9 = - Y;
+       V0 = V9;
+       if (V - Y == V + V0) printf("Seems O.K.\n");
+       else {
+               printf("finds a ");
+               BadCond(Flaw, "-(-Y) differs from Y.\n");
+               }
+       if (Z != Y) {
+               BadCond(Serious, "");
+               printf("overflow past %.17e\n\tshrinks to %.17e .\n", Y, Z);
+               }
+       if (I) {
+               Y = V * (HInvrse * U2 - HInvrse);
+               Z = Y + ((One - HInvrse) * U2) * V;
+               if (Z < V0) Y = Z;
+               if (Y < V0) V = Y;
+               if (V0 - V < V0) V = V0;
+               }
+       else {
+               V = Y * (HInvrse * U2 - HInvrse);
+               V = V + ((One - HInvrse) * U2) * Y;
+               }
+       printf("Overflow threshold is V  = %.17e .\n", V);
+       if (I) printf("Overflow saturates at V0 = %.17e .\n", V0);
+       else printf("There is no saturation value because \
+the system traps on overflow.\n");
+       V9 = V * One;
+       printf("No Overflow should be signaled for V * 1 = %.17e\n", V9);
+       V9 = V / One;
+       printf("                           nor for V / 1 = %.17e .\n", V9);
+       printf("Any overflow signal separating this * from the one\n");
+       printf("above is a DEFECT.\n");
+       /*=============================================*/
+       Milestone = 170;
+       /*=============================================*/
+       if (!(-V < V && -V0 < V0 && -UfThold < V && UfThold < V)) {
+               BadCond(Failure, "Comparisons involving ");
+               printf("+-%g, +-%g\nand +-%g are confused by Overflow.",
+                       V, V0, UfThold);
+               }
+       /*=============================================*/
+       Milestone = 175;
+       /*=============================================*/
+       printf("\n");
+       for(Indx = 1; Indx <= 3; ++Indx) {
+               switch (Indx)  {
+                       case 1: Z = UfThold; break;
+                       case 2: Z = E0; break;
+                       case 3: Z = PseudoZero; break;
+                       }
+               if (Z != Zero) {
+                       V9 = SQRT(Z);
+                       Y = V9 * V9;
+                       if (Y / (One - Radix * E9) < Z
+                          || Y > (One + Radix * E9) * Z) { /* dgh: + E9 --> * E9 */
+                               if (V9 > U1) BadCond(Serious, "");
+                               else BadCond(Defect, "");
+                               printf("Comparison alleges that what prints as Z = %.17e\n", Z);
+                               printf(" is too far from sqrt(Z) ^ 2 = %.17e .\n", Y);
+                               }
+                       }
+               }
+       /*=============================================*/
+       Milestone = 180;
+       /*=============================================*/
+       for(Indx = 1; Indx <= 2; ++Indx) {
+               if (Indx == 1) Z = V;
+               else Z = V0;
+               V9 = SQRT(Z);
+               X = (One - Radix * E9) * V9;
+               V9 = V9 * X;
+               if (((V9 < (One - Two * Radix * E9) * Z) || (V9 > Z))) {
+                       Y = V9;
+                       if (X < W) BadCond(Serious, "");
+                       else BadCond(Defect, "");
+                       printf("Comparison alleges that Z = %17e\n", Z);
+                       printf(" is too far from sqrt(Z) ^ 2 (%.17e) .\n", Y);
+                       }
+               }
+       /*=============================================*/
+       /*SPLIT
+       }
+#include "paranoia.h"
+int part8(VOID){
+*/
+       Milestone = 190;
+       /*=============================================*/
+       Pause();
+       X = UfThold * V;
+       Y = Radix * Radix;
+       if (X*Y < One || X > Y) {
+               if (X * Y < U1 || X > Y/U1) BadCond(Defect, "Badly");
+               else BadCond(Flaw, "");
+                       
+               printf(" unbalanced range; UfThold * V = %.17e\n\t%s\n",
+                       X, "is too far from 1.\n");
+               }
+       /*=============================================*/
+       Milestone = 200;
+       /*=============================================*/
+       for (Indx = 1; Indx <= 5; ++Indx)  {
+               X = F9;
+               switch (Indx)  {
+                       case 2: X = One + U2; break;
+                       case 3: X = V; break;
+                       case 4: X = UfThold; break;
+                       case 5: X = Radix;
+                       }
+               Y = X;
+               sigsave = sigfpe;
+               if (setjmp(ovfl_buf))
+                       printf("  X / X  traps when X = %g\n", X);
+               else {
+                       V9 = (Y / X - Half) - Half;
+                       if (V9 == Zero) continue;
+                       if (V9 == - U1 && Indx < 5) BadCond(Flaw, "");
+                       else BadCond(Serious, "");
+                       printf("  X / X differs from 1 when X = %.17e\n", X);
+                       printf("  instead, X / X - 1/2 - 1/2 = %.17e .\n", V9);
+                       }
+               sigsave = 0;
+               }
+       /*=============================================*/
+       Milestone = 210;
+       /*=============================================*/
+       MyZero = Zero;
+       printf("\n");
+       printf("What message and/or values does Division by Zero produce?\n") ;
+#ifndef NOPAUSE
+       printf("This can interupt your program.  You can ");
+       printf("skip this part if you wish.\n");
+       printf("Do you wish to compute 1 / 0? ");
+       fflush(stdout);
+       read (KEYBOARD, ch, 8);
+       if ((ch[0] == 'Y') || (ch[0] == 'y')) {
+#endif
+               sigsave = sigfpe;
+               printf("    Trying to compute 1 / 0 produces ...");
+               if (!setjmp(ovfl_buf)) printf("  %.7e .\n", One / MyZero);
+               sigsave = 0;
+#ifndef NOPAUSE
+               }
+       else printf("O.K.\n");
+       printf("\nDo you wish to compute 0 / 0? ");
+       fflush(stdout);
+       read (KEYBOARD, ch, 80);
+       if ((ch[0] == 'Y') || (ch[0] == 'y')) {
+#endif
+               sigsave = sigfpe;
+               printf("\n    Trying to compute 0 / 0 produces ...");
+               if (!setjmp(ovfl_buf)) printf("  %.7e .\n", Zero / MyZero);
+               sigsave = 0;
+#ifndef NOPAUSE
+               }
+       else printf("O.K.\n");
+#endif
+       /*=============================================*/
+       Milestone = 220;
+       /*=============================================*/
+       Pause();
+       printf("\n");
+       {
+               static char *msg[] = {
+                       "FAILUREs  encountered =",
+                       "SERIOUS DEFECTs  discovered =",
+                       "DEFECTs  discovered =",
+                       "FLAWs  discovered =" };
+               int i;
+               for(i = 0; i < 4; i++) if (ErrCnt[i])
+                       printf("The number of  %-29s %d.\n",
+                               msg[i], ErrCnt[i]);
+               }
+       printf("\n");
+       if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect]
+                       + ErrCnt[Flaw]) > 0) {
+               if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[
+                       Defect] == 0) && (ErrCnt[Flaw] > 0)) {
+                       printf("The arithmetic diagnosed seems ");
+                       printf("Satisfactory though flawed.\n");
+                       }
+               if ((ErrCnt[Failure] + ErrCnt[Serious] == 0)
+                       && ( ErrCnt[Defect] > 0)) {
+                       printf("The arithmetic diagnosed may be Acceptable\n");
+                       printf("despite inconvenient Defects.\n");
+                       }
+               if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0) {
+                       printf("The arithmetic diagnosed has ");
+                       printf("unacceptable Serious Defects.\n");
+                       }
+               if (ErrCnt[Failure] > 0) {
+                       printf("Potentially fatal FAILURE may have spoiled this");
+                       printf(" program's subsequent diagnoses.\n");
+                       }
+               }
+       else {
+               printf("No failures, defects nor flaws have been discovered.\n");
+               if (! ((RMult == Rounded) && (RDiv == Rounded)
+                       && (RAddSub == Rounded) && (RSqrt == Rounded))) 
+                       printf("The arithmetic diagnosed seems Satisfactory.\n");
+               else {
+                       if (StickyBit >= One &&
+                               (Radix - Two) * (Radix - Nine - One) == Zero) {
+                               printf("Rounding appears to conform to ");
+                               printf("the proposed IEEE standard P");
+                               if ((Radix == Two) &&
+                                        ((Precision - Four * Three * Two) *
+                                         ( Precision - TwentySeven -
+                                          TwentySeven + One) == Zero)) 
+                                       printf("754");
+                               else printf("854");
+                               if (IEEE) printf(".\n");
+                               else {
+                                       printf(",\nexcept for possibly Double Rounding");
+                                       printf(" during Gradual Underflow.\n");
+                                       }
+                               }
+                       printf("The arithmetic diagnosed appears to be Excellent!\n");
+                       }
+               }
+       if (fpecount)
+               printf("\nA total of %d floating point exceptions were registered.\n",
+                       fpecount);
+       printf("END OF TEST.\n");
+       return 0;
+       }
+
+/*SPLIT subs.c
+#include "paranoia.h"
+*/
+
+ FLOAT
+Sign (FP X)
+#ifdef KR_headers
+FLOAT X;
+#endif
+{ return X >= 0. ? 1.0 : -1.0; }
+
+ void
+Pause(VOID)
+{
+#ifndef NOPAUSE
+       char ch[8];
+
+       printf("\nTo continue, press RETURN");
+       fflush(stdout);
+       read(KEYBOARD, ch, 8);
+#endif
+       printf("\nDiagnosis resumes after milestone Number %d", Milestone);
+       printf("          Page: %d\n\n", PageNo);
+       ++Milestone;
+       ++PageNo;
+       }
+
+ void
+TstCond (INT K, INT Valid, CHARP T)
+#ifdef KR_headers
+int K, Valid;
+char *T;
+#endif
+{ if (! Valid) { BadCond(K,T); printf(".\n"); } }
+
+ void
+BadCond(INT K, CHARP T)
+#ifdef KR_headers
+int K;
+char *T;
+#endif
+{
+       static char *msg[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" };
+
+       ErrCnt [K] = ErrCnt [K] + 1;
+       printf("%s:  %s", msg[K], T);
+       }
+
+
+ FLOAT
+Random(VOID)
+/*  Random computes
+     X = (Random1 + Random9)^5
+     Random1 = X - FLOOR(X) + 0.000005 * X;
+   and returns the new value of Random1
+*/
+{
+       FLOAT X, Y;
+       
+       X = Random1 + Random9;
+       Y = X * X;
+       Y = Y * Y;
+       X = X * Y;
+       Y = X - FLOOR(X);
+       Random1 = Y + X * 0.000005;
+       return(Random1);
+       }
+
+ void
+SqXMinX (INT ErrKind)
+#ifdef KR_headers
+int ErrKind;
+#endif
+{
+       FLOAT XA, XB;
+       
+       XB = X * BInvrse;
+       XA = X - XB;
+       SqEr = ((SQRT(X * X) - XB) - XA) / OneUlp;
+       if (SqEr != Zero) {
+               if (SqEr < MinSqEr) MinSqEr = SqEr;
+               if (SqEr > MaxSqEr) MaxSqEr = SqEr;
+               J = J + 1.0;
+               BadCond(ErrKind, "\n");
+               printf("sqrt( %.17e) - %.17e  = %.17e\n", X * X, X, OneUlp * SqEr);
+               printf("\tinstead of correct value 0 .\n");
+               }
+       }
+
+ void
+NewD(VOID)
+{
+       X = Z1 * Q;
+       X = FLOOR(Half - X / Radix) * Radix + X;
+       Q = (Q - X * Z) / Radix + X * X * (D / Radix);
+       Z = Z - Two * X * D;
+       if (Z <= Zero) {
+               Z = - Z;
+               Z1 = - Z1;
+               }
+       D = Radix * D;
+       }
+
+ void
+SR3750(VOID)
+{
+       if (! ((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2))) {
+               I = I + 1;
+               X2 = SQRT(X * D);
+               Y2 = (X2 - Z2) - (Y - Z2);
+               X2 = X8 / (Y - Half);
+               X2 = X2 - Half * X2 * X2;
+               SqEr = (Y2 + Half) + (Half - X2);
+               if (SqEr < MinSqEr) MinSqEr = SqEr;
+               SqEr = Y2 - X2;
+               if (SqEr > MaxSqEr) MaxSqEr = SqEr;
+               }
+       }
+
+ void
+IsYeqX(VOID)
+{
+       if (Y != X) {
+               if (N <= 0) {
+                       if (Z == Zero && Q <= Zero)
+                               printf("WARNING:  computing\n");
+                       else BadCond(Defect, "computing\n");
+                       printf("\t(%.17e) ^ (%.17e)\n", Z, Q);
+                       printf("\tyielded %.17e;\n", Y);
+                       printf("\twhich compared unequal to correct %.17e ;\n",
+                               X);
+                       printf("\t\tthey differ by %.17e .\n", Y - X);
+                       }
+               N = N + 1; /* ... count discrepancies. */
+               }
+       }
+
+ void
+SR3980(VOID)
+{
+       do {
+               Q = (FLOAT) I;
+               Y = POW(Z, Q);
+               IsYeqX();
+               if (++I > M) break;
+               X = Z * X;
+               } while ( X < W );
+       }
+
+ void
+PrintIfNPositive(VOID)
+{
+       if (N > 0) printf("Similar discrepancies have occurred %d times.\n", N);
+       }
+
+ void
+TstPtUf(VOID)
+{
+       N = 0;
+       if (Z != Zero) {
+               printf("Since comparison denies Z = 0, evaluating ");
+               printf("(Z + Z) / Z should be safe.\n");
+               sigsave = sigfpe;
+               if (setjmp(ovfl_buf)) goto very_serious;
+               Q9 = (Z + Z) / Z;
+               printf("What the machine gets for (Z + Z) / Z is  %.17e .\n",
+                       Q9);
+               if (FABS(Q9 - Two) < Radix * U2) {
+                       printf("This is O.K., provided Over/Underflow");
+                       printf(" has NOT just been signaled.\n");
+                       }
+               else {
+                       if ((Q9 < One) || (Q9 > Two)) {
+very_serious:
+                               N = 1;
+                               ErrCnt [Serious] = ErrCnt [Serious] + 1;
+                               printf("This is a VERY SERIOUS DEFECT!\n");
+                               }
+                       else {
+                               N = 1;
+                               ErrCnt [Defect] = ErrCnt [Defect] + 1;
+                               printf("This is a DEFECT!\n");
+                               }
+                       }
+               sigsave = 0;
+               V9 = Z * One;
+               Random1 = V9;
+               V9 = One * Z;
+               Random2 = V9;
+               V9 = Z / One;
+               if ((Z == Random1) && (Z == Random2) && (Z == V9)) {
+                       if (N > 0) Pause();
+                       }
+               else {
+                       N = 1;
+                       BadCond(Defect, "What prints as Z = ");
+                       printf("%.17e\n\tcompares different from  ", Z);
+                       if (Z != Random1) printf("Z * 1 = %.17e ", Random1);
+                       if (! ((Z == Random2)
+                               || (Random2 == Random1)))
+                               printf("1 * Z == %g\n", Random2);
+                       if (! (Z == V9)) printf("Z / 1 = %.17e\n", V9);
+                       if (Random2 != Random1) {
+                               ErrCnt [Defect] = ErrCnt [Defect] + 1;
+                               BadCond(Defect, "Multiplication does not commute!\n");
+                               printf("\tComparison alleges that 1 * Z = %.17e\n",
+                                       Random2);
+                               printf("\tdiffers from Z * 1 = %.17e\n", Random1);
+                               }
+                       Pause();
+                       }
+               }
+       }
+
+ void
+notify(CHARP s)
+#ifdef KR_headers
+ char *s;
+#endif
+{
+       printf("%s test appears to be inconsistent...\n", s);
+       printf("   PLEASE NOTIFY KARPINKSI!\n");
+       }
+
+/*SPLIT msgs.c
+#include "paranoia.h"
+*/
+
+ void
+msglist(CHARPP s)
+#ifdef KR_headers
+char **s;
+#endif
+{ while(*s) printf("%s\n", *s++); }
+
+ void
+Instructions(VOID)
+{
+  static char *instr[] = {
+       "Lest this program stop prematurely, i.e. before displaying\n",
+       "    `END OF TEST',\n",
+       "try to persuade the computer NOT to terminate execution when an",
+       "error like Over/Underflow or Division by Zero occurs, but rather",
+       "to persevere with a surrogate value after, perhaps, displaying some",
+       "warning.  If persuasion avails naught, don't despair but run this",
+       "program anyway to see how many milestones it passes, and then",
+       "amend it to make further progress.\n",
+       "Answer questions with Y, y, N or n (unless otherwise indicated).\n",
+       0};
+
+       msglist(instr);
+       }
+
+ void
+Heading(VOID)
+{
+  static char *head[] = {
+       "Users are invited to help debug and augment this program so it will",
+       "cope with unanticipated and newly uncovered arithmetic pathologies.\n",
+       "Please send suggestions and interesting results to",
+       "\tRichard Karpinski",
+       "\tComputer Center U-76",
+       "\tUniversity of California",
+       "\tSan Francisco, CA 94143-0704, USA\n",
+       "In doing so, please include the following information:",
+#ifdef Single
+       "\tPrecision:\tsingle;",
+#else
+       "\tPrecision:\tdouble;",
+#endif
+       "\tVersion:\t10 February 1989;",
+       "\tComputer:\n",
+       "\tCompiler:\n",
+       "\tOptimization level:\n",
+       "\tOther relevant compiler options:",
+       0};
+
+       msglist(head);
+       }
+
+ void
+Characteristics(VOID)
+{
+       static char *chars[] = {
+        "Running this program should reveal these characteristics:",
+       "     Radix = 1, 2, 4, 8, 10, 16, 100, 256 ...",
+       "     Precision = number of significant digits carried.",
+       "     U2 = Radix/Radix^Precision = One Ulp",
+       "\t(OneUlpnit in the Last Place) of 1.000xxx .",
+       "     U1 = 1/Radix^Precision = One Ulp of numbers a little less than 1.0 .",
+       "     Adequacy of guard digits for Mult., Div. and Subt.",
+       "     Whether arithmetic is chopped, correctly rounded, or something else",
+       "\tfor Mult., Div., Add/Subt. and Sqrt.",
+       "     Whether a Sticky Bit used correctly for rounding.",
+       "     UnderflowThreshold = an underflow threshold.",
+       "     E0 and PseudoZero tell whether underflow is abrupt, gradual, or fuzzy.",
+       "     V = an overflow threshold, roughly.",
+       "     V0  tells, roughly, whether  Infinity  is represented.",
+       "     Comparisions are checked for consistency with subtraction",
+       "\tand for contamination with pseudo-zeros.",
+       "     Sqrt is tested.  Y^X is not tested.",
+       "     Extra-precise subexpressions are revealed but NOT YET tested.",
+       "     Decimal-Binary conversion is NOT YET tested for accuracy.",
+       0};
+
+       msglist(chars);
+       }
+
+ void
+History(VOID)
+{ /* History */
+ /* Converted from Brian Wichmann's Pascal version to C by Thos Sumner,
+       with further massaging by David M. Gay. */
+
+  static char *hist[] = {
+       "The program attempts to discriminate among",
+       "   FLAWs, like lack of a sticky bit,",
+       "   Serious DEFECTs, like lack of a guard digit, and",
+       "   FAILUREs, like 2+2 == 5 .",
+       "Failures may confound subsequent diagnoses.\n",
+       "The diagnostic capabilities of this program go beyond an earlier",
+       "program called `MACHAR', which can be found at the end of the",
+       "book  `Software Manual for the Elementary Functions' (1980) by",
+       "W. J. Cody and W. Waite. Although both programs try to discover",
+       "the Radix, Precision and range (over/underflow thresholds)",
+       "of the arithmetic, this program tries to cope with a wider variety",
+       "of pathologies, and to say how well the arithmetic is implemented.",
+       "\nThe program is based upon a conventional radix representation for",
+       "floating-point numbers, but also allows logarithmic encoding",
+       "as used by certain early WANG machines.\n",
+       "BASIC version of this program (C) 1983 by Prof. W. M. Kahan;",
+       "see source comments for more history.",
+       0};
+
+       msglist(hist);
+       }
diff --git a/src/tests/Simple.c b/src/tests/Simple.c
new file mode 100644 (file)
index 0000000..bb8452e
--- /dev/null
@@ -0,0 +1,9 @@
+#include <string.h>
+
+char *a = "bar";
+
+volatile char buf[] = "Hello World";
+
+int _start() {
+    return strlen("foo");
+}
diff --git a/src/tests/SpeedTest.java b/src/tests/SpeedTest.java
new file mode 100644 (file)
index 0000000..5362961
--- /dev/null
@@ -0,0 +1,66 @@
+package tests;
+
+import org.xwt.mips.Runtime;
+import org.xwt.mips.Interpreter;
+
+class SpeedTest {
+    private static long start,end;
+    private static long now() { return System.currentTimeMillis(); }
+    private static void start()  { start = now(); }
+    private static void end() { end = now(); }
+    private static float diff() { return ((float)(end-start))/1000; }
+    
+    public static void main(String[] args) throws Exception {
+        float d;
+        
+        if(args.length < 2) { System.err.println("Usage: SpeedTest {classname|mips binary} number_of_runs args"); System.exit(1); }
+        String className = args[0];
+        int runs = Integer.parseInt(args[1]);
+        if(runs < 5) throw new Error("Runs must be >= 5");
+        String[] appArgs = new String[args.length-1];
+        appArgs[0] = className;
+        for(int i=2;i<args.length;i++) appArgs[i-1] = args[i];
+        
+        Class c = null;
+        boolean binary = className.endsWith(".mips");
+        if(!binary) {
+            start();
+            c = Class.forName(className);
+            end();
+            d = diff();
+            System.out.println("Class.forName() took " + d + "sec");
+            
+            start();
+            c.newInstance();
+            end();
+            d = diff();
+            System.out.println("c.newInstance() took " + d + "sec");
+            
+            if(!Runtime.class.isAssignableFrom(c)) { System.err.println(className + " isn't a MIPS compiled class"); System.exit(1); }
+        }
+            
+        float times[] = new float[runs];
+        
+        for(int i=0;i<runs;i++) {
+            Runtime runtime = binary ? new Interpreter(className) : (Runtime) c.newInstance();
+            System.gc();
+            start();
+            int status = runtime.run(appArgs);
+            if(status != 0) { System.err.println(className + " failed with exit status: " + status); System.exit(1); }
+            end();
+            times[i] = diff();
+        }
+        
+        for(int i=0;i<runs;i++)
+            System.out.println("Run " + (i+1) + ": " + times[i] + " sec");
+        java.util.Arrays.sort(times);
+        
+        System.out.println("Best: " + times[0]);
+        System.out.println("Worst: " + times[times.length-1]);
+        float sum = 0.0f;
+        for(int i=2;i<times.length-2;i++)
+            sum += times[i];
+        float avg = sum / (times.length-4);
+        System.out.println("Avg of middle " + (times.length-4) + ": " + avg);
+    }
+}
diff --git a/src/tests/Test.c b/src/tests/Test.c
new file mode 100644 (file)
index 0000000..5b0dda0
--- /dev/null
@@ -0,0 +1,208 @@
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <sys/unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/signal.h>
+#include <time.h>
+#include <dirent.h>
+#include <wchar.h>
+#include <math.h>
+
+char *user_info[1024];
+
+extern void _pause();
+extern int _call_java(int a, int b, int c, int d);
+
+void suckram();
+
+int main(int argc, char **argv) {
+    int i,n,fd;
+    time_t now;
+    DIR *dir;
+    struct dirent *dent;
+    char buf[1024];
+    unsigned char ubuf[1024];
+    unsigned short sbuf[1024];
+    char *s;
+    
+    printf("Entered main()\n");
+    
+    if(argc > 1 && strcmp(argv[1],"calltest")==0)  {
+        printf("pausing for call test\n");
+        _pause();
+        printf("unpaused from call test\n");
+        
+        for(i=1;i<=3;i++) {
+            char *s = (char*)_call_java(i,0,0,0);
+            printf("_call_java(%d,0,0,0) = \"%s\" (%d chars)\n",i,s,strlen(s));
+            free(s);
+        }
+        fd = _call_java(4,0,0,0);
+        if(fd != -1) {
+            FILE *fp;
+            fprintf(stderr,"fd: %i\n",fd);
+            fp = fdopen(fd,"w");
+            if(fp != NULL) {
+                fprintf(fp,"It worked! fp is %p - Hello, Java!\n",fp);
+                fclose(fp);
+            } else {
+                fprintf(stderr,"fdopen failed\n");
+                close(fd);
+            }
+        } else {
+            fprintf(stderr,"fd == -1\n");
+        }
+        
+        printf("In main() in MIPS\n");
+        _call_java(5,0,0,0);
+        printf("Back in main() in MIPS\n");
+    } else if(argc > 2 && strcmp(argv[1],"fdtest")==0)  {
+        printf("opening %s\n",argv[2]);
+        fd = open(argv[2],O_RDONLY);
+        if(fd < 0) { perror("open"); exit(1); }
+        
+        printf("reading up to 64 bytes\n");
+        n = read(fd,buf,64);
+        if(n < 0) {perror("read"); exit(1); }
+        printf("read %d bytes\n",n);
+        for(i=0;i<n;i++) if(buf[i]=='\n' || buf[i]=='\r') { buf[i] = '\0'; break; }
+        printf("Read \"%s\"...\n",n == 0 ? NULL : buf);
+        
+        printf("seeking back to pos 4...\n");
+        if(lseek(fd,4,SEEK_SET) < 0) { perror("lseek"); exit(1); }
+        
+        printf("reading up to 64 bytes\n");
+        n = read(fd,buf,64);
+        if(n < 0) {perror("read"); exit(1); }
+        printf("read %d bytes\n",n);
+        for(i=0;i<n;i++) if(buf[i]=='\n' || buf[i]=='\r') { buf[i] = '\0'; break; }
+        printf("Read \"%s\"...\n",n == 0 ? NULL : buf);
+
+        printf("reading up to 64 bytes\n");
+        n = read(fd,buf,64);
+        if(n < 0) {perror("read"); exit(1); }
+        printf("read %d bytes\n",n);
+        for(i=0;i<n;i++) if(buf[i]=='\n' || buf[i]=='\r') { buf[i] = '\0'; break; }
+        printf("Read \"%s\"...\n",n == 0 ? NULL : buf);
+    } else if(argc > 1 && strcmp(argv[1],"fptest")==0)  {
+        double d = 0.0;
+        while(d != 10.0) {
+            printf("d: %f\n",d);
+            d += 2.5;
+        }
+    } else if(argc > 1 && strcmp(argv[1],"nullderef")==0) {
+        volatile int *mem = 0;
+        *mem = 1;
+    } else { 
+        printf("%d\n", 0xffffff);
+        printf("%u\n", 0xffffffU);
+        printf("%li\n",0xffffffL);
+        printf("%lu\n",0xffffffUL);
+
+        
+        for(i=0;i<argc;i++)
+            printf("argv[%d] = \"%s\"\n",i,argv[i]);
+        for(i=0;user_info[i];i++)
+            printf("user_info[%d] = \"%s\"\n",i,user_info[i]);
+        
+        printf("getenv(\"USER\") = \"%s\"\n",getenv("USER"));
+        printf("getenv(\"HOME\") = \"%s\"\n",getenv("HOME"));
+        printf("getenv(\"TZ\") = \"%s\"\n",getenv("TZ"));
+    
+        time(&now);
+        tzset();
+        printf("%s %s %d\n",tzname[0],tzname[1],(int)_timezone);
+        
+        printf("Running ctime\n");
+        s = ctime(&now);
+        printf("ctime returned: %p\n",s);
+        printf("Current time: %s",s);
+        
+        printf("Trying to open /nonexistent\n");
+        fd = open("/nonexistent",O_RDONLY);
+        if(fd < 0) perror("open");
+        else close(fd);
+        
+        printf("Tyring to mkdir .mkdirtest\n");
+        if(mkdir(".mkdirtest",0700) < 0) perror("mkdir");
+        
+        printf("Trying to opendir /\n");
+        dir = opendir("/");
+        if(dir) {
+            while((dent=readdir(dir))!=NULL)
+                printf("\t[%s] %lu\n",dent->d_name,dent->d_ino);
+            closedir(dir);
+        } else {
+            perror("opendir");
+        }
+                
+    
+#if 0
+        printf("Sleeping...\n");
+        sleep(1);
+        printf("Done\n");
+#endif
+        
+        fd = open("test.txt",O_RDONLY);
+        if(fd != -1) {
+            printf("Opened test.txt\n");
+            n = read(fd,sbuf,sizeof(sbuf));
+            printf("n: %d\n",n);
+            if(n < 0) perror("read");
+            ubuf[n] = '\0';
+            printf("buf: %s\n",buf);
+            for(i=0;i<n/2;i++) {
+                printf("Char %d: [%x]\n",i,sbuf[i]);
+            }
+        }
+        
+        {
+            static double f = 1.574;
+            int n;
+            printf("%e\n",f);
+            f += 20.001;
+            f *= -2.0;
+            n = (int) f;
+            printf("%el\n",f);
+            printf("%d\n",n);
+            printf("%e\n",f);
+            printf("%e\n",fabs(f));
+        }
+    }
+        
+    printf("exiting\n");
+    return 0;
+}
+
+void suckram() {
+    int total = 0;
+    fprintf(stderr,"Eating up all available memory\n");
+    while(malloc(1024*1024) != NULL) total ++;
+    fprintf(stderr,"Ate up %d megs\n",total);
+}
+
+__attribute__((constructor)) static void my_ctor()  { printf("Constructor!\n"); }
+__attribute__((destructor)) static void my_dtor()  { printf("Destructor!\n"); }
+
+int callme(int a1,int a2, int a3, int a4, int a5, int a6)  __attribute__((section(".text")));
+int callme(int a1,int a2, int a3, int a4, int a5, int a6) {
+    printf("You said: %d %d %d %d %d %d\n",a1,a2,a3,a4,a5,a6);
+    return a1+a2+a3+a4+a5+a6;
+}
+
+void echo(const char *string, int count)  __attribute__((section(".text")));
+void echo(const char *string, int count) {
+    int i;
+    for(i=0;i<count;i++)
+        printf("%d: %s\n",i,string);
+}
+
+void backinmips()  __attribute__((section(".text")));
+void backinmips() {
+    fprintf(stderr,"In backinmips() in mips\n");
+}
diff --git a/src/tests/check.sh b/src/tests/check.sh
new file mode 100755 (executable)
index 0000000..1ea7ac0
--- /dev/null
@@ -0,0 +1,164 @@
+#!/bin/sh -e
+
+[ -z "$JAVA" ] && JAVA=java
+CLASSPATH="$(pwd)/build"; export CLASSPATH
+if [ "$1" != "running_from_make" ]; then
+       echo "Please don't run this scipt directly. Use make check" >&2
+       exit 1
+fi
+
+INT="$2"
+
+cd tmp
+
+if [ ! -e .skipmspack ]; then
+
+mkdir -p mspack
+cd mspack
+rm -f *.TTT *.inf FONTINST.EXE *.DLL *.TXT;
+for f in \
+    andale32.exe arial32.exe arialb32.exe comic32.exe courie32.exe georgi32.exe \
+    impact32.exe times32.exe trebuc32.exe verdan32.exe webdin32.exe; \
+do
+       [ -e "$f" ] || wget "http://dist.xwt.org/corefonts/$f" || rm -f "$f"
+       [ -e "$f" ] ||  exit 1
+done
+
+echo "Extracting MS Core Fonts using MSPackBench..."
+$JAVA tests.MSPackBench *32.exe
+
+cat <<EOF | md5sum -cv
+663974c9fe3ba55b228724fd4d4e445f  AndaleMo.TTF
+3e7043e8125f1c8998347310f2c315bc  AriBlk.TTF
+f11c0317db527bdd80fa0afa04703441  Arial.TTF
+34cd8fd9e4fae9f075d4c9a2c971d065  Arialbd.TTF
+a2b3bcdb39097b6aed17a766652b92b2  Arialbi.TTF
+25633f73d92a0646e733e50cf2cc3b07  Ariali.TTF
+a50f9c96a76356e3d01013e0b042989f  Comic.TTF
+81d64ec3675c4adc14e9ad2c5c8103a7  Comicbd.TTF
+f4b306eed95aa7d274840533be635532  Georgia.TTF
+c61b355a5811e56ed3d7cea5d67c900e  Georgiab.TTF
+1e4e5d1975bdf4a5c648afbf8872fa13  Georgiai.TTF
+e5d52bbfff45e1044381bacb7fc8e300  Georgiaz.TTF
+8fc622c3a2e2d992ec059cca61e3dfc0  Impact.TTF
+4f97f4d6ba74767259ccfb242ce0e3f7  Times.TTF
+ed6e29caf3843142d739232aa8642158  Timesbd.TTF
+6d2bd425ff00a79dd02e4c95f689861b  Timesbi.TTF
+957dd4f17296522dead302ab4fcdfa8d  Timesi.TTF
+055460df9ab3c8aadd3330bd30805f11  Trebucbd.ttf
+3ba52ab1fa0cd726e7868e9c6673902c  Verdana.TTF
+a2b4dc9afc18e76cfcaa0071fa7cd0da  Verdanab.TTF
+24b3a293c865a2c265280f017fb24ba5  Verdanai.TTF
+f7310c29df0070530c48a47f2dca9014  Verdanaz.TTF
+1a56b45a66b07b4c576d5ead048ed992  Webdings.TTF
+20f23317e90516cbb7d38bd53b3d1c5b  cour.ttf
+7d94f95bf383769b51379d095139f2d7  courbd.ttf
+da414c01f951b020bb09a4165d3fb5fa  courbi.ttf
+167e27add66e9e8eb0d28a1235dd3bda  couri.ttf
+70e7be8567bc05f771b59abd9d696407  trebuc.ttf
+fb5d68cb58c6ad7e88249d65f6900740  trebucbi.ttf
+8f308fe77b584e20b246aa1f8403d2e9  trebucit.ttf
+663974c9fe3ba55b228724fd4d4e445f  AndaleMo.TTF
+3e7043e8125f1c8998347310f2c315bc  AriBlk.TTF
+f11c0317db527bdd80fa0afa04703441  Arial.TTF
+34cd8fd9e4fae9f075d4c9a2c971d065  Arialbd.TTF
+a2b3bcdb39097b6aed17a766652b92b2  Arialbi.TTF
+25633f73d92a0646e733e50cf2cc3b07  Ariali.TTF
+a50f9c96a76356e3d01013e0b042989f  Comic.TTF
+81d64ec3675c4adc14e9ad2c5c8103a7  Comicbd.TTF
+f4b306eed95aa7d274840533be635532  Georgia.TTF
+c61b355a5811e56ed3d7cea5d67c900e  Georgiab.TTF
+1e4e5d1975bdf4a5c648afbf8872fa13  Georgiai.TTF
+e5d52bbfff45e1044381bacb7fc8e300  Georgiaz.TTF
+8fc622c3a2e2d992ec059cca61e3dfc0  Impact.TTF
+4f97f4d6ba74767259ccfb242ce0e3f7  Times.TTF
+ed6e29caf3843142d739232aa8642158  Timesbd.TTF
+6d2bd425ff00a79dd02e4c95f689861b  Timesbi.TTF
+957dd4f17296522dead302ab4fcdfa8d  Timesi.TTF
+055460df9ab3c8aadd3330bd30805f11  Trebucbd.ttf
+3ba52ab1fa0cd726e7868e9c6673902c  Verdana.TTF
+a2b4dc9afc18e76cfcaa0071fa7cd0da  Verdanab.TTF
+24b3a293c865a2c265280f017fb24ba5  Verdanai.TTF
+f7310c29df0070530c48a47f2dca9014  Verdanaz.TTF
+1a56b45a66b07b4c576d5ead048ed992  Webdings.TTF
+20f23317e90516cbb7d38bd53b3d1c5b  cour.ttf
+7d94f95bf383769b51379d095139f2d7  courbd.ttf
+da414c01f951b020bb09a4165d3fb5fa  courbi.ttf
+167e27add66e9e8eb0d28a1235dd3bda  couri.ttf
+70e7be8567bc05f771b59abd9d696407  trebuc.ttf
+fb5d68cb58c6ad7e88249d65f6900740  trebucbi.ttf
+8f308fe77b584e20b246aa1f8403d2e9  trebucit.ttf
+EOF
+
+echo "Core Fonts extracted successfully!"
+
+cd ..
+
+fi
+
+if [ ! -e .skipdjpeg ]; then
+echo "Decoding some jpegs with DJpeg..."
+
+rm -f *.tga
+
+[ -e banner.jpg ] || wget http://www.xwt.org/image/banner.jpg
+[ -e banner.jpg ] || exit 1
+
+$JAVA tests.DJpeg -targa -outfile thebride_1280.tga thebride_1280.jpg 
+echo "e90f6b915aee2fc0d2eb9fc60ace6203  thebride_1280.tga" | md5sum -cv
+
+$JAVA tests.DJpeg -targa -outfile banner.tga banner.jpg
+echo "4c7cc29ae2094191a9b0308cf9a04fbd  banner.tga" | md5sum -cv
+
+echo "JPEGs decoded successfully!"
+
+fi
+
+if [ ! -e .skipfreetype ]; then
+
+cd mspack
+
+echo "Rendering some fonts with FTBench..."
+if ! [ -e Verdana.TTF -a -e Arial.TTF -a -e Comic.TTF ]; then
+       echo "Can't find the corefonts - did the mspack test complete?"
+       exit 1
+fi
+
+rm -f *.render
+
+for f in Verdana.TTF Arial.TTF Comic.TTF; do
+       $JAVA tests.FTBench "$f" "$f".render
+done
+
+cat <<EOF|md5sum -cv
+e33b9db5a413af214b2524265af18026  Arial.TTF.render
+61dee4f697a61ebc1b47decbed04b2da  Comic.TTF.render
+d5a6d39a63e49c597ed860913e27d2bb  Verdana.TTF.render
+EOF
+
+echo "Fonts rendered successfully"
+cd ..
+
+fi
+
+if [ ! -e .skipgc ]; then
+
+echo "Running gctest from the boehm-gc library..."
+$JAVA tests.GCTest
+
+fi
+
+if [ ! -e .busybox -a -e ../build/tests/BusyBox.class ]; then
+       echo "Running busybox's md5sum command on some ttfs"
+       $JAVA tests.BusyBox ash -c "md5sum mspack/*.ttf > md5.1"
+       md5sum mspack/*.ttf > md5.2
+       cmp md5.1 md5.2 && echo "The BusyBox md5sum command and sh work properly!"
+fi
+
+cat <<EOF
+* * * * * * * * * * * * * * * * * * * * * 
+* All tests completed with no failures  *
+* * * * * * * * * * * * * * * * * * * * * 
+
+EOF
diff --git a/upstream/Makefile b/upstream/Makefile
new file mode 100644 (file)
index 0000000..d525669
--- /dev/null
@@ -0,0 +1,227 @@
+# Inspired by XWT's Makefile.upstream
+
+version_gcc = 3.3.3
+url_gcc-core = http://mirrors.rcn.net/pub/sourceware/gcc/releases/gcc-$(version_gcc)/gcc-core-$(version_gcc).tar.gz
+url_gcc-c++ = http://mirrors.rcn.net/pub/sourceware/gcc/releases/gcc-$(version_gcc)/gcc-g++-$(version_gcc).tar.gz
+patches_gcc = gcc-fixes.patch gcc-fdata-sections-bss.patch
+configure_gcc = --target=mips-unknown-elf --disable-threads --with-gnu-ld --with-gnu-as --with-newlib=yes --enable-sjlj-exceptions --enable-languages="c"
+configure_gcc_step2 = $(configure_gcc) --enable-languages="c,c++"
+
+version_binutils = 2.14
+url_binutils = ftp://ftp.gnu.org/gnu/binutils/binutils-$(version_binutils).tar.gz
+patches_binutils = binutils-no64.patch
+configure_binutils = --target=mips-unknown-elf
+
+version_newlib = 1.11.0
+url_newlib = http://mirrors.rcn.net/pub/sourceware/newlib/newlib-$(version_newlib).tar.gz
+patches_newlib = newlib-mips.patch newlib-tzset.patch newlib-malloc.patch
+configure_newlib = --enable-multilib --target=mips-unknown-elf
+
+url_openbsdglob = http://www.brianweb.net/xwt/openbsdglob.tar.gz
+url_regex = ftp://ftp.zoo.toronto.edu/pub/regex.shar
+
+version_bcel = 5.1
+url_bcel = http://mirrors.mix5.com/apache/jakarta/bcel/binaries/bcel-$(version_bcel).tar.gz
+
+.SECONDARY: # This is broken in gmake < 3.79.1
+
+upstream = $(shell pwd)
+root = $(shell dirname "`pwd`")
+prefix = $(upstream)/install
+
+PATH := $(prefix)/bin:$(PATH)
+export PATH
+
+# Solaris' patch doesn't work, use gnu patch on solaris
+PATCH = $(shell test `uname` = SunOS && echo gpatch || echo patch)
+
+tasks/full_toolchain: tasks/build_binutils tasks/build_gcc_step2 tasks/build_libc
+       touch $@
+
+tasks/build_gcc: tasks/build_binutils
+tasks/build_newlib: tasks/build_gcc
+
+tasks/build_libc: tasks/build_newlib tasks/build_regex tasks/build_openbsdglob
+       rm -f install/mips-unknown-elf/lib/crt0.o
+       ln -s $(root)/build/org/xwt/mips/crt0.o install/mips-unknown-elf/lib/crt0.o 
+       echo '#include <unistd.h>' > install/mips-unknown-elf/include/getopt.h
+       touch $@
+
+clean_%:
+       rm -rf "build/$(*)"*
+       rm -f "tasks/build_$*" "tasks/patch_$*" "tasks/extract_$*"
+
+tasks/download_%:
+       if [ -z "$(url_$*)" ]; then echo "No url for $*" >&2; false; fi
+       mkdir -p download
+       cd download && wget --passive-ftp -N $(url_$*)
+       touch $@
+
+tasks/download_gcc: tasks/download_gcc-core tasks/download_gcc-c++
+       touch $@
+
+tasks/extract_%: tasks/download_%
+       mkdir -p build
+       cd build && \
+               gzip -dc  ../download/$*-$(version_$*).tar.gz | tar xf - && \
+               rm -f $* && \
+               ln -s $*-$(version_$*) $*
+       touch $@
+
+tasks/extract_gcc: tasks/download_gcc
+       mkdir -p build
+       cd build && gzip -dc ../download/gcc-core-$(version_gcc).tar.gz | tar xf -
+       cd build && gzip -dc ../download/gcc-g++-$(version_gcc).tar.gz | tar xf -
+       touch $@
+
+tasks/patch_%: tasks/extract_%
+       cd build/$*-$(version_$*) &&  \
+       for p in $(patches_$*) end; do \
+               [ "$$p" = "end" ] || $(PATCH) -p0 < ../../patches/$$p || exit 1; \
+       done
+       touch $@
+
+tasks/build_%: tasks/patch_%
+       mkdir -p install
+       @[ "$*" = "newlib" ] && rm -f install/mips-unknown-elf/lib/crt0.o || true
+       mkdir -p build/$*-obj && cd build/$*-obj && \
+               ../$*-$(version_$*)/configure --prefix=$(prefix) $(configure_$*) && \
+               $(MAKE) TARGET_CFLAGS="$(MIPS_CFLAGS)" && \
+               $(MAKE) install
+       touch $@
+
+tasks/build_gcc_step2: tasks/patch_gcc tasks/build_libc
+       mkdir -p install
+       mkdir -p build/gcc-obj && cd build/gcc-obj && \
+               ../gcc-$(version_gcc)/configure --prefix=$(prefix) $(configure_gcc_step2) && \
+               $(MAKE) TARGET_CFLAGS="$(MIPS_CFLAGS)" && \
+               $(MAKE) install
+       touch $@
+
+tasks/build_openbsdglob: tasks/download_openbsdglob tasks/build_newlib
+       @mkdir -p install/mips-unknown-elf/{include,lib}
+       cd build && gzip -dc ../download/openbsdglob.tar.gz | tar xf -
+       cd build/openbsdglob && \
+               mips-unknown-elf-gcc '-Dissetugid()=0' -DARG_MAX=65536 $(MIPS_CFLAGS) -I. -c -o glob.o glob.c && \
+               mips-unknown-elf-gcc -O2 -Wall -Werror -I. -c -o fnmatch.o fnmatch.c && \
+               mips-unknown-elf-ar cr libglob.a *.o && \
+               mips-unknown-elf-ranlib libglob.a && \
+               cp *.h ../../install/mips-unknown-elf/include && \
+               cp *.a ../../install/mips-unknown-elf/lib
+       touch $@
+
+tasks/build_regex: tasks/download_regex tasks/build_newlib
+       @mkdir -p install/mips-unknown-elf/{include,lib}
+       mkdir -p build/regex build/regex/fake
+       cd build/regex && \
+               sh ../../download/regex.shar && \
+               make CC=mips-unknown-elf-gcc CFLAGS="-I. $(MIPS_CFLAGS)" regcomp.o regexec.o regerror.o regfree.o && \
+               mips-unknown-elf-ar cr libregex.a regcomp.o regexec.o regerror.o regfree.o && \
+               mips-unknown-elf-ranlib libregex.a && \
+               cp regex.h ../../install/mips-unknown-elf/include && \
+               cp libregex.a ../../install/mips-unknown-elf/lib 
+       touch $@
+
+
+#
+# Tests
+# These are simply here for convenience. They aren't required 
+# to build or run mips2java
+#
+
+tasks/build_freetype: tasks/full_toolchain
+tasks/build_libjpeg: tasks/full_toolchain
+tasks/build_boehmgc: tasks/full_toolchain
+tasks/build_libmspack: tasks/full_toolchain
+tasks/build_freetype: tasks/full_toolchain
+
+version_libjpeg = 6b
+url_libjpeg = http://www.ijg.org/files/jpegsrc.v$(version_libjpeg).tar.gz
+
+version_libmspack = 20030726
+url_libmspack = http://www.kyz.uklinux.net/downloads/libmspack-$(version_libmspack).tar.gz
+patches_libmspack = libmspack.patch
+
+version_freetype = 2.1.4
+url_freetype = http://umn.dl.sourceforge.net/sourceforge/freetype/freetype-$(version_freetype).tar.gz
+patches_freetype = freetype.patch ft-nostdio.patch
+
+version_boehmgc = 6.3alpha2
+url_boehmgc = http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc$(version_boehmgc).tar.gz
+patches_boehmgc = boehm-gc.patch
+
+version_busybox = 0.60.5
+url_busybox = http://busybox.net/downloads/busybox-$(version_busybox).tar.gz
+patches_busybox = busybox.patch
+
+
+tasks/extract_libjpeg: tasks/download_libjpeg
+       mkdir -p build
+       cd build && \
+               gzip -dc ../download/jpegsrc.v$(version_libjpeg).tar.gz | tar xf - && \
+               mv jpeg-$(version_libjpeg) libjpeg-$(version_libjpeg) && \
+               rm -f libjpeg && \
+               ln -s libjpeg-$(version_libjpeg)  libjpeg
+       touch $@    
+
+tasks/build_libjpeg: tasks/patch_libjpeg
+       cd build/libjpeg-$(version_libjpeg) && \
+               ./configure && \
+               make CC="mips-unknown-elf-gcc" \
+                       AR="mips-unknown-elf-ar rc" \
+                       AR2="mips-unknown-elf-ranlib" \
+                       CFLAGS="$(MIPS_CFLAGS)" \
+                       LDFLAGS="$(MIPS_LDFLAGS)"
+       touch $@    
+
+tasks/extract_libmspack: tasks/download_libmspack
+       mkdir -p build
+       cd build && \
+               gzip -dc ../download/libmspack-$(version_libmspack).tar.gz | tar xf - && \
+               mv libmspack libmspack-$(version_libmspack) && \
+               rm -f libmspack && \
+               ln -s libmspack-$(version_libmspack)  libmspack
+       touch $@    
+
+tasks/build_libmspack: tasks/patch_libmspack tasks/full_toolchain
+       cd build/libmspack-$(version_libmspack)/mspack && \
+               make CC="mips-unknown-elf-gcc" \
+                       AR="mips-unknown-elf-ar" \
+                       RANLIB="mips-unknown-elf-ranlib" \
+                       OPTIM="$(MIPS_CFLAGS)"
+       touch $@    
+
+tasks/build_freetype: tasks/patch_freetype tasks/full_toolchain
+       cd build/freetype-$(version_freetype) && \
+               $(MAKE) setup ansi && \
+               $(MAKE) CC="mips-unknown-elf-gcc" \
+                   CFLAGS="-c $(MIPS_CFLAGS)" \
+                       AR="mips-unknown-elf-ar" \
+                       RANLIB="mips-unknown-elf-ranlib" && \
+               mips-unknown-elf-ranlib objs/libfreetype.a
+       touch $@    
+
+tasks/extract_boehmgc: tasks/download_boehmgc
+       mkdir -p build
+       cd build && \
+               rm -rf gc$(version_boehmgc) && \
+               gzip -dc ../download/gc$(version_boehmgc).tar.gz | tar xf - && \
+               rm -f boehmgc boehmgc-$(version_boehmgc) && \
+               ln -s gc$(version_boehmgc)  boehmgc && \
+               ln -s gc$(version_boehmgc)  boehmgc-$(version_boehmgc)
+       touch $@
+
+tasks/build_boehmgc: tasks/patch_boehmgc tasks/full_toolchain
+       cd build/gc$(version_boehmgc) && \
+               CC="mips-unknown-elf-gcc" CFLAGS="$(MIPS_CFLAGS)" LDFLAGS="$(MIPS_LDFLAGS)" \
+               ./configure --host=mips-unknown-elf --disable-shared --disable-threads && \
+               make && \
+               make gctest 
+       touch $@
+
+tasks/build_busybox: tasks/patch_busybox tasks/full_toolchain
+       cd build && \
+               rm -f busybox && \
+               ln -s busybox-$(version_busybox) busybox
+       cd build/busybox && $(MAKE) SHELL=/bin/bash LDFLAGS="$(MIPS_LDFLAGS)" CFLAGS_EXTRA="$(MIPS_CFLAGS) -g"
+       touch $@
diff --git a/upstream/patches/binutils-no64.patch b/upstream/patches/binutils-no64.patch
new file mode 100644 (file)
index 0000000..ca684f9
--- /dev/null
@@ -0,0 +1,29 @@
+diff -ru ../binutils-2.14/bfd/config.bfd ./bfd/config.bfd
+--- ../binutils-2.14/bfd/config.bfd    Mon Jun  2 16:35:20 2003
++++ ./bfd/config.bfd   Mon Sep  1 01:06:32 2003
+@@ -777,6 +777,10 @@
+     targ_defvec=bfd_elf32_littlemips_vec
+     targ_selvecs="bfd_elf32_bigmips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec"
+     ;;
++  mips*-unknown-elf*)
++    targ_defvec=bfd_elf32_bigmips_vec
++    targ_selvecs=bfd_elf32_littlemips_vec
++    ;;
+   mips*-*-elf* | mips*-*-rtems* | mips*-*-vxworks*)
+     targ_defvec=bfd_elf32_bigmips_vec
+     targ_selvecs="bfd_elf32_littlemips_vec bfd_elf64_bigmips_vec bfd_elf64_littlemips_vec"
+Only in ./bfd: config.bfd.old
+Only in ./bfd: config.bfd~
+diff -ru ../binutils-2.14/ld/configure.tgt ./ld/configure.tgt
+--- ../binutils-2.14/ld/configure.tgt  Thu Jun 12 10:25:52 2003
++++ ./ld/configure.tgt Mon Sep  1 01:07:42 2003
+@@ -405,6 +405,7 @@
+ mips*vr5000el-*-elf*) targ_emul=elf32l4300 ;;
+ mips*vr5000-*-elf*)   targ_emul=elf32b4300 ;;
+ mips*el-*-elf*)               targ_emul=elf32elmip ;;
++mips*-unknown-elf*)     targ_emul=elf32ebmip ;;
+ mips*-*-elf*)         targ_emul=elf32ebmip ;;
+ mips*el-*-rtems*)     targ_emul=elf32elmip ;;
+ mips*-*-rtems*)               targ_emul=elf32ebmip ;;
+Only in ./ld: configure.tgt.old
+Only in ./ld: configure.tgt~
diff --git a/upstream/patches/boehm-gc.patch b/upstream/patches/boehm-gc.patch
new file mode 100644 (file)
index 0000000..48103d3
--- /dev/null
@@ -0,0 +1,2879 @@
+diff -ruN ../gc6.3alpha2/configure ./configure
+--- ../gc6.3alpha2/configure   Wed Oct  1 19:34:32 2003
++++ ./configure        Wed Nov 19 04:17:25 2003
+@@ -1,7 +1,7 @@
+ #! /bin/sh
+ # From configure.in Revision: 1.2 .
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.53 for gc 6.3alpha2.
++# Generated by GNU Autoconf 2.57 for gc 6.3alpha2.
+ #
+ # Report bugs to <Hans.Boehm@hp.com>.
+ #
+@@ -9,173 +9,6 @@
+ # Free Software Foundation, Inc.
+ # This configure script is free software; the Free Software Foundation
+ # gives unlimited permission to copy, distribute and modify it.
+-
+-# Find the correct PATH separator.  Usually this is `:', but
+-# DJGPP uses `;' like DOS.
+-if test "X${PATH_SEPARATOR+set}" != Xset; then
+-  UNAME=${UNAME-`uname 2>/dev/null`}
+-  case X$UNAME in
+-    *-DOS) lt_cv_sys_path_separator=';' ;;
+-    *)     lt_cv_sys_path_separator=':' ;;
+-  esac
+-  PATH_SEPARATOR=$lt_cv_sys_path_separator
+-fi
+-
+-
+-# Check that we are running under the correct shell.
+-SHELL=${CONFIG_SHELL-/bin/sh}
+-
+-case X$ECHO in
+-X*--fallback-echo)
+-  # Remove one level of quotation (which was required for Make).
+-  ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
+-  ;;
+-esac
+-
+-echo=${ECHO-echo}
+-if test "X$1" = X--no-reexec; then
+-  # Discard the --no-reexec flag, and continue.
+-  shift
+-elif test "X$1" = X--fallback-echo; then
+-  # Avoid inline document here, it may be left over
+-  :
+-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+-  # Yippee, $echo works!
+-  :
+-else
+-  # Restart under the correct shell.
+-  exec $SHELL "$0" --no-reexec ${1+"$@"}
+-fi
+-
+-if test "X$1" = X--fallback-echo; then
+-  # used as fallback echo
+-  shift
+-  cat <<EOF
+-
+-EOF
+-  exit 0
+-fi
+-
+-# The HP-UX ksh and POSIX shell print the target directory to stdout
+-# if CDPATH is set.
+-if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+-
+-if test -z "$ECHO"; then
+-if test "X${echo_test_string+set}" != Xset; then
+-# find a string as large as possible, as long as the shell can cope with it
+-  for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+-    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+-    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+-       echo_test_string="`eval $cmd`" &&
+-       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+-    then
+-      break
+-    fi
+-  done
+-fi
+-
+-if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+-   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+-   test "X$echo_testing_string" = "X$echo_test_string"; then
+-  :
+-else
+-  # The Solaris, AIX, and Digital Unix default echo programs unquote
+-  # backslashes.  This makes it impossible to quote backslashes using
+-  #   echo "$something" | sed 's/\\/\\\\/g'
+-  #
+-  # So, first we look for a working echo in the user's PATH.
+-
+-  IFS="${IFS=         }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+-  for dir in $PATH /usr/ucb; do
+-    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+-       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+-       echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+-       test "X$echo_testing_string" = "X$echo_test_string"; then
+-      echo="$dir/echo"
+-      break
+-    fi
+-  done
+-  IFS="$save_ifs"
+-
+-  if test "X$echo" = Xecho; then
+-    # We didn't find a better echo, so look for alternatives.
+-    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+-       echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+-       test "X$echo_testing_string" = "X$echo_test_string"; then
+-      # This shell has a builtin print -r that does the trick.
+-      echo='print -r'
+-    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+-       test "X$CONFIG_SHELL" != X/bin/ksh; then
+-      # If we have ksh, try running configure again with it.
+-      ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+-      export ORIGINAL_CONFIG_SHELL
+-      CONFIG_SHELL=/bin/ksh
+-      export CONFIG_SHELL
+-      exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+-    else
+-      # Try using printf.
+-      echo='printf %s\n'
+-      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+-       echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+-       test "X$echo_testing_string" = "X$echo_test_string"; then
+-      # Cool, printf works
+-      :
+-      elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+-         test "X$echo_testing_string" = 'X\t' &&
+-         echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+-         test "X$echo_testing_string" = "X$echo_test_string"; then
+-      CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+-      export CONFIG_SHELL
+-      SHELL="$CONFIG_SHELL"
+-      export SHELL
+-      echo="$CONFIG_SHELL $0 --fallback-echo"
+-      elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+-         test "X$echo_testing_string" = 'X\t' &&
+-         echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+-         test "X$echo_testing_string" = "X$echo_test_string"; then
+-      echo="$CONFIG_SHELL $0 --fallback-echo"
+-      else
+-      # maybe with a smaller string...
+-      prev=:
+-
+-      for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+-        if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+-        then
+-          break
+-        fi
+-        prev="$cmd"
+-      done
+-
+-      if test "$prev" != 'sed 50q "$0"'; then
+-        echo_test_string=`eval $prev`
+-        export echo_test_string
+-        exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+-      else
+-        # Oops.  We lost completely, so just stick with echo.
+-        echo=echo
+-      fi
+-      fi
+-    fi
+-  fi
+-fi
+-fi
+-
+-# Copy echo and quote the copy suitably for passing to libtool from
+-# the Makefile, instead of quoting the original, which is used later.
+-ECHO=$echo
+-if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+-   ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+-fi
+-
+-
+-
+-if expr a : '\(a\)' >/dev/null 2>&1; then
+-  as_expr=expr
+-else
+-  as_expr=false
+-fi
+-
+-
+ ## --------------------- ##
+ ## M4sh Initialization.  ##
+ ## --------------------- ##
+@@ -184,11 +17,13 @@
+ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+   emulate sh
+   NULLCMD=:
++  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
++  # is contrary to our usage.  Disable this feature.
++  alias -g '${1+"$@"}'='"$@"'
+ elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+   set -o posix
+ fi
+-# NLS nuisances.
+ # Support unset when possible.
+ if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+   as_unset=unset
+@@ -196,34 +31,42 @@
+   as_unset=false
+ fi
+-(set +x; test -n "`(LANG=C; export LANG) 2>&1`") &&
+-    { $as_unset LANG || test "${LANG+set}" != set; } ||
+-      { LANG=C; export LANG; }
+-(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") &&
+-    { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } ||
+-      { LC_ALL=C; export LC_ALL; }
+-(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") &&
+-    { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } ||
+-      { LC_TIME=C; export LC_TIME; }
+-(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") &&
+-    { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } ||
+-      { LC_CTYPE=C; export LC_CTYPE; }
+-(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") &&
+-    { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } ||
+-      { LANGUAGE=C; export LANGUAGE; }
+-(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") &&
+-    { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } ||
+-      { LC_COLLATE=C; export LC_COLLATE; }
+-(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") &&
+-    { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } ||
+-      { LC_NUMERIC=C; export LC_NUMERIC; }
+-(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") &&
+-    { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } ||
+-      { LC_MESSAGES=C; export LC_MESSAGES; }
++
++# Work around bugs in pre-3.0 UWIN ksh.
++$as_unset ENV MAIL MAILPATH
++PS1='$ '
++PS2='> '
++PS4='+ '
++
++# NLS nuisances.
++for as_var in \
++  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
++  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
++  LC_TELEPHONE LC_TIME
++do
++  if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
++    eval $as_var=C; export $as_var
++  else
++    $as_unset $as_var
++  fi
++done
++
++# Required to use basename.
++if expr a : '\(a\)' >/dev/null 2>&1; then
++  as_expr=expr
++else
++  as_expr=false
++fi
++
++if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
++  as_basename=basename
++else
++  as_basename=false
++fi
+ # Name of the executable.
+-as_me=`(basename "$0") 2>/dev/null ||
++as_me=`$as_basename "$0" ||
+ $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+@@ -234,6 +77,7 @@
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
++
+ # PATH needs CR, and LINENO needs CR and PATH.
+ # Avoid depending upon Character Ranges.
+ as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+@@ -244,15 +88,15 @@
+ # The user is always right.
+ if test "${PATH_SEPARATOR+set}" != set; then
+-  echo "#! /bin/sh" >conftest.sh
+-  echo  "exit 0"   >>conftest.sh
+-  chmod +x conftest.sh
+-  if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then
++  echo "#! /bin/sh" >conf$$.sh
++  echo  "exit 0"   >>conf$$.sh
++  chmod +x conf$$.sh
++  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+     PATH_SEPARATOR=';'
+   else
+     PATH_SEPARATOR=:
+   fi
+-  rm -f conftest.sh
++  rm -f conf$$.sh
+ fi
+@@ -300,6 +144,8 @@
+   as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+   test "x$as_lineno_1" != "x$as_lineno_2" &&
+   test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
++           $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
++           $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+@@ -372,6 +218,12 @@
+ fi
+ rm -f conf$$ conf$$.exe conf$$.file
++if mkdir -p . 2>/dev/null; then
++  as_mkdir_p=:
++else
++  as_mkdir_p=false
++fi
++
+ as_executable_p="test -f"
+ # Sed expression to map a string onto a valid CPP name.
+@@ -388,7 +240,166 @@
+ IFS="         $as_nl"
+ # CDPATH.
+-$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; }
++$as_unset CDPATH
++
++
++# Find the correct PATH separator.  Usually this is `:', but
++# DJGPP uses `;' like DOS.
++if test "X${PATH_SEPARATOR+set}" != Xset; then
++  UNAME=${UNAME-`uname 2>/dev/null`}
++  case X$UNAME in
++    *-DOS) lt_cv_sys_path_separator=';' ;;
++    *)     lt_cv_sys_path_separator=':' ;;
++  esac
++  PATH_SEPARATOR=$lt_cv_sys_path_separator
++fi
++
++
++# Check that we are running under the correct shell.
++SHELL=${CONFIG_SHELL-/bin/sh}
++
++case X$ECHO in
++X*--fallback-echo)
++  # Remove one level of quotation (which was required for Make).
++  ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
++  ;;
++esac
++
++echo=${ECHO-echo}
++if test "X$1" = X--no-reexec; then
++  # Discard the --no-reexec flag, and continue.
++  shift
++elif test "X$1" = X--fallback-echo; then
++  # Avoid inline document here, it may be left over
++  :
++elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
++  # Yippee, $echo works!
++  :
++else
++  # Restart under the correct shell.
++  exec $SHELL "$0" --no-reexec ${1+"$@"}
++fi
++
++if test "X$1" = X--fallback-echo; then
++  # used as fallback echo
++  shift
++  cat <<EOF
++
++EOF
++  exit 0
++fi
++
++# The HP-UX ksh and POSIX shell print the target directory to stdout
++# if CDPATH is set.
++if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
++
++if test -z "$ECHO"; then
++if test "X${echo_test_string+set}" != Xset; then
++# find a string as large as possible, as long as the shell can cope with it
++  for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
++    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
++    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
++       echo_test_string="`eval $cmd`" &&
++       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
++    then
++      break
++    fi
++  done
++fi
++
++if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
++   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
++   test "X$echo_testing_string" = "X$echo_test_string"; then
++  :
++else
++  # The Solaris, AIX, and Digital Unix default echo programs unquote
++  # backslashes.  This makes it impossible to quote backslashes using
++  #   echo "$something" | sed 's/\\/\\\\/g'
++  #
++  # So, first we look for a working echo in the user's PATH.
++
++  IFS="${IFS=         }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR
++  for dir in $PATH /usr/ucb; do
++    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
++       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
++       echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
++       test "X$echo_testing_string" = "X$echo_test_string"; then
++      echo="$dir/echo"
++      break
++    fi
++  done
++  IFS="$save_ifs"
++
++  if test "X$echo" = Xecho; then
++    # We didn't find a better echo, so look for alternatives.
++    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
++       echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
++       test "X$echo_testing_string" = "X$echo_test_string"; then
++      # This shell has a builtin print -r that does the trick.
++      echo='print -r'
++    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
++       test "X$CONFIG_SHELL" != X/bin/ksh; then
++      # If we have ksh, try running configure again with it.
++      ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
++      export ORIGINAL_CONFIG_SHELL
++      CONFIG_SHELL=/bin/ksh
++      export CONFIG_SHELL
++      exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
++    else
++      # Try using printf.
++      echo='printf %s\n'
++      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
++       echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
++       test "X$echo_testing_string" = "X$echo_test_string"; then
++      # Cool, printf works
++      :
++      elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
++         test "X$echo_testing_string" = 'X\t' &&
++         echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
++         test "X$echo_testing_string" = "X$echo_test_string"; then
++      CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
++      export CONFIG_SHELL
++      SHELL="$CONFIG_SHELL"
++      export SHELL
++      echo="$CONFIG_SHELL $0 --fallback-echo"
++      elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
++         test "X$echo_testing_string" = 'X\t' &&
++         echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
++         test "X$echo_testing_string" = "X$echo_test_string"; then
++      echo="$CONFIG_SHELL $0 --fallback-echo"
++      else
++      # maybe with a smaller string...
++      prev=:
++
++      for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
++        if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
++        then
++          break
++        fi
++        prev="$cmd"
++      done
++
++      if test "$prev" != 'sed 50q "$0"'; then
++        echo_test_string=`eval $prev`
++        export echo_test_string
++        exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
++      else
++        # Oops.  We lost completely, so just stick with echo.
++        echo=echo
++      fi
++      fi
++    fi
++  fi
++fi
++fi
++
++# Copy echo and quote the copy suitably for passing to libtool from
++# the Makefile, instead of quoting the original, which is used later.
++ECHO=$echo
++if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
++   ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
++fi
++
+ # Name of the host.
+@@ -402,6 +413,7 @@
+ # Initializations.
+ #
+ ac_default_prefix=/usr/local
++ac_config_libobj_dir=.
+ cross_compiling=no
+ subdirs=
+ MFLAGS=
+@@ -458,6 +470,8 @@
+ # include <unistd.h>
+ #endif"
++ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM AWK SET_MAKE GC_VERSION CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE CCAS CCASFLAGS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT GC_CFLAGS THREADLIBS POWERPC_DARWIN_TRUE POWERPC_DARWIN_FALSE EXTRA_TEST_LIBS target_all CPLUSPLUS_TRUE CPLUSPLUS_FALSE INCLUDES CXXINCLUDES addobjs addincludes addlibs addtests LN_S ECHO CPP EGREP LIBTOOL MY_CFLAGS USE_LIBDIR_TRUE USE_LIBDIR_FALSE LIBOBJS LTLIBOBJS'
++ac_subst_files=''
+ # Initialize some variables set by options.
+ ac_init_help=
+@@ -881,6 +895,9 @@
+    { (exit 1); exit 1; }; }
+   fi
+ fi
++(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
++  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
++   { (exit 1); exit 1; }; }
+ srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ ac_env_build_alias_set=${build_alias+set}
+ ac_env_build_alias_value=$build_alias
+@@ -1080,7 +1097,7 @@
+ # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+ # absolute.
+ ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+-ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd`
++ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+ ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+@@ -1107,7 +1124,7 @@
+ if $ac_init_version; then
+   cat <<\_ACEOF
+ gc configure 6.3alpha2
+-generated by GNU Autoconf 2.53
++generated by GNU Autoconf 2.57
+ Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+ Free Software Foundation, Inc.
+@@ -1122,7 +1139,7 @@
+ running configure, to aid debugging if configure makes a mistake.
+ It was created by gc $as_me 6.3alpha2, which was
+-generated by GNU Autoconf 2.53.  Invocation command line was
++generated by GNU Autoconf 2.57.  Invocation command line was
+   $ $0 $@
+@@ -1174,27 +1191,54 @@
+ # Keep a trace of the command line.
+ # Strip out --no-create and --no-recursion so they do not pile up.
++# Strip out --silent because we don't want to record it for future runs.
+ # Also quote any args containing shell meta-characters.
++# Make two passes to allow for proper duplicate-argument suppression.
+ ac_configure_args=
++ac_configure_args0=
++ac_configure_args1=
+ ac_sep=
+-for ac_arg
++ac_must_keep_next=false
++for ac_pass in 1 2
+ do
+-  case $ac_arg in
+-  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+-  | --no-cr | --no-c | -n ) continue ;;
+-  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+-  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+-    continue ;;
+-  *" "*|*"    "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+-    ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+-  esac
+-  case " $ac_configure_args " in
+-    *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+-    *) ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+-       ac_sep=" " ;;
+-  esac
+-  # Get rid of the leading space.
++  for ac_arg
++  do
++    case $ac_arg in
++    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
++    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
++    | -silent | --silent | --silen | --sile | --sil)
++      continue ;;
++    *" "*|*"  "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
++      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
++    esac
++    case $ac_pass in
++    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
++    2)
++      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
++      if test $ac_must_keep_next = true; then
++        ac_must_keep_next=false # Got value, back to normal.
++      else
++        case $ac_arg in
++          *=* | --config-cache | -C | -disable-* | --disable-* \
++          | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
++          | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
++          | -with-* | --with-* | -without-* | --without-* | --x)
++            case "$ac_configure_args0 " in
++              "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
++            esac
++            ;;
++          -* ) ac_must_keep_next=true ;;
++        esac
++      fi
++      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
++      # Get rid of the leading space.
++      ac_sep=" "
++      ;;
++    esac
++  done
+ done
++$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
++$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+ # When interrupted or exit'd, cleanup temporary files, and complete
+ # config.log.  We remove comments because anyway the quotes in there
+@@ -1205,6 +1249,7 @@
+   # Save into config.log some information that might help in debugging.
+   {
+     echo
++
+     cat <<\_ASBOX
+ ## ---------------- ##
+ ## Cache variables. ##
+@@ -1227,6 +1272,35 @@
+     esac;
+ }
+     echo
++
++    cat <<\_ASBOX
++## ----------------- ##
++## Output variables. ##
++## ----------------- ##
++_ASBOX
++    echo
++    for ac_var in $ac_subst_vars
++    do
++      eval ac_val=$`echo $ac_var`
++      echo "$ac_var='"'"'$ac_val'"'"'"
++    done | sort
++    echo
++
++    if test -n "$ac_subst_files"; then
++      cat <<\_ASBOX
++## ------------- ##
++## Output files. ##
++## ------------- ##
++_ASBOX
++      echo
++      for ac_var in $ac_subst_files
++      do
++      eval ac_val=$`echo $ac_var`
++        echo "$ac_var='"'"'$ac_val'"'"'"
++      done | sort
++      echo
++    fi
++
+     if test -s confdefs.h; then
+       cat <<\_ASBOX
+ ## ----------- ##
+@@ -1234,7 +1308,7 @@
+ ## ----------- ##
+ _ASBOX
+       echo
+-      sed "/^$/d" confdefs.h
++      sed "/^$/d" confdefs.h | sort
+       echo
+     fi
+     test "$ac_signal" != 0 &&
+@@ -1399,6 +1473,7 @@
++
+     ## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)?
+ ac_aux_dir=
+@@ -1743,15 +1818,15 @@
+   test -n "$AWK" && break
+ done
+-echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5
+-echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6
++echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
++echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+ set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
+ if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+   echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+   cat >conftest.make <<\_ACEOF
+ all:
+-      @echo 'ac_maketemp="${MAKE}"'
++      @echo 'ac_maketemp="$(MAKE)"'
+ _ACEOF
+ # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+ eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+@@ -2116,9 +2191,7 @@
+     # However, it has the same basename, so the bogon will be chosen
+     # first if we set CC to just the basename; use the full file name.
+     shift
+-    set dummy "$as_dir/$ac_word" ${1+"$@"}
+-    shift
+-    ac_cv_prog_CC="$@"
++    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+   fi
+ fi
+ fi
+@@ -2223,8 +2296,10 @@
+ fi
+-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH" >&5
+-echo "$as_me: error: no acceptable C compiler found in \$PATH" >&2;}
++test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
++See \`config.log' for more details." >&5
++echo "$as_me: error: no acceptable C compiler found in \$PATH
++See \`config.log' for more details." >&2;}
+    { (exit 1); exit 1; }; }
+ # Provide some information about the compiler.
+@@ -2249,14 +2324,12 @@
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -2266,7 +2339,7 @@
+ }
+ _ACEOF
+ ac_clean_files_save=$ac_clean_files
+-ac_clean_files="$ac_clean_files a.out a.exe"
++ac_clean_files="$ac_clean_files a.out a.exe b.out"
+ # Try to create an executable without -o first, disregard a.out.
+ # It will help us diagnose broken compilers, and finding out an intuition
+ # of exeext.
+@@ -2285,26 +2358,39 @@
+ # Be careful to initialize this variable, since it used to be cached.
+ # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ ac_cv_exeext=
+-for ac_file in `ls a_out.exe a.exe conftest.exe 2>/dev/null;
+-                ls a.out conftest 2>/dev/null;
+-                ls a.* conftest.* 2>/dev/null`; do
++# b.out is created by i960 compilers.
++for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
++do
++  test -f "$ac_file" || continue
+   case $ac_file in
+-    *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb | *.xSYM ) ;;
+-    a.out ) # We found the default executable, but exeext='' is most
+-            # certainly right.
+-            break;;
+-    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+-          # FIXME: I believe we export ac_cv_exeext for Libtool --akim.
+-          export ac_cv_exeext
+-          break;;
+-    * ) break;;
++    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
++        ;;
++    conftest.$ac_ext )
++        # This is the source file.
++        ;;
++    [ab].out )
++        # We found the default executable, but exeext='' is most
++        # certainly right.
++        break;;
++    *.* )
++        ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
++        # FIXME: I believe we export ac_cv_exeext for Libtool,
++        # but it would be cool to find out if it's true.  Does anybody
++        # maintain Libtool? --akim.
++        export ac_cv_exeext
++        break;;
++    * )
++        break;;
+   esac
+ done
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
+-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables" >&5
+-echo "$as_me: error: C compiler cannot create executables" >&2;}
++sed 's/^/| /' conftest.$ac_ext >&5
++
++{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
++See \`config.log' for more details." >&5
++echo "$as_me: error: C compiler cannot create executables
++See \`config.log' for more details." >&2;}
+    { (exit 77); exit 77; }; }
+ fi
+@@ -2331,9 +2417,11 @@
+       cross_compiling=yes
+     else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+-If you meant to cross compile, use \`--host'." >&5
++If you meant to cross compile, use \`--host'.
++See \`config.log' for more details." >&5
+ echo "$as_me: error: cannot run C compiled programs.
+-If you meant to cross compile, use \`--host'." >&2;}
++If you meant to cross compile, use \`--host'.
++See \`config.log' for more details." >&2;}
+    { (exit 1); exit 1; }; }
+     fi
+   fi
+@@ -2341,7 +2429,7 @@
+ echo "$as_me:$LINENO: result: yes" >&5
+ echo "${ECHO_T}yes" >&6
+-rm -f a.out a.exe conftest$ac_cv_exeext
++rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ ac_clean_files=$ac_clean_files_save
+ # Check the compiler produces executables we can run.  If not, either
+ # the compiler is broken, or we cross compile.
+@@ -2361,9 +2449,10 @@
+ # catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+ # work properly (i.e., refer to `conftest.exe'), while it won't with
+ # `rm'.
+-for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do
++for ac_file in conftest.exe conftest conftest.*; do
++  test -f "$ac_file" || continue
+   case $ac_file in
+-    *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;;
++    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+     *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+           export ac_cv_exeext
+           break;;
+@@ -2371,8 +2460,10 @@
+   esac
+ done
+ else
+-  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link" >&5
+-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link" >&2;}
++  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
++See \`config.log' for more details." >&5
++echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
++See \`config.log' for more details." >&2;}
+    { (exit 1); exit 1; }; }
+ fi
+@@ -2390,14 +2481,12 @@
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -2414,16 +2503,19 @@
+   (exit $ac_status); }; then
+   for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+   case $ac_file in
+-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb ) ;;
++    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+     *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+        break;;
+   esac
+ done
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
+-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile" >&5
+-echo "$as_me: error: cannot compute suffix of object files: cannot compile" >&2;}
++sed 's/^/| /' conftest.$ac_ext >&5
++
++{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
++See \`config.log' for more details." >&5
++echo "$as_me: error: cannot compute suffix of object files: cannot compile
++See \`config.log' for more details." >&2;}
+    { (exit 1); exit 1; }; }
+ fi
+@@ -2440,14 +2532,12 @@
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -2474,7 +2564,8 @@
+   ac_compiler_gnu=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_compiler_gnu=no
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+@@ -2494,14 +2585,12 @@
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -2525,7 +2614,8 @@
+   ac_cv_prog_cc_g=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_cv_prog_cc_g=no
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+@@ -2547,6 +2637,102 @@
+     CFLAGS=
+   fi
+ fi
++echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
++echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
++if test "${ac_cv_prog_cc_stdc+set}" = set; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  ac_cv_prog_cc_stdc=no
++ac_save_CC=$CC
++cat >conftest.$ac_ext <<_ACEOF
++#line $LINENO "configure"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++#include <stdarg.h>
++#include <stdio.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
++struct buf { int x; };
++FILE * (*rcsopen) (struct buf *, struct stat *, int);
++static char *e (p, i)
++     char **p;
++     int i;
++{
++  return p[i];
++}
++static char *f (char * (*g) (char **, int), char **p, ...)
++{
++  char *s;
++  va_list v;
++  va_start (v,p);
++  s = g (p, va_arg (v,int));
++  va_end (v);
++  return s;
++}
++int test (int i, double x);
++struct s1 {int (*f) (int a);};
++struct s2 {int (*f) (double a);};
++int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
++int argc;
++char **argv;
++int
++main ()
++{
++return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
++  ;
++  return 0;
++}
++_ACEOF
++# Don't try gcc -ansi; that turns off useful extensions and
++# breaks some systems' header files.
++# AIX                 -qlanglvl=ansi
++# Ultrix and OSF/1    -std1
++# HP-UX 10.20 and later       -Ae
++# HP-UX older versions        -Aa -D_HPUX_SOURCE
++# SVR4                        -Xc -D__EXTENSIONS__
++for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
++do
++  CC="$ac_save_CC $ac_arg"
++  rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++  (eval $ac_compile) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } &&
++         { ac_try='test -s conftest.$ac_objext'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; }; then
++  ac_cv_prog_cc_stdc=$ac_arg
++break
++else
++  echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++fi
++rm -f conftest.$ac_objext
++done
++rm -f conftest.$ac_ext conftest.$ac_objext
++CC=$ac_save_CC
++
++fi
++
++case "x$ac_cv_prog_cc_stdc" in
++  x|xno)
++    echo "$as_me:$LINENO: result: none needed" >&5
++echo "${ECHO_T}none needed" >&6 ;;
++  *)
++    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
++echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
++    CC="$CC $ac_cv_prog_cc_stdc" ;;
++esac
++
+ # Some people use a C++ compiler to compile C.  Since we use `exit',
+ # in C++ we need to declare it.  In case someone uses the same compiler
+ # for both compiling C and C++ we need to have the C++ compiler decide
+@@ -2579,15 +2765,13 @@
+ do
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ #include <stdlib.h>
+ $ac_declaration
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -2611,20 +2795,19 @@
+   :
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ continue
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ $ac_declaration
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -2648,7 +2831,8 @@
+   break
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+ done
+@@ -2661,7 +2845,8 @@
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+ ac_ext=c
+@@ -2680,7 +2865,7 @@
+ rmdir .deps 2>/dev/null
+-ac_config_commands="$ac_config_commands depfiles"
++          ac_config_commands="$ac_config_commands depfiles"
+ am_make=${MAKE-make}
+@@ -2932,14 +3117,12 @@
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -2966,7 +3149,8 @@
+   ac_compiler_gnu=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_compiler_gnu=no
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+@@ -2986,14 +3170,12 @@
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -3017,7 +3199,8 @@
+   ac_cv_prog_cxx_g=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_cv_prog_cxx_g=no
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+@@ -3050,15 +3233,13 @@
+ do
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ #include <stdlib.h>
+ $ac_declaration
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -3082,20 +3263,19 @@
+   :
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ continue
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ $ac_declaration
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -3119,7 +3299,8 @@
+   break
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+ done
+@@ -3751,7 +3932,11 @@
+ LIBS="-ldl  $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ /* Override any gcc2 internal prototype to avoid an error.  */
+ #ifdef __cplusplus
+@@ -3760,12 +3945,6 @@
+ /* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+ char dlopen ();
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -3789,7 +3968,8 @@
+   ac_cv_lib_dl_dlopen=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_cv_lib_dl_dlopen=no
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+@@ -3936,6 +4116,13 @@
+     ;;
+  mips*-*-linux*)
+     ;;
++ mips-unknown-elf*)
++    machdep="mips2java_mach_dep.lo"
++    cat >>confdefs.h <<\_ACEOF
++#define MIPS2JAVA 1
++_ACEOF
++
++    ;;
+  mips-*-*)
+     machdep="mips_sgi_mach_dep.lo"
+     cat >>confdefs.h <<\_ACEOF
+@@ -4595,18 +4782,28 @@
+ do
+   # Use a header file that comes with gcc, so configuring glibc
+   # with a fresh cross-compiler works.
++  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++  # <limits.h> exists even on freestanding compilers.
+   # On the NeXT, cc -E runs the code through the compiler's parser,
+   # not just through cpp. "Syntax error" is here to catch this case.
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
+-#include <assert.h>
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#endif
+                      Syntax error
+ _ACEOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+   ac_status=$?
+-  egrep -v '^ *\+' conftest.er1 >conftest.err
++  grep -v '^ *+' conftest.er1 >conftest.err
+   rm -f conftest.er1
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+@@ -4623,7 +4820,8 @@
+   :
+ else
+   echo "$as_me: failed program was:" >&5
+-  cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+   # Broken: fails on valid input.
+ continue
+ fi
+@@ -4633,13 +4831,17 @@
+   # can be detected and how.
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ #include <ac_nonexistent.h>
+ _ACEOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+   ac_status=$?
+-  egrep -v '^ *\+' conftest.er1 >conftest.err
++  grep -v '^ *+' conftest.er1 >conftest.err
+   rm -f conftest.er1
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+@@ -4657,7 +4859,8 @@
+ continue
+ else
+   echo "$as_me: failed program was:" >&5
+-  cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+   # Passes both tests.
+ ac_preproc_ok=:
+ break
+@@ -4686,18 +4889,28 @@
+ do
+   # Use a header file that comes with gcc, so configuring glibc
+   # with a fresh cross-compiler works.
++  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++  # <limits.h> exists even on freestanding compilers.
+   # On the NeXT, cc -E runs the code through the compiler's parser,
+   # not just through cpp. "Syntax error" is here to catch this case.
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
+-#include <assert.h>
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#endif
+                      Syntax error
+ _ACEOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+   ac_status=$?
+-  egrep -v '^ *\+' conftest.er1 >conftest.err
++  grep -v '^ *+' conftest.er1 >conftest.err
+   rm -f conftest.er1
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+@@ -4714,7 +4927,8 @@
+   :
+ else
+   echo "$as_me: failed program was:" >&5
+-  cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+   # Broken: fails on valid input.
+ continue
+ fi
+@@ -4724,13 +4938,17 @@
+   # can be detected and how.
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ #include <ac_nonexistent.h>
+ _ACEOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+   ac_status=$?
+-  egrep -v '^ *\+' conftest.er1 >conftest.err
++  grep -v '^ *+' conftest.er1 >conftest.err
+   rm -f conftest.er1
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+@@ -4748,7 +4966,8 @@
+ continue
+ else
+   echo "$as_me: failed program was:" >&5
+-  cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+   # Passes both tests.
+ ac_preproc_ok=:
+ break
+@@ -4761,8 +4980,10 @@
+ if $ac_preproc_ok; then
+   :
+ else
+-  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check" >&5
+-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;}
++  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
++See \`config.log' for more details." >&5
++echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
++See \`config.log' for more details." >&2;}
+    { (exit 1); exit 1; }; }
+ fi
+@@ -4773,6 +4994,21 @@
+ ac_compiler_gnu=$ac_cv_c_compiler_gnu
++echo "$as_me:$LINENO: checking for egrep" >&5
++echo $ECHO_N "checking for egrep... $ECHO_C" >&6
++if test "${ac_cv_prog_egrep+set}" = set; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
++    then ac_cv_prog_egrep='grep -E'
++    else ac_cv_prog_egrep='egrep'
++    fi
++fi
++echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
++echo "${ECHO_T}$ac_cv_prog_egrep" >&6
++ EGREP=$ac_cv_prog_egrep
++
++
+ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+ echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+ if test "${ac_cv_header_stdc+set}" = set; then
+@@ -4780,48 +5016,59 @@
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ #include <stdlib.h>
+ #include <stdarg.h>
+ #include <string.h>
+ #include <float.h>
++int
++main ()
++{
++
++  ;
++  return 0;
++}
+ _ACEOF
+-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
++rm -f conftest.$ac_objext
++if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++  (eval $ac_compile) 2>&5
+   ac_status=$?
+-  egrep -v '^ *\+' conftest.er1 >conftest.err
+-  rm -f conftest.er1
+-  cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+-  (exit $ac_status); } >/dev/null; then
+-  if test -s conftest.err; then
+-    ac_cpp_err=$ac_c_preproc_warn_flag
+-  else
+-    ac_cpp_err=
+-  fi
+-else
+-  ac_cpp_err=yes
+-fi
+-if test -z "$ac_cpp_err"; then
++  (exit $ac_status); } &&
++         { ac_try='test -s conftest.$ac_objext'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; }; then
+   ac_cv_header_stdc=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-  cat conftest.$ac_ext >&5
+-  ac_cv_header_stdc=no
++sed 's/^/| /' conftest.$ac_ext >&5
++
++ac_cv_header_stdc=no
+ fi
+-rm -f conftest.err conftest.$ac_ext
++rm -f conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_header_stdc = yes; then
+   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ #include <string.h>
+ _ACEOF
+ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+-  egrep "memchr" >/dev/null 2>&1; then
++  $EGREP "memchr" >/dev/null 2>&1; then
+   :
+ else
+   ac_cv_header_stdc=no
+@@ -4834,12 +5081,16 @@
+   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ #include <stdlib.h>
+ _ACEOF
+ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+-  egrep "free" >/dev/null 2>&1; then
++  $EGREP "free" >/dev/null 2>&1; then
+   :
+ else
+   ac_cv_header_stdc=no
+@@ -4855,13 +5106,18 @@
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ #include <ctype.h>
+ #if ((' ' & 0x0FF) == 0x020)
+ # define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+ # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+ #else
+-# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \
++# define ISLOWER(c) \
++                   (('a' <= (c) && (c) <= 'i') \
+                      || ('j' <= (c) && (c) <= 'r') \
+                      || ('s' <= (c) && (c) <= 'z'))
+ # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+@@ -4894,11 +5150,12 @@
+ else
+   echo "$as_me: program exited with status $ac_status" >&5
+ echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ( exit $ac_status )
+ ac_cv_header_stdc=no
+ fi
+-rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
++rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+ fi
+ fi
+ fi
+@@ -4933,7 +5190,11 @@
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ $ac_includes_default
+ #include <$ac_header>
+@@ -4953,7 +5214,8 @@
+   eval "$as_ac_Header=yes"
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ eval "$as_ac_Header=no"
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+@@ -4988,7 +5250,11 @@
+ echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ $ac_includes_default
+ #include <$ac_header>
+ _ACEOF
+@@ -5007,7 +5273,8 @@
+   ac_header_compiler=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_header_compiler=no
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+@@ -5019,13 +5286,17 @@
+ echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ #include <$ac_header>
+ _ACEOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+   ac_status=$?
+-  egrep -v '^ *\+' conftest.er1 >conftest.err
++  grep -v '^ *+' conftest.er1 >conftest.err
+   rm -f conftest.er1
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+@@ -5042,7 +5313,8 @@
+   ac_header_preproc=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-  cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+   ac_header_preproc=no
+ fi
+ rm -f conftest.err conftest.$ac_ext
+@@ -5055,14 +5327,32 @@
+     { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+ echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+     { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
++echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
++    (
++      cat <<\_ASBOX
++## ------------------------------------ ##
++## Report this to bug-autoconf@gnu.org. ##
++## ------------------------------------ ##
++_ASBOX
++    ) |
++      sed "s/^/$as_me: WARNING:     /" >&2
++    ;;
+   no:yes )
+     { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+ echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+     { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+ echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+     { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
++echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
++    (
++      cat <<\_ASBOX
++## ------------------------------------ ##
++## Report this to bug-autoconf@gnu.org. ##
++## ------------------------------------ ##
++_ASBOX
++    ) |
++      sed "s/^/$as_me: WARNING:     /" >&2
++    ;;
+ esac
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+ echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+@@ -5403,7 +5693,7 @@
+ case $host in
+ *-*-irix6*)
+   # Find out which ABI we are using.
+-  echo '#line 5406 "configure"' > conftest.$ac_ext
++  echo '#line 5696 "configure"' > conftest.$ac_ext
+   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+   (eval $ac_compile) 2>&5
+   ac_status=$?
+@@ -5443,14 +5733,12 @@
+      cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -5474,7 +5762,8 @@
+   lt_cv_cc_needs_belf=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ lt_cv_cc_needs_belf=no
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+@@ -5777,14 +6066,12 @@
+     CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
+     cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -5823,7 +6110,8 @@
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+       lt_cv_prog_cc_pic_works=no
+ fi
+@@ -5866,14 +6154,12 @@
+   LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -5897,7 +6183,8 @@
+   lt_cv_prog_cc_static_works=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+   LDFLAGS="$save_LDFLAGS"
+@@ -5939,7 +6226,7 @@
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+ compiler_c_o=no
+-if { (eval echo configure:5942: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
++if { (eval echo configure:6229: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+   # The compiler can only warn and ignore the option if not recognized
+   # So say no if there are warnings
+   if test -s out/conftest.err; then
+@@ -5981,14 +6268,12 @@
+   ac_objext=lo
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -6019,7 +6304,8 @@
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+   ac_objext="$save_objext"
+@@ -6067,14 +6353,12 @@
+   compiler_rtti_exceptions=no
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -6105,7 +6389,8 @@
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+   CFLAGS="$save_CFLAGS"
+@@ -7326,37 +7611,44 @@
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ /* System header to define __stub macros and hopefully few prototypes,
+-    which can conflict with char shl_load (); below.  */
+-#include <assert.h>
++    which can conflict with char shl_load (); below.
++    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++    <limits.h> exists even on freestanding compilers.  */
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#endif
+ /* Override any gcc2 internal prototype to avoid an error.  */
+ #ifdef __cplusplus
+ extern "C"
++{
+ #endif
+ /* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+ char shl_load ();
+-char (*f) ();
+-
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+-int
+-main ()
+-{
+ /* The GNU C library defines this for functions which it implements
+     to always fail with ENOSYS.  Some functions are actually named
+     something starting with __ and the normal name is an alias.  */
+ #if defined (__stub_shl_load) || defined (__stub___shl_load)
+ choke me
+ #else
+-f = shl_load;
++char (*f) () = shl_load;
++#endif
++#ifdef __cplusplus
++}
+ #endif
++int
++main ()
++{
++return f != shl_load;
+   ;
+   return 0;
+ }
+@@ -7376,7 +7668,8 @@
+   ac_cv_func_shl_load=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_cv_func_shl_load=no
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+@@ -7395,7 +7688,11 @@
+ LIBS="-ldld  $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ /* Override any gcc2 internal prototype to avoid an error.  */
+ #ifdef __cplusplus
+@@ -7404,12 +7701,6 @@
+ /* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+ char shl_load ();
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -7433,7 +7724,8 @@
+   ac_cv_lib_dld_shl_load=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_cv_lib_dld_shl_load=no
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+@@ -7451,37 +7743,44 @@
+ else
+   cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ /* System header to define __stub macros and hopefully few prototypes,
+-    which can conflict with char dlopen (); below.  */
+-#include <assert.h>
++    which can conflict with char dlopen (); below.
++    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++    <limits.h> exists even on freestanding compilers.  */
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#endif
+ /* Override any gcc2 internal prototype to avoid an error.  */
+ #ifdef __cplusplus
+ extern "C"
++{
+ #endif
+ /* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+ char dlopen ();
+-char (*f) ();
+-
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+-int
+-main ()
+-{
+ /* The GNU C library defines this for functions which it implements
+     to always fail with ENOSYS.  Some functions are actually named
+     something starting with __ and the normal name is an alias.  */
+ #if defined (__stub_dlopen) || defined (__stub___dlopen)
+ choke me
+ #else
+-f = dlopen;
++char (*f) () = dlopen;
++#endif
++#ifdef __cplusplus
++}
+ #endif
++int
++main ()
++{
++return f != dlopen;
+   ;
+   return 0;
+ }
+@@ -7501,7 +7800,8 @@
+   ac_cv_func_dlopen=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_cv_func_dlopen=no
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+@@ -7520,7 +7820,11 @@
+ LIBS="-ldl  $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ /* Override any gcc2 internal prototype to avoid an error.  */
+ #ifdef __cplusplus
+@@ -7529,12 +7833,6 @@
+ /* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+ char dlopen ();
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -7558,7 +7856,8 @@
+   ac_cv_lib_dl_dlopen=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_cv_lib_dl_dlopen=no
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+@@ -7578,7 +7877,11 @@
+ LIBS="-lsvld  $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ /* Override any gcc2 internal prototype to avoid an error.  */
+ #ifdef __cplusplus
+@@ -7587,12 +7890,6 @@
+ /* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+ char dlopen ();
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -7616,7 +7913,8 @@
+   ac_cv_lib_svld_dlopen=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_cv_lib_svld_dlopen=no
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+@@ -7636,7 +7934,11 @@
+ LIBS="-ldld  $LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ /* Override any gcc2 internal prototype to avoid an error.  */
+ #ifdef __cplusplus
+@@ -7645,12 +7947,6 @@
+ /* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+ char dld_link ();
+-#ifdef F77_DUMMY_MAIN
+-#  ifdef __cplusplus
+-     extern "C"
+-#  endif
+-   int F77_DUMMY_MAIN() { return 1; }
+-#endif
+ int
+ main ()
+ {
+@@ -7674,7 +7970,8 @@
+   ac_cv_lib_dld_dld_link=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_cv_lib_dld_dld_link=no
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+@@ -7732,7 +8029,7 @@
+     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+   lt_status=$lt_dlunknown
+   cat > conftest.$ac_ext <<EOF
+-#line 7735 "configure"
++#line 8032 "configure"
+ #include "confdefs.h"
+ #if HAVE_DLFCN_H
+@@ -7830,7 +8127,7 @@
+     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+   lt_status=$lt_dlunknown
+   cat > conftest.$ac_ext <<EOF
+-#line 7833 "configure"
++#line 8130 "configure"
+ #include "confdefs.h"
+ #if HAVE_DLFCN_H
+@@ -8575,7 +8872,11 @@
+ echo $ECHO_N "checking sys/dg_sys_info.h usability... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ $ac_includes_default
+ #include <sys/dg_sys_info.h>
+ _ACEOF
+@@ -8594,7 +8895,8 @@
+   ac_header_compiler=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+ ac_header_compiler=no
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+@@ -8606,13 +8908,17 @@
+ echo $ECHO_N "checking sys/dg_sys_info.h presence... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+-#include "confdefs.h"
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
+ #include <sys/dg_sys_info.h>
+ _ACEOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+   ac_status=$?
+-  egrep -v '^ *\+' conftest.er1 >conftest.err
++  grep -v '^ *+' conftest.er1 >conftest.err
+   rm -f conftest.er1
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+@@ -8629,7 +8935,8 @@
+   ac_header_preproc=yes
+ else
+   echo "$as_me: failed program was:" >&5
+-  cat conftest.$ac_ext >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
+   ac_header_preproc=no
+ fi
+ rm -f conftest.err conftest.$ac_ext
+@@ -8642,14 +8949,32 @@
+     { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: accepted by the compiler, rejected by the preprocessor!" >&5
+ echo "$as_me: WARNING: sys/dg_sys_info.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+     { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&5
+-echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&2;};;
++echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&2;}
++    (
++      cat <<\_ASBOX
++## ------------------------------------ ##
++## Report this to bug-autoconf@gnu.org. ##
++## ------------------------------------ ##
++_ASBOX
++    ) |
++      sed "s/^/$as_me: WARNING:     /" >&2
++    ;;
+   no:yes )
+     { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: present but cannot be compiled" >&5
+ echo "$as_me: WARNING: sys/dg_sys_info.h: present but cannot be compiled" >&2;}
+     { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: check for missing prerequisite headers?" >&5
+ echo "$as_me: WARNING: sys/dg_sys_info.h: check for missing prerequisite headers?" >&2;}
+     { echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&5
+-echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&2;};;
++echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&2;}
++    (
++      cat <<\_ASBOX
++## ------------------------------------ ##
++## Report this to bug-autoconf@gnu.org. ##
++## ------------------------------------ ##
++_ASBOX
++    ) |
++      sed "s/^/$as_me: WARNING:     /" >&2
++    ;;
+ esac
+ echo "$as_me:$LINENO: checking for sys/dg_sys_info.h" >&5
+ echo $ECHO_N "checking for sys/dg_sys_info.h... $ECHO_C" >&6
+@@ -8880,8 +9205,8 @@
+ fi
+-ac_config_files="$ac_config_files Makefile doc/Makefile include/Makefile"
+-ac_config_commands="$ac_config_commands default"
++                              ac_config_files="$ac_config_files Makefile doc/Makefile include/Makefile"
++          ac_config_commands="$ac_config_commands default"
+ cat >confcache <<\_ACEOF
+ # This file is a shell script that caches the results of configure
+ # tests run on this system so they can be shared between configure
+@@ -8892,7 +9217,7 @@
+ # config.status only pays attention to the cache file if you give it
+ # the --recheck option to rerun configure.
+ #
+-# `ac_cv_env_foo' variables (set or unset) will be overriden when
++# `ac_cv_env_foo' variables (set or unset) will be overridden when
+ # loading this file, other *unset* `ac_cv_foo' will be assigned the
+ # following values.
+@@ -8927,7 +9252,7 @@
+      t end
+      /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+      : end' >>confcache
+-if cmp -s $cache_file confcache; then :; else
++if diff $cache_file confcache >/dev/null 2>&1; then :; else
+   if test -w $cache_file; then
+     test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+     cat confcache >$cache_file
+@@ -8989,6 +9314,21 @@
+ rm -f confdef2opt.sed
++ac_libobjs=
++ac_ltlibobjs=
++for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
++  # 1. Remove the extension, and $U if already installed.
++  ac_i=`echo "$ac_i" |
++         sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
++  # 2. Add them.
++  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
++  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
++done
++LIBOBJS=$ac_libobjs
++
++LTLIBOBJS=$ac_ltlibobjs
++
++
+ if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+   { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+ Usually this means the macro was only invoked conditionally." >&5
+@@ -9038,11 +9378,12 @@
+ # configure, is in config.log if it exists.
+ debug=false
++ac_cs_recheck=false
++ac_cs_silent=false
+ SHELL=\${CONFIG_SHELL-$SHELL}
+ _ACEOF
+ cat >>$CONFIG_STATUS <<\_ACEOF
+-
+ ## --------------------- ##
+ ## M4sh Initialization.  ##
+ ## --------------------- ##
+@@ -9051,11 +9392,13 @@
+ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+   emulate sh
+   NULLCMD=:
++  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
++  # is contrary to our usage.  Disable this feature.
++  alias -g '${1+"$@"}'='"$@"'
+ elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+   set -o posix
+ fi
+-# NLS nuisances.
+ # Support unset when possible.
+ if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+   as_unset=unset
+@@ -9063,34 +9406,42 @@
+   as_unset=false
+ fi
+-(set +x; test -n "`(LANG=C; export LANG) 2>&1`") &&
+-    { $as_unset LANG || test "${LANG+set}" != set; } ||
+-      { LANG=C; export LANG; }
+-(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") &&
+-    { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } ||
+-      { LC_ALL=C; export LC_ALL; }
+-(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") &&
+-    { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } ||
+-      { LC_TIME=C; export LC_TIME; }
+-(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") &&
+-    { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } ||
+-      { LC_CTYPE=C; export LC_CTYPE; }
+-(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") &&
+-    { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } ||
+-      { LANGUAGE=C; export LANGUAGE; }
+-(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") &&
+-    { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } ||
+-      { LC_COLLATE=C; export LC_COLLATE; }
+-(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") &&
+-    { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } ||
+-      { LC_NUMERIC=C; export LC_NUMERIC; }
+-(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") &&
+-    { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } ||
+-      { LC_MESSAGES=C; export LC_MESSAGES; }
++
++# Work around bugs in pre-3.0 UWIN ksh.
++$as_unset ENV MAIL MAILPATH
++PS1='$ '
++PS2='> '
++PS4='+ '
++
++# NLS nuisances.
++for as_var in \
++  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
++  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
++  LC_TELEPHONE LC_TIME
++do
++  if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
++    eval $as_var=C; export $as_var
++  else
++    $as_unset $as_var
++  fi
++done
++
++# Required to use basename.
++if expr a : '\(a\)' >/dev/null 2>&1; then
++  as_expr=expr
++else
++  as_expr=false
++fi
++
++if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
++  as_basename=basename
++else
++  as_basename=false
++fi
+ # Name of the executable.
+-as_me=`(basename "$0") 2>/dev/null ||
++as_me=`$as_basename "$0" ||
+ $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+@@ -9101,6 +9452,7 @@
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
++
+ # PATH needs CR, and LINENO needs CR and PATH.
+ # Avoid depending upon Character Ranges.
+ as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+@@ -9111,15 +9463,15 @@
+ # The user is always right.
+ if test "${PATH_SEPARATOR+set}" != set; then
+-  echo "#! /bin/sh" >conftest.sh
+-  echo  "exit 0"   >>conftest.sh
+-  chmod +x conftest.sh
+-  if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then
++  echo "#! /bin/sh" >conf$$.sh
++  echo  "exit 0"   >>conf$$.sh
++  chmod +x conf$$.sh
++  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+     PATH_SEPARATOR=';'
+   else
+     PATH_SEPARATOR=:
+   fi
+-  rm -f conftest.sh
++  rm -f conf$$.sh
+ fi
+@@ -9168,6 +9520,8 @@
+   as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+   test "x$as_lineno_1" != "x$as_lineno_2" &&
+   test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
++           $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
++           $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+@@ -9241,6 +9595,12 @@
+ fi
+ rm -f conf$$ conf$$.exe conf$$.file
++if mkdir -p . 2>/dev/null; then
++  as_mkdir_p=:
++else
++  as_mkdir_p=false
++fi
++
+ as_executable_p="test -f"
+ # Sed expression to map a string onto a valid CPP name.
+@@ -9257,7 +9617,7 @@
+ IFS="         $as_nl"
+ # CDPATH.
+-$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; }
++$as_unset CDPATH
+ exec 6>&1
+@@ -9274,7 +9634,7 @@
+ cat >&5 <<_CSEOF
+ This file was extended by gc $as_me 6.3alpha2, which was
+-generated by GNU Autoconf 2.53.  Invocation command line was
++generated by GNU Autoconf 2.57.  Invocation command line was
+   CONFIG_FILES    = $CONFIG_FILES
+   CONFIG_HEADERS  = $CONFIG_HEADERS
+@@ -9314,6 +9674,7 @@
+   -h, --help       print this help, then exit
+   -V, --version    print version number, then exit
++  -q, --quiet      do not print progress messages
+   -d, --debug      don't remove temporary files
+       --recheck    update $as_me by reconfiguring in the same conditions
+   --file=FILE[:TEMPLATE]
+@@ -9331,7 +9692,7 @@
+ cat >>$CONFIG_STATUS <<_ACEOF
+ ac_cs_version="\\
+ gc config.status 6.3alpha2
+-configured by $0, generated by GNU Autoconf 2.53,
++configured by $0, generated by GNU Autoconf 2.57,
+   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+ Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+@@ -9352,25 +9713,25 @@
+   --*=*)
+     ac_option=`expr "x$1" : 'x\([^=]*\)='`
+     ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+-    shift
+-    set dummy "$ac_option" "$ac_optarg" ${1+"$@"}
+-    shift
++    ac_shift=:
++    ;;
++  -*)
++    ac_option=$1
++    ac_optarg=$2
++    ac_shift=shift
+     ;;
+-  -*);;
+   *) # This is not an option, so the user has probably given explicit
+      # arguments.
++     ac_option=$1
+      ac_need_defaults=false;;
+   esac
+-  case $1 in
++  case $ac_option in
+   # Handling of the options.
+ _ACEOF
+-cat >>$CONFIG_STATUS <<_ACEOF
+-  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+-    echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion"
+-    exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;;
+-_ACEOF
+ cat >>$CONFIG_STATUS <<\_ACEOF
++  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
++    ac_cs_recheck=: ;;
+   --version | --vers* | -V )
+     echo "$ac_cs_version"; exit 0 ;;
+   --he | --h)
+@@ -9385,13 +9746,16 @@
+   --debug | --d* | -d )
+     debug=: ;;
+   --file | --fil | --fi | --f )
+-    shift
+-    CONFIG_FILES="$CONFIG_FILES $1"
++    $ac_shift
++    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+     ac_need_defaults=false;;
+   --header | --heade | --head | --hea )
+-    shift
+-    CONFIG_HEADERS="$CONFIG_HEADERS $1"
++    $ac_shift
++    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+     ac_need_defaults=false;;
++  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
++  | -silent | --silent | --silen | --sile | --sil | --si | --s)
++    ac_cs_silent=: ;;
+   # This is an error.
+   -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+@@ -9406,6 +9770,20 @@
+   shift
+ done
++ac_configure_extra_args=
++
++if $ac_cs_silent; then
++  exec 6>/dev/null
++  ac_configure_extra_args="$ac_configure_extra_args --silent"
++fi
++
++_ACEOF
++cat >>$CONFIG_STATUS <<_ACEOF
++if \$ac_cs_recheck; then
++  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
++  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
++fi
++
+ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF
+@@ -9450,6 +9828,9 @@
+   test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+ fi
++# Have a temporary directory for convenience.  Make it in the build tree
++# simply because there is no reason to put it here, and in addition,
++# creating and moving files from /tmp can sometimes cause problems.
+ # Create a temporary directory, and hook for its removal unless debugging.
+ $debug ||
+ {
+@@ -9458,17 +9839,17 @@
+ }
+ # Create a (secure) tmp directory for tmp files.
+-: ${TMPDIR=/tmp}
++
+ {
+-  tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` &&
++  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+   test -n "$tmp" && test -d "$tmp"
+ }  ||
+ {
+-  tmp=$TMPDIR/cs$$-$RANDOM
++  tmp=./confstat$$-$RANDOM
+   (umask 077 && mkdir $tmp)
+ } ||
+ {
+-   echo "$me: cannot create a temporary directory in $TMPDIR" >&2
++   echo "$me: cannot create a temporary directory in ." >&2
+    { (exit 1); exit 1; }
+ }
+@@ -9590,10 +9971,13 @@
+ s,@LN_S@,$LN_S,;t t
+ s,@ECHO@,$ECHO,;t t
+ s,@CPP@,$CPP,;t t
++s,@EGREP@,$EGREP,;t t
+ s,@LIBTOOL@,$LIBTOOL,;t t
+ s,@MY_CFLAGS@,$MY_CFLAGS,;t t
+ s,@USE_LIBDIR_TRUE@,$USE_LIBDIR_TRUE,;t t
+ s,@USE_LIBDIR_FALSE@,$USE_LIBDIR_FALSE,;t t
++s,@LIBOBJS@,$LIBOBJS,;t t
++s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+ CEOF
+ _ACEOF
+@@ -9664,25 +10048,30 @@
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+-  { case "$ac_dir" in
+-  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+-  *)                      as_incr_dir=.;;
+-esac
+-as_dummy="$ac_dir"
+-for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+-  case $as_mkdir_dir in
+-    # Skip DOS drivespec
+-    ?:) as_incr_dir=$as_mkdir_dir ;;
+-    *)
+-      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+-      test -d "$as_incr_dir" ||
+-        mkdir "$as_incr_dir" ||
+-      { { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5
+-echo "$as_me: error: cannot create \"$ac_dir\"" >&2;}
+-   { (exit 1); exit 1; }; }
+-    ;;
+-  esac
+-done; }
++  { if $as_mkdir_p; then
++    mkdir -p "$ac_dir"
++  else
++    as_dir="$ac_dir"
++    as_dirs=
++    while test ! -d "$as_dir"; do
++      as_dirs="$as_dir $as_dirs"
++      as_dir=`(dirname "$as_dir") 2>/dev/null ||
++$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++         X"$as_dir" : 'X\(//\)[^/]' \| \
++         X"$as_dir" : 'X\(//\)$' \| \
++         X"$as_dir" : 'X\(/\)' \| \
++         .     : '\(.\)' 2>/dev/null ||
++echo X"$as_dir" |
++    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
++        /^X\(\/\/\)[^/].*/{ s//\1/; q; }
++        /^X\(\/\/\)$/{ s//\1/; q; }
++        /^X\(\/\).*/{ s//\1/; q; }
++        s/.*/./; q'`
++    done
++    test ! -n "$as_dirs" || mkdir $as_dirs
++  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
++echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
++   { (exit 1); exit 1; }; }; }
+   ac_builddir=.
+@@ -9712,7 +10101,7 @@
+ # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+ # absolute.
+ ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+-ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd`
++ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+ ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+@@ -9842,7 +10231,7 @@
+ # Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+ # absolute.
+ ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+-ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd`
++ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+ ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+@@ -9911,25 +10300,30 @@
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+-    { case $dirpart/$fdir in
+-  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+-  *)                      as_incr_dir=.;;
+-esac
+-as_dummy=$dirpart/$fdir
+-for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+-  case $as_mkdir_dir in
+-    # Skip DOS drivespec
+-    ?:) as_incr_dir=$as_mkdir_dir ;;
+-    *)
+-      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+-      test -d "$as_incr_dir" ||
+-        mkdir "$as_incr_dir" ||
+-      { { echo "$as_me:$LINENO: error: cannot create $dirpart/$fdir" >&5
+-echo "$as_me: error: cannot create $dirpart/$fdir" >&2;}
+-   { (exit 1); exit 1; }; }
+-    ;;
+-  esac
+-done; }
++    { if $as_mkdir_p; then
++    mkdir -p $dirpart/$fdir
++  else
++    as_dir=$dirpart/$fdir
++    as_dirs=
++    while test ! -d "$as_dir"; do
++      as_dirs="$as_dir $as_dirs"
++      as_dir=`(dirname "$as_dir") 2>/dev/null ||
++$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++         X"$as_dir" : 'X\(//\)[^/]' \| \
++         X"$as_dir" : 'X\(//\)$' \| \
++         X"$as_dir" : 'X\(/\)' \| \
++         .     : '\(.\)' 2>/dev/null ||
++echo X"$as_dir" |
++    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
++        /^X\(\/\/\)[^/].*/{ s//\1/; q; }
++        /^X\(\/\/\)$/{ s//\1/; q; }
++        /^X\(\/\).*/{ s//\1/; q; }
++        s/.*/./; q'`
++    done
++    test ! -n "$as_dirs" || mkdir $as_dirs
++  fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5
++echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;}
++   { (exit 1); exit 1; }; }; }
+     # echo "creating $dirpart/$file"
+     echo '# dummy' > "$dirpart/$file"
+@@ -9958,8 +10352,11 @@
+ # need to make the FD available again.
+ if test "$no_create" != yes; then
+   ac_cs_success=:
++  ac_config_status_args=
++  test "$silent" = yes &&
++    ac_config_status_args="$ac_config_status_args --quiet"
+   exec 5>/dev/null
+-  $SHELL $CONFIG_STATUS || ac_cs_success=false
++  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+   exec 5>>config.log
+   # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+   # would make configure fail if this is the last instruction.
+diff -ruN ../gc6.3alpha2/configure.in ./configure.in
+--- ../gc6.3alpha2/configure.in        Mon Sep 29 14:13:34 2003
++++ ./configure.in     Wed Nov 19 04:17:15 2003
+@@ -275,6 +275,10 @@
+     ;;
+  mips*-*-linux*) 
+     ;; 
++ mips-unknown-elf*)
++    machdep="mips2java_mach_dep.lo"
++    AC_DEFINE(MIPS2JAVA)
++    ;;
+  mips-*-*)
+     machdep="mips_sgi_mach_dep.lo"
+     AC_DEFINE(NO_EXECUTE_PERMISSION)
+diff -ruN ../gc6.3alpha2/include/private/gcconfig.h ./include/private/gcconfig.h
+--- ../gc6.3alpha2/include/private/gcconfig.h  Wed Sep  3 14:16:01 2003
++++ ./include/private/gcconfig.h       Wed Nov 19 04:47:25 2003
+@@ -115,7 +115,7 @@
+ #    if defined(nec_ews) || defined(_nec_ews)
+ #      define EWS4800
+ #    endif
+-#    if !defined(LINUX) && !defined(EWS4800)
++#    if !defined(LINUX) && !defined(EWS4800) && !defined(MIPS2JAVA)
+ #      if defined(ultrix) || defined(__ultrix) || defined(__NetBSD__)
+ #      define ULTRIX
+ #      else
+@@ -1236,6 +1236,16 @@
+ # ifdef MIPS
+ #   define MACH_TYPE "MIPS"
++
++#   ifdef MIPS2JAVA
++extern int _etext[];
++extern int _end[];
++#   define ALIGNMENT 4
++#   define STACKBOTTOM 0x10000000
++#   define DATASTART (_etext)
++#   define DATAEND (_end)
++#   endif /* MIPS2JAVA */
++
+ #   ifdef LINUX
+       /* This was developed for a linuxce style platform.  Probably   */
+       /* needs to be tweaked for workstation class machines.          */
+diff -ruN ../gc6.3alpha2/mips2java_mach_dep.s ./mips2java_mach_dep.s
+--- ../gc6.3alpha2/mips2java_mach_dep.s        Wed Dec 31 19:00:00 1969
++++ ./mips2java_mach_dep.s     Wed Nov 19 04:56:28 2003
+@@ -0,0 +1,43 @@
++    .set    noreorder
++    .text
++    .align    2
++    .globl  GC_push_regs
++    .ent    GC_push_regs
++GC_push_regs:
++    subu $sp,$sp,24
++    sw $31,20($sp)
++    
++    jal GC_push_one
++    move $4,$1
++    jal GC_push_one
++    move $4,$16
++    jal GC_push_one
++    move $4,$17
++    jal GC_push_one
++    move $4,$18
++    jal GC_push_one
++    move $4,$19
++    jal GC_push_one
++    move $4,$20
++    jal GC_push_one
++    move $4,$21
++    jal GC_push_one
++    move $4,$22
++    jal GC_push_one
++    move $4,$23
++    jal GC_push_one
++    move $4,$26
++    jal GC_push_one
++    move $4,$27
++    jal GC_push_one
++    move $4,$28
++    jal GC_push_one
++    move $4,$29
++    jal GC_push_one
++    move $4,$30
++    
++    lw $31,20($sp)
++      j $31
++    addu $sp,$sp,24
++    
++    .end GC_push_regs
+diff -ruN ../gc6.3alpha2/os_dep.c ./os_dep.c
+--- ../gc6.3alpha2/os_dep.c    Mon Sep 22 18:49:47 2003
++++ ./os_dep.c Wed Nov 19 04:12:13 2003
+@@ -497,7 +497,7 @@
+ #  if !defined(PCR) && !defined(AMIGA) && !defined(MSWIN32) \
+       && !defined(MSWINCE) \
+       && !defined(MACOS) && !defined(DJGPP) && !defined(DOS4GW) \
+-      && !defined(NOSYS) && !defined(ECOS)
++      && !defined(NOSYS) && !defined(ECOS) && !defined(MIPS2JAVA) \
+ #   if defined(sigmask) && !defined(UTS4) && !defined(HURD)
+       /* Use the traditional BSD interface */
diff --git a/upstream/patches/busybox.patch b/upstream/patches/busybox.patch
new file mode 100644 (file)
index 0000000..ce510eb
--- /dev/null
@@ -0,0 +1,825 @@
+Only in .: BusyBox.class
+Only in .: BusyBox.java
+diff -ur ../busybox-0.60.5/Config.h ./Config.h
+--- ../busybox-0.60.5/Config.h Tue Sep 17 18:04:28 2002
++++ ./Config.h Tue Nov 25 11:05:07 2003
+@@ -12,95 +12,95 @@
+ #define BB_ASH
+ #define BB_BASENAME
+ #define BB_CAT
+-#define BB_CHGRP
+-#define BB_CHMOD
+-#define BB_CHOWN
+-#define BB_CHROOT
+-#define BB_CHVT
++//#define BB_CHGRP
++//#define BB_CHMOD
++//#define BB_CHOWN
++//#define BB_CHROOT
++//#define BB_CHVT
+ #define BB_CLEAR
+-//#define BB_CMP
+-#define BB_CP
++#define BB_CMP
++//#define BB_CP
+ //#define BB_CPIO
+ #define BB_CUT
+ #define BB_DATE
+ //#define BB_DC
+-#define BB_DD
++//#define BB_DD
+ //#define BB_DEALLOCVT
+-#define BB_DF
++//#define BB_DF
+ #define BB_DIRNAME
+-#define BB_DMESG
++//#define BB_DMESG
+ //#define BB_DOS2UNIX
+ //#define BB_DPKG
+ //#define BB_DPKG_DEB
+ //#define BB_DUTMP
+-#define BB_DU
++//#define BB_DU
+ //#define BB_DUMPKMAP
+ #define BB_ECHO
+-#define BB_ENV
++//#define BB_ENV
+ //#define BB_EXPR
+ //#define BB_FBSET
+ //#define BB_FDFLUSH
+-#define BB_FIND
+-#define BB_FREE
++//#define BB_FIND
++//#define BB_FREE
+ //#define BB_FREERAMDISK
+ //#define BB_FSCK_MINIX
+ //#define BB_GETOPT
+ #define BB_GREP
+-#define BB_GUNZIP
++//#define BB_GUNZIP
+ #define BB_GZIP
+-#define BB_HALT
++//#define BB_HALT
+ #define BB_HEAD
+ //#define BB_HOSTID
+ //#define BB_HOSTNAME
+ //#define BB_HUSH
+-#define BB_ID
++//#define BB_ID
+ //#define BB_IFCONFIG
+-#define BB_INIT
++//#define BB_INIT
+ //#define BB_INSMOD
+-#define BB_KILL
+-#define BB_KILLALL
+-#define BB_KLOGD
++//#define BB_KILL
++//#define BB_KILLALL
++//#define BB_KLOGD
+ //#define BB_LASH
+ //#define BB_LENGTH
+-#define BB_LN
++//#define BB_LN
+ //#define BB_LOADACM
+ //#define BB_LOADFONT
+ //#define BB_LOADKMAP
+-#define BB_LOGGER
++//#define BB_LOGGER
+ //#define BB_LOGNAME
+ //#define BB_LOSETUP
+ #define BB_LS
+-#define BB_LSMOD
++//#define BB_LSMOD
+ //#define BB_MAKEDEVS
+-//#define BB_MD5SUM
++#define BB_MD5SUM
+ #define BB_MKDIR
+ //#define BB_MKFIFO
+ //#define BB_MKFS_MINIX
+-#define BB_MKNOD
+-#define BB_MKSWAP
++//#define BB_MKNOD
++//#define BB_MKSWAP
+ //#define BB_MKTEMP
+-#define BB_MODPROBE
+-#define BB_MORE
+-#define BB_MOUNT
++//#define BB_MODPROBE
++//#define BB_MORE
++//#define BB_MOUNT
+ //#define BB_MSH
+ //#define BB_MT
+-#define BB_MV
++//#define BB_MV
+ //#define BB_NC
+ //#define BB_NSLOOKUP
+-#define BB_PIDOF
++//#define BB_PIDOF
+ //#define BB_PING
+ //#define BB_PIVOT_ROOT
+-#define BB_POWEROFF
+-//#define BB_PRINTF
+-#define BB_PS
+-#define BB_PWD
++//#define BB_POWEROFF
++#define BB_PRINTF
++//#define BB_PS
++//#define BB_PWD
+ //#define BB_RDATE
+ //#define BB_READLINK
+-#define BB_REBOOT
++//#define BB_REBOOT
+ //#define BB_RENICE
+ #define BB_RESET
+-#define BB_RM
+-#define BB_RMDIR
++//#define BB_RM
++//#define BB_RMDIR
+ //#define BB_RMMOD
+ //#define BB_ROUTE
+ //#define BB_RPM2CPIO
+@@ -109,13 +109,13 @@
+ #define BB_SLEEP
+ #define BB_SORT
+ //#define BB_STTY
+-#define BB_SWAPONOFF
+-#define BB_SYNC
+-#define BB_SYSLOGD
++//#define BB_SWAPONOFF
++//#define BB_SYNC
++//#define BB_SYSLOGD
+ #define BB_TAIL
+-#define BB_TAR
+-//#define BB_TEE
+-//#define BB_TEST
++//#define BB_TAR
++#define BB_TEE
++#define BB_TEST
+ //#define BB_TELNET
+ //#define BB_TFTP
+ //#define BB_TIME
+@@ -124,15 +124,15 @@
+ //#define BB_TR
+ //#define BB_TRACEROUTE
+ #define BB_TRUE_FALSE
+-#define BB_TTY
++//#define BB_TTY
+ //#define BB_UNIX2DOS
+ //#define BB_UUENCODE
+ //#define BB_UUDECODE
+-#define BB_UMOUNT
++//#define BB_UMOUNT
+ #define BB_UNIQ
+-#define BB_UNAME
++//#define BB_UNAME
+ //#define BB_UPDATE
+-#define BB_UPTIME
++//#define BB_UPTIME
+ //#define BB_USLEEP
+ //#define BB_VI
+ //#define BB_WATCHDOG
+@@ -140,7 +140,7 @@
+ //#define BB_WGET
+ #define BB_WHICH
+ #define BB_WHOAMI
+-#define BB_XARGS
++//#define BB_XARGS
+ #define BB_YES
+ // End of Applications List
+ //
+@@ -182,13 +182,13 @@
+ //#define BB_FEATURE_USE_DEVPS_PATCH
+ //
+ // show verbose usage messages
+-#define BB_FEATURE_VERBOSE_USAGE
++//#define BB_FEATURE_VERBOSE_USAGE
+ //
+ // Use termios to manipulate the screen ('more' is prettier with this on)
+ //#define BB_FEATURE_USE_TERMIOS
+ //
+ // calculate terminal & column widths (for more, ls, and telnet)
+-#define BB_FEATURE_AUTOWIDTH
++//#define BB_FEATURE_AUTOWIDTH
+ //
+ // show username/groupnames for ls
+ #define BB_FEATURE_LS_USERNAME
+@@ -271,11 +271,11 @@
+ //
+ // Enable command line editing in the shell.  
+ // Only relevant if a shell is enabled. On by default.
+-#define BB_FEATURE_COMMAND_EDITING
++//#define BB_FEATURE_COMMAND_EDITING
+ //
+ // Enable tab completion in the shell.  This is now working quite nicely.
+ // This feature adds a bit over 4k. Only relevant if a shell is enabled.
+-#define BB_FEATURE_COMMAND_TAB_COMPLETION
++//#define BB_FEATURE_COMMAND_TAB_COMPLETION
+ //
+ // Attempts to match usernames in a ~-prefixed path
+ //#define BB_FEATURE_COMMAND_USERNAME_COMPLETION
+@@ -284,7 +284,7 @@
+ //were shell builtins.  Nice for staticly linking an emergency rescue shell,
+ //among other things. Off by default.
+ // Only relevant if a shell is enabled.
+-//#define BB_FEATURE_SH_STANDALONE_SHELL
++#define BB_FEATURE_SH_STANDALONE_SHELL
+ //
+ //When this is enabled, busybox shell applets can be called using full path
+ //names.  This causes applets (i.e., most busybox commands) to override
+@@ -306,7 +306,7 @@
+ // are doing is running scripts).  Disabing this is bad for interactive
+ // use, since when you hit ^C in an application, it will also kill the 
+ // shell.  This adds about 2.5k on an x86 system.
+-#define BB_FEATURE_ASH_JOB_CONTROL
++//#define BB_FEATURE_ASH_JOB_CONTROL
+ //
+ //Turn on extra fbset options
+ //#define BB_FEATURE_FBSET_FANCY
+@@ -371,7 +371,7 @@
+ #define BB_FEATURE_FIND_TYPE
+ //
+ // Support for the find -perm option.
+-#define BB_FEATURE_FIND_PERM
++//#define BB_FEATURE_FIND_PERM
+ //
+ // Support for the find -mtime option.
+ #define BB_FEATURE_FIND_MTIME
+@@ -420,7 +420,10 @@
+ // Nothing beyond this point should ever be touched by 
+ // mere mortals so leave this stuff alone.
+ //
++#ifdef _GNU_SOURCE
+ #include <features.h>
++#endif
++
+ #if defined(__uClinux__)
+       #undef BB_ASH                   /* Not even a chance it will work */
+       #undef BB_RPM2CPIO              /* Uses gz_open(), which uses fork() */
+diff -ur ../busybox-0.60.5/Makefile ./Makefile
+--- ../busybox-0.60.5/Makefile Sun Oct 27 00:47:54 2002
++++ ./Makefile Tue Nov 25 11:27:30 2003
+@@ -49,7 +49,7 @@
+ # just 1.4k to the binary size (which is a _lot_ less then glibc NSS costs).
+ # Note that if you want hostname resolution to work with glibc, you still need
+ # the libnss_* libraries.  
+-USE_SYSTEM_PWD_GRP = true
++USE_SYSTEM_PWD_GRP = false
+ # This enables compiling with dmalloc ( http://dmalloc.com/ )
+ # which is an excellent public domain mem leak and malloc problem
+@@ -83,7 +83,7 @@
+ # If you are running a cross compiler, you may want to set this
+ # to something more interesting, like "powerpc-linux-".
+-CROSS =
++CROSS = mips-unknown-elf-
+ CC = $(CROSS)gcc
+ AR = $(CROSS)ar
+ STRIP = $(CROSS)strip
+@@ -106,11 +106,11 @@
+ #
+ # For other libraries, you are on your own...
+ #LDFLAGS+=-nostdlib
+-#LIBRARIES = $(LIBCDIR)/lib/libc.a -lgcc
++LIBRARIES = -lglob -lregex
+ #CROSS_CFLAGS+=-nostdinc -I$(LIBCDIR)/include -I$(GCCINCDIR)
+ #GCCINCDIR = $(shell gcc -print-search-dirs | sed -ne "s/install: \(.*\)/\1include/gp")
+-WARNINGS = -Wall -Wshadow
++WARNINGS = -Wall -Wshadow -Werror -Wno-unused
+ ARFLAGS = -r
+@@ -181,9 +181,9 @@
+     LDFLAGS += -Wl,-warn-common
+     STRIPCMD    = /bin/true -Since_we_are_debugging
+ else
+-    CFLAGS  += $(WARNINGS) $(OPTIMIZATIONS) -D_GNU_SOURCE
+-    LDFLAGS += -s -Wl,-warn-common
+-    STRIPCMD    = $(STRIP) -s --remove-section=.note --remove-section=.comment
++    CFLAGS  += $(WARNINGS) $(OPTIMIZATIONS) -DNEWLIB_ASH
++    LDFLAGS += -Wl,-warn-common
++    STRIPCMD    = true
+ endif
+ ifeq ($(strip $(DOSTATIC)),true)
+     LDFLAGS += --static
+@@ -260,7 +260,7 @@
+     PWD_LIB     = libpwd.a
+     PWD_CSRC=__getpwent.c pwent.c getpwnam.c getpwuid.c putpwent.c getpw.c \
+           fgetpwent.c __getgrent.c grent.c getgrnam.c getgrgid.c fgetgrent.c \
+-          initgroups.c setgroups.c
++          initgroups.c
+     PWD_OBJS=$(patsubst %.c,$(PWD_GRP)/%.o, $(PWD_CSRC))
+ ifneq ($(strip $(BB_SRC_DIR)),)
+     PWD_CFLAGS = -I- -I.
+@@ -273,19 +273,19 @@
+ LIBBB   = libbb
+ LIBBB_LIB = libbb.a
+ LIBBB_CSRC= ask_confirmation.c chomp.c concat_path_file.c copy_file.c \
+-copy_file_chunk.c libc5.c device_open.c error_msg.c inode_hash.c \
+-error_msg_and_die.c fgets_str.c find_mount_point.c find_pid_by_name.c \
+-find_root_device.c full_read.c full_write.c get_console.c \
++copy_file_chunk.c device_open.c error_msg.c inode_hash.c \
++error_msg_and_die.c fgets_str.c find_pid_by_name.c \
++find_root_device.c full_read.c full_write.c \
+ get_last_path_component.c get_line_from_file.c gz_open.c human_readable.c \
+-isdirectory.c kernel_version.c loop.c mode_string.c module_syscalls.c mtab.c \
++isdirectory.c mode_string.c \
+ mtab_file.c my_getgrnam.c my_getgrgid.c my_getpwnam.c my_getpwnamegid.c \
+ my_getpwuid.c parse_mode.c parse_number.c perror_msg.c perror_msg_and_die.c \
+ print_file.c process_escape_sequence.c read_package_field.c recursive_action.c \
+-safe_read.c safe_strncpy.c syscalls.c syslog_msg_with_name.c time_string.c \
++safe_read.c safe_strncpy.c time_string.c \
+ trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \
+-xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \
+-copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \
+-dirname.c make_directory.c create_icmp_socket.c u_signal_names.c arith.c \
++xgetcwd.c xreadlink.c xregcomp.c remove_file.c last_char_is.c \
++copyfd.c herror_msg.c herror_msg_and_die.c \
++dirname.c make_directory.c u_signal_names.c arith.c \
+ simplify_path.c
+ LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC))
+ ifeq ($(strip $(BB_SRC_DIR)),)
+diff -ur ../busybox-0.60.5/ash.c ./ash.c
+--- ../busybox-0.60.5/ash.c    Tue Oct 22 18:14:29 2002
++++ ./ash.c    Tue Nov 25 11:17:08 2003
+@@ -84,11 +84,15 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#ifndef NEWLIB_ASH
+ #include <sysexits.h>
++#endif
+ #include <unistd.h>
+ #include <sys/stat.h>
+ #include <sys/cdefs.h>
++#ifndef NEWLIB_ASH
+ #include <sys/ioctl.h>
++#endif
+ #include <sys/param.h>
+ #include <sys/resource.h>
+ #include <sys/time.h>
+@@ -268,6 +272,7 @@
+  * more fun than worrying about efficiency and portability. :-))
+  */
++#ifndef NEWLIB_ASH
+ static void onint(void);
+ static volatile int suppressint;
+ static volatile int intpending;
+@@ -287,6 +292,16 @@
+ #define CLEAR_PENDING_INT intpending = 0
+ #define int_pending() intpending
++#else
++
++#define INTON
++#define INTOFF
++#define FORCEINTON
++#define CLEAR_PENDING_INT
++#define int_pending() 0
++
++#endif
++
+ typedef void *pointer;
+@@ -1556,7 +1571,9 @@
+ #endif
+ static int unsetcmd(int, char **);
+ static int waitcmd(int, char **);
++#ifndef NEWLIB_ASH
+ static int ulimitcmd(int, char **);
++#endif
+ static int timescmd(int, char **);
+ #ifdef CONFIG_ASH_MATH_SUPPORT
+@@ -1647,10 +1664,14 @@
+       {BUILTIN_NOSPEC "setvar", setvarcmd},
+       {BUILTIN_SPECIAL "shift", shiftcmd},
+       {BUILTIN_SPECIAL "times", timescmd},
++#ifndef NEWLIB_ASH
+       {BUILTIN_SPECIAL "trap", trapcmd},
++#endif
+       {BUILTIN_REGULAR "true", true_main},
+       {BUILTIN_NOSPEC "type", typecmd},
++#ifndef NEWLIB_ASH
+       {BUILTIN_NOSPEC "ulimit", ulimitcmd},
++#endif
+       {BUILTIN_REGULAR "umask", umaskcmd},
+ #ifdef CONFIG_ASH_ALIAS
+       {BUILTIN_REGULAR "unalias", unaliascmd},
+@@ -1918,6 +1939,8 @@
+  * just defensive programming.)
+  */
++#ifndef NEWLIB_ASH
++
+ static void onint(void)
+ {
+       sigset_t mysigset;
+@@ -1937,6 +1960,7 @@
+       /* NOTREACHED */
+ }
++#endif
+ static char *commandname;     /* currently executing command */
+@@ -2086,7 +2110,7 @@
+ }
+-#ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
++#if defined(CONFIG_ASH_OPTIMIZE_FOR_SIZE) && !defined(NEWLIB_ASH)
+ static void __inton()
+ {
+       if (--suppressint == 0 && intpending) {
+@@ -5597,7 +5621,6 @@
+ static void init(void)
+ {
+-
+       /* from cd.c: */
+       {
+               curdir = nullstr;
+@@ -5621,8 +5644,10 @@
+                       }
+               }
++#ifndef NEWLIB_ASH
+               snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
+               setvar("PPID", ppid, 0);
++#endif
+       }
+ }
+@@ -6214,12 +6239,16 @@
+                               else    /* WIFSIGNALED(ps->status) */
+ #endif
+                                       i = WTERMSIG(ps->status);
++#ifndef NEWLIB_ASH
+                               if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
+                                       strcpy(s, sys_siglist[i & 0x7F]);
+                               else
++#endif
+                                       snprintf(s, 64, "Signal %d", i & 0x7F);
++#ifndef NEWLIB_ASH
+                               if (WCOREDUMP(ps->status))
+                                       strcat(s, " (core dumped)");
++#endif
+                       }
+                       out1str(s);
+                       col += strlen(s);
+@@ -6641,7 +6670,11 @@
+ #endif
+       if (block == 0)
+               flags |= WNOHANG;
++#ifndef NEWLIB_ASH
+       return wait3(status, flags, (struct rusage *) NULL);
++#else
++    return waitpid(-1,status,flags);
++#endif
+ }
+ static int dowait(int block, struct job *job)
+@@ -6700,7 +6733,9 @@
+       }
+       INTON;
+       if (!rootshell || !iflag || (job && thisjob == job)) {
++#ifndef NEWLIB_ASH
+               core = WCOREDUMP(status);
++#endif
+ #ifdef BB_FEATURE_ASH_JOB_CONTROL
+               if (WIFSTOPPED(status))
+                       sig = WSTOPSIG(status);
+@@ -6718,12 +6753,16 @@
+                       if (sig == SIGTSTP && rootshell && iflag)
+                               out2fmt("%%%ld ", (long) (job - jobtab + 1));
+ #endif
++#ifndef NEWLIB_ASH
+                       if (sig < NSIG && sys_siglist[sig])
+                               out2str(sys_siglist[sig]);
+                       else
++#endif
+                               out2fmt("Signal %d", sig);
++#ifndef NEWLIB_ASH
+                       if (core)
+                               out2str(" - core dumped");
++#endif
+                       out2c('\n');
+               } else {
+                       TRACE(("Not printing status: status=%d, sig=%d\n", status, sig));
+@@ -7993,6 +8032,8 @@
+       {NULL, 0, 0}
+ };
++#ifndef NEWLIB_ASH
++
+ static int ulimitcmd(int argc, char **argv)
+ {
+       static const char unlimited_string[] = "unlimited";
+@@ -8118,6 +8159,8 @@
+       return 0;
+ }
++#endif /* !NEWLIB_ASH */
++
+ /*
+  * prefix -- see if pfx is a prefix of string.
+  */
+@@ -11426,6 +11469,8 @@
+  * The trap builtin.
+  */
++#ifndef NEWLIB_ASH
++
+ static int trapcmd(int argc, char **argv)
+ {
+       char *action;
+@@ -11475,6 +11520,7 @@
+       return 0;
+ }
++#endif /*!NEWLIB_ASH */
+ /*
+  * Set the signal handler for the specified signal.  The routine figures
+@@ -11485,7 +11531,9 @@
+ {
+       int action;
+       char *t;
++#ifndef NEWLIB_ASH
+       struct sigaction act;
++#endif
+       if ((t = trap[signo]) == NULL)
+               action = S_DFL;
+@@ -11527,6 +11575,7 @@
+               /*
+                * current setting unknown
+                */
++#ifndef NEWLIB_ASH
+               if (sigaction(signo, 0, &act) == -1) {
+                       /*
+                        * Pretend it worked; maybe we should give a warning
+@@ -11536,6 +11585,7 @@
+                       return;
+               }
+               if (act.sa_handler == SIG_IGN) {
++
+                       if (mflag && (signo == SIGTSTP ||
+                                                 signo == SIGTTIN || signo == SIGTTOU)) {
+                               *t = S_IGN;     /* don't hard ignore these */
+@@ -11544,15 +11594,22 @@
+               } else {
+                       *t = S_RESET;   /* force to be set */
+               }
++#else
++        *t = S_DFL;
++#endif
+       }
+       if (*t == S_HARD_IGN || *t == action)
+               return;
++      *t = action;
++#ifndef NEWLIB_ASH
+       act.sa_handler = ((action == S_CATCH) ? onsig
+                                         : ((action == S_IGN) ? SIG_IGN : SIG_DFL));
+-      *t = action;
+       act.sa_flags = 0;
+       sigemptyset(&act.sa_mask);
+       sigaction(signo, &act, 0);
++#else
++    signal(signo,((action == S_CATCH) ? onsig : ((action == S_IGN) ? SIG_IGN : SIG_DFL)));
++#endif
+ }
+ /*
+@@ -11574,10 +11631,12 @@
+ static void onsig(int signo)
+ {
++#ifndef NEWLIB_ASH
+       if (signo == SIGINT && trap[SIGINT] == NULL) {
+               onint();
+               return;
+       }
++#endif
+       gotsig[signo - 1] = 1;
+       pendingsigs++;
+ }
+@@ -12153,6 +12212,7 @@
+ static struct var **findvar(struct var **vpp, const char *name)
+ {
++    int n=0;
+       for (; *vpp; vpp = &(*vpp)->next) {
+               if (varequal((*vpp)->text, name)) {
+                       break;
+@@ -12168,8 +12228,11 @@
+ static int timescmd(int argc, char **argv)
+ {
+       struct tms buf;
++#ifdef NEWLIB_ASH
++    long int clk_tck = _CLOCKS_PER_SEC_;
++#else
+       long int clk_tck = sysconf(_SC_CLK_TCK);
+-
++#endif
+       times(&buf);
+       printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
+                  (int) (buf.tms_utime / clk_tck / 60),
+diff -ur ../busybox-0.60.5/busybox.h ./busybox.h
+--- ../busybox-0.60.5/busybox.h        Fri Mar 15 21:11:46 2002
++++ ./busybox.h        Tue Nov 25 11:10:52 2003
+@@ -37,8 +37,9 @@
+ #include "dmalloc.h"
+ #endif
++#ifdef _GNU_SOURCE
+ #include <features.h>
+-
++#endif
+ enum Location {
+       _BB_DIR_ROOT = 0,
+@@ -85,7 +86,9 @@
+ /* Bit map related macros -- libc5 doens't provide these... sigh.  */
+ #ifndef setbit
++#ifndef NBBY
+ #define NBBY            CHAR_BIT
++#endif
+ #define setbit(a,i)     ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
+ #define clrbit(a,i)     ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+ #define isset(a,i)      ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
+Only in ../busybox-0.60.5: busybox.links
+diff -ur ../busybox-0.60.5/busybox.sh ./busybox.sh
+--- ../busybox-0.60.5/busybox.sh       Wed Sep 26 02:20:54 2001
++++ ./busybox.sh       Tue Nov 25 10:57:58 2003
+@@ -5,7 +5,7 @@
+ RAW=` \
+     $CC -E -dM ${1:-Config.h} | \
+-    sed -n -e '/^.*BB_FEATURE.*$/d;s/^#define.*\<BB_\(.*\)\>/\1.c/gp;' \
++     sed -n -e '/^.*BB_FEATURE.*$/d;s/^#define.*BB_\([A-Z0-9_]*\)/\1.c/gp;' \
+     | tr A-Z a-z | sort
+ `
+ test "${RAW}" != "" ||  exit
+diff -ur ../busybox-0.60.5/date.c ./date.c
+--- ../busybox-0.60.5/date.c   Sat Jun 15 10:35:13 2002
++++ ./date.c   Tue Nov 25 11:26:25 2003
+@@ -210,9 +210,7 @@
+               /* if setting time, set it */
+               if (set_time) {
+-                      if (stime(&tm) < 0) {
+-                              perror_msg("cannot set date");
+-                      }
++            perror_msg("cannot set date");
+               }
+       }
+Only in ../busybox-0.60.5/docs: BusyBox.1
+Only in ../busybox-0.60.5/docs: BusyBox.html
+Only in ../busybox-0.60.5/docs: BusyBox.txt
+Only in ../busybox-0.60.5/docs: busybox.pod
+diff -ur ../busybox-0.60.5/libbb/libbb.h ./libbb/libbb.h
+--- ../busybox-0.60.5/libbb/libbb.h    Wed Sep 18 15:21:07 2002
++++ ./libbb/libbb.h    Tue Nov 25 11:10:27 2003
+@@ -25,8 +25,6 @@
+ #include <sys/stat.h>
+ #include <sys/types.h>
+-#include <netdb.h>
+-
+ #ifndef _BB_INTERNAL_H_
+ #include "../busybox.h"
+ #endif
+@@ -35,7 +33,9 @@
+ #include "dmalloc.h"
+ #endif
++#ifdef _GNU_SOURCE
+ #include <features.h>
++#endif
+ #if (__GNU_LIBRARY__ < 5) && (!defined __dietlibc__)
+ /* libc5 doesn't define socklen_t */
+diff -ur ../busybox-0.60.5/ls.c ./ls.c
+--- ../busybox-0.60.5/ls.c     Mon Sep 16 01:53:01 2002
++++ ./ls.c     Tue Nov 25 11:29:41 2003
+@@ -43,7 +43,7 @@
+ enum {
+       TERMINAL_WIDTH = 80,            /* use 79 if terminal has linefold bug */
+-      COLUMN_WIDTH = 14,                      /* default if AUTOWIDTH not defined */
++      COLUMN_WIDTH = 18,                      /* default if AUTOWIDTH not defined */
+       COLUMN_GAP = 2,                         /* includes the file type char */
+ };
+@@ -61,8 +61,10 @@
+ #include <stdlib.h>
+ #include <fcntl.h>
+ #include <signal.h>
++#ifdef BB_FEATURE_AUTOWIDTH
+ #include <termios.h>
+ #include <sys/ioctl.h>
++#endif
+ #include "busybox.h"
+ #ifdef BB_FEATURE_LS_TIMESTAMPS
+@@ -484,7 +486,7 @@
+               column_width = COLUMN_WIDTH;
+       }
+ #else
+-      ncols= TERMINAL_WIDTH;
++    ncols= (int) (TERMINAL_WIDTH / (COLUMN_WIDTH+COLUMN_GAP));
+ #endif
+       switch (style_fmt) {
+               case STYLE_LONG:        /* one record per line, extended info */
+diff -ur ../busybox-0.60.5/md5sum.c ./md5sum.c
+--- ../busybox-0.60.5/md5sum.c Tue Oct 22 18:13:57 2002
++++ ./md5sum.c Tue Nov 25 11:22:37 2003
+@@ -44,13 +44,17 @@
+ #include <getopt.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include <endian.h>
+ #include <sys/types.h>
+ #if defined HAVE_LIMITS_H
+ # include <limits.h>
+ #endif
+ #include "busybox.h"
++typedef unsigned int u_int32_t;
++#ifndef __P
++#define __P(x) x
++#endif
++
+ /* For some silly reason, this file uses backwards TRUE and FALSE conventions */
+ #undef TRUE
+ #undef FALSE
+@@ -146,11 +150,7 @@
+ //----------------------------------------------------------------------------
+ /* Handle endian-ness */
+-#if __BYTE_ORDER == __LITTLE_ENDIAN
+-      #define SWAP(n) (n)
+-#else
+-      #define SWAP(n) ((n << 24) | ((n&65280)<<8) | ((n&16711680)>>8) | (n>>24))
+-#endif
++#define SWAP(n) ((n << 24) | ((n&65280)<<8) | ((n&16711680)>>8) | (n>>24))
+diff -ur ../busybox-0.60.5/printf.c ./printf.c
+--- ../busybox-0.60.5/printf.c Mon Mar 19 14:25:49 2001
++++ ./printf.c Tue Nov 25 11:22:49 2003
+@@ -57,6 +57,10 @@
+ #include <ctype.h>
+ #include "busybox.h"
++#ifndef __P
++#define __P(x) x
++#endif
++
+ #ifndef S_IFMT
+ static const int S_IFMT = 0170000;
+diff -ur ../busybox-0.60.5/pwd_grp/grp.h ./pwd_grp/grp.h
+--- ../busybox-0.60.5/pwd_grp/grp.h    Sat Jan 27 03:24:39 2001
++++ ./pwd_grp/grp.h    Tue Nov 25 11:05:36 2003
+@@ -5,8 +5,14 @@
+ #include <grp.h>
+ #else
++#ifndef __P
++#define __P(x) x
++#endif
++
+ #include <sys/types.h>
++#ifdef _GNU_SOURCE
+ #include <features.h>
++#endif
+ #include <stdio.h>
+ /* The group structure */
+diff -ur ../busybox-0.60.5/pwd_grp/pwd.h ./pwd_grp/pwd.h
+--- ../busybox-0.60.5/pwd_grp/pwd.h    Sat Jan 27 03:24:39 2001
++++ ./pwd_grp/pwd.h    Tue Nov 25 11:05:09 2003
+@@ -5,8 +5,14 @@
+ #include <pwd.h>
+ #else
++#ifndef __P
++#define __P(x) x
++#endif
++
+ #include <sys/types.h>
++#ifdef _GNU_SOURCE
+ #include <features.h>
++#endif
+ #include <stdio.h>
+ /* The passwd structure.  */
diff --git a/upstream/patches/freetype.patch b/upstream/patches/freetype.patch
new file mode 100644 (file)
index 0000000..caefc0d
--- /dev/null
@@ -0,0 +1,25 @@
+--- include/freetype/config/ftmodule.h Thu Jul 31 12:59:06 2003
++++ include/freetype/config/ftmodule.h Thu Jul 31 12:59:17 2003
+@@ -1,4 +1,5 @@
+ FT_USE_MODULE(autohint_module_class)
++/*
+ FT_USE_MODULE(cff_driver_class)
+ FT_USE_MODULE(t1cid_driver_class)
+ FT_USE_MODULE(pcf_driver_class)
+@@ -7,13 +8,15 @@
+ FT_USE_MODULE(psnames_module_class)
+ FT_USE_MODULE(pshinter_module_class)
+ FT_USE_MODULE(ft_raster1_renderer_class)
++*/
+ FT_USE_MODULE(sfnt_module_class)
+ FT_USE_MODULE(ft_smooth_renderer_class)
+ FT_USE_MODULE(ft_smooth_lcd_renderer_class)
+ FT_USE_MODULE(ft_smooth_lcdv_renderer_class)
+ FT_USE_MODULE(tt_driver_class)
++/*
+ FT_USE_MODULE(t1_driver_class)
+ FT_USE_MODULE(t42_driver_class)
+ FT_USE_MODULE(pfr_driver_class)
+ FT_USE_MODULE(winfnt_driver_class)
+-
++*/
diff --git a/upstream/patches/ft-nostdio.patch b/upstream/patches/ft-nostdio.patch
new file mode 100644 (file)
index 0000000..6098c50
--- /dev/null
@@ -0,0 +1,83 @@
+--- src/base/ftsystem.c.origf  Mon Dec 29 05:45:54 2003
++++ src/base/ftsystem.c        Mon Dec 29 05:46:08 2003
+@@ -32,7 +32,8 @@
+ #include FT_ERRORS_H
+ #include FT_TYPES_H
+-#include <stdio.h>
++#include <fcntl.h>
++#include <unistd.h>
+ #include <stdlib.h>
+@@ -151,7 +152,7 @@
+   /* We use the macro STREAM_FILE for convenience to extract the       */
+   /* system-specific stream handle from a given FreeType stream object */
+-#define STREAM_FILE( stream )  ( (FILE*)stream->descriptor.pointer )
++#define STREAM_FD( stream )  ( (int)stream->descriptor.value )
+   /*************************************************************************/
+@@ -168,7 +169,7 @@
+   FT_CALLBACK_DEF( void )
+   ft_ansi_stream_close( FT_Stream  stream )
+   {
+-    fclose( STREAM_FILE( stream ) );
++    close(STREAM_FD(stream));
+     stream->descriptor.pointer = NULL;
+     stream->size               = 0;
+@@ -202,14 +203,14 @@
+                      unsigned char*  buffer,
+                      unsigned long   count )
+   {
+-    FILE*  file;
++    int fd;
+-    file = STREAM_FILE( stream );
++    fd = STREAM_FD( stream );
+-    fseek( file, offset, SEEK_SET );
++    if(lseek( fd, offset, SEEK_SET ) < 0) return 0;
+-    return (unsigned long)fread( buffer, 1, count, file );
++    return (unsigned long) read(fd,buffer,count);
+   }
+@@ -219,14 +220,14 @@
+   FT_Stream_Open( FT_Stream    stream,
+                   const char*  filepathname )
+   {
+-    FILE*  file;
++    int fd,n;
+     if ( !stream )
+       return FT_Err_Invalid_Stream_Handle;
+-    file = fopen( filepathname, "rb" );
+-    if ( !file )
++    fd = open( filepathname, O_RDONLY);
++    if (fd < 0)
+     {
+       FT_ERROR(( "FT_Stream_Open:" ));
+       FT_ERROR(( " could not open `%s'\n", filepathname ));
+@@ -234,11 +235,11 @@
+       return FT_Err_Cannot_Open_Resource;
+     }
+-    fseek( file, 0, SEEK_END );
+-    stream->size = ftell( file );
+-    fseek( file, 0, SEEK_SET );
++    n = lseek( fd, 0, SEEK_END );
++    stream-> size = n < 0 ? 0 : n;
++    lseek( fd, 0, SEEK_SET );
+-    stream->descriptor.pointer = file;
++    stream->descriptor.value   = fd;
+     stream->pathname.pointer   = (char*)filepathname;
+     stream->pos                = 0;
diff --git a/upstream/patches/gcc-fdata-sections-bss.patch b/upstream/patches/gcc-fdata-sections-bss.patch
new file mode 100644 (file)
index 0000000..d921ae6
--- /dev/null
@@ -0,0 +1,30 @@
+--- gcc/config/mips/mips.c.orig        Mon Dec 29 06:30:42 2003
++++ gcc/config/mips/mips.c     Mon Dec 29 07:16:35 2003
+@@ -10535,11 +10535,13 @@
+   int len, size, sec;
+   const char *name, *prefix;
+   char *string;
+-  static const char *const prefixes[4][2] = {
++  static const char *const prefixes[6][2] = {
+     { ".text.", ".gnu.linkonce.t." },
+     { ".rodata.", ".gnu.linkonce.r." },
+     { ".data.", ".gnu.linkonce.d." },
+-    { ".sdata.", ".gnu.linkonce.s." }
++    { ".sdata.", ".gnu.linkonce.s." },
++    { ".bss.", ".gnu.linkonce.b." },
++    { ".sbss.", ".gnu.linkonce.sb." }
+   };
+   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+@@ -10551,8 +10553,9 @@
+   if (TREE_CODE (decl) == FUNCTION_DECL)
+     sec = 0;
+   else if (DECL_INITIAL (decl) == 0
+-           || DECL_INITIAL (decl) == error_mark_node)
+-    sec = 2;
++           || DECL_INITIAL (decl) == error_mark_node
++           || initializer_zerop (DECL_INITIAL (decl)))
++    sec = (size > 0 && size <= mips_section_threshold) ? 5 : 4;
+   else if ((TARGET_EMBEDDED_PIC || TARGET_MIPS16)
+       && TREE_CODE (decl) == STRING_CST
+       && !flag_writable_strings)
diff --git a/upstream/patches/gcc-fixes.patch b/upstream/patches/gcc-fixes.patch
new file mode 100644 (file)
index 0000000..ab6a652
--- /dev/null
@@ -0,0 +1,65 @@
+diff -urN ../gcc-3.3.1/gcc/builtin-attrs.def ./gcc/builtin-attrs.def
+--- ../gcc-3.3.1/gcc/builtin-attrs.def Tue Mar  4 09:37:20 2003
++++ ./gcc/builtin-attrs.def    Wed Aug 27 00:09:45 2003
+@@ -110,6 +110,7 @@
+                       ATTR_NOTHROW_LIST)
+ /* Construct a tree for a format attribute.  */
++#if 0
+ #define DEF_FORMAT_ATTRIBUTE(TYPE, FA, VALUES)                                 \
+   DEF_ATTR_TREE_LIST (CONCAT4 (ATTR_,TYPE,_,VALUES), ATTR_NULL,                \
+                     CONCAT2 (ATTR_,TYPE), CONCAT2 (ATTR_LIST_,VALUES)) \
+@@ -128,6 +129,32 @@
+ DEF_FORMAT_ATTRIBUTE(STRFTIME,3,3_0)
+ DEF_FORMAT_ATTRIBUTE(STRFMON,3,3_4)
+ #undef DEF_FORMAT_ATTRIBUTE
++#else
++DEF_ATTR_TREE_LIST (ATTR_PRINTF_1_0, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_1_0)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_1_0, ATTR_FORMAT, ATTR_PRINTF_1_0, ATTR_NONNULL_1)
++DEF_ATTR_TREE_LIST (ATTR_PRINTF_1_2, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_1_2)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_1_2, ATTR_FORMAT, ATTR_PRINTF_1_2, ATTR_NONNULL_1)
++DEF_ATTR_TREE_LIST (ATTR_PRINTF_2_0, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_2_0)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_2_0, ATTR_FORMAT, ATTR_PRINTF_2_0, ATTR_NONNULL_2)
++DEF_ATTR_TREE_LIST (ATTR_PRINTF_2_3, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_2_3)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_2_3, ATTR_FORMAT, ATTR_PRINTF_2_3, ATTR_NONNULL_2)
++DEF_ATTR_TREE_LIST (ATTR_PRINTF_3_0, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_3_0)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_3_0, ATTR_FORMAT, ATTR_PRINTF_3_0, ATTR_NONNULL_3)
++DEF_ATTR_TREE_LIST (ATTR_PRINTF_3_4, ATTR_NULL, ATTR_PRINTF, ATTR_LIST_3_4)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_PRINTF_3_4, ATTR_FORMAT, ATTR_PRINTF_3_4, ATTR_NONNULL_3)
++DEF_ATTR_TREE_LIST (ATTR_SCANF_1_0, ATTR_NULL, ATTR_SCANF, ATTR_LIST_1_0)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_SCANF_1_0, ATTR_FORMAT, ATTR_SCANF_1_0, ATTR_NONNULL_1)
++DEF_ATTR_TREE_LIST (ATTR_SCANF_1_2, ATTR_NULL, ATTR_SCANF, ATTR_LIST_1_2)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_SCANF_1_2, ATTR_FORMAT, ATTR_SCANF_1_2, ATTR_NONNULL_1)
++DEF_ATTR_TREE_LIST (ATTR_SCANF_2_0, ATTR_NULL, ATTR_SCANF, ATTR_LIST_2_0)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_SCANF_2_0, ATTR_FORMAT, ATTR_SCANF_2_0, ATTR_NONNULL_2)
++DEF_ATTR_TREE_LIST (ATTR_SCANF_2_3, ATTR_NULL, ATTR_SCANF, ATTR_LIST_2_3)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_SCANF_2_3, ATTR_FORMAT, ATTR_SCANF_2_3, ATTR_NONNULL_2)
++DEF_ATTR_TREE_LIST (ATTR_STRFTIME_3_0, ATTR_NULL, ATTR_STRFTIME, ATTR_LIST_3_0)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_STRFTIME_3_0, ATTR_FORMAT, ATTR_STRFTIME_3_0, ATTR_NONNULL_3)
++DEF_ATTR_TREE_LIST (ATTR_STRFMON_3_4, ATTR_NULL, ATTR_STRFMON, ATTR_LIST_3_4)
++DEF_ATTR_TREE_LIST (ATTR_FORMAT_STRFMON_3_4, ATTR_FORMAT, ATTR_STRFMON_3_4, ATTR_NONNULL_3)
++#endif
+ /* Construct a tree for a format_arg attribute.  */
+ #define DEF_FORMAT_ARG_ATTRIBUTE(FA)                                  \
+diff -urN ../gcc-3.3.1/gcc/config/mips/t-unknown ./gcc/config/mips/t-unknown
+--- ../gcc-3.3.1/gcc/config/mips/t-unknown     Wed Dec 31 19:00:00 1969
++++ ./gcc/config/mips/t-unknown        Mon Sep  1 01:19:35 2003
+@@ -0,0 +1,3 @@
++MULTILIB_OPTIONS= 
++MULTILIB_DIRNAMES = 
++MULTILIB_MATCHES = 
+diff -urN ../gcc-3.3.1/gcc/config.gcc ./gcc/config.gcc
+--- ../gcc-3.3.1/gcc/config.gcc        Fri Jun 27 07:44:22 2003
++++ ./gcc/config.gcc   Sun Aug 31 12:39:12 2003
+@@ -1932,6 +1932,10 @@
+       target_cpu_default="MASK_64BIT|MASK_FLOAT64|MASK_GAS"
+       tm_defines="MIPS_ISA_DEFAULT=64 MIPS_CPU_STRING_DEFAULT=\\\"sb1\\\" MIPS_ABI_DEFAULT=ABI_O64"
+       ;;
++mips*-unknown-elf*)
++      tm_file="${tm_file} mips/elf.h"
++      tmake_file="mips/t-elf mips/t-unknown"
++        ;;
+ mips-*-elf* | mipsel-*-elf*)
+       tm_file="${tm_file} mips/elf.h"
+       tmake_file=mips/t-elf
diff --git a/upstream/patches/libmspack.patch b/upstream/patches/libmspack.patch
new file mode 100644 (file)
index 0000000..cb40f62
--- /dev/null
@@ -0,0 +1,25 @@
+--- ../libmspack.orig/mspack/Makefile  Sat Jul 26 10:44:57 2003
++++ mspack/Makefile    Sun Nov  2 17:12:35 2003
+@@ -1,12 +1,13 @@
+ CC=gcc
+ RM=rm -f
+ AR=ar
++RANLIB=ranlib
+ WARNINGS=-Wall -Wsign-compare -Wconversion -pedantic
+ LARGEFILE=-std=c99 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+ DEBUG=-g -DDEBUG
+ OPTIM=-O3
+-CFLAGS= $(WARNINGS) $(LARGEFILE) $(DEBUG) $(OPTIM) -I.
++CFLAGS= $(WARNINGS) $(LARGEFILE) $(OPTIM) -I. #-DMSPACK_NO_DEFAULT_SYSTEM
+ all: libmspack.a
+@@ -27,6 +28,7 @@
+ libmspack.a: $(OBJS)
+       -$(RM) $@
+       $(AR) q $@ $(OBJS)
++      $(RANLIB) $@
+ .c.o:
+       $(CC) $(CFLAGS) -o $@ -c $<
diff --git a/upstream/patches/newlib-malloc.patch b/upstream/patches/newlib-malloc.patch
new file mode 100644 (file)
index 0000000..fdf36be
--- /dev/null
@@ -0,0 +1,21 @@
+--- newlib/libc/stdlib/mallocr.c.old   Sun Nov 23 18:41:21 2003
++++ newlib/libc/stdlib/mallocr.c       Sun Nov 23 18:43:03 2003
+@@ -301,7 +301,8 @@
+ #define SEPARATE_OBJECTS
+ #define HAVE_MMAP 0
+ #define MORECORE(size) _sbrk_r(reent_ptr, (size))
+-#define MORECORE_CLEARS 0
++#define MORECORE_CLEARS 1
++#define malloc_getpagesize getpagesize()
+ #define MALLOC_LOCK __malloc_lock(reent_ptr)
+ #define MALLOC_UNLOCK __malloc_unlock(reent_ptr)
+@@ -310,7 +311,7 @@
+ # undef WIN32
+ #endif
+-#ifndef _WIN32
++#if !defined(_WIN32) && !defined(malloc_getpagesize)
+ #ifdef SMALL_MEMORY
+ #define malloc_getpagesize (128)
+ #else
diff --git a/upstream/patches/newlib-mips.patch b/upstream/patches/newlib-mips.patch
new file mode 100644 (file)
index 0000000..474d0d3
--- /dev/null
@@ -0,0 +1,2863 @@
+diff -urN ../newlib-1.11.0.orig/libgloss/configure ./libgloss/configure
+--- ../newlib-1.11.0.orig/libgloss/configure   Tue Nov 25 09:05:13 2003
++++ ./libgloss/configure       Mon Nov 24 20:12:14 2003
+@@ -762,6 +762,9 @@
+   mips*-*-pe)
+       configdirs="wince"
+       ;;
++  mips*-unknown-elf*)
++        configdirs="${configdirs}"
++        ;;
+   mips*-*-*)
+       configdirs="${configdirs} mips testsuite"
+       ;;
+@@ -818,7 +821,7 @@
+ # Extract the first word of "gcc", so it can be a program name with args.
+ set dummy gcc; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:822: checking for $ac_word" >&5
++echo "configure:825: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+   echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -848,7 +851,7 @@
+   # Extract the first word of "cc", so it can be a program name with args.
+ set dummy cc; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:852: checking for $ac_word" >&5
++echo "configure:855: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+   echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -897,7 +900,7 @@
+ fi
+ echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+-echo "configure:901: checking whether we are using GNU C" >&5
++echo "configure:904: checking whether we are using GNU C" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+   echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -906,7 +909,7 @@
+   yes;
+ #endif
+ EOF
+-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:910: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
++if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:913: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+   ac_cv_prog_gcc=yes
+ else
+   ac_cv_prog_gcc=no
+@@ -921,7 +924,7 @@
+   ac_save_CFLAGS="$CFLAGS"
+   CFLAGS=
+   echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+-echo "configure:925: checking whether ${CC-cc} accepts -g" >&5
++echo "configure:928: checking whether ${CC-cc} accepts -g" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+   echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -953,7 +956,7 @@
+ # Extract the first word of "ar", so it can be a program name with args.
+ set dummy ar; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:957: checking for $ac_word" >&5
++echo "configure:960: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+   echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -987,7 +990,7 @@
+ # Extract the first word of "ranlib", so it can be a program name with args.
+ set dummy ranlib; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:991: checking for $ac_word" >&5
++echo "configure:994: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+   echo $ac_n "(cached) $ac_c" 1>&6
+ else
+diff -urN ../newlib-1.11.0.orig/libgloss/configure.in ./libgloss/configure.in
+--- ../newlib-1.11.0.orig/libgloss/configure.in        Tue Nov 25 09:05:13 2003
++++ ./libgloss/configure.in    Mon Nov 24 20:12:14 2003
+@@ -73,6 +73,9 @@
+   mips*-*-pe)
+       configdirs="wince"
+       ;;
++  mips*-unknown-elf*)
++        configdirs="${configdirs}"
++        ;;
+   mips*-*-*)
+       configdirs="${configdirs} mips testsuite"
+       ;;
+diff -urN ../newlib-1.11.0.orig/newlib/configure.host ./newlib/configure.host
+--- ../newlib-1.11.0.orig/newlib/configure.host        Tue Nov 25 09:05:13 2003
++++ ./newlib/configure.host    Tue Nov 25 08:30:02 2003
+@@ -356,6 +356,9 @@
+   m8*-bug-*)
+       sys_dir=m88kbug
+       ;;
++  mips*-unknown-elf*)
++      sys_dir=mipsunknown
++      ;;
+   mips*-dec-*)
+       sys_dir=decstation
+       ;;
+@@ -508,6 +511,10 @@
+       newlib_cflags="${newlib_cflags}"
+       syscall_dir=syscalls
+       ;;
++  mips*-unknown-elf*)
++      newlib_cflags="${newlib_cflags} -DREENTRANT_SYSCALLS_PROVIDED -DHAVE_GETTIMEOFDAY -DHAVE_FCNTL"
++      syscall_dir=syscalls
++        ;;
+   mmix-*)
+       syscall_dir=syscalls
+       # We need every symbol 32-bit aligned, so the invalid
+diff -urN ../newlib-1.11.0.orig/newlib/libc/include/paths.h ./newlib/libc/include/paths.h
+--- ../newlib-1.11.0.orig/newlib/libc/include/paths.h  Thu Feb 17 14:39:46 2000
++++ ./newlib/libc/include/paths.h      Tue Nov 25 09:48:09 2003
+@@ -3,5 +3,6 @@
+ #define _PATH_DEV     "/dev/"
+ #define _PATH_BSHELL    "/bin/sh"
++#define _PATH_DEVNULL "/dev/null"
+ #endif /* _PATHS_H_ */
+diff -urN ../newlib-1.11.0.orig/newlib/libc/include/stdlib.h ./newlib/libc/include/stdlib.h
+--- ../newlib-1.11.0.orig/newlib/libc/include/stdlib.h Fri Dec  6 13:58:50 2002
++++ ./newlib/libc/include/stdlib.h     Tue Nov 25 09:50:46 2003
+@@ -158,10 +158,12 @@
+ _VOID _EXFUN(cfree,(_PTR));
+ #else
+ char *        _EXFUN(realpath,(const char *, char *));
++#endif
+ void  _EXFUN(unsetenv,(const char *__string));
+ void  _EXFUN(_unsetenv_r,(struct _reent *, const char *__string));
+ int   _EXFUN(random,(_VOID));
+ long  _EXFUN(srandom,(unsigned __seed));
++#ifdef __CYGWIN__
+ char *  _EXFUN(ptsname, (int));
+ int     _EXFUN(grantpt, (int));
+ int     _EXFUN(unlockpt,(int));
+diff -urN ../newlib-1.11.0.orig/newlib/libc/include/sys/signal.h ./newlib/libc/include/sys/signal.h
+--- ../newlib-1.11.0.orig/newlib/libc/include/sys/signal.h     Wed Jul 24 14:18:07 2002
++++ ./newlib/libc/include/sys/signal.h Tue Nov 25 09:56:00 2003
+@@ -142,6 +142,8 @@
+ int _EXFUN(pthread_sigmask, (int how, const sigset_t *set, sigset_t *oset));
+ #endif
++int _EXFUN(kill, (int, int));
++
+ /* protos for functions found in winsup sources for CYGWIN */
+ #if defined(__CYGWIN__) || defined(__rtems__)
+ #undef sigaddset
+@@ -150,7 +152,6 @@
+    <sys/types.h> always defines pid_t to be int.  If that ever
+    changes, then we will need to do something else, perhaps along the
+    lines of <machine/types.h>.  */
+-int _EXFUN(kill, (int, int));
+ int _EXFUN(killpg, (pid_t, int));
+ int _EXFUN(sigaction, (int, const struct sigaction *, struct sigaction *));
+ int _EXFUN(sigaddset, (sigset_t *, const int));
+diff -urN ../newlib-1.11.0.orig/newlib/libc/include/sys/stat.h ./newlib/libc/include/sys/stat.h
+--- ../newlib-1.11.0.orig/newlib/libc/include/sys/stat.h       Sat Feb 23 15:46:28 2002
++++ ./newlib/libc/include/sys/stat.h   Tue Nov 25 09:41:35 2003
+@@ -127,7 +127,7 @@
+ int   _EXFUN(stat,( const char *__path, struct stat *__sbuf ));
+ mode_t        _EXFUN(umask,( mode_t __mask ));
+-#if defined(__rtems__) || defined(__CYGWIN__)
++#if defined(__rtems__) || defined(__CYGWIN__) || 1
+ int   _EXFUN(lstat,( const char *__path, struct stat *__buf ));
+ int   _EXFUN(mknod,( const char *__path, mode_t __mode, dev_t __dev ));
+ #endif
+diff -urN ../newlib-1.11.0.orig/newlib/libc/include/sys/unistd.h ./newlib/libc/include/sys/unistd.h
+--- ../newlib-1.11.0.orig/newlib/libc/include/sys/unistd.h     Sun Aug 18 02:08:39 2002
++++ ./newlib/libc/include/sys/unistd.h Tue Nov 25 09:46:58 2003
+@@ -158,9 +158,9 @@
+ #endif
+ char *        _EXFUN(mktemp, (char *));
+ int     _EXFUN(sync, (void));
++#endif
+ int     _EXFUN(readlink, (const char *__path, char *__buf, int __buflen));
+ int     _EXFUN(symlink, (const char *__name1, const char *__name2));
+-#endif
+ #define       F_OK    0
+ #define       R_OK    4
+diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/Makefile.am ./newlib/libc/sys/mipsunknown/Makefile.am
+--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/Makefile.am      Wed Dec 31 19:00:00 1969
++++ ./newlib/libc/sys/mipsunknown/Makefile.am  Mon Nov 24 21:04:11 2003
+@@ -0,0 +1,14 @@
++## Process this file with automake to generate Makefile.in
++
++AUTOMAKE_OPTIONS = cygnus
++
++INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
++
++noinst_LIBRARIES = lib.a
++
++lib_a_SOURCES = syscalls.c
++
++all: crt0.o
++
++ACLOCAL_AMFLAGS = -I ../../..
++CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
+diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/Makefile.in ./newlib/libc/sys/mipsunknown/Makefile.in
+--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/Makefile.in      Wed Dec 31 19:00:00 1969
++++ ./newlib/libc/sys/mipsunknown/Makefile.in  Mon Nov 24 21:04:22 2003
+@@ -0,0 +1,329 @@
++# Makefile.in generated automatically by automake 1.4 from Makefile.am
++
++# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
++# This Makefile.in is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
++# PARTICULAR PURPOSE.
++
++
++SHELL = @SHELL@
++
++srcdir = @srcdir@
++top_srcdir = @top_srcdir@
++VPATH = @srcdir@
++prefix = @prefix@
++exec_prefix = @exec_prefix@
++
++bindir = @bindir@
++sbindir = @sbindir@
++libexecdir = @libexecdir@
++datadir = @datadir@
++sysconfdir = @sysconfdir@
++sharedstatedir = @sharedstatedir@
++localstatedir = @localstatedir@
++libdir = @libdir@
++infodir = @infodir@
++mandir = @mandir@
++includedir = @includedir@
++oldincludedir = /usr/include
++
++DESTDIR =
++
++pkgdatadir = $(datadir)/@PACKAGE@
++pkglibdir = $(libdir)/@PACKAGE@
++pkgincludedir = $(includedir)/@PACKAGE@
++
++top_builddir = .
++
++ACLOCAL = @ACLOCAL@
++AUTOCONF = @AUTOCONF@
++AUTOMAKE = @AUTOMAKE@
++AUTOHEADER = @AUTOHEADER@
++
++INSTALL = @INSTALL@
++INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
++INSTALL_DATA = @INSTALL_DATA@
++INSTALL_SCRIPT = @INSTALL_SCRIPT@
++transform = @program_transform_name@
++
++NORMAL_INSTALL = :
++PRE_INSTALL = :
++POST_INSTALL = :
++NORMAL_UNINSTALL = :
++PRE_UNINSTALL = :
++POST_UNINSTALL = :
++build_alias = @build_alias@
++build_triplet = @build@
++host_alias = @host_alias@
++host_triplet = @host@
++target_alias = @target_alias@
++target_triplet = @target@
++AR = @AR@
++AS = @AS@
++CC = @CC@
++CPP = @CPP@
++EXEEXT = @EXEEXT@
++LDFLAGS = @LDFLAGS@
++MAINT = @MAINT@
++MAKEINFO = @MAKEINFO@
++NEWLIB_CFLAGS = @NEWLIB_CFLAGS@
++OBJEXT = @OBJEXT@
++PACKAGE = @PACKAGE@
++RANLIB = @RANLIB@
++VERSION = @VERSION@
++aext = @aext@
++libm_machine_dir = @libm_machine_dir@
++machine_dir = @machine_dir@
++newlib_basedir = @newlib_basedir@
++oext = @oext@
++sys_dir = @sys_dir@
++
++AUTOMAKE_OPTIONS = cygnus
++
++INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
++
++noinst_LIBRARIES = lib.a
++
++lib_a_SOURCES = syscalls.c
++
++ACLOCAL_AMFLAGS = -I ../../..
++CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
++mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../mkinstalldirs
++CONFIG_CLEAN_FILES = 
++LIBRARIES =  $(noinst_LIBRARIES)
++
++
++DEFS = @DEFS@ -I. -I$(srcdir) 
++CPPFLAGS = @CPPFLAGS@
++LIBS = @LIBS@
++lib_a_LIBADD = 
++lib_a_OBJECTS =  syscalls.o
++CFLAGS = @CFLAGS@
++COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
++CCLD = $(CC)
++LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
++DIST_COMMON =  Makefile.am Makefile.in aclocal.m4 configure configure.in
++
++
++DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
++
++TAR = gnutar
++GZIP_ENV = --best
++SOURCES = $(lib_a_SOURCES)
++OBJECTS = $(lib_a_OBJECTS)
++
++all: all-redirect
++.SUFFIXES:
++.SUFFIXES: .S .c .o .s
++$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
++      cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile
++
++Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
++      cd $(top_builddir) \
++        && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
++
++$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in  \
++              ../../../acinclude.m4 ../../../aclocal.m4 \
++              ../../../libtool.m4
++      cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
++
++config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
++      $(SHELL) ./config.status --recheck
++$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
++      cd $(srcdir) && $(AUTOCONF)
++
++mostlyclean-noinstLIBRARIES:
++
++clean-noinstLIBRARIES:
++      -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
++
++distclean-noinstLIBRARIES:
++
++maintainer-clean-noinstLIBRARIES:
++
++.c.o:
++      $(COMPILE) -c $<
++
++.s.o:
++      $(COMPILE) -c $<
++
++.S.o:
++      $(COMPILE) -c $<
++
++mostlyclean-compile:
++      -rm -f *.o core *.core
++
++clean-compile:
++
++distclean-compile:
++      -rm -f *.tab.c
++
++maintainer-clean-compile:
++
++lib.a: $(lib_a_OBJECTS) $(lib_a_DEPENDENCIES)
++      -rm -f lib.a
++      $(AR) cru lib.a $(lib_a_OBJECTS) $(lib_a_LIBADD)
++      $(RANLIB) lib.a
++
++tags: TAGS
++
++ID: $(HEADERS) $(SOURCES) $(LISP)
++      list='$(SOURCES) $(HEADERS)'; \
++      unique=`for i in $$list; do echo $$i; done | \
++        awk '    { files[$$0] = 1; } \
++             END { for (i in files) print i; }'`; \
++      here=`pwd` && cd $(srcdir) \
++        && mkid -f$$here/ID $$unique $(LISP)
++
++TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
++      tags=; \
++      here=`pwd`; \
++      list='$(SOURCES) $(HEADERS)'; \
++      unique=`for i in $$list; do echo $$i; done | \
++        awk '    { files[$$0] = 1; } \
++             END { for (i in files) print i; }'`; \
++      test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
++        || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
++
++mostlyclean-tags:
++
++clean-tags:
++
++distclean-tags:
++      -rm -f TAGS ID
++
++maintainer-clean-tags:
++
++distdir = $(PACKAGE)-$(VERSION)
++top_distdir = $(distdir)
++
++# This target untars the dist file and tries a VPATH configuration.  Then
++# it guarantees that the distribution is self-contained by making another
++# tarfile.
++distcheck: dist
++      -rm -rf $(distdir)
++      GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
++      mkdir $(distdir)/=build
++      mkdir $(distdir)/=inst
++      dc_install_base=`cd $(distdir)/=inst && pwd`; \
++      cd $(distdir)/=build \
++        && ../configure --srcdir=.. --prefix=$$dc_install_base \
++        && $(MAKE) $(AM_MAKEFLAGS) \
++        && $(MAKE) $(AM_MAKEFLAGS) dvi \
++        && $(MAKE) $(AM_MAKEFLAGS) check \
++        && $(MAKE) $(AM_MAKEFLAGS) install \
++        && $(MAKE) $(AM_MAKEFLAGS) installcheck \
++        && $(MAKE) $(AM_MAKEFLAGS) dist
++      -rm -rf $(distdir)
++      @banner="$(distdir).tar.gz is ready for distribution"; \
++      dashes=`echo "$$banner" | sed s/./=/g`; \
++      echo "$$dashes"; \
++      echo "$$banner"; \
++      echo "$$dashes"
++dist: distdir
++      -chmod -R a+r $(distdir)
++      GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
++      -rm -rf $(distdir)
++dist-all: distdir
++      -chmod -R a+r $(distdir)
++      GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
++      -rm -rf $(distdir)
++distdir: $(DISTFILES)
++      -rm -rf $(distdir)
++      mkdir $(distdir)
++      -chmod 777 $(distdir)
++      @for file in $(DISTFILES); do \
++        if test -f $$file; then d=.; else d=$(srcdir); fi; \
++        if test -d $$d/$$file; then \
++          cp -pr $$/$$file $(distdir)/$$file; \
++        else \
++          test -f $(distdir)/$$file \
++          || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
++          || cp -p $$d/$$file $(distdir)/$$file || :; \
++        fi; \
++      done
++info-am:
++info: info-am
++dvi-am:
++dvi: dvi-am
++check-am:
++check: check-am
++installcheck-am:
++installcheck: installcheck-am
++install-info-am: 
++install-info: install-info-am
++install-exec-am:
++install-exec: install-exec-am
++
++install-data-am:
++install-data: install-data-am
++
++install-am: all-am
++      @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
++install: install-am
++uninstall-am:
++uninstall: uninstall-am
++all-am: Makefile $(LIBRARIES)
++all-redirect: all-am
++install-strip:
++      $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
++installdirs:
++
++
++mostlyclean-generic:
++
++clean-generic:
++
++distclean-generic:
++      -rm -f Makefile $(CONFIG_CLEAN_FILES)
++      -rm -f config.cache config.log stamp-h stamp-h[0-9]*
++
++maintainer-clean-generic:
++mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
++              mostlyclean-tags mostlyclean-generic
++
++mostlyclean: mostlyclean-am
++
++clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
++              mostlyclean-am
++
++clean: clean-am
++
++distclean-am:  distclean-noinstLIBRARIES distclean-compile \
++              distclean-tags distclean-generic clean-am
++
++distclean: distclean-am
++      -rm -f config.status
++
++maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
++              maintainer-clean-compile maintainer-clean-tags \
++              maintainer-clean-generic distclean-am
++      @echo "This command is intended for maintainers to use;"
++      @echo "it deletes files that may require special tools to rebuild."
++
++maintainer-clean: maintainer-clean-am
++      -rm -f config.status
++
++.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
++clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
++mostlyclean-compile distclean-compile clean-compile \
++maintainer-clean-compile tags mostlyclean-tags distclean-tags \
++clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
++check-am installcheck-am installcheck install-info-am install-info \
++install-exec-am install-exec install-data-am install-data install-am \
++install uninstall-am uninstall all-redirect all-am all installdirs \
++mostlyclean-generic distclean-generic clean-generic \
++maintainer-clean-generic clean mostlyclean distclean maintainer-clean
++
++
++all: crt0.o 
++
++# Tell versions [3.59,3.63) of GNU make to not export all variables.
++# Otherwise a system limit (for SysV at least) may be exceeded.
++.NOEXPORT:
+diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/aclocal.m4 ./newlib/libc/sys/mipsunknown/aclocal.m4
+--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/aclocal.m4       Wed Dec 31 19:00:00 1969
++++ ./newlib/libc/sys/mipsunknown/aclocal.m4   Mon Nov 24 20:40:47 2003
+@@ -0,0 +1,324 @@
++dnl aclocal.m4 generated automatically by aclocal 1.4
++
++dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
++dnl This file is free software; the Free Software Foundation
++dnl gives unlimited permission to copy and/or distribute it,
++dnl with or without modifications, as long as this notice is preserved.
++
++dnl This program is distributed in the hope that it will be useful,
++dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
++dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
++dnl PARTICULAR PURPOSE.
++
++dnl This provides configure definitions used by all the newlib
++dnl configure.in files.
++
++dnl Basic newlib configury.  This calls basic introductory stuff,
++dnl including AM_INIT_AUTOMAKE and AC_CANONICAL_HOST.  It also runs
++dnl configure.host.  The only argument is the relative path to the top
++dnl newlib directory.
++
++AC_DEFUN(NEWLIB_CONFIGURE,
++[
++dnl Default to --enable-multilib
++AC_ARG_ENABLE(multilib,
++[  --enable-multilib         build many library versions (default)],
++[case "${enableval}" in
++  yes) multilib=yes ;;
++  no)  multilib=no ;;
++  *)   AC_MSG_ERROR(bad value ${enableval} for multilib option) ;;
++ esac], [multilib=yes])dnl
++
++dnl Support --enable-target-optspace
++AC_ARG_ENABLE(target-optspace,
++[  --enable-target-optspace  optimize for space],
++[case "${enableval}" in
++  yes) target_optspace=yes ;;
++  no)  target_optspace=no ;;
++  *)   AC_MSG_ERROR(bad value ${enableval} for target-optspace option) ;;
++ esac], [target_optspace=])dnl
++
++dnl Support --enable-malloc-debugging - currently only supported for Cygwin
++AC_ARG_ENABLE(malloc-debugging,
++[  --enable-malloc-debugging indicate malloc debugging requested],
++[case "${enableval}" in
++  yes) malloc_debugging=yes ;;
++  no)  malloc_debugging=no ;;
++  *)   AC_MSG_ERROR(bad value ${enableval} for malloc-debugging option) ;;
++ esac], [malloc_debugging=])dnl
++
++dnl Support --enable-newlib-mb
++AC_ARG_ENABLE(newlib-mb,
++[  --enable-newlib-mb        enable multibyte support],
++[case "${enableval}" in
++  yes) newlib_mb=yes ;;
++  no)  newlib_mb=no ;;
++  *)   AC_MSG_ERROR(bad value ${enableval} for newlib-mb option) ;;
++ esac], [newlib_mb=])dnl
++
++dnl Support --enable-newlib-multithread
++AC_ARG_ENABLE(newlib-multithread,
++[  --enable-newlib-multithread        enable support for multiple threads],
++[case "${enableval}" in
++  yes) newlib_multithread=yes ;;
++  no)  newlib_multithread=no ;;
++  *)   AC_MSG_ERROR(bad value ${enableval} for newlib-multithread option) ;;
++ esac], [newlib_multithread=yes])dnl
++
++dnl Support --enable-newlib-elix-level
++AC_ARG_ENABLE(newlib-elix-level,
++[  --enable-newlib-elix-level         supply desired elix library level (1-4)],
++[case "${enableval}" in
++  0)   newlib_elix_level=0 ;;
++  1)   newlib_elix_level=1 ;;
++  2)   newlib_elix_level=2 ;;
++  3)   newlib_elix_level=3 ;;
++  4)   newlib_elix_level=4 ;;
++  *)   AC_MSG_ERROR(bad value ${enableval} for newlib-elix-level option) ;;
++ esac], [newlib_elix_level=0])dnl
++
++dnl Support --disable-newlib-io-float
++AC_ARG_ENABLE(newlib-io-float,
++[  --disable-newlib-io-float disable printf/scanf family float support],
++[case "${enableval}" in
++  yes) newlib_io_float=yes ;;
++  no)  newlib_io_float=no ;;
++  *)   AC_MSG_ERROR(bad value ${enableval} for newlib-io-float option) ;;
++ esac], [newlib_io_float=yes])dnl
++
++
++dnl We may get other options which we don't document:
++dnl --with-target-subdir, --with-multisrctop, --with-multisubdir
++
++test -z "[$]{with_target_subdir}" && with_target_subdir=.
++
++if test "[$]{srcdir}" = "."; then
++  if test "[$]{with_target_subdir}" != "."; then
++    newlib_basedir="[$]{srcdir}/[$]{with_multisrctop}../$1"
++  else
++    newlib_basedir="[$]{srcdir}/[$]{with_multisrctop}$1"
++  fi
++else
++  newlib_basedir="[$]{srcdir}/$1"
++fi
++AC_SUBST(newlib_basedir)
++
++AC_CANONICAL_SYSTEM
++
++AM_INIT_AUTOMAKE(newlib, 1.11.0)
++
++# FIXME: We temporarily define our own version of AC_PROG_CC.  This is
++# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS.  We
++# are probably using a cross compiler, which will not be able to fully
++# link an executable.  This should really be fixed in autoconf
++# itself.
++
++AC_DEFUN(LIB_AC_PROG_CC,
++[AC_BEFORE([$0], [AC_PROG_CPP])dnl
++AC_CHECK_PROG(CC, gcc, gcc)
++if test -z "$CC"; then
++  AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc)
++  test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH])
++fi
++
++AC_PROG_CC_GNU
++
++if test $ac_cv_prog_gcc = yes; then
++  GCC=yes
++dnl Check whether -g works, even if CFLAGS is set, in case the package
++dnl plays around with CFLAGS (such as to build both debugging and
++dnl normal versions of a library), tasteless as that idea is.
++  ac_test_CFLAGS="${CFLAGS+set}"
++  ac_save_CFLAGS="$CFLAGS"
++  CFLAGS=
++  AC_PROG_CC_G
++  if test "$ac_test_CFLAGS" = set; then
++    CFLAGS="$ac_save_CFLAGS"
++  elif test $ac_cv_prog_cc_g = yes; then
++    CFLAGS="-g -O2"
++  else
++    CFLAGS="-O2"
++  fi
++else
++  GCC=
++  test "${CFLAGS+set}" = set || CFLAGS="-g"
++fi
++])
++
++LIB_AC_PROG_CC
++
++AC_CHECK_TOOL(AS, as)
++AC_CHECK_TOOL(AR, ar)
++AC_CHECK_TOOL(RANLIB, ranlib, :)
++
++AC_PROG_INSTALL
++
++AM_MAINTAINER_MODE
++
++# We need AC_EXEEXT to keep automake happy in cygnus mode.  However,
++# at least currently, we never actually build a program, so we never
++# need to use $(EXEEXT).  Moreover, the test for EXEEXT normally
++# fails, because we are probably configuring with a cross compiler
++# which can't create executables.  So we include AC_EXEEXT to keep
++# automake happy, but we don't execute it, since we don't care about
++# the result.
++if false; then
++  AC_EXEEXT
++fi
++
++. [$]{newlib_basedir}/configure.host
++
++newlib_cflags="[$]{newlib_cflags} -fno-builtin"
++
++NEWLIB_CFLAGS=${newlib_cflags}
++AC_SUBST(NEWLIB_CFLAGS)
++
++LDFLAGS=${ldflags}
++AC_SUBST(LDFLAGS)
++
++AM_CONDITIONAL(ELIX_LEVEL_0, test x[$]{newlib_elix_level} = x0)
++AM_CONDITIONAL(ELIX_LEVEL_1, test x[$]{newlib_elix_level} = x1)
++AM_CONDITIONAL(ELIX_LEVEL_2, test x[$]{newlib_elix_level} = x2)
++AM_CONDITIONAL(ELIX_LEVEL_3, test x[$]{newlib_elix_level} = x3)
++AM_CONDITIONAL(ELIX_LEVEL_4, test x[$]{newlib_elix_level} = x4)
++
++AM_CONDITIONAL(USE_LIBTOOL, test x[$]{use_libtool} = xyes)
++
++# Hard-code OBJEXT.  Normally it is set by AC_OBJEXT, but we
++# use oext, which is set in configure.host based on the target platform.
++OBJEXT=${oext}
++
++AC_SUBST(OBJEXT)
++AC_SUBST(oext)
++AC_SUBST(aext)
++
++AC_SUBST(libm_machine_dir)
++AC_SUBST(machine_dir)
++AC_SUBST(sys_dir)
++])
++
++# Do all the work for Automake.  This macro actually does too much --
++# some checks are only needed if your package does certain things.
++# But this isn't really a big deal.
++
++# serial 1
++
++dnl Usage:
++dnl AM_INIT_AUTOMAKE(package,version, [no-define])
++
++AC_DEFUN(AM_INIT_AUTOMAKE,
++[AC_REQUIRE([AC_PROG_INSTALL])
++PACKAGE=[$1]
++AC_SUBST(PACKAGE)
++VERSION=[$2]
++AC_SUBST(VERSION)
++dnl test to see if srcdir already configured
++if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
++  AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
++fi
++ifelse([$3],,
++AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
++AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
++AC_REQUIRE([AM_SANITY_CHECK])
++AC_REQUIRE([AC_ARG_PROGRAM])
++dnl FIXME This is truly gross.
++missing_dir=`cd $ac_aux_dir && pwd`
++AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
++AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
++AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
++AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
++AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
++AC_REQUIRE([AC_PROG_MAKE_SET])])
++
++#
++# Check to make sure that the build environment is sane.
++#
++
++AC_DEFUN(AM_SANITY_CHECK,
++[AC_MSG_CHECKING([whether build environment is sane])
++# Just in case
++sleep 1
++echo timestamp > conftestfile
++# Do `set' in a subshell so we don't clobber the current shell's
++# arguments.  Must try -L first in case configure is actually a
++# symlink; some systems play weird games with the mod time of symlinks
++# (eg FreeBSD returns the mod time of the symlink's containing
++# directory).
++if (
++   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
++   if test "[$]*" = "X"; then
++      # -L didn't work.
++      set X `ls -t $srcdir/configure conftestfile`
++   fi
++   if test "[$]*" != "X $srcdir/configure conftestfile" \
++      && test "[$]*" != "X conftestfile $srcdir/configure"; then
++
++      # If neither matched, then we have a broken ls.  This can happen
++      # if, for instance, CONFIG_SHELL is bash and it inherits a
++      # broken ls alias from the environment.  This has actually
++      # happened.  Such a system could not be considered "sane".
++      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
++alias in your environment])
++   fi
++
++   test "[$]2" = conftestfile
++   )
++then
++   # Ok.
++   :
++else
++   AC_MSG_ERROR([newly created file is older than distributed files!
++Check your system clock])
++fi
++rm -f conftest*
++AC_MSG_RESULT(yes)])
++
++dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
++dnl The program must properly implement --version.
++AC_DEFUN(AM_MISSING_PROG,
++[AC_MSG_CHECKING(for working $2)
++# Run test in a subshell; some versions of sh will print an error if
++# an executable is not found, even if stderr is redirected.
++# Redirect stdin to placate older versions of autoconf.  Sigh.
++if ($2 --version) < /dev/null > /dev/null 2>&1; then
++   $1=$2
++   AC_MSG_RESULT(found)
++else
++   $1="$3/missing $2"
++   AC_MSG_RESULT(missing)
++fi
++AC_SUBST($1)])
++
++# Add --enable-maintainer-mode option to configure.
++# From Jim Meyering
++
++# serial 1
++
++AC_DEFUN(AM_MAINTAINER_MODE,
++[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
++  dnl maintainer-mode is disabled by default
++  AC_ARG_ENABLE(maintainer-mode,
++[  --enable-maintainer-mode enable make rules and dependencies not useful
++                          (and sometimes confusing) to the casual installer],
++      USE_MAINTAINER_MODE=$enableval,
++      USE_MAINTAINER_MODE=no)
++  AC_MSG_RESULT($USE_MAINTAINER_MODE)
++  AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes)
++  MAINT=$MAINTAINER_MODE_TRUE
++  AC_SUBST(MAINT)dnl
++]
++)
++
++# Define a conditional.
++
++AC_DEFUN(AM_CONDITIONAL,
++[AC_SUBST($1_TRUE)
++AC_SUBST($1_FALSE)
++if $2; then
++  $1_TRUE=
++  $1_FALSE='#'
++else
++  $1_TRUE='#'
++  $1_FALSE=
++fi])
++
+diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/configure ./newlib/libc/sys/mipsunknown/configure
+--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/configure        Wed Dec 31 19:00:00 1969
++++ ./newlib/libc/sys/mipsunknown/configure    Mon Nov 24 20:43:05 2003
+@@ -0,0 +1,1863 @@
++#! /bin/sh
++
++# Guess values for system-dependent variables and create Makefiles.
++# Generated automatically using autoconf version 2.13 
++# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
++#
++# This configure script is free software; the Free Software Foundation
++# gives unlimited permission to copy, distribute and modify it.
++
++# Defaults:
++ac_help=
++ac_default_prefix=/usr/local
++# Any additions from configure.in:
++ac_help="$ac_help
++  --enable-multilib         build many library versions (default)"
++ac_help="$ac_help
++  --enable-target-optspace  optimize for space"
++ac_help="$ac_help
++  --enable-malloc-debugging indicate malloc debugging requested"
++ac_help="$ac_help
++  --enable-newlib-mb        enable multibyte support"
++ac_help="$ac_help
++  --enable-newlib-multithread        enable support for multiple threads"
++ac_help="$ac_help
++  --enable-newlib-elix-level         supply desired elix library level (1-4)"
++ac_help="$ac_help
++  --disable-newlib-io-float disable printf/scanf family float support"
++ac_help="$ac_help
++  --enable-maintainer-mode enable make rules and dependencies not useful
++                          (and sometimes confusing) to the casual installer"
++
++# Initialize some variables set by options.
++# The variables have the same names as the options, with
++# dashes changed to underlines.
++build=NONE
++cache_file=./config.cache
++exec_prefix=NONE
++host=NONE
++no_create=
++nonopt=NONE
++no_recursion=
++prefix=NONE
++program_prefix=NONE
++program_suffix=NONE
++program_transform_name=s,x,x,
++silent=
++site=
++sitefile=
++srcdir=
++target=NONE
++verbose=
++x_includes=NONE
++x_libraries=NONE
++bindir='${exec_prefix}/bin'
++sbindir='${exec_prefix}/sbin'
++libexecdir='${exec_prefix}/libexec'
++datadir='${prefix}/share'
++sysconfdir='${prefix}/etc'
++sharedstatedir='${prefix}/com'
++localstatedir='${prefix}/var'
++libdir='${exec_prefix}/lib'
++includedir='${prefix}/include'
++oldincludedir='/usr/include'
++infodir='${prefix}/info'
++mandir='${prefix}/man'
++
++# Initialize some other variables.
++subdirs=
++MFLAGS= MAKEFLAGS=
++SHELL=${CONFIG_SHELL-/bin/sh}
++# Maximum number of lines to put in a shell here document.
++ac_max_here_lines=12
++
++ac_prev=
++for ac_option
++do
++
++  # If the previous option needs an argument, assign it.
++  if test -n "$ac_prev"; then
++    eval "$ac_prev=\$ac_option"
++    ac_prev=
++    continue
++  fi
++
++  case "$ac_option" in
++  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
++  *) ac_optarg= ;;
++  esac
++
++  # Accept the important Cygnus configure options, so we can diagnose typos.
++
++  case "$ac_option" in
++
++  -bindir | --bindir | --bindi | --bind | --bin | --bi)
++    ac_prev=bindir ;;
++  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
++    bindir="$ac_optarg" ;;
++
++  -build | --build | --buil | --bui | --bu)
++    ac_prev=build ;;
++  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
++    build="$ac_optarg" ;;
++
++  -cache-file | --cache-file | --cache-fil | --cache-fi \
++  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
++    ac_prev=cache_file ;;
++  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
++  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
++    cache_file="$ac_optarg" ;;
++
++  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
++    ac_prev=datadir ;;
++  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
++  | --da=*)
++    datadir="$ac_optarg" ;;
++
++  -disable-* | --disable-*)
++    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
++    # Reject names that are not valid shell variable names.
++    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
++      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
++    fi
++    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
++    eval "enable_${ac_feature}=no" ;;
++
++  -enable-* | --enable-*)
++    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
++    # Reject names that are not valid shell variable names.
++    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
++      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
++    fi
++    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
++    case "$ac_option" in
++      *=*) ;;
++      *) ac_optarg=yes ;;
++    esac
++    eval "enable_${ac_feature}='$ac_optarg'" ;;
++
++  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
++  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
++  | --exec | --exe | --ex)
++    ac_prev=exec_prefix ;;
++  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
++  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
++  | --exec=* | --exe=* | --ex=*)
++    exec_prefix="$ac_optarg" ;;
++
++  -gas | --gas | --ga | --g)
++    # Obsolete; use --with-gas.
++    with_gas=yes ;;
++
++  -help | --help | --hel | --he)
++    # Omit some internal or obsolete options to make the list less imposing.
++    # This message is too long to be a string in the A/UX 3.1 sh.
++    cat << EOF
++Usage: configure [options] [host]
++Options: [defaults in brackets after descriptions]
++Configuration:
++  --cache-file=FILE       cache test results in FILE
++  --help                  print this message
++  --no-create             do not create output files
++  --quiet, --silent       do not print \`checking...' messages
++  --site-file=FILE        use FILE as the site file
++  --version               print the version of autoconf that created configure
++Directory and file names:
++  --prefix=PREFIX         install architecture-independent files in PREFIX
++                          [$ac_default_prefix]
++  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
++                          [same as prefix]
++  --bindir=DIR            user executables in DIR [EPREFIX/bin]
++  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
++  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
++  --datadir=DIR           read-only architecture-independent data in DIR
++                          [PREFIX/share]
++  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
++  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
++                          [PREFIX/com]
++  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
++  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
++  --includedir=DIR        C header files in DIR [PREFIX/include]
++  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
++  --infodir=DIR           info documentation in DIR [PREFIX/info]
++  --mandir=DIR            man documentation in DIR [PREFIX/man]
++  --srcdir=DIR            find the sources in DIR [configure dir or ..]
++  --program-prefix=PREFIX prepend PREFIX to installed program names
++  --program-suffix=SUFFIX append SUFFIX to installed program names
++  --program-transform-name=PROGRAM
++                          run sed PROGRAM on installed program names
++EOF
++    cat << EOF
++Host type:
++  --build=BUILD           configure for building on BUILD [BUILD=HOST]
++  --host=HOST             configure for HOST [guessed]
++  --target=TARGET         configure for TARGET [TARGET=HOST]
++Features and packages:
++  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
++  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
++  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
++  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
++  --x-includes=DIR        X include files are in DIR
++  --x-libraries=DIR       X library files are in DIR
++EOF
++    if test -n "$ac_help"; then
++      echo "--enable and --with options recognized:$ac_help"
++    fi
++    exit 0 ;;
++
++  -host | --host | --hos | --ho)
++    ac_prev=host ;;
++  -host=* | --host=* | --hos=* | --ho=*)
++    host="$ac_optarg" ;;
++
++  -includedir | --includedir | --includedi | --included | --include \
++  | --includ | --inclu | --incl | --inc)
++    ac_prev=includedir ;;
++  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
++  | --includ=* | --inclu=* | --incl=* | --inc=*)
++    includedir="$ac_optarg" ;;
++
++  -infodir | --infodir | --infodi | --infod | --info | --inf)
++    ac_prev=infodir ;;
++  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
++    infodir="$ac_optarg" ;;
++
++  -libdir | --libdir | --libdi | --libd)
++    ac_prev=libdir ;;
++  -libdir=* | --libdir=* | --libdi=* | --libd=*)
++    libdir="$ac_optarg" ;;
++
++  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
++  | --libexe | --libex | --libe)
++    ac_prev=libexecdir ;;
++  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
++  | --libexe=* | --libex=* | --libe=*)
++    libexecdir="$ac_optarg" ;;
++
++  -localstatedir | --localstatedir | --localstatedi | --localstated \
++  | --localstate | --localstat | --localsta | --localst \
++  | --locals | --local | --loca | --loc | --lo)
++    ac_prev=localstatedir ;;
++  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
++  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
++  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
++    localstatedir="$ac_optarg" ;;
++
++  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
++    ac_prev=mandir ;;
++  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
++    mandir="$ac_optarg" ;;
++
++  -nfp | --nfp | --nf)
++    # Obsolete; use --without-fp.
++    with_fp=no ;;
++
++  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
++  | --no-cr | --no-c)
++    no_create=yes ;;
++
++  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
++  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
++    no_recursion=yes ;;
++
++  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
++  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
++  | --oldin | --oldi | --old | --ol | --o)
++    ac_prev=oldincludedir ;;
++  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
++  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
++  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
++    oldincludedir="$ac_optarg" ;;
++
++  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
++    ac_prev=prefix ;;
++  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
++    prefix="$ac_optarg" ;;
++
++  -program-prefix | --program-prefix | --program-prefi | --program-pref \
++  | --program-pre | --program-pr | --program-p)
++    ac_prev=program_prefix ;;
++  -program-prefix=* | --program-prefix=* | --program-prefi=* \
++  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
++    program_prefix="$ac_optarg" ;;
++
++  -program-suffix | --program-suffix | --program-suffi | --program-suff \
++  | --program-suf | --program-su | --program-s)
++    ac_prev=program_suffix ;;
++  -program-suffix=* | --program-suffix=* | --program-suffi=* \
++  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
++    program_suffix="$ac_optarg" ;;
++
++  -program-transform-name | --program-transform-name \
++  | --program-transform-nam | --program-transform-na \
++  | --program-transform-n | --program-transform- \
++  | --program-transform | --program-transfor \
++  | --program-transfo | --program-transf \
++  | --program-trans | --program-tran \
++  | --progr-tra | --program-tr | --program-t)
++    ac_prev=program_transform_name ;;
++  -program-transform-name=* | --program-transform-name=* \
++  | --program-transform-nam=* | --program-transform-na=* \
++  | --program-transform-n=* | --program-transform-=* \
++  | --program-transform=* | --program-transfor=* \
++  | --program-transfo=* | --program-transf=* \
++  | --program-trans=* | --program-tran=* \
++  | --progr-tra=* | --program-tr=* | --program-t=*)
++    program_transform_name="$ac_optarg" ;;
++
++  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
++  | -silent | --silent | --silen | --sile | --sil)
++    silent=yes ;;
++
++  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
++    ac_prev=sbindir ;;
++  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
++  | --sbi=* | --sb=*)
++    sbindir="$ac_optarg" ;;
++
++  -sharedstatedir | --sharedstatedir | --sharedstatedi \
++  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
++  | --sharedst | --shareds | --shared | --share | --shar \
++  | --sha | --sh)
++    ac_prev=sharedstatedir ;;
++  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
++  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
++  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
++  | --sha=* | --sh=*)
++    sharedstatedir="$ac_optarg" ;;
++
++  -site | --site | --sit)
++    ac_prev=site ;;
++  -site=* | --site=* | --sit=*)
++    site="$ac_optarg" ;;
++
++  -site-file | --site-file | --site-fil | --site-fi | --site-f)
++    ac_prev=sitefile ;;
++  -site-file=* | --site-file=* | --site-fil=* | --site-fi=* | --site-f=*)
++    sitefile="$ac_optarg" ;;
++
++  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
++    ac_prev=srcdir ;;
++  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
++    srcdir="$ac_optarg" ;;
++
++  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
++  | --syscon | --sysco | --sysc | --sys | --sy)
++    ac_prev=sysconfdir ;;
++  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
++  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
++    sysconfdir="$ac_optarg" ;;
++
++  -target | --target | --targe | --targ | --tar | --ta | --t)
++    ac_prev=target ;;
++  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
++    target="$ac_optarg" ;;
++
++  -v | -verbose | --verbose | --verbos | --verbo | --verb)
++    verbose=yes ;;
++
++  -version | --version | --versio | --versi | --vers)
++    echo "configure generated by autoconf version 2.13"
++    exit 0 ;;
++
++  -with-* | --with-*)
++    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
++    # Reject names that are not valid shell variable names.
++    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
++      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
++    fi
++    ac_package=`echo $ac_package| sed 's/-/_/g'`
++    case "$ac_option" in
++      *=*) ;;
++      *) ac_optarg=yes ;;
++    esac
++    eval "with_${ac_package}='$ac_optarg'" ;;
++
++  -without-* | --without-*)
++    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
++    # Reject names that are not valid shell variable names.
++    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
++      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
++    fi
++    ac_package=`echo $ac_package| sed 's/-/_/g'`
++    eval "with_${ac_package}=no" ;;
++
++  --x)
++    # Obsolete; use --with-x.
++    with_x=yes ;;
++
++  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
++  | --x-incl | --x-inc | --x-in | --x-i)
++    ac_prev=x_includes ;;
++  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
++  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
++    x_includes="$ac_optarg" ;;
++
++  -x-libraries | --x-libraries | --x-librarie | --x-librari \
++  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
++    ac_prev=x_libraries ;;
++  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
++  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
++    x_libraries="$ac_optarg" ;;
++
++  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
++    ;;
++
++  *)
++    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
++      echo "configure: warning: $ac_option: invalid host type" 1>&2
++    fi
++    if test "x$nonopt" != xNONE; then
++      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
++    fi
++    nonopt="$ac_option"
++    ;;
++
++  esac
++done
++
++if test -n "$ac_prev"; then
++  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
++fi
++
++trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
++
++# File descriptor usage:
++# 0 standard input
++# 1 file creation
++# 2 errors and warnings
++# 3 some systems may open it to /dev/tty
++# 4 used on the Kubota Titan
++# 6 checking for... messages and results
++# 5 compiler messages saved in config.log
++if test "$silent" = yes; then
++  exec 6>/dev/null
++else
++  exec 6>&1
++fi
++exec 5>./config.log
++
++echo "\
++This file contains any messages produced by compilers while
++running configure, to aid debugging if configure makes a mistake.
++" 1>&5
++
++# Strip out --no-create and --no-recursion so they do not pile up.
++# Also quote any args containing shell metacharacters.
++ac_configure_args=
++for ac_arg
++do
++  case "$ac_arg" in
++  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
++  | --no-cr | --no-c) ;;
++  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
++  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
++  *" "*|*"    "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
++  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
++  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
++  esac
++done
++
++# NLS nuisances.
++# Only set these to C if already set.  These must not be set unconditionally
++# because not all systems understand e.g. LANG=C (notably SCO).
++# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
++# Non-C LC_CTYPE values break the ctype check.
++if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
++if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
++if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
++if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
++
++# confdefs.h avoids OS command line length limits that DEFS can exceed.
++rm -rf conftest* confdefs.h
++# AIX cpp loses on an empty file, so make sure it contains at least a newline.
++echo > confdefs.h
++
++# A filename unique to this package, relative to the directory that
++# configure is in, which we can look for to find out if srcdir is correct.
++ac_unique_file=syscalls.c
++
++# Find the source files, if location was not specified.
++if test -z "$srcdir"; then
++  ac_srcdir_defaulted=yes
++  # Try the directory containing this script, then its parent.
++  ac_prog=$0
++  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
++  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
++  srcdir=$ac_confdir
++  if test ! -r $srcdir/$ac_unique_file; then
++    srcdir=..
++  fi
++else
++  ac_srcdir_defaulted=no
++fi
++if test ! -r $srcdir/$ac_unique_file; then
++  if test "$ac_srcdir_defaulted" = yes; then
++    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
++  else
++    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
++  fi
++fi
++srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
++
++# Prefer explicitly selected file to automatically selected ones.
++if test -z "$sitefile"; then
++  if test -z "$CONFIG_SITE"; then
++    if test "x$prefix" != xNONE; then
++      CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
++    else
++      CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
++    fi
++  fi
++else
++  CONFIG_SITE="$sitefile"
++fi
++for ac_site_file in $CONFIG_SITE; do
++  if test -r "$ac_site_file"; then
++    echo "loading site script $ac_site_file"
++    . "$ac_site_file"
++  fi
++done
++
++if test -r "$cache_file"; then
++  echo "loading cache $cache_file"
++  . $cache_file
++else
++  echo "creating cache $cache_file"
++  > $cache_file
++fi
++
++ac_ext=c
++# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
++ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
++cross_compiling=$ac_cv_prog_cc_cross
++
++ac_exeext=
++ac_objext=o
++if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
++  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
++  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
++    ac_n= ac_c='
++' ac_t='      '
++  else
++    ac_n=-n ac_c= ac_t=
++  fi
++else
++  ac_n= ac_c='\c' ac_t=
++fi
++
++
++
++ac_aux_dir=
++for ac_dir in ../../../.. $srcdir/../../../..; do
++  if test -f $ac_dir/install-sh; then
++    ac_aux_dir=$ac_dir
++    ac_install_sh="$ac_aux_dir/install-sh -c"
++    break
++  elif test -f $ac_dir/install.sh; then
++    ac_aux_dir=$ac_dir
++    ac_install_sh="$ac_aux_dir/install.sh -c"
++    break
++  fi
++done
++if test -z "$ac_aux_dir"; then
++  { echo "configure: error: can not find install-sh or install.sh in ../../../.. $srcdir/../../../.." 1>&2; exit 1; }
++fi
++ac_config_guess=$ac_aux_dir/config.guess
++ac_config_sub=$ac_aux_dir/config.sub
++ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
++
++
++# Find a good install program.  We prefer a C program (faster),
++# so one script is as good as another.  But avoid the broken or
++# incompatible versions:
++# SysV /etc/install, /usr/sbin/install
++# SunOS /usr/etc/install
++# IRIX /sbin/install
++# AIX /bin/install
++# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
++# AFS /usr/afsws/bin/install, which mishandles nonexistent args
++# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
++# ./install, which can be erroneously created by make from ./install.sh.
++echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
++echo "configure:586: checking for a BSD compatible install" >&5
++if test -z "$INSTALL"; then
++if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++    IFS="${IFS=       }"; ac_save_IFS="$IFS"; IFS=":"
++  for ac_dir in $PATH; do
++    # Account for people who put trailing slashes in PATH elements.
++    case "$ac_dir/" in
++    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
++    *)
++      # OSF1 and SCO ODT 3.0 have their own names for install.
++      # Don't use installbsd from OSF since it installs stuff as root
++      # by default.
++      for ac_prog in ginstall scoinst install; do
++        if test -f $ac_dir/$ac_prog; then
++        if test $ac_prog = install &&
++            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
++          # AIX install.  It has an incompatible calling convention.
++          :
++        else
++          ac_cv_path_install="$ac_dir/$ac_prog -c"
++          break 2
++        fi
++      fi
++      done
++      ;;
++    esac
++  done
++  IFS="$ac_save_IFS"
++
++fi
++  if test "${ac_cv_path_install+set}" = set; then
++    INSTALL="$ac_cv_path_install"
++  else
++    # As a last resort, use the slow shell script.  We don't cache a
++    # path for INSTALL within a source directory, because that will
++    # break other packages using the cache if that directory is
++    # removed, or if the path is relative.
++    INSTALL="$ac_install_sh"
++  fi
++fi
++echo "$ac_t""$INSTALL" 1>&6
++
++# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
++# It thinks the first close brace ends the variable substitution.
++test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
++
++test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
++
++test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
++
++echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
++echo "configure:639: checking whether build environment is sane" >&5
++# Just in case
++sleep 1
++echo timestamp > conftestfile
++# Do `set' in a subshell so we don't clobber the current shell's
++# arguments.  Must try -L first in case configure is actually a
++# symlink; some systems play weird games with the mod time of symlinks
++# (eg FreeBSD returns the mod time of the symlink's containing
++# directory).
++if (
++   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
++   if test "$*" = "X"; then
++      # -L didn't work.
++      set X `ls -t $srcdir/configure conftestfile`
++   fi
++   if test "$*" != "X $srcdir/configure conftestfile" \
++      && test "$*" != "X conftestfile $srcdir/configure"; then
++
++      # If neither matched, then we have a broken ls.  This can happen
++      # if, for instance, CONFIG_SHELL is bash and it inherits a
++      # broken ls alias from the environment.  This has actually
++      # happened.  Such a system could not be considered "sane".
++      { echo "configure: error: ls -t appears to fail.  Make sure there is not a broken
++alias in your environment" 1>&2; exit 1; }
++   fi
++
++   test "$2" = conftestfile
++   )
++then
++   # Ok.
++   :
++else
++   { echo "configure: error: newly created file is older than distributed files!
++Check your system clock" 1>&2; exit 1; }
++fi
++rm -f conftest*
++echo "$ac_t""yes" 1>&6
++if test "$program_transform_name" = s,x,x,; then
++  program_transform_name=
++else
++  # Double any \ or $.  echo might interpret backslashes.
++  cat <<\EOF_SED > conftestsed
++s,\\,\\\\,g; s,\$,$$,g
++EOF_SED
++  program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
++  rm -f conftestsed
++fi
++test "$program_prefix" != NONE &&
++  program_transform_name="s,^,${program_prefix},; $program_transform_name"
++# Use a double $ so make ignores it.
++test "$program_suffix" != NONE &&
++  program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
++
++# sed with no file args requires a program.
++test "$program_transform_name" = "" && program_transform_name="s,x,x,"
++
++echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
++echo "configure:696: checking whether ${MAKE-make} sets \${MAKE}" >&5
++set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
++if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  cat > conftestmake <<\EOF
++all:
++      @echo 'ac_maketemp="${MAKE}"'
++EOF
++# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
++eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
++if test -n "$ac_maketemp"; then
++  eval ac_cv_prog_make_${ac_make}_set=yes
++else
++  eval ac_cv_prog_make_${ac_make}_set=no
++fi
++rm -f conftestmake
++fi
++if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
++  echo "$ac_t""yes" 1>&6
++  SET_MAKE=
++else
++  echo "$ac_t""no" 1>&6
++  SET_MAKE="MAKE=${MAKE-make}"
++fi
++
++if test $host != $build; then
++  ac_tool_prefix=${host_alias}-
++else
++  ac_tool_prefix=
++fi
++
++echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
++echo "configure:729: checking for Cygwin environment" >&5
++if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  cat > conftest.$ac_ext <<EOF
++#line 734 "configure"
++#include "confdefs.h"
++
++int main() {
++
++#ifndef __CYGWIN__
++#define __CYGWIN__ __CYGWIN32__
++#endif
++return __CYGWIN__;
++; return 0; }
++EOF
++if { (eval echo configure:745: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
++  rm -rf conftest*
++  ac_cv_cygwin=yes
++else
++  echo "configure: failed program was:" >&5
++  cat conftest.$ac_ext >&5
++  rm -rf conftest*
++  ac_cv_cygwin=no
++fi
++rm -f conftest*
++rm -f conftest*
++fi
++
++echo "$ac_t""$ac_cv_cygwin" 1>&6
++CYGWIN=
++test "$ac_cv_cygwin" = yes && CYGWIN=yes
++echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
++echo "configure:762: checking for mingw32 environment" >&5
++if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  cat > conftest.$ac_ext <<EOF
++#line 767 "configure"
++#include "confdefs.h"
++
++int main() {
++return __MINGW32__;
++; return 0; }
++EOF
++if { (eval echo configure:774: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
++  rm -rf conftest*
++  ac_cv_mingw32=yes
++else
++  echo "configure: failed program was:" >&5
++  cat conftest.$ac_ext >&5
++  rm -rf conftest*
++  ac_cv_mingw32=no
++fi
++rm -f conftest*
++rm -f conftest*
++fi
++
++echo "$ac_t""$ac_cv_mingw32" 1>&6
++MINGW32=
++test "$ac_cv_mingw32" = yes && MINGW32=yes
++
++# Check whether --enable-multilib or --disable-multilib was given.
++if test "${enable_multilib+set}" = set; then
++  enableval="$enable_multilib"
++  case "${enableval}" in
++  yes) multilib=yes ;;
++  no)  multilib=no ;;
++  *)   { echo "configure: error: bad value ${enableval} for multilib option" 1>&2; exit 1; } ;;
++ esac
++else
++  multilib=yes
++fi
++
++# Check whether --enable-target-optspace or --disable-target-optspace was given.
++if test "${enable_target_optspace+set}" = set; then
++  enableval="$enable_target_optspace"
++  case "${enableval}" in
++  yes) target_optspace=yes ;;
++  no)  target_optspace=no ;;
++  *)   { echo "configure: error: bad value ${enableval} for target-optspace option" 1>&2; exit 1; } ;;
++ esac
++else
++  target_optspace=
++fi
++
++# Check whether --enable-malloc-debugging or --disable-malloc-debugging was given.
++if test "${enable_malloc_debugging+set}" = set; then
++  enableval="$enable_malloc_debugging"
++  case "${enableval}" in
++  yes) malloc_debugging=yes ;;
++  no)  malloc_debugging=no ;;
++  *)   { echo "configure: error: bad value ${enableval} for malloc-debugging option" 1>&2; exit 1; } ;;
++ esac
++else
++  malloc_debugging=
++fi
++
++# Check whether --enable-newlib-mb or --disable-newlib-mb was given.
++if test "${enable_newlib_mb+set}" = set; then
++  enableval="$enable_newlib_mb"
++  case "${enableval}" in
++  yes) newlib_mb=yes ;;
++  no)  newlib_mb=no ;;
++  *)   { echo "configure: error: bad value ${enableval} for newlib-mb option" 1>&2; exit 1; } ;;
++ esac
++else
++  newlib_mb=
++fi
++
++# Check whether --enable-newlib-multithread or --disable-newlib-multithread was given.
++if test "${enable_newlib_multithread+set}" = set; then
++  enableval="$enable_newlib_multithread"
++  case "${enableval}" in
++  yes) newlib_multithread=yes ;;
++  no)  newlib_multithread=no ;;
++  *)   { echo "configure: error: bad value ${enableval} for newlib-multithread option" 1>&2; exit 1; } ;;
++ esac
++else
++  newlib_multithread=yes
++fi
++
++# Check whether --enable-newlib-elix-level or --disable-newlib-elix-level was given.
++if test "${enable_newlib_elix_level+set}" = set; then
++  enableval="$enable_newlib_elix_level"
++  case "${enableval}" in
++  0)   newlib_elix_level=0 ;;
++  1)   newlib_elix_level=1 ;;
++  2)   newlib_elix_level=2 ;;
++  3)   newlib_elix_level=3 ;;
++  4)   newlib_elix_level=4 ;;
++  *)   { echo "configure: error: bad value ${enableval} for newlib-elix-level option" 1>&2; exit 1; } ;;
++ esac
++else
++  newlib_elix_level=0
++fi
++
++# Check whether --enable-newlib-io-float or --disable-newlib-io-float was given.
++if test "${enable_newlib_io_float+set}" = set; then
++  enableval="$enable_newlib_io_float"
++  case "${enableval}" in
++  yes) newlib_io_float=yes ;;
++  no)  newlib_io_float=no ;;
++  *)   { echo "configure: error: bad value ${enableval} for newlib-io-float option" 1>&2; exit 1; } ;;
++ esac
++else
++  newlib_io_float=yes
++fi
++
++
++
++test -z "${with_target_subdir}" && with_target_subdir=.
++
++if test "${srcdir}" = "."; then
++  if test "${with_target_subdir}" != "."; then
++    newlib_basedir="${srcdir}/${with_multisrctop}../../../.."
++  else
++    newlib_basedir="${srcdir}/${with_multisrctop}../../.."
++  fi
++else
++  newlib_basedir="${srcdir}/../../.."
++fi
++
++
++
++# Do some error checking and defaulting for the host and target type.
++# The inputs are:
++#    configure --host=HOST --target=TARGET --build=BUILD NONOPT
++#
++# The rules are:
++# 1. You are not allowed to specify --host, --target, and nonopt at the
++#    same time.
++# 2. Host defaults to nonopt.
++# 3. If nonopt is not specified, then host defaults to the current host,
++#    as determined by config.guess.
++# 4. Target and build default to nonopt.
++# 5. If nonopt is not specified, then target and build default to host.
++
++# The aliases save the names the user supplied, while $host etc.
++# will get canonicalized.
++case $host---$target---$nonopt in
++NONE---*---* | *---NONE---* | *---*---NONE) ;;
++*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
++esac
++
++
++# Make sure we can run config.sub.
++if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
++else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
++fi
++
++echo $ac_n "checking host system type""... $ac_c" 1>&6
++echo "configure:921: checking host system type" >&5
++
++host_alias=$host
++case "$host_alias" in
++NONE)
++  case $nonopt in
++  NONE)
++    if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
++    else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
++    fi ;;
++  *) host_alias=$nonopt ;;
++  esac ;;
++esac
++
++host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
++host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
++host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
++host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
++echo "$ac_t""$host" 1>&6
++
++echo $ac_n "checking target system type""... $ac_c" 1>&6
++echo "configure:942: checking target system type" >&5
++
++target_alias=$target
++case "$target_alias" in
++NONE)
++  case $nonopt in
++  NONE) target_alias=$host_alias ;;
++  *) target_alias=$nonopt ;;
++  esac ;;
++esac
++
++target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
++target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
++target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
++target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
++echo "$ac_t""$target" 1>&6
++
++echo $ac_n "checking build system type""... $ac_c" 1>&6
++echo "configure:960: checking build system type" >&5
++
++build_alias=$build
++case "$build_alias" in
++NONE)
++  case $nonopt in
++  NONE) build_alias=$host_alias ;;
++  *) build_alias=$nonopt ;;
++  esac ;;
++esac
++
++build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
++build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
++build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
++build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
++echo "$ac_t""$build" 1>&6
++
++test "$host_alias" != "$target_alias" &&
++  test "$program_prefix$program_suffix$program_transform_name" = \
++    NONENONEs,x,x, &&
++  program_prefix=${target_alias}-
++
++
++
++PACKAGE=newlib
++
++VERSION=1.11.0
++
++if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
++  { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
++fi
++cat >> confdefs.h <<EOF
++#define PACKAGE "$PACKAGE"
++EOF
++
++cat >> confdefs.h <<EOF
++#define VERSION "$VERSION"
++EOF
++
++
++
++missing_dir=`cd $ac_aux_dir && pwd`
++echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
++echo "configure:1003: checking for working aclocal" >&5
++# Run test in a subshell; some versions of sh will print an error if
++# an executable is not found, even if stderr is redirected.
++# Redirect stdin to placate older versions of autoconf.  Sigh.
++if (aclocal --version) < /dev/null > /dev/null 2>&1; then
++   ACLOCAL=aclocal
++   echo "$ac_t""found" 1>&6
++else
++   ACLOCAL="$missing_dir/missing aclocal"
++   echo "$ac_t""missing" 1>&6
++fi
++
++echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
++echo "configure:1016: checking for working autoconf" >&5
++# Run test in a subshell; some versions of sh will print an error if
++# an executable is not found, even if stderr is redirected.
++# Redirect stdin to placate older versions of autoconf.  Sigh.
++if (autoconf --version) < /dev/null > /dev/null 2>&1; then
++   AUTOCONF=autoconf
++   echo "$ac_t""found" 1>&6
++else
++   AUTOCONF="$missing_dir/missing autoconf"
++   echo "$ac_t""missing" 1>&6
++fi
++
++echo $ac_n "checking for working automake""... $ac_c" 1>&6
++echo "configure:1029: checking for working automake" >&5
++# Run test in a subshell; some versions of sh will print an error if
++# an executable is not found, even if stderr is redirected.
++# Redirect stdin to placate older versions of autoconf.  Sigh.
++if (automake --version) < /dev/null > /dev/null 2>&1; then
++   AUTOMAKE=automake
++   echo "$ac_t""found" 1>&6
++else
++   AUTOMAKE="$missing_dir/missing automake"
++   echo "$ac_t""missing" 1>&6
++fi
++
++echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
++echo "configure:1042: checking for working autoheader" >&5
++# Run test in a subshell; some versions of sh will print an error if
++# an executable is not found, even if stderr is redirected.
++# Redirect stdin to placate older versions of autoconf.  Sigh.
++if (autoheader --version) < /dev/null > /dev/null 2>&1; then
++   AUTOHEADER=autoheader
++   echo "$ac_t""found" 1>&6
++else
++   AUTOHEADER="$missing_dir/missing autoheader"
++   echo "$ac_t""missing" 1>&6
++fi
++
++echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
++echo "configure:1055: checking for working makeinfo" >&5
++# Run test in a subshell; some versions of sh will print an error if
++# an executable is not found, even if stderr is redirected.
++# Redirect stdin to placate older versions of autoconf.  Sigh.
++if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
++   MAKEINFO=makeinfo
++   echo "$ac_t""found" 1>&6
++else
++   MAKEINFO="$missing_dir/missing makeinfo"
++   echo "$ac_t""missing" 1>&6
++fi
++
++
++
++# FIXME: We temporarily define our own version of AC_PROG_CC.  This is
++# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS.  We
++# are probably using a cross compiler, which will not be able to fully
++# link an executable.  This should really be fixed in autoconf
++# itself.
++
++
++
++# Extract the first word of "gcc", so it can be a program name with args.
++set dummy gcc; ac_word=$2
++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
++echo "configure:1080: checking for $ac_word" >&5
++if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++  IFS="${IFS=         }"; ac_save_ifs="$IFS"; IFS=":"
++  ac_dummy="$PATH"
++  for ac_dir in $ac_dummy; do
++    test -z "$ac_dir" && ac_dir=.
++    if test -f $ac_dir/$ac_word; then
++      ac_cv_prog_CC="gcc"
++      break
++    fi
++  done
++  IFS="$ac_save_ifs"
++fi
++fi
++CC="$ac_cv_prog_CC"
++if test -n "$CC"; then
++  echo "$ac_t""$CC" 1>&6
++else
++  echo "$ac_t""no" 1>&6
++fi
++
++if test -z "$CC"; then
++  # Extract the first word of "cc", so it can be a program name with args.
++set dummy cc; ac_word=$2
++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
++echo "configure:1110: checking for $ac_word" >&5
++if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++  IFS="${IFS=         }"; ac_save_ifs="$IFS"; IFS=":"
++  ac_prog_rejected=no
++  ac_dummy="$PATH"
++  for ac_dir in $ac_dummy; do
++    test -z "$ac_dir" && ac_dir=.
++    if test -f $ac_dir/$ac_word; then
++      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
++        ac_prog_rejected=yes
++      continue
++      fi
++      ac_cv_prog_CC="cc"
++      break
++    fi
++  done
++  IFS="$ac_save_ifs"
++if test $ac_prog_rejected = yes; then
++  # We found a bogon in the path, so make sure we never use it.
++  set dummy $ac_cv_prog_CC
++  shift
++  if test $# -gt 0; then
++    # We chose a different compiler from the bogus one.
++    # However, it has the same basename, so the bogon will be chosen
++    # first if we set CC to just the basename; use the full file name.
++    shift
++    set dummy "$ac_dir/$ac_word" "$@"
++    shift
++    ac_cv_prog_CC="$@"
++  fi
++fi
++fi
++fi
++CC="$ac_cv_prog_CC"
++if test -n "$CC"; then
++  echo "$ac_t""$CC" 1>&6
++else
++  echo "$ac_t""no" 1>&6
++fi
++
++  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
++fi
++
++echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
++echo "configure:1159: checking whether we are using GNU C" >&5
++if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  cat > conftest.c <<EOF
++#ifdef __GNUC__
++  yes;
++#endif
++EOF
++if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1168: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
++  ac_cv_prog_gcc=yes
++else
++  ac_cv_prog_gcc=no
++fi
++fi
++
++echo "$ac_t""$ac_cv_prog_gcc" 1>&6
++
++if test $ac_cv_prog_gcc = yes; then
++  GCC=yes
++  ac_test_CFLAGS="${CFLAGS+set}"
++  ac_save_CFLAGS="$CFLAGS"
++  CFLAGS=
++  echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
++echo "configure:1183: checking whether ${CC-cc} accepts -g" >&5
++if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  echo 'void f(){}' > conftest.c
++if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
++  ac_cv_prog_cc_g=yes
++else
++  ac_cv_prog_cc_g=no
++fi
++rm -f conftest*
++
++fi
++
++echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
++  if test "$ac_test_CFLAGS" = set; then
++    CFLAGS="$ac_save_CFLAGS"
++  elif test $ac_cv_prog_cc_g = yes; then
++    CFLAGS="-g -O2"
++  else
++    CFLAGS="-O2"
++  fi
++else
++  GCC=
++  test "${CFLAGS+set}" = set || CFLAGS="-g"
++fi
++
++
++# Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
++set dummy ${ac_tool_prefix}as; ac_word=$2
++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
++echo "configure:1214: checking for $ac_word" >&5
++if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  if test -n "$AS"; then
++  ac_cv_prog_AS="$AS" # Let the user override the test.
++else
++  IFS="${IFS=         }"; ac_save_ifs="$IFS"; IFS=":"
++  ac_dummy="$PATH"
++  for ac_dir in $ac_dummy; do
++    test -z "$ac_dir" && ac_dir=.
++    if test -f $ac_dir/$ac_word; then
++      ac_cv_prog_AS="${ac_tool_prefix}as"
++      break
++    fi
++  done
++  IFS="$ac_save_ifs"
++  test -z "$ac_cv_prog_AS" && ac_cv_prog_AS="as"
++fi
++fi
++AS="$ac_cv_prog_AS"
++if test -n "$AS"; then
++  echo "$ac_t""$AS" 1>&6
++else
++  echo "$ac_t""no" 1>&6
++fi
++
++
++
++# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
++set dummy ${ac_tool_prefix}ar; ac_word=$2
++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
++echo "configure:1246: checking for $ac_word" >&5
++if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  if test -n "$AR"; then
++  ac_cv_prog_AR="$AR" # Let the user override the test.
++else
++  IFS="${IFS=         }"; ac_save_ifs="$IFS"; IFS=":"
++  ac_dummy="$PATH"
++  for ac_dir in $ac_dummy; do
++    test -z "$ac_dir" && ac_dir=.
++    if test -f $ac_dir/$ac_word; then
++      ac_cv_prog_AR="${ac_tool_prefix}ar"
++      break
++    fi
++  done
++  IFS="$ac_save_ifs"
++  test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="ar"
++fi
++fi
++AR="$ac_cv_prog_AR"
++if test -n "$AR"; then
++  echo "$ac_t""$AR" 1>&6
++else
++  echo "$ac_t""no" 1>&6
++fi
++
++
++
++# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
++set dummy ${ac_tool_prefix}ranlib; ac_word=$2
++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
++echo "configure:1278: checking for $ac_word" >&5
++if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  if test -n "$RANLIB"; then
++  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
++else
++  IFS="${IFS=         }"; ac_save_ifs="$IFS"; IFS=":"
++  ac_dummy="$PATH"
++  for ac_dir in $ac_dummy; do
++    test -z "$ac_dir" && ac_dir=.
++    if test -f $ac_dir/$ac_word; then
++      ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
++      break
++    fi
++  done
++  IFS="$ac_save_ifs"
++fi
++fi
++RANLIB="$ac_cv_prog_RANLIB"
++if test -n "$RANLIB"; then
++  echo "$ac_t""$RANLIB" 1>&6
++else
++  echo "$ac_t""no" 1>&6
++fi
++
++
++if test -z "$ac_cv_prog_RANLIB"; then
++if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "ranlib", so it can be a program name with args.
++set dummy ranlib; ac_word=$2
++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
++echo "configure:1310: checking for $ac_word" >&5
++if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  if test -n "$RANLIB"; then
++  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
++else
++  IFS="${IFS=         }"; ac_save_ifs="$IFS"; IFS=":"
++  ac_dummy="$PATH"
++  for ac_dir in $ac_dummy; do
++    test -z "$ac_dir" && ac_dir=.
++    if test -f $ac_dir/$ac_word; then
++      ac_cv_prog_RANLIB="ranlib"
++      break
++    fi
++  done
++  IFS="$ac_save_ifs"
++  test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
++fi
++fi
++RANLIB="$ac_cv_prog_RANLIB"
++if test -n "$RANLIB"; then
++  echo "$ac_t""$RANLIB" 1>&6
++else
++  echo "$ac_t""no" 1>&6
++fi
++
++else
++  RANLIB=":"
++fi
++fi
++
++
++# Find a good install program.  We prefer a C program (faster),
++# so one script is as good as another.  But avoid the broken or
++# incompatible versions:
++# SysV /etc/install, /usr/sbin/install
++# SunOS /usr/etc/install
++# IRIX /sbin/install
++# AIX /bin/install
++# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
++# AFS /usr/afsws/bin/install, which mishandles nonexistent args
++# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
++# ./install, which can be erroneously created by make from ./install.sh.
++echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
++echo "configure:1355: checking for a BSD compatible install" >&5
++if test -z "$INSTALL"; then
++if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++    IFS="${IFS=       }"; ac_save_IFS="$IFS"; IFS=":"
++  for ac_dir in $PATH; do
++    # Account for people who put trailing slashes in PATH elements.
++    case "$ac_dir/" in
++    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
++    *)
++      # OSF1 and SCO ODT 3.0 have their own names for install.
++      # Don't use installbsd from OSF since it installs stuff as root
++      # by default.
++      for ac_prog in ginstall scoinst install; do
++        if test -f $ac_dir/$ac_prog; then
++        if test $ac_prog = install &&
++            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
++          # AIX install.  It has an incompatible calling convention.
++          :
++        else
++          ac_cv_path_install="$ac_dir/$ac_prog -c"
++          break 2
++        fi
++      fi
++      done
++      ;;
++    esac
++  done
++  IFS="$ac_save_IFS"
++
++fi
++  if test "${ac_cv_path_install+set}" = set; then
++    INSTALL="$ac_cv_path_install"
++  else
++    # As a last resort, use the slow shell script.  We don't cache a
++    # path for INSTALL within a source directory, because that will
++    # break other packages using the cache if that directory is
++    # removed, or if the path is relative.
++    INSTALL="$ac_install_sh"
++  fi
++fi
++echo "$ac_t""$INSTALL" 1>&6
++
++# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
++# It thinks the first close brace ends the variable substitution.
++test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
++
++test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
++
++test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
++
++
++echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
++echo "configure:1409: checking whether to enable maintainer-specific portions of Makefiles" >&5
++    # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
++if test "${enable_maintainer_mode+set}" = set; then
++  enableval="$enable_maintainer_mode"
++  USE_MAINTAINER_MODE=$enableval
++else
++  USE_MAINTAINER_MODE=no
++fi
++
++  echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6
++  
++
++if test $USE_MAINTAINER_MODE = yes; then
++  MAINTAINER_MODE_TRUE=
++  MAINTAINER_MODE_FALSE='#'
++else
++  MAINTAINER_MODE_TRUE='#'
++  MAINTAINER_MODE_FALSE=
++fi
++  MAINT=$MAINTAINER_MODE_TRUE
++  
++
++
++# We need AC_EXEEXT to keep automake happy in cygnus mode.  However,
++# at least currently, we never actually build a program, so we never
++# need to use $(EXEEXT).  Moreover, the test for EXEEXT normally
++# fails, because we are probably configuring with a cross compiler
++# which can't create executables.  So we include AC_EXEEXT to keep
++# automake happy, but we don't execute it, since we don't care about
++# the result.
++if false; then
++  
++
++echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
++echo "configure:1443: checking for executable suffix" >&5
++if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
++  ac_cv_exeext=.exe
++else
++  rm -f conftest*
++  echo 'int main () { return 0; }' > conftest.$ac_ext
++  ac_cv_exeext=
++  if { (eval echo configure:1453: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
++    for file in conftest.*; do
++      case $file in
++      *.c | *.o | *.obj | *.ilk | *.pdb) ;;
++      *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
++      esac
++    done
++  else
++    { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
++  fi
++  rm -f conftest*
++  test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
++fi
++fi
++
++EXEEXT=""
++test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
++echo "$ac_t""${ac_cv_exeext}" 1>&6
++ac_exeext=$EXEEXT
++
++fi
++
++. ${newlib_basedir}/configure.host
++
++newlib_cflags="${newlib_cflags} -fno-builtin"
++
++NEWLIB_CFLAGS=${newlib_cflags}
++
++
++LDFLAGS=${ldflags}
++
++
++
++
++if test x${newlib_elix_level} = x0; then
++  ELIX_LEVEL_0_TRUE=
++  ELIX_LEVEL_0_FALSE='#'
++else
++  ELIX_LEVEL_0_TRUE='#'
++  ELIX_LEVEL_0_FALSE=
++fi
++
++
++if test x${newlib_elix_level} = x1; then
++  ELIX_LEVEL_1_TRUE=
++  ELIX_LEVEL_1_FALSE='#'
++else
++  ELIX_LEVEL_1_TRUE='#'
++  ELIX_LEVEL_1_FALSE=
++fi
++
++
++if test x${newlib_elix_level} = x2; then
++  ELIX_LEVEL_2_TRUE=
++  ELIX_LEVEL_2_FALSE='#'
++else
++  ELIX_LEVEL_2_TRUE='#'
++  ELIX_LEVEL_2_FALSE=
++fi
++
++
++if test x${newlib_elix_level} = x3; then
++  ELIX_LEVEL_3_TRUE=
++  ELIX_LEVEL_3_FALSE='#'
++else
++  ELIX_LEVEL_3_TRUE='#'
++  ELIX_LEVEL_3_FALSE=
++fi
++
++
++if test x${newlib_elix_level} = x4; then
++  ELIX_LEVEL_4_TRUE=
++  ELIX_LEVEL_4_FALSE='#'
++else
++  ELIX_LEVEL_4_TRUE='#'
++  ELIX_LEVEL_4_FALSE=
++fi
++
++
++
++if test x${use_libtool} = xyes; then
++  USE_LIBTOOL_TRUE=
++  USE_LIBTOOL_FALSE='#'
++else
++  USE_LIBTOOL_TRUE='#'
++  USE_LIBTOOL_FALSE=
++fi
++
++# Hard-code OBJEXT.  Normally it is set by AC_OBJEXT, but we
++# use oext, which is set in configure.host based on the target platform.
++OBJEXT=${oext}
++
++
++
++
++
++
++
++
++
++
++trap '' 1 2 15
++cat > confcache <<\EOF
++# This file is a shell script that caches the results of configure
++# tests run on this system so they can be shared between configure
++# scripts and configure runs.  It is not useful on other systems.
++# If it contains results you don't want to keep, you may remove or edit it.
++#
++# By default, configure uses ./config.cache as the cache file,
++# creating it if it does not exist already.  You can give configure
++# the --cache-file=FILE option to use a different cache file; that is
++# what configure does when it calls configure scripts in
++# subdirectories, so they share the cache.
++# Giving --cache-file=/dev/null disables caching, for debugging configure.
++# config.status only pays attention to the cache file if you give it the
++# --recheck option to rerun configure.
++#
++EOF
++# The following way of writing the cache mishandles newlines in values,
++# but we know of no workaround that is simple, portable, and efficient.
++# So, don't put newlines in cache variables' values.
++# Ultrix sh set writes to stderr and can't be redirected directly,
++# and sets the high bit in the cache file unless we assign to the vars.
++(set) 2>&1 |
++  case `(ac_space=' '; set | grep ac_space) 2>&1` in
++  *ac_space=\ *)
++    # `set' does not quote correctly, so add quotes (double-quote substitution
++    # turns \\\\ into \\, and sed turns \\ into \).
++    sed -n \
++      -e "s/'/'\\\\''/g" \
++      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
++    ;;
++  *)
++    # `set' quotes correctly as required by POSIX, so do not add quotes.
++    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
++    ;;
++  esac >> confcache
++if cmp -s $cache_file confcache; then
++  :
++else
++  if test -w $cache_file; then
++    echo "updating cache $cache_file"
++    cat confcache > $cache_file
++  else
++    echo "not updating unwritable cache $cache_file"
++  fi
++fi
++rm -f confcache
++
++trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
++
++test "x$prefix" = xNONE && prefix=$ac_default_prefix
++# Let make expand exec_prefix.
++test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
++
++# Any assignment to VPATH causes Sun make to only execute
++# the first set of double-colon rules, so remove it if not needed.
++# If there is a colon in the path, we need to keep it.
++if test "x$srcdir" = x.; then
++  ac_vpsub='/^[       ]*VPATH[        ]*=[^:]*$/d'
++fi
++
++trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
++
++# Transform confdefs.h into DEFS.
++# Protect against shell expansion while executing Makefile rules.
++# Protect against Makefile macro expansion.
++cat > conftest.defs <<\EOF
++s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
++s%[   `~#$^&*(){}\\|;'"<>?]%\\&%g
++s%\[%\\&%g
++s%\]%\\&%g
++s%\$%$$%g
++EOF
++DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
++rm -f conftest.defs
++
++
++# Without the "./", some shells look in PATH for config.status.
++: ${CONFIG_STATUS=./config.status}
++
++echo creating $CONFIG_STATUS
++rm -f $CONFIG_STATUS
++cat > $CONFIG_STATUS <<EOF
++#! /bin/sh
++# Generated automatically by configure.
++# Run this file to recreate the current configuration.
++# This directory was configured as follows,
++# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
++#
++# $0 $ac_configure_args
++#
++# Compiler output produced by configure, useful for debugging
++# configure, is in ./config.log if it exists.
++
++ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
++for ac_option
++do
++  case "\$ac_option" in
++  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
++    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
++    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
++  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
++    echo "$CONFIG_STATUS generated by autoconf version 2.13"
++    exit 0 ;;
++  -help | --help | --hel | --he | --h)
++    echo "\$ac_cs_usage"; exit 0 ;;
++  *) echo "\$ac_cs_usage"; exit 1 ;;
++  esac
++done
++
++ac_given_srcdir=$srcdir
++ac_given_INSTALL="$INSTALL"
++
++trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
++EOF
++cat >> $CONFIG_STATUS <<EOF
++
++# Protect against being on the right side of a sed subst in config.status.
++sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
++ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
++$ac_vpsub
++$extrasub
++s%@SHELL@%$SHELL%g
++s%@CFLAGS@%$CFLAGS%g
++s%@CPPFLAGS@%$CPPFLAGS%g
++s%@CXXFLAGS@%$CXXFLAGS%g
++s%@FFLAGS@%$FFLAGS%g
++s%@DEFS@%$DEFS%g
++s%@LDFLAGS@%$LDFLAGS%g
++s%@LIBS@%$LIBS%g
++s%@exec_prefix@%$exec_prefix%g
++s%@prefix@%$prefix%g
++s%@program_transform_name@%$program_transform_name%g
++s%@bindir@%$bindir%g
++s%@sbindir@%$sbindir%g
++s%@libexecdir@%$libexecdir%g
++s%@datadir@%$datadir%g
++s%@sysconfdir@%$sysconfdir%g
++s%@sharedstatedir@%$sharedstatedir%g
++s%@localstatedir@%$localstatedir%g
++s%@libdir@%$libdir%g
++s%@includedir@%$includedir%g
++s%@oldincludedir@%$oldincludedir%g
++s%@infodir@%$infodir%g
++s%@mandir@%$mandir%g
++s%@newlib_basedir@%$newlib_basedir%g
++s%@host@%$host%g
++s%@host_alias@%$host_alias%g
++s%@host_cpu@%$host_cpu%g
++s%@host_vendor@%$host_vendor%g
++s%@host_os@%$host_os%g
++s%@target@%$target%g
++s%@target_alias@%$target_alias%g
++s%@target_cpu@%$target_cpu%g
++s%@target_vendor@%$target_vendor%g
++s%@target_os@%$target_os%g
++s%@build@%$build%g
++s%@build_alias@%$build_alias%g
++s%@build_cpu@%$build_cpu%g
++s%@build_vendor@%$build_vendor%g
++s%@build_os@%$build_os%g
++s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
++s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
++s%@INSTALL_DATA@%$INSTALL_DATA%g
++s%@PACKAGE@%$PACKAGE%g
++s%@VERSION@%$VERSION%g
++s%@ACLOCAL@%$ACLOCAL%g
++s%@AUTOCONF@%$AUTOCONF%g
++s%@AUTOMAKE@%$AUTOMAKE%g
++s%@AUTOHEADER@%$AUTOHEADER%g
++s%@MAKEINFO@%$MAKEINFO%g
++s%@SET_MAKE@%$SET_MAKE%g
++s%@CC@%$CC%g
++s%@AS@%$AS%g
++s%@AR@%$AR%g
++s%@RANLIB@%$RANLIB%g
++s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g
++s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g
++s%@MAINT@%$MAINT%g
++s%@EXEEXT@%$EXEEXT%g
++s%@NEWLIB_CFLAGS@%$NEWLIB_CFLAGS%g
++s%@ELIX_LEVEL_0_TRUE@%$ELIX_LEVEL_0_TRUE%g
++s%@ELIX_LEVEL_0_FALSE@%$ELIX_LEVEL_0_FALSE%g
++s%@ELIX_LEVEL_1_TRUE@%$ELIX_LEVEL_1_TRUE%g
++s%@ELIX_LEVEL_1_FALSE@%$ELIX_LEVEL_1_FALSE%g
++s%@ELIX_LEVEL_2_TRUE@%$ELIX_LEVEL_2_TRUE%g
++s%@ELIX_LEVEL_2_FALSE@%$ELIX_LEVEL_2_FALSE%g
++s%@ELIX_LEVEL_3_TRUE@%$ELIX_LEVEL_3_TRUE%g
++s%@ELIX_LEVEL_3_FALSE@%$ELIX_LEVEL_3_FALSE%g
++s%@ELIX_LEVEL_4_TRUE@%$ELIX_LEVEL_4_TRUE%g
++s%@ELIX_LEVEL_4_FALSE@%$ELIX_LEVEL_4_FALSE%g
++s%@USE_LIBTOOL_TRUE@%$USE_LIBTOOL_TRUE%g
++s%@USE_LIBTOOL_FALSE@%$USE_LIBTOOL_FALSE%g
++s%@OBJEXT@%$OBJEXT%g
++s%@oext@%$oext%g
++s%@aext@%$aext%g
++s%@libm_machine_dir@%$libm_machine_dir%g
++s%@machine_dir@%$machine_dir%g
++s%@sys_dir@%$sys_dir%g
++
++CEOF
++EOF
++
++cat >> $CONFIG_STATUS <<\EOF
++
++# Split the substitutions into bite-sized pieces for seds with
++# small command number limits, like on Digital OSF/1 and HP-UX.
++ac_max_sed_cmds=60 # Maximum number of lines to put in a sed script.
++ac_file=1 # Number of current file.
++ac_beg=1 # First line for current file.
++ac_end=$ac_max_sed_cmds # Line after last line for current file.
++ac_more_lines=:
++ac_sed_cmds=""
++while $ac_more_lines; do
++  if test $ac_beg -gt 1; then
++    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
++  else
++    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
++  fi
++  if test ! -s conftest.s$ac_file; then
++    ac_more_lines=false
++    rm -f conftest.s$ac_file
++  else
++    if test -z "$ac_sed_cmds"; then
++      ac_sed_cmds="sed -f conftest.s$ac_file"
++    else
++      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
++    fi
++    ac_file=`expr $ac_file + 1`
++    ac_beg=$ac_end
++    ac_end=`expr $ac_end + $ac_max_sed_cmds`
++  fi
++done
++if test -z "$ac_sed_cmds"; then
++  ac_sed_cmds=cat
++fi
++EOF
++
++cat >> $CONFIG_STATUS <<EOF
++
++CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
++EOF
++cat >> $CONFIG_STATUS <<\EOF
++for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
++  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
++  case "$ac_file" in
++  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
++       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
++  *) ac_file_in="${ac_file}.in" ;;
++  esac
++
++  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
++
++  # Remove last slash and all that follows it.  Not all systems have dirname.
++  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
++  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
++    # The file is in a subdirectory.
++    test ! -d "$ac_dir" && mkdir "$ac_dir"
++    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
++    # A "../" for each directory in $ac_dir_suffix.
++    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
++  else
++    ac_dir_suffix= ac_dots=
++  fi
++
++  case "$ac_given_srcdir" in
++  .)  srcdir=.
++      if test -z "$ac_dots"; then top_srcdir=.
++      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
++  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
++  *) # Relative path.
++    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
++    top_srcdir="$ac_dots$ac_given_srcdir" ;;
++  esac
++
++  case "$ac_given_INSTALL" in
++  [/$]*) INSTALL="$ac_given_INSTALL" ;;
++  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
++  esac
++
++  echo creating "$ac_file"
++  rm -f "$ac_file"
++  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
++  case "$ac_file" in
++  *Makefile*) ac_comsub="1i\\
++# $configure_input" ;;
++  *) ac_comsub= ;;
++  esac
++
++  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
++  sed -e "$ac_comsub
++s%@configure_input@%$configure_input%g
++s%@srcdir@%$srcdir%g
++s%@top_srcdir@%$top_srcdir%g
++s%@INSTALL@%$INSTALL%g
++" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
++fi; done
++rm -f conftest.s*
++
++EOF
++cat >> $CONFIG_STATUS <<EOF
++
++EOF
++cat >> $CONFIG_STATUS <<\EOF
++
++exit 0
++EOF
++chmod +x $CONFIG_STATUS
++rm -fr confdefs* $ac_clean_files
++test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
++
+diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/configure.in ./newlib/libc/sys/mipsunknown/configure.in
+--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/configure.in     Wed Dec 31 19:00:00 1969
++++ ./newlib/libc/sys/mipsunknown/configure.in Mon Nov 24 20:33:46 2003
+@@ -0,0 +1,12 @@
++dnl This is the newlib/libc/sys/mipsunknown configure.in file.
++dnl Process this file with autoconf to produce a configure script.
++
++AC_PREREQ(2.5)
++AC_INIT(syscalls.c)
++
++dnl Can't be done in NEWLIB_CONFIGURE because that confuses automake. 
++AC_CONFIG_AUX_DIR(../../../..)
++
++NEWLIB_CONFIGURE(../../..)
++
++AC_OUTPUT(Makefile)
+diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/crt0.c ./newlib/libc/sys/mipsunknown/crt0.c
+--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/crt0.c   Wed Dec 31 19:00:00 1969
++++ ./newlib/libc/sys/mipsunknown/crt0.c       Mon Nov 24 21:03:56 2003
+@@ -0,0 +1,7 @@
++/* This is just here to make the build proccess happy. The real crt0.c is included in the
++   mips2java dist and will replace this after mips2java is installed */
++
++extern void puts(const char *s);   
++void _start() {
++    puts("Your build is broken... you shouldn't be using the crt0.c in newlib");
++}
+diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/sys/dirent.h ./newlib/libc/sys/mipsunknown/sys/dirent.h
+--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/sys/dirent.h     Wed Dec 31 19:00:00 1969
++++ ./newlib/libc/sys/mipsunknown/sys/dirent.h Mon Nov 24 22:46:36 2003
+@@ -0,0 +1,24 @@
++#ifndef _SYS_DIRENT_H
++#define _SYS_DIRENT_H
++
++#include <sys/types.h>
++
++struct dirent {
++      long    d_ino;
++      char    d_name[1024];
++};
++
++typedef struct {
++      int     dd_fd;
++    int dd_pos;
++    struct dirent ent;
++} DIR;
++
++# define __dirfd(dp)  ((dp)->dd_fd)
++
++DIR *opendir (const char *);
++struct dirent *readdir (DIR *);
++void rewinddir (DIR *);
++int closedir (DIR *);
++
++#endif
+diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/sys/utime.h ./newlib/libc/sys/mipsunknown/sys/utime.h
+--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/sys/utime.h      Wed Dec 31 19:00:00 1969
++++ ./newlib/libc/sys/mipsunknown/sys/utime.h  Tue Nov 25 09:45:17 2003
+@@ -0,0 +1,20 @@
++#ifndef _SYS_UTIME_H
++#define _SYS_UTIME_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct utimbuf 
++{
++  time_t actime;
++  time_t modtime; 
++};
++
++extern int utime(const char *file, const struct utimbuf *buf);
++
++#ifdef __cplusplus
++};
++#endif
++
++#endif /* _SYS_UTIME_H */
+diff -urN ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/syscalls.c ./newlib/libc/sys/mipsunknown/syscalls.c
+--- ../newlib-1.11.0.orig/newlib/libc/sys/mipsunknown/syscalls.c       Wed Dec 31 19:00:00 1969
++++ ./newlib/libc/sys/mipsunknown/syscalls.c   Tue Nov 25 09:33:57 2003
+@@ -0,0 +1,49 @@
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <utime.h>
++#include <errno.h>
++#undef errno
++
++/* These are just connectors for the reent versions */
++
++extern int _mkdir_r(struct _reent *ptr, const char *path, mode_t mode);
++int mkdir(const char *path, mode_t mode) { return _mkdir_r(_REENT, path, mode); }
++
++extern int _utime_r(struct _reent *ptr, const char *file, struct utimbuf *buf);
++int utime(const char *file, const struct utimbuf *buf) { return _utime_r(_REENT,file,buf); }
++
++extern int _lstat_r(struct _reent *ptr, const char *path, struct stat *sb);
++int lstat(const char *path, struct stat *sb) { return _lstat_r(_REENT,path,sb); }
++
++extern int _chdir_r(struct _reent *ptr, const char *path);
++int chdir(const char *path) { return _chdir_r(_REENT,path); }
++
++extern int _pipe_r(struct _reent *ptr, int *filedes);
++int pipe(int *filedes) { return _pipe_r(_REENT,filedes); }
++
++extern int _dup2_r(struct _reent *ptr, int oldd, int newd);
++int dup2(int oldd,int newd) { return _dup2_r(_REENT,oldd,newd); }
++
++extern int _waitpid_r(struct _reent *ptr, pid_t pid, int *status, int opts);
++int waitpid(pid_t pid, int *status, int opts) { return _waitpid_r(_REENT,pid,status,opts); }
++
++extern char* _getcwd_r(struct _reent *ptr, char *buf, size_t size);
++char* getcwd(char *buf, size_t size) { return _getcwd_r(_REENT,buf,size); }
++
++extern int _symlink_r(struct _reent *ptr, const char *name1, const char *name2);
++int symlink(const char *name1, const char *name2) { return _symlink_r(_REENT,name1,name2); }
++
++extern int _readlink_r(struct _reent *ptr, const char *path, const char *buf, int bufsize);
++int readlink(const char *path, const char *buf, int bufsize) { return _readlink_r(_REENT,path,buf,bufsize); }
++
++extern int _chown_r(struct _reent *ptr, const char *path, uid_t uid, gid_t gid);
++int chown(const char *path, uid_t uid, gid_t gid) { return _chown_r(_REENT,path,uid,gid); }
++
++extern int _fchown_r(struct _reent *ptr, int fd, uid_t uid, gid_t gid);
++int fchown(int fd, uid_t uid, gid_t gid) { return _fchown_r(_REENT,fd,uid,gid); }
++
++extern int _chmod_r(struct _reent *ptr, const char *path, mode_t mode);
++int chmod(const char *path, mode_t mode) { return _chmod_r(_REENT,path,mode); }
++
++extern int _fchmod_r(struct _reent *ptr, int fd, mode_t mode);
++int fchmod(int fd, mode_t mode) { return _fchmod_r(_REENT,fd,mode); }
diff --git a/upstream/patches/newlib-tzset.patch b/upstream/patches/newlib-tzset.patch
new file mode 100644 (file)
index 0000000..bf16fa9
--- /dev/null
@@ -0,0 +1,17 @@
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/time/tzset_r.c,v
+retrieving revision 1.2
+retrieving revision 1.3
+diff -u -r1.2 -r1.3
+--- newlib/libc/time/tzset_r.c 2002/08/26 18:56:09     1.2
++++ snewlib/libc/time/tzset_r.c        2003/06/03 18:42:09     1.3
+@@ -28,7 +28,8 @@
+         struct _reent *reent_ptr)
+ {
+   char *tzenv;
+-  int hh, mm, ss, sign, m, w, d, n;
++  unsigned short hh, mm, ss, m, w, d;
++  int sign, n;
+   int i, ch;
+   if ((tzenv = _getenv_r (reent_ptr, "TZ")) == NULL)