[re]-merged in Brians stuff
authoradam <adam@megacz.com>
Mon, 27 Dec 2004 10:28:45 +0000 (10:28 +0000)
committeradam <adam@megacz.com>
Mon, 27 Dec 2004 10:28:45 +0000 (10:28 +0000)
darcs-hash:20041227102845-5007d-e25e78c33aebc6b9a6e3a8fcbcf46e3b5f33fa2d.gz

63 files changed:
src/gnu/gcj/RawData.java [new file with mode: 0644]
src/org/ibex/core/Box.java
src/org/ibex/core/Ibex.java
src/org/ibex/core/Scheduler.java
src/org/ibex/core/Stream.java
src/org/ibex/graphics/Font.java
src/org/ibex/graphics/MSPack.java
src/org/ibex/js/ByteCodes.java [deleted file]
src/org/ibex/js/Directory.java [deleted file]
src/org/ibex/js/Interpreter.java [deleted file]
src/org/ibex/js/JS.java [deleted file]
src/org/ibex/js/JSArray.java [deleted file]
src/org/ibex/js/JSDate.java [deleted file]
src/org/ibex/js/JSExn.java [deleted file]
src/org/ibex/js/JSFunction.java [deleted file]
src/org/ibex/js/JSMath.java [deleted file]
src/org/ibex/js/JSNumber.java [deleted file]
src/org/ibex/js/JSPrimitive.java [deleted file]
src/org/ibex/js/JSReflection.java [deleted file]
src/org/ibex/js/JSRegexp.java [deleted file]
src/org/ibex/js/JSScope.java [deleted file]
src/org/ibex/js/JSString.java [deleted file]
src/org/ibex/js/Lexer.java [deleted file]
src/org/ibex/js/Parser.java [deleted file]
src/org/ibex/js/PropertyFile.java [deleted file]
src/org/ibex/js/Stream.java [deleted file]
src/org/ibex/js/Test.java [deleted file]
src/org/ibex/js/Tokens.java [deleted file]
src/org/ibex/js/Trap.java [deleted file]
src/org/ibex/net/HTTP.java [deleted file]
src/org/ibex/net/SOAP.java [deleted file]
src/org/ibex/net/XMLRPC.java [deleted file]
src/org/ibex/plat/Darwin.java
src/org/ibex/plat/Linux.java
src/org/ibex/plat/Win32.java
src/org/ibex/util/AccessibleCharArrayWriter.java [deleted file]
src/org/ibex/util/BalancedTree.java [deleted file]
src/org/ibex/util/CAB.java [deleted file]
src/org/ibex/util/Cache.java [deleted file]
src/org/ibex/util/CachedInputStream.java [deleted file]
src/org/ibex/util/Callback.java [deleted file]
src/org/ibex/util/CounterEnumeration.java [deleted file]
src/org/ibex/util/DirtyList.java [deleted file]
src/org/ibex/util/EjAlbertBrowserLauncher.java [deleted file]
src/org/ibex/util/FileNameEncoder.java [deleted file]
src/org/ibex/util/Grammar.java [deleted file]
src/org/ibex/util/Hash.java [deleted file]
src/org/ibex/util/InputStreamToByteArray.java [deleted file]
src/org/ibex/util/KnownLength.java [deleted file]
src/org/ibex/util/LineReader.java [deleted file]
src/org/ibex/util/Log.java [deleted file]
src/org/ibex/util/MSPack.c [deleted file]
src/org/ibex/util/MSPack.java [deleted file]
src/org/ibex/util/NanoGoat.java [deleted file]
src/org/ibex/util/PackBytesIntoString.java [deleted file]
src/org/ibex/util/Preprocessor.java [deleted file]
src/org/ibex/util/Queue.java [deleted file]
src/org/ibex/util/Scheduler.java [deleted file]
src/org/ibex/util/Semaphore.java [deleted file]
src/org/ibex/util/Simplex.java [deleted file]
src/org/ibex/util/Task.java [deleted file]
src/org/ibex/util/Vec.java [deleted file]
src/org/ibex/util/XML.java [deleted file]

diff --git a/src/gnu/gcj/RawData.java b/src/gnu/gcj/RawData.java
new file mode 100644 (file)
index 0000000..3293970
--- /dev/null
@@ -0,0 +1,3 @@
+package gnu.gcj;
+public class RawData {
+}
index 96aa0a0..677fe0c 100644 (file)
@@ -57,7 +57,7 @@ public final class Box extends JS.O implements Task {
 
     static final Font DEFAULT_FONT;
     static {
 
     static final Font DEFAULT_FONT;
     static {
-        try { DEFAULT_FONT = Font.getFont(Main.builtin.get(JS.S("fonts/vera/Vera.ttf")), 10); }
+        try { DEFAULT_FONT = Font.getFont((JS)Main.builtin.get(JS.S("fonts/vera/Vera.ttf")), 10); }
         catch(JSExn e) { throw new Error("Error loading default font: " + e); }
     }
 
         catch(JSExn e) { throw new Error("Error loading default font: " + e); }
     }
 
@@ -443,7 +443,7 @@ public final class Box extends JS.O implements Task {
     public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
         switch (nargs) {
             case 1: {
     public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
         switch (nargs) {
             case 1: {
-                //#jswitch(method)
+                //#switch(JS.toString(method))
                 case "indexof":
                     Box b = (Box)a0;
                     if (b.parent != this)
                 case "indexof":
                     Box b = (Box)a0;
                     if (b.parent != this)
@@ -469,7 +469,7 @@ public final class Box extends JS.O implements Task {
         if (JS.isInt(name))
             return redirect == null ? null : redirect == this ? getChild(JS.toInt(name)) : redirect.get(name);
 
         if (JS.isInt(name))
             return redirect == null ? null : redirect == this ? getChild(JS.toInt(name)) : redirect.get(name);
 
-        //#jswitch(name)
+        //#switch(JS.toString(name))
         case "surface": return parent == null ? null : parent.getAndTriggerTraps(name);
         case "indexof": return METHOD;
         case "distanceto": return METHOD;
         case "surface": return parent == null ? null : parent.getAndTriggerTraps(name);
         case "indexof": return METHOD;
         case "distanceto": return METHOD;
@@ -527,7 +527,7 @@ public final class Box extends JS.O implements Task {
 
     private class Mouse extends JS implements JS.Cloneable {
         public JS get(JS key) throws JSExn {
 
     private class Mouse extends JS implements JS.Cloneable {
         public JS get(JS key) throws JSExn {
-            //#jswitch(key)
+            //#switch(JS.toString(key))
             case "x": return N(globalToLocalX(getSurface()._mousex));
             case "y": return N(globalToLocalY(getSurface()._mousey));
 
             case "x": return N(globalToLocalX(getSurface()._mousex));
             case "y": return N(globalToLocalY(getSurface()._mousey));
 
@@ -555,7 +555,7 @@ public final class Box extends JS.O implements Task {
 
     public void put(JS name, JS value) throws JSExn {
         if (JS.isInt(name)) { put(JS.toInt(name), value); return; }
 
     public void put(JS name, JS value) throws JSExn {
         if (JS.isInt(name)) { put(JS.toInt(name), value); return; }
-        //#jswitch(name)
+        //#switch(JS.toString(name))
         case "thisbox":     if (value == null) removeSelf();
         case "text":        { String s = value == null ?  "" : JS.toString(value); CHECKSET_STRING(text); RECONSTRAIN(); dirty(); }
         case "strokecolor": value = N(Color.stringToColor(JS.toString(value))); CHECKSET_INT(strokecolor); dirty();
         case "thisbox":     if (value == null) removeSelf();
         case "text":        { String s = value == null ?  "" : JS.toString(value); CHECKSET_STRING(text); RECONSTRAIN(); dirty(); }
         case "strokecolor": value = N(Color.stringToColor(JS.toString(value))); CHECKSET_INT(strokecolor); dirty();
@@ -684,7 +684,7 @@ public final class Box extends JS.O implements Task {
 
     private void setAlign(JS value) throws JSExn {
         clear(ALIGNS);
 
     private void setAlign(JS value) throws JSExn {
         clear(ALIGNS);
-        //#jswitch(value)
+        //#switch(JS.toString(value))
         case "topleft": set(ALIGN_TOP | ALIGN_LEFT);
         case "bottomleft": set(ALIGN_BOTTOM | ALIGN_LEFT);
         case "topright": set(ALIGN_TOP | ALIGN_RIGHT);
         case "topleft": set(ALIGN_TOP | ALIGN_LEFT);
         case "bottomleft": set(ALIGN_BOTTOM | ALIGN_LEFT);
         case "topright": set(ALIGN_TOP | ALIGN_RIGHT);
index 447ee1d..9427c20 100644 (file)
@@ -59,7 +59,7 @@ public final class Ibex extends JS implements JS.Cloneable {
         // FIXME: SHouldn't need this (just trap [""])
         if (JS.isString(name) && JS.toString(name).length() == 0) return rr;
         // FEATURE: Preprocessor hack to generate specialized JS instances (avoid all this string concatenation)
         // FIXME: SHouldn't need this (just trap [""])
         if (JS.isString(name) && JS.toString(name).length() == 0) return rr;
         // FEATURE: Preprocessor hack to generate specialized JS instances (avoid all this string concatenation)
-        //#jswitch(name)
+        //#switch(JS.toString(name))
         case "math": return ibexMath;
         case "string": return ibexString;
         case "date": return METHOD;
         case "math": return ibexMath;
         case "string": return ibexString;
         case "date": return METHOD;
@@ -129,7 +129,7 @@ public final class Ibex extends JS implements JS.Cloneable {
     }
 
     public void put(JS name, JS value) throws JSExn {
     }
 
     public void put(JS name, JS value) throws JSExn {
-        //#jswitch(name)
+        //#switch(JS.toString(name))
         case "thread": Scheduler.add((Task)value); return;
         case "ui.clipboard": Platform.setClipBoard(JS.toString(value)); return;
         case "ui.frame": Platform.createSurface((Box)value, true, true); return;
         case "thread": Scheduler.add((Task)value); return;
         case "ui.clipboard": Platform.setClipBoard(JS.toString(value)); return;
         case "ui.frame": Platform.createSurface((Box)value, true, true); return;
@@ -144,7 +144,7 @@ public final class Ibex extends JS implements JS.Cloneable {
 
     public JS callMethod(JS name, JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn {
         try {
 
     public JS callMethod(JS name, JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn {
         try {
-            //#jswitch(name)
+            //#switch(JS.toString(name))
             case "date": return new JSDate(a, b, c, rest, nargs);
             case "net.rpc.soap": return new SOAP(JS.toString(a), "", JS.toString(b), JS.toString(c));
                 // FIXME support object dumping
             case "date": return new JSDate(a, b, c, rest, nargs);
             case "net.rpc.soap": return new SOAP(JS.toString(a), "", JS.toString(b), JS.toString(c));
                 // FIXME support object dumping
@@ -156,21 +156,21 @@ public final class Ibex extends JS implements JS.Cloneable {
  
             switch (nargs) {
                 case 0:
  
             switch (nargs) {
                 case 0:
-                    //#jswitch(name)
+                    //#switch(JS.toString(name))
                     case "thread.yield": sleep(0); return null;
                     //#end
                     break;
                 case 1:
                     case "thread.yield": sleep(0); return null;
                     //#end
                     break;
                 case 1:
-                    //#jswitch(name)
+                    //#switch(JS.toString(name))
                     case "clone":
                         if(a == null) throw new JSExn("can't clone the null value");
                         return ((JS)a).jsclone();
                     case "bless": return bless((JS)a);
                     case "ui.browser": Platform.newBrowserWindow(JS.toString(a)); return null;
                     case "clone":
                         if(a == null) throw new JSExn("can't clone the null value");
                         return ((JS)a).jsclone();
                     case "bless": return bless((JS)a);
                     case "ui.browser": Platform.newBrowserWindow(JS.toString(a)); return null;
-                    case "stream.unzip": return a == null ? null : new Stream.Zip(a);
-                    case "stream.uncab": return a == null ? null : new Stream.Cab(a);
+                    case "stream.unzip": return a == null ? null : new Stream.Zip((Stream)a);
+                       //case "stream.uncab": return a == null ? null : new Stream.Cab(a);
                     case "stream.cache":
                     case "stream.cache":
-                        try { return a == null ? null : new Stream.CachedStream(a, "resources", true); }
+                        try { return a == null ? null : new Stream.CachedStream((Stream)a, "resources", true); }
                         catch (Stream.NotCacheableException e) { throw new JSExn("this resource cannot be cached"); }
                     case "stream.url": {
                         String url = JS.toString(a);
                         catch (Stream.NotCacheableException e) { throw new JSExn("this resource cannot be cached"); }
                     case "stream.url": {
                         String url = JS.toString(a);
@@ -200,12 +200,12 @@ public final class Ibex extends JS implements JS.Cloneable {
                     //#end
                     break;
                 case 2:
                     //#end
                     break;
                 case 2:
-                    //#jswitch(name)
-                    case "stream.watch": return new Stream.ProgressWatcher(a, b);
+                    //#switch(JS.toString(name))
+                    case "stream.watch": return new Stream.ProgressWatcher((Stream)a, b);
                     case "regexp": return new JSRegexp(a, b);
                     //#end
                 case 3:
                     case "regexp": return new JSRegexp(a, b);
                     //#end
                 case 3:
-                    //#jswitch(name)
+                    //#switch(JS.toString(name))
                     case "ui.font.height": return N(Font.getFont(a, JS.toInt(b)).textheight(JS.toString(c)));
                     case "ui.font.wait": throw new Error("FIXME: ibex.ui.font.wait not implemented");
                     case "ui.font.width": return N(Font.getFont(a, JS.toInt(b)).textwidth(JS.toString(c)));
                     case "ui.font.height": return N(Font.getFont(a, JS.toInt(b)).textheight(JS.toString(c)));
                     case "ui.font.wait": throw new Error("FIXME: ibex.ui.font.wait not implemented");
                     case "ui.font.width": return N(Font.getFont(a, JS.toInt(b)).textwidth(JS.toString(c)));
@@ -247,7 +247,7 @@ public final class Ibex extends JS implements JS.Cloneable {
             // FEATURE: find a cleaner way to do this
             private JS gs = /*new JSScope.Global();*/ null; // FIXME: Global scope
             public JS get(JS key) throws JSExn {
             // FEATURE: find a cleaner way to do this
             private JS gs = /*new JSScope.Global();*/ null; // FIXME: Global scope
             public JS get(JS key) throws JSExn {
-                //#jswitch(key)
+                //#switch(JS.toString(key))
                 case "isNaN": return METHOD;
                 case "isFinite": return METHOD;
                 case "NaN": return METHOD;
                 case "isNaN": return METHOD;
                 case "isFinite": return METHOD;
                 case "NaN": return METHOD;
@@ -256,7 +256,7 @@ public final class Ibex extends JS implements JS.Cloneable {
                 return MATH.get(key);
             }
             public JS callMethod(JS name, JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn {
                 return MATH.get(key);
             }
             public JS callMethod(JS name, JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn {
-                //#jswitch(name)
+                //#switch(JS.toString(name))
                 case "isNaN": return gs.callMethod(name,a,b,c,rest,nargs);
                 case "isFinite": return gs.callMethod(name,a,b,c,rest,nargs);
                 case "NaN": return gs.callMethod(name,a,b,c,rest,nargs);
                 case "isNaN": return gs.callMethod(name,a,b,c,rest,nargs);
                 case "isFinite": return gs.callMethod(name,a,b,c,rest,nargs);
                 case "NaN": return gs.callMethod(name,a,b,c,rest,nargs);
@@ -269,7 +269,7 @@ public final class Ibex extends JS implements JS.Cloneable {
     public static final JS ibexString = new JS() {
             private JS gs = /*new JSScope.Global();*/ null; // FIXME: Global scope
             public JS get(JS key) throws JSExn {
     public static final JS ibexString = new JS() {
             private JS gs = /*new JSScope.Global();*/ null; // FIXME: Global scope
             public JS get(JS key) throws JSExn {
-                //#jswitch(key)
+                //#switch(JS.toString(key))
                 case "parseInt": return METHOD;
                 case "parseFloat": return METHOD;
                 case "decodeURI": return METHOD;
                 case "parseInt": return METHOD;
                 case "parseFloat": return METHOD;
                 case "decodeURI": return METHOD;
@@ -283,7 +283,7 @@ public final class Ibex extends JS implements JS.Cloneable {
                 return super.get(key);
             }
             public JS callMethod(JS name, JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn {
                 return super.get(key);
             }
             public JS callMethod(JS name, JS a, JS b, JS c, JS[] rest, int nargs) throws JSExn {
-                //#jswitch(name)
+                //#switch(JS.toString(name))
                 case "parseInt": return gs.callMethod(name,a,b,c,rest,nargs);
                 case "parseFloat": return gs.callMethod(name,a,b,c,rest,nargs);
                 case "decodeURI": return gs.callMethod(name,a,b,c,rest,nargs);
                 case "parseInt": return gs.callMethod(name,a,b,c,rest,nargs);
                 case "parseFloat": return gs.callMethod(name,a,b,c,rest,nargs);
                 case "decodeURI": return gs.callMethod(name,a,b,c,rest,nargs);
index e4c85fa..f6c0774 100644 (file)
@@ -1,5 +1,5 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.util;
+package org.ibex.core;
 
 import java.io.IOException;
 
 
 import java.io.IOException;
 
index 40fc71f..24f96c4 100644 (file)
@@ -1,10 +1,11 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.js;
+package org.ibex.core;
 
 import java.io.*;
 import java.util.zip.*;
 
 import java.io.*;
 import java.util.zip.*;
+import org.ibex.js.*;
 import org.ibex.util.*;
 import org.ibex.util.*;
-//import org.ibex.plat.*;
+import org.ibex.plat.*;
 import org.ibex.net.*;
 
 /**
 import org.ibex.net.*;
 
 /**
@@ -13,7 +14,7 @@ import org.ibex.net.*;
  *   be totally independent of the others (ie separate stream position
  *   and state) although they draw from the same data source.
  */
  *   be totally independent of the others (ie separate stream position
  *   and state) although they draw from the same data source.
  */
-public abstract class Stream extends JS.Cloneable {
+public abstract class Stream extends JS.O implements JS.Cloneable {
 
     // Public Interface //////////////////////////////////////////////////////////////////////////////
 
 
     // Public Interface //////////////////////////////////////////////////////////////////////////////
 
@@ -38,11 +39,11 @@ public abstract class Stream extends JS.Cloneable {
     /** HTTP or HTTPS resource */
     public static class HTTP extends Stream {
         private String url;
     /** HTTP or HTTPS resource */
     public static class HTTP extends Stream {
         private String url;
-        public String toString() { return "Stream.HTTP:" + url; }
+        //public String toString() { return "Stream.HTTP:" + url; }
         public HTTP(String url) { while (url.endsWith("/")) url = url.substring(0, url.length() - 1); this.url = url; }
         public Object _get(Object key) { return new HTTP(url + "/" + (String)key); }
         public String getCacheKey(Vec path) throws NotCacheableException { return url; }
         public HTTP(String url) { while (url.endsWith("/")) url = url.substring(0, url.length() - 1); this.url = url; }
         public Object _get(Object key) { return new HTTP(url + "/" + (String)key); }
         public String getCacheKey(Vec path) throws NotCacheableException { return url; }
-        public InputStream getInputStream() throws IOException { return new org.ibex.net.HTTP(url).GET(); }
+        public InputStream getInputStream() throws IOException { return new org.ibex.net.HTTP(url).GET(null, null); }
     }
 
     /** byte arrays */
     }
 
     /** byte arrays */
@@ -59,7 +60,7 @@ public abstract class Stream extends JS.Cloneable {
     public static class File extends Stream {
         private String path;
         public File(String path) { this.path = path; }
     public static class File extends Stream {
         private String path;
         public File(String path) { this.path = path; }
-        public String toString() { return "file:" + path; }
+        //public String toString() { return "file:" + path; }
         public String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); /* already on disk */ }
         public InputStream getInputStream() throws IOException { return new FileInputStream(path); }
         public Object _get(Object key) { return new File(path + java.io.File.separatorChar + (String)key); }
         public String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); /* already on disk */ }
         public InputStream getInputStream() throws IOException { return new FileInputStream(path); }
         public Object _get(Object key) { return new File(path + java.io.File.separatorChar + (String)key); }
@@ -88,6 +89,7 @@ public abstract class Stream extends JS.Cloneable {
     }
 
     /** "unwrap" a Cab archive */
     }
 
     /** "unwrap" a Cab archive */
+    /*
     public static class Cab extends Stream {
         private Stream parent;
         private String path;
     public static class Cab extends Stream {
         private Stream parent;
         private String path;
@@ -97,6 +99,7 @@ public abstract class Stream extends JS.Cloneable {
         public Object _get(Object key) { return new Cab(parent, path==null?(String)key:path+'/'+(String)key); }
         public InputStream getInputStream() throws IOException { return new MSPack(parent.getInputStream()).getInputStream(path); }
     }
         public Object _get(Object key) { return new Cab(parent, path==null?(String)key:path+'/'+(String)key); }
         public InputStream getInputStream() throws IOException { return new MSPack(parent.getInputStream()).getInputStream(path); }
     }
+    */
 
     /** the Builtin resource */
     public static class Builtin extends Stream {
 
     /** the Builtin resource */
     public static class Builtin extends Stream {
index 96c65c4..619e5b7 100644 (file)
@@ -4,6 +4,7 @@ import org.ibex.util.*;
 import java.io.*;
 import java.util.Hashtable;
 import org.ibex.js.*;
 import java.io.*;
 import java.util.Hashtable;
 import org.ibex.js.*;
+import org.ibex.core.*;
 import org.ibex.nestedvm.*;
 import org.ibex.plat.*;
 import org.ibex.nestedvm.Runtime;
 import org.ibex.nestedvm.*;
 import org.ibex.plat.*;
 import org.ibex.nestedvm.Runtime;
index 6236df6..971bf79 100644 (file)
@@ -1,4 +1,4 @@
-package org.ibex.util;
+package org.ibex.graphics;
 
 import org.ibex.core.Main;
 import org.ibex.util.*;
 
 import org.ibex.core.Main;
 import org.ibex.util.*;
diff --git a/src/org/ibex/js/ByteCodes.java b/src/org/ibex/js/ByteCodes.java
deleted file mode 100644 (file)
index 84c5926..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.js;
-
-/**
- *  Constants for the various JavaScript ByteCode operations.
- *
- *  Each instruction is an opcode and an optional literal literal;
- *  some Tokens are also valid; see Tokens.java
- */
-interface ByteCodes {
-
-    /** push the literal onto the stack */
-    public static final byte LITERAL = -2;
-
-    /** push a new array onto the stack with length equal to the literal */
-    public static final byte ARRAY = -3;         
-
-    /** push an empty object onto the stack */
-    public static final byte OBJECT = -4;        
-
-    /** create a new instance; literal is a reference to the corresponding ForthBlock */
-    public static final byte NEWFUNCTION = -5;      
-
-    /** if given a non-null argument declare its argument in the current scope and push
-        it to the stack, else, declares the element on the top of the stack and leaves it
-        there */
-    //public static final byte DECLARE = -6;       
-
-    /** push a reference to the current scope onto the stack */
-    // FIXME: Document this
-    public static final byte GLOBALSCOPE = -7;
-
-    /** if given a null literal pop two elements off the stack; push stack[-1].get(stack[top])
-        else pop one element off the stack, push stack[top].get(literal) */
-    public static final byte GET = -8;           
-
-    /** push stack[-1].get(stack[top]) */
-    public static final byte GET_PRESERVE = -9; 
-
-    /** pop two elements off the stack; stack[-2].put(stack[-1], stack[top]); push stack[top] */
-    public static final byte PUT = -10;           
-
-    /** literal is a relative address; pop stacktop and jump if the value is true */
-    public static final byte JT = -11;           
-
-    /** literal is a relative address; pop stacktop and jump if the value is false */
-    public static final byte JF = -12;           
-
-    /** literal is a relative address; jump to it */
-    public static final byte JMP = -13;          
-
-    /** discard the top stack element */
-    static public final byte POP = -14;          
-
-    /** pop element; call stack[top](stack[-n], stack[-n+1]...) where n is the number of args to the function */
-    public static final byte CALL = -15;         
-
-    /** pop an element; push a JS.JSArray containing the keys of the popped element */
-    public static final byte PUSHKEYS = -16;     
-
-    /** push the top element down so that (arg) elements are on top of it; all other elements retain ordering */
-    public static final byte SWAP = -17;         
-
-    /** execute the bytecode block pointed to by the literal in a fresh scope with parentScope==THIS */
-    public static final byte NEWSCOPE = -18;        
-
-    /** execute the bytecode block pointed to by the literal in a fresh scope with parentScope==THIS */
-    public static final byte OLDSCOPE = -19;
-
-    /** push a copy of the top stack element */
-    public static final byte DUP = -20;          
-
-    /** a NOP; confers a label upon the following instruction */
-    public static final byte LABEL = -21;          
-
-    /** execute the ForthBlock pointed to by the literal until BREAK encountered; push TRUE onto the stack for the first iteration
-     *  and FALSE for all subsequent iterations */
-    public static final byte LOOP = -22;        
-     
-    /** similar effect a a GET followed by a CALL */
-    public static final byte CALLMETHOD = -23;
-
-    /** finish a finally block and carry out whatever instruction initiated the finally block */
-    public static final byte FINALLY_DONE = -24;
-    
-    /** finish a finally block and carry out whatever instruction initiated the finally block */
-    public static final byte MAKE_GRAMMAR = -25;
-    
-    // FIXME: Document these and NEWSCOPE/OLDSCOPE/TOPSCOPE changes
-    public static final byte SCOPEGET = -26;
-    public static final byte SCOPEPUT = -27;    
-    
-    public static final String[] bytecodeToString = new String[] {
-        "", "", "LITERAL", "ARRAY", "OBJECT", "NEWFUNCTION", "DECLARE", "GLOBALSCOPE",
-        "GET", "GET_PRESERVE", "PUT", "JT", "JF", "JMP", "POP", "CALL", "PUSHKEYS",
-        "SWAP", "NEWSCOPE", "OLDSCOPE", "DUP", "LABEL", "LOOP", "CALLMETHOD",
-        "FINALLY_DONE", "MAKE_GRAMMAR", "SCOPEGET", "SCOPEPUT"
-    };
-}
diff --git a/src/org/ibex/js/Directory.java b/src/org/ibex/js/Directory.java
deleted file mode 100644 (file)
index 98469d5..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] 
-package org.ibex.js; 
-
-import org.ibex.util.*; 
-import java.util.*;
-import java.io.*;
-
-// FEATURE: support for move
-// FEATURE: support for bytestreams
-// FEATURE: cache directories so we can do equality checking on them?
-// FEATURE: autoconvert "true" to true and "0.3" to 0.3 on readback
-
-/** 
- * A crude mechanism for using a filesystem as object storage.
- *
- *  This object represents a directory; writing a string, number, or
- *  boolean to any of its properties will create a file with the
- *  (encoded) property name as its filename and the "stringified"
- *  value as its contents.
- *
- *  Writing 'null' to one of this object's properties will
- *  [recursively if necessary] delete the corresponding directory
- *  entry.
- *  
- *  Writing any other object to one of this object's properties will
- *  create a new Directory object and copy the other object's keys()
- *  into the new Directory.  This means that assigning one directory
- *  to a property of another directory will <i>copy</i> the directory,
- *  not move it.  There is currently no way to move directories.
- *
- *  If an object is written to a property that already has an entry,
- *  the old one is deleted (equivalent to writing 'null') first.
- * 
- *  WARNING: when instantiating a Directory object with a file
- *  argument that points to a non-directory File, this class will
- *  delete that file and create a directory!
- */
-public class Directory extends JS {
-
-    File f;
-
-    /** 
-     *  Create the directory object.  Existing directories will be
-     *  preserved; if a file is present it will be obliterated.
-     */ 
-
-    public Directory(File f) throws IOException {
-        this.f = f;
-        if (!f.exists()) new Directory(new File(f.getParent()));
-        if (!f.isDirectory()) destroy(f);
-        f.mkdirs();
-    }
-
-    private static void destroy(File f) throws IOException {
-        if (!f.exists()) return;
-        if (f.isDirectory()) {
-            String[] entries = f.list();
-            for(int i=0; i<entries.length; i++) destroy(new File(f.getAbsolutePath() + File.separatorChar + entries[i]));
-        }
-        f.delete();
-    }
-
-    public void put(JS key0, JS val) throws JSExn {
-        try {
-            if (key0 == null) return;
-            String key = toString(key0);
-            File f2 = new File(f.getAbsolutePath() + File.separatorChar + FileNameEncoder.encode(key));
-            destroy(f2);
-            if (val == null) return;
-            if (val instanceof JSPrimitive) {
-                OutputStream out = new FileOutputStream(f2);
-                Writer w = new OutputStreamWriter(out);
-                w.write(toString(val));
-                w.flush();
-                out.close();
-            } else {
-                Directory d2 = new Directory(f2);
-                JS.Enumeration e = val.keys();
-                while(e.hasMoreElements()) {
-                    JS k = e.nextElement();
-                    JS v = val.get(k);
-                    d2.put(k, v);
-                }
-            }
-        } catch (IOException ioe) {
-            throw new JSExn.IO(ioe);
-        }
-    }
-
-    public JS get(JS key0) throws JSExn {
-        try {
-            if (key0 == null) return null;
-            String key = toString(key0);
-            File f2 = new File(f.getAbsolutePath() + File.separatorChar + FileNameEncoder.encode(key));
-            if (!f2.exists()) return null;
-            if (f2.isDirectory()) return new Directory(f2);
-            char[] chars = new char[((int)f2.length()) * 2];
-            int numchars = 0;
-            Reader r = new InputStreamReader(new FileInputStream(f2));
-            while(true) {
-                int numread = r.read(chars, numchars, chars.length - numchars);
-                if (numread == -1) return JS.S(new String(chars, 0, numchars));
-                numchars += numread;
-            }
-        } catch (IOException ioe) {
-            throw new JSExn.IO(ioe);
-        }
-    }
-
-    public Enumeration keys() {
-        final String[] elements = f.list();
-        return new Enumeration(null) {
-                int i = 0;
-                public boolean _hasMoreElements() { return i < elements.length; }
-                public JS _nextElement() { return JS.S(FileNameEncoder.decode(elements[i++])); }
-            };
-    }
-}
diff --git a/src/org/ibex/js/Interpreter.java b/src/org/ibex/js/Interpreter.java
deleted file mode 100644 (file)
index 04f6784..0000000
+++ /dev/null
@@ -1,705 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.js;
-
-import org.ibex.util.*;
-import java.util.*;
-
-/** Encapsulates a single JS interpreter (ie call stack) */
-class Interpreter implements ByteCodes, Tokens {
-    // Thread-Interpreter Mapping /////////////////////////////////////////////////////////////////////////
-
-    static Interpreter current() { return (Interpreter)threadToInterpreter.get(Thread.currentThread()); }
-    private static Hashtable threadToInterpreter = new Hashtable();
-
-    
-    // Instance members and methods //////////////////////////////////////////////////////////////////////
-    
-    int pausecount;               ///< the number of times pause() has been invoked; -1 indicates unpauseable
-    JSFunction f = null;          ///< the currently-executing JSFunction
-    JSScope scope;                ///< the current top-level scope (LIFO stack via NEWSCOPE/OLDSCOPE)
-    final Stack stack = new Stack(); ///< the object stack
-    int pc = 0;                   ///< the program counter
-
-    Interpreter(JSFunction f, boolean pauseable, JSArgs args) {
-        this.f = f;
-        this.pausecount = pauseable ? 0 : -1;
-        this.scope = f.parentScope;
-        try {
-            stack.push(new CallMarker(null));    // the "root function returned" marker -- f==null
-            stack.push(args);
-        } catch(JSExn e) {
-            throw new Error("should never happen");
-        }
-    }
-    
-    Interpreter(Trap t, JS val, boolean pauseOnPut) {
-        this.pausecount = -1;
-        try {
-            setupTrap(t,val,new TrapMarker(null,t,val,pauseOnPut));
-        } catch(JSExn e) {
-            throw new Error("should never happen");
-        }
-    }
-    
-    /** this is the only synchronization point we need in order to be threadsafe */
-    synchronized JS resume() throws JSExn {
-        if(f == null) throw new RuntimeException("function already finished");
-        if(scope == null) throw new RuntimeException("scope is null");
-        Thread t = Thread.currentThread();
-        Interpreter old = (Interpreter)threadToInterpreter.get(t);
-        threadToInterpreter.put(t, this);
-        try {
-            return run();
-        } finally {
-            if (old == null) threadToInterpreter.remove(t);
-            else threadToInterpreter.put(t, old);
-        }
-    }
-
-    static int getLine() {
-        Interpreter c = Interpreter.current();
-        return c == null || c.f == null || c.pc < 0 || c.pc >= c.f.size ? -1 : c.f.line[c.pc];
-    }
-
-    static String getSourceName() {
-        Interpreter c = Interpreter.current();
-        return c == null || c.f == null ? null : c.f.sourceName;
-    } 
-
-    private static JSExn je(String s) { return new JSExn(getSourceName() + ":" + getLine() + " " + s); }
-
-    private JS run() throws JSExn {
-
-        // if pausecount changes after a get/put/call, we know we've been paused
-        final int initialPauseCount = pausecount;
-
-        OUTER: for(;; pc++) {
-        try {
-            int op = f.op[pc];
-            Object arg = f.arg[pc];
-            if(op == FINALLY_DONE) {
-                FinallyData fd = (FinallyData) stack.pop();
-                if(fd == null) continue OUTER; // NOP
-                if(fd.exn != null) throw fd.exn;
-                op = fd.op;
-                arg = fd.arg;
-            }
-            switch(op) {
-            case LITERAL: stack.push((JS)arg); break;
-            case OBJECT: stack.push(new JS.O()); break;
-            case ARRAY: stack.push(new JSArray(JS.toInt((JS)arg))); break;
-            //case DECLARE: scope.declare((JS)(arg==null ? stack.peek() : arg)); if(arg != null) stack.push((JS)arg); break;
-            case JT: if (JS.toBoolean(stack.pop())) pc += JS.toInt((JS)arg) - 1; break;
-            case JF: if (!JS.toBoolean(stack.pop())) pc += JS.toInt((JS)arg) - 1; break;
-            case JMP: pc += JS.toInt((JS)arg) - 1; break;
-            case POP: stack.pop(); break;
-            case SWAP: stack.swap(); break;
-            case DUP: stack.push(stack.peek()); break;
-            case NEWSCOPE: {
-                int n = JS.toInt((JS)arg);
-                scope = new JSScope(scope,(n>>>16)&0xffff,(n>>>0)&0xffff);
-                break;
-            }
-            case OLDSCOPE: scope = scope.parent; break;
-            case GLOBALSCOPE: stack.push(scope.getGlobal()); break;
-            case SCOPEGET: stack.push(scope.get((JS)arg)); break;
-            case SCOPEPUT: scope.put((JS)arg,stack.peek()); break;
-            case ASSERT: if (!JS.toBoolean(stack.pop())) throw je("ibex.assertion.failed"); break;
-            case BITNOT: stack.push(JS.N(~JS.toLong(stack.pop()))); break;
-            case BANG: stack.push(JS.B(!JS.toBoolean(stack.pop()))); break;
-            case NEWFUNCTION: stack.push(((JSFunction)arg)._cloneWithNewParentScope(scope)); break;
-            case LABEL: break;
-
-            case TYPEOF: {
-                Object o = stack.pop();
-                if (o == null) stack.push(null);
-                else if (o instanceof JSString) stack.push(JS.S("string"));
-                else if (o instanceof JSNumber.B) stack.push(JS.S("boolean"));
-                else if (o instanceof JSNumber) stack.push(JS.S("number"));
-                else stack.push(JS.S("object"));
-                break;
-            }
-
-            case PUSHKEYS: {
-                JS o = stack.peek();
-                stack.push(o == null ? null : o.keys());
-                break;
-            }
-
-            case LOOP:
-                stack.push(new LoopMarker(pc, pc > 0 && f.op[pc - 1] == LABEL ? (String)f.arg[pc - 1] : (String)null, scope));
-                stack.push(JS.T);
-                break;
-
-            case BREAK:
-            case CONTINUE:
-                while(!stack.empty()) {
-                    JS o = stack.pop();
-                    if (o instanceof CallMarker) je("break or continue not within a loop");
-                    if (o instanceof TryMarker) {
-                        if(((TryMarker)o).finallyLoc < 0) continue; // no finally block, keep going
-                        stack.push(new FinallyData(op, arg));
-                        scope = ((TryMarker)o).scope;
-                        pc = ((TryMarker)o).finallyLoc - 1;
-                        continue OUTER;
-                    }
-                    if (o instanceof LoopMarker) {
-                        if (arg == null || arg.equals(((LoopMarker)o).label)) {
-                            int loopInstructionLocation = ((LoopMarker)o).location;
-                            int endOfLoop = JS.toInt((JS)f.arg[loopInstructionLocation]) + loopInstructionLocation;
-                            scope = ((LoopMarker)o).scope;
-                            if (op == CONTINUE) { stack.push(o); stack.push(JS.F); }
-                            pc = op == BREAK ? endOfLoop - 1 : loopInstructionLocation;
-                            continue OUTER;
-                        }
-                    }
-                }
-                throw new Error("CONTINUE/BREAK invoked but couldn't find LoopMarker at " +
-                                getSourceName() + ":" + getLine());
-
-            case TRY: {
-                int[] jmps = (int[]) arg;
-                // jmps[0] is how far away the catch block is, jmps[1] is how far away the finally block is
-                // each can be < 0 if the specified block does not exist
-                stack.push(new TryMarker(jmps[0] < 0 ? -1 : pc + jmps[0], jmps[1] < 0 ? -1 : pc + jmps[1], this));
-                break;
-            }
-
-            case RETURN: {
-                JS retval = stack.pop();
-                while(!stack.empty()) {
-                    Object o = stack.pop();
-                    if (o instanceof TryMarker) {
-                        if(((TryMarker)o).finallyLoc < 0) continue;
-                        stack.push(retval); 
-                        stack.push(new FinallyData(RETURN));
-                        scope = ((TryMarker)o).scope;
-                        pc = ((TryMarker)o).finallyLoc - 1;
-                        continue OUTER;
-                    } else if (o instanceof CallMarker) {
-                        boolean didTrapPut = false;
-                        if (o instanceof TrapMarker) { // handles return component of a write trap
-                            TrapMarker tm = (TrapMarker) o;
-                            boolean cascade = tm.t.isWriteTrap() && !tm.cascadeHappened && !JS.toBoolean(retval);
-                            if(cascade) {
-                                Trap t = tm.t.nextWriteTrap();
-                                if(t == null && tm.t.target instanceof JS.Clone) {
-                                    t = ((JS.Clone)tm.t.target).clonee.getTrap(tm.t.key);
-                                    if(t != null) t = t.writeTrap();
-                                }
-                                if(t != null) {
-                                    tm.t = t; // we reuse the old trap marker
-                                    setupTrap(t,tm.val,tm);
-                                    pc--; // we increment it on the next iter
-                                    continue OUTER;
-                                } else {
-                                    didTrapPut = true;
-                                    if(!tm.pauseOnPut) tm.t.target.put(tm.t.key,tm.val);
-                                }
-                            }
-                        }
-                        CallMarker cm = (CallMarker) o;
-                        scope = cm.scope;
-                        pc = cm.pc - 1;
-                        f = cm.f;
-                        if (didTrapPut) {
-                            if (((TrapMarker)cm).pauseOnPut) { pc++; return ((TrapMarker)cm).val; }
-                            if (pausecount > initialPauseCount) { pc++; return null; }   // we were paused
-                        } else {
-                            stack.push(retval);
-                        }
-                        if (f == null) return retval;
-                        continue OUTER;
-                    }
-                }
-                throw new Error("error: RETURN invoked but couldn't find a CallMarker!");
-            }
-                
-            case CASCADE: {
-                boolean write = JS.toBoolean((JS)arg);
-                JS val = write ? stack.pop() : null;
-                CallMarker o = stack.findCall();
-                if(!(o instanceof TrapMarker)) throw new JSExn("tried to CASCADE while not in a trap");
-                TrapMarker tm = (TrapMarker) o;
-                JS key = tm.t.key;
-                JS target = tm.t.target;
-                if(tm.t.isWriteTrap() != write) throw new JSExn("tried to do a " + (write?"write":"read") + " cascade in a " + (write?"read":"write") + " trap");
-                Trap t = write ? tm.t.nextWriteTrap() : tm.t.nextReadTrap();
-                // FIXME: Doesn't handle multiple levels of clone's (probably can just make this a while loop)
-                if(t == null && target instanceof JS.Clone) {
-                    target = ((JS.Clone)target).clonee;
-                    t = target.getTrap(key);
-                    if(t != null) t = write ? t.writeTrap() : t.readTrap();
-                }
-                if(write) {
-                    tm.cascadeHappened = true;
-                    stack.push(val);
-                }
-                if(t != null) {
-                    setupTrap(t,val,new TrapMarker(this,t,val,tm.pauseOnPut));
-                    pc--; // we increment later
-                } else {
-                    if(write) {
-                        if (tm.pauseOnPut) { pc++; return val; }
-                        target.put(key,val);
-                    } else {
-                        JS ret = target.get(key);
-                        if (ret == JS.METHOD) ret = new Stub(target, key);
-                        stack.push(ret);                        
-                    }
-                    if (pausecount > initialPauseCount) { pc++; return null; }   // we were paused                    
-                }
-                break;
-            }
-                
-            case PUT: {
-                JS val = stack.pop();
-                JS key = stack.pop();
-                JS target = stack.peek();
-                if (target == null) throw je("tried to put " + JS.debugToString(val) + " to the " + JS.debugToString(key) + " property on the null value");
-                if (key == null) throw je("tried to assign \"" + JS.debugToString(val) + "\" to the null key");
-                
-                Trap t = target.getTrap(key);
-                if(t != null) t = t.writeTrap();
-                
-                if(t == null && target instanceof JS.Clone) {
-                    target = ((JS.Clone)target).clonee;
-                    t = target.getTrap(key);
-                    if(t != null) t = t.writeTrap();
-                }
-
-                stack.push(val);
-                
-                if(t != null) {
-                    setupTrap(t,val,new TrapMarker(this,t,val));
-                    pc--; // we increment later
-                } else {
-                    target.put(key,val);
-                    if (pausecount > initialPauseCount) { pc++; return null; }   // we were paused
-                }
-                break;
-            }
-
-            case GET:
-            case GET_PRESERVE: {
-                JS target, key;
-                if (op == GET) {
-                    key = arg == null ? stack.pop() : (JS)arg;
-                    target = stack.pop();
-                } else {
-                    key = stack.pop();
-                    target = stack.peek();
-                    stack.push(key);
-                }
-                JS ret = null;
-                if (key == null) throw je("tried to get the null key from " + JS.debugToString(target));
-                if (target == null) throw je("tried to get property \"" + JS.debugToString(key) + "\" from the null object");
-                
-                Trap t = target.getTrap(key);
-                if(t != null) t = t.readTrap();
-                
-                if(t == null && target instanceof JS.Clone) {
-                    target = ((JS.Clone)target).clonee;
-                    t = target.getTrap(key);
-                    if(t != null) t = t.readTrap();
-                }
-                
-                if(t != null) {
-                    setupTrap(t,null,new TrapMarker(this,t,null));
-                    pc--; // we increment later
-                } else {
-                    ret = target.get(key);
-                    if (pausecount > initialPauseCount) { pc++; return null; }   // we were paused
-                    if (ret == JS.METHOD) ret = new Stub(target, key);
-                    stack.push(ret);
-                }
-                break;
-            }
-            
-            case CALL: case CALLMETHOD: {
-                int numArgs = JS.toInt((JS)arg);
-                
-                JS[] rest = numArgs > 3 ? new JS[numArgs - 3] : null;
-                for(int i=numArgs - 1; i>2; i--) rest[i-3] = stack.pop();
-                JS a2 = numArgs <= 2 ? null : stack.pop();
-                JS a1 = numArgs <= 1 ? null : stack.pop();
-                JS a0 = numArgs <= 0 ? null : stack.pop();
-                
-                JS method = null;
-                JS ret = null;
-                JS object = stack.pop();
-
-                if (op == CALLMETHOD) {
-                    if (object == JS.METHOD) {
-                        method = stack.pop();
-                        object = stack.pop();
-                    } else if (object == null) {
-                        method = stack.pop();
-                        object = stack.pop();
-                        throw new JSExn("function '"+JS.debugToString(method)+"' not found in " + object.getClass().getName());
-                    } else {
-                        stack.pop();
-                        stack.pop();
-                    }
-                }
-
-                if (object instanceof JSFunction) {
-                    stack.push(new CallMarker(this));
-                    stack.push(new JSArgs(a0,a1,a2,rest,numArgs,object));
-                    f = (JSFunction)object;
-                    scope = f.parentScope;
-                    pc = -1;
-                    break;
-                } else {
-                    JS c = (JS)object;
-                    ret = method == null ? c.call(a0, a1, a2, rest, numArgs) : c.callMethod(method, a0, a1, a2, rest, numArgs);
-                }
-                
-                if (pausecount > initialPauseCount) { pc++; return null; }
-                stack.push(ret);
-                break;
-            }
-
-            case THROW:
-                throw new JSExn(stack.pop(), this);
-
-                /* FIXME GRAMMAR
-            case MAKE_GRAMMAR: {
-                final Grammar r = (Grammar)arg;
-                final JSScope final_scope = scope;
-                Grammar r2 = new Grammar() {
-                        public int match(String s, int start, Hash v, JSScope scope) throws JSExn {
-                            return r.match(s, start, v, final_scope);
-                        }
-                        public int matchAndWrite(String s, int start, Hash v, JSScope scope, String key) throws JSExn {
-                            return r.matchAndWrite(s, start, v, final_scope, key);
-                        }
-                        public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
-                            Hash v = new Hash();
-                            r.matchAndWrite((String)a0, 0, v, final_scope, "foo");
-                            return v.get("foo");
-                        }
-                    };
-                Object obj = stack.pop();
-                if (obj != null && obj instanceof Grammar) r2 = new Grammar.Alternative((Grammar)obj, r2);
-                stack.push(r2);
-                break;
-            }
-                */
-            case ADD_TRAP: case DEL_TRAP: {
-                JS val = stack.pop();
-                JS key = stack.pop();
-                JS js = stack.peek();
-                // A trap addition/removal
-                if(!(val instanceof JSFunction)) throw new JSExn("tried to add/remove a non-function trap");
-                if(op == ADD_TRAP) js.addTrap(key, (JSFunction)val);
-                else js.delTrap(key, (JSFunction)val);
-                break;
-            }
-
-            case ADD: {
-                int count = ((JSNumber)arg).toInt();
-                if(count < 2) throw new Error("this should never happen");
-                if(count == 2) {
-                    // common case
-                    JS right = stack.pop();
-                    JS left = stack.pop();
-                    JS ret;
-                    if(left instanceof JSString || right instanceof JSString)
-                        ret = JS.S(JS.toString(left).concat(JS.toString(right)));
-                    else if(left instanceof JSNumber.D || right instanceof JSNumber.D)
-                        ret = JS.N(JS.toDouble(left) + JS.toDouble(right));
-                    else {
-                        long l = JS.toLong(left) + JS.toLong(right);
-                        if(l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) ret = JS.N(l);
-                        ret = JS.N((int)l);
-                    }
-                    stack.push(ret);
-                } else {
-                    JS[] args = new JS[count];
-                    while(--count >= 0) args[count] = stack.pop();
-                    if(args[0] instanceof JSString) {
-                        StringBuffer sb = new StringBuffer(64);
-                        for(int i=0;i<args.length;i++) sb.append(JS.toString(args[i]));
-                        stack.push(JS.S(sb.toString()));
-                    } else {
-                        int numStrings = 0;
-                        for(int i=0;i<args.length;i++) if(args[i] instanceof JSString) numStrings++;
-                        if(numStrings == 0) {
-                            double d = 0.0;
-                            for(int i=0;i<args.length;i++) d += JS.toDouble(args[i]);
-                            stack.push(JS.N(d));
-                        } else {
-                            int i=0;
-                            StringBuffer sb = new StringBuffer(64);
-                            if(!(args[0] instanceof JSString || args[1] instanceof JSString)) {
-                                double d=0.0;
-                                do {
-                                    d += JS.toDouble(args[i++]);
-                                } while(!(args[i] instanceof JSString));
-                                sb.append(JS.toString(JS.N(d)));
-                            }
-                            while(i < args.length) sb.append(JS.toString(args[i++]));
-                            stack.push(JS.S(sb.toString()));
-                        }
-                    }
-                }
-                break;
-            }
-
-            default: {
-                JS right = stack.pop();
-                JS left = stack.pop();
-                switch(op) {
-                        
-                case BITOR: stack.push(JS.N(JS.toLong(left) | JS.toLong(right))); break;
-                case BITXOR: stack.push(JS.N(JS.toLong(left) ^ JS.toLong(right))); break;
-                case BITAND: stack.push(JS.N(JS.toLong(left) & JS.toLong(right))); break;
-
-                case SUB: stack.push(JS.N(JS.toDouble(left) - JS.toDouble(right))); break;
-                case MUL: stack.push(JS.N(JS.toDouble(left) * JS.toDouble(right))); break;
-                case DIV: stack.push(JS.N(JS.toDouble(left) / JS.toDouble(right))); break;
-                case MOD: stack.push(JS.N(JS.toDouble(left) % JS.toDouble(right))); break;
-                        
-                case LSH: stack.push(JS.N(JS.toLong(left) << JS.toLong(right))); break;
-                case RSH: stack.push(JS.N(JS.toLong(left) >> JS.toLong(right))); break;
-                case URSH: stack.push(JS.N(JS.toLong(left) >>> JS.toLong(right))); break;
-                        
-                //#repeat </<=/>/>= LT/LE/GT/GE
-                case LT: {
-                    if(left instanceof JSString && right instanceof JSString)
-                        stack.push(JS.B(JS.toString(left).compareTo(JS.toString(right)) < 0));
-                    else
-                        stack.push(JS.B(JS.toDouble(left) < JS.toDouble(right)));
-                }
-                //#end
-                    
-                case EQ:
-                case NE: {
-                    boolean ret;
-                    if(left == null && right == null) ret = true;
-                    else if(left == null || right == null) ret = false;
-                    else ret = left.jsequals(right);
-                    stack.push(JS.B(op == EQ ? ret : !ret)); break;
-                }
-
-                default: throw new Error("unknown opcode " + op);
-                } }
-            }
-
-        } catch(JSExn e) {
-            catchException(e);
-            pc--; // it'll get incremented on the next iteration
-        } // end try/catch
-        } // end for
-    }
-    
-    /** tries to find a handler withing the call chain for this exception
-        if a handler is found the interpreter is setup to call the exception handler
-        if a handler is not found the exception is thrown
-    */
-    void catchException(JSExn e) throws JSExn {
-        while(!stack.empty()) {
-            JS o = stack.pop();
-            if (o instanceof CatchMarker || o instanceof TryMarker) {
-                boolean inCatch = o instanceof CatchMarker;
-                if(inCatch) {
-                    o = stack.pop();
-                    if(((TryMarker)o).finallyLoc < 0) continue; // no finally block, keep going
-                }
-                if(!inCatch && ((TryMarker)o).catchLoc >= 0) {
-                    // run the catch block, this will implicitly run the finally block, if it exists
-                    stack.push(o);
-                    stack.push(catchMarker);
-                    stack.push(e.getObject());
-                    f = ((TryMarker)o).f;
-                    scope = ((TryMarker)o).scope;
-                    pc = ((TryMarker)o).catchLoc;
-                    return;
-                } else {
-                    stack.push(new FinallyData(e));
-                    f = ((TryMarker)o).f;
-                    scope = ((TryMarker)o).scope;
-                    pc = ((TryMarker)o).finallyLoc;
-                    return;
-                }
-            }
-        }
-        throw e;
-    }
-
-    void setupTrap(Trap t, JS val, CallMarker cm) throws JSExn {
-        stack.push(cm);
-        stack.push(new TrapArgs(t,val));
-        f = t.f;
-        scope = f.parentScope;
-        pc = 0;
-    }
-
-
-    // Markers //////////////////////////////////////////////////////////////////////
-
-    static class Marker extends JS {
-        public JS get(JS key) throws JSExn { throw new Error("this should not be accessible from a script"); }
-        public void put(JS key, JS val) throws JSExn { throw new Error("this should not be accessible from a script"); }
-        public String coerceToString() { throw new Error("this should not be accessible from a script"); }
-        public JS call(JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn { throw new Error("this should not be accessible from a script"); }
-    }
-    
-    static class CallMarker extends Marker {
-        final int pc;
-        final JSScope scope;
-        final JSFunction f;
-        public CallMarker(Interpreter cx) {
-            pc = cx == null ? -1 : cx.pc + 1;
-            scope = cx == null ? null : cx.scope;
-            f = cx == null ? null : cx.f;
-        }
-    }
-    
-    static class TrapMarker extends CallMarker {
-        Trap t;
-        JS val;
-        boolean cascadeHappened;
-        final boolean pauseOnPut;
-        public TrapMarker(Interpreter cx, Trap t, JS val) { this(cx,t,val,false); } 
-        public TrapMarker(Interpreter cx, Trap t, JS val, boolean pauseOnPut) {
-            super(cx);
-            this.t = t;
-            this.val = val;
-            this.pauseOnPut = pauseOnPut;
-        }
-    }
-    
-    static class CatchMarker extends Marker { }
-    private static CatchMarker catchMarker = new CatchMarker();
-    
-    static class LoopMarker extends Marker {
-        final public int location;
-        final public String label;
-        final public JSScope scope;
-        public LoopMarker(int location, String label, JSScope scope) {
-            this.location = location;
-            this.label = label;
-            this.scope = scope;
-        }
-    }
-    static class TryMarker extends Marker {
-        final public int catchLoc;
-        final public int finallyLoc;
-        final public JSScope scope;
-        final public JSFunction f;
-        public TryMarker(int catchLoc, int finallyLoc, Interpreter cx) {
-            this.catchLoc = catchLoc;
-            this.finallyLoc = finallyLoc;
-            this.scope = cx.scope;
-            this.f = cx.f;
-        }
-    }
-    static class FinallyData extends Marker {
-        final public int op;
-        final public Object arg;
-        final public JSExn exn;
-        public FinallyData(int op) { this(op,null); }
-        public FinallyData(int op, Object arg) { this.op = op; this.arg = arg; this.exn = null; }
-        public FinallyData(JSExn exn) { this.exn = exn; this.op = -1; this.arg = null; } // Just throw this exn
-    }
-
-    static class TrapArgs extends JS {
-        private Trap t;
-        private JS val;
-        public TrapArgs(Trap t, JS val) { this.t = t; this.val = val; }
-        public JS get(JS key) throws JSExn {
-            if(JS.isInt(key) && JS.toInt(key) == 0) return val;
-            //#jswitch(key)
-            case "trapee": return t.target;
-            case "callee": return t.f;
-            case "trapname": return t.key;
-            case "length": return t.isWriteTrap() ? ONE : ZERO;
-            //#end
-            return super.get(key);
-        }
-    }
-    
-    static class JSArgs extends JS {
-        private final JS a0;
-        private final JS a1;
-        private final JS a2;
-        private final JS[] rest;
-        private final int nargs;
-        private final JS callee;
-        
-        public JSArgs(JS callee) { this(null,null,null,null,0,callee); }
-        public JSArgs(JS a0, JS callee) { this(a0,null,null,null,1,callee); }
-        public JSArgs(JS a0, JS a1, JS a2, JS[] rest, int nargs, JS callee) {
-            this.a0 = a0; this.a1 = a1; this.a2 = a2;
-            this.rest = rest; this.nargs = nargs;
-            this.callee = callee;
-        }
-        
-        public JS get(JS key) throws JSExn {
-            if(JS.isInt(key)) {
-                int n = JS.toInt(key);
-                switch(n) {
-                    case 0: return a0;
-                    case 1: return a1;
-                    case 2: return a2;
-                    default: return n>= 0 && n < nargs ? rest[n-3] : null;
-                }
-            }
-            //#jswitch(key)
-            case "callee": return callee;
-            case "length": return JS.N(nargs);
-            //#end
-            return super.get(key);
-        }
-    }
-
-    static class Stub extends JS {
-        private JS method;
-        JS obj;
-        public Stub(JS obj, JS method) { this.obj = obj; this.method = method; }
-        public JS call(JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-            return ((JS)obj).callMethod(method, a0, a1, a2, rest, nargs);
-        }
-    }
-    
-    static class Stack {
-        private static final int MAX_STACK_SIZE = 512;
-        private JS[] stack = new JS[64];
-        private int sp = 0;
-        
-        boolean empty() { return sp == 0; }
-        void push(JS o) throws JSExn { if(sp == stack.length) grow(); stack[sp++] = o; }
-        JS peek() { if(sp == 0) throw new RuntimeException("Stack underflow"); return stack[sp-1]; }
-        final JS pop() { if(sp == 0) throw new RuntimeException("Stack underflow"); return stack[--sp]; }
-        void swap() throws JSExn {
-            if(sp < 2) throw new JSExn("stack overflow");
-            JS tmp = stack[sp-2];
-            stack[sp-2] = stack[sp-1];
-            stack[sp-1] = tmp;
-        }
-        CallMarker findCall() {
-            for(int i=sp-1;i>=0;i--) if(stack[i] instanceof CallMarker) return (CallMarker) stack[i];
-            return null;
-        }
-        void grow() throws JSExn {
-            if(stack.length >= MAX_STACK_SIZE) throw new JSExn("Stack overflow");
-            JS[] stack2 = new JS[stack.length * 2];
-            System.arraycopy(stack,0,stack2,0,stack.length);
-        }       
-        
-        void backtrace(JSExn e) {
-            for(int i=sp-1;i>=0;i--) {
-                if (stack[i] instanceof CallMarker) {
-                    CallMarker cm = (CallMarker)stack[i];
-                    if(cm.f == null) break;
-                    String s = cm.f.sourceName + ":" + cm.f.line[cm.pc-1];
-                    if(cm instanceof Interpreter.TrapMarker) 
-                        s += " (trap on " + JS.debugToString(((Interpreter.TrapMarker)cm).t.key) + ")";
-                    e.addBacktrace(s);
-                }
-            }
-        }
-    }
-}
diff --git a/src/org/ibex/js/JS.java b/src/org/ibex/js/JS.java
deleted file mode 100644 (file)
index e81c4cf..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] 
-package org.ibex.js; 
-
-import org.ibex.util.*; 
-import java.io.*;
-import java.util.*;
-
-/** The minimum set of functionality required for objects which are manipulated by JavaScript */
-public abstract class JS { 
-    public static final JS METHOD = new JS() { };
-
-    public JS.Enumeration keys() throws JSExn { throw new JSExn("you can't enumerate the keys of this object (class=" + getClass().getName() +")"); }
-    public JS get(JS key) throws JSExn { return null; }
-    public void put(JS key, JS val) throws JSExn { throw new JSExn("" + key + " is read only (class=" + getClass().getName() +")"); }
-    
-    public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-        throw new JSExn("method not found (" + JS.debugToString(method) + ")");
-    }
-    public JS call(JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-        throw new JSExn("you cannot call this object (class=" + this.getClass().getName() +")");
-    }
-    public InputStream getInputStream() throws IOException {
-        throw new IOException("this object doesn't have a stream associated with it " + getClass().getName() + ")");
-    }
-    
-    public final JS unclone() { return _unclone(); }
-    public final JS jsclone() throws JSExn { return new Clone(this); }
-    public final boolean hasTrap(JS key) { return getTrap(key) != null; }
-    public final boolean equals(Object o) { return this == o || ((o instanceof JS) && jsequals((JS)o)); }
-    // Discourage people from using toString()
-    public final String toString() { return "JS Object [class=" + getClass().getName() + "]"; }
-    
-    // Package private methods
-    Trap getTrap(JS key) { return null; }
-    void putTrap(JS key, Trap value) throws JSExn { throw new JSExn("traps cannot be placed on this object (class=" + this.getClass().getName() +")"); }
-    String coerceToString() throws JSExn { throw new JSExn("can't coerce to a string (class=" + getClass().getName() +")"); }
-    boolean jsequals(JS o) { return this == o; }
-    JS _unclone() { return this; }
-        
-    public static class O extends JS implements Cloneable {
-        private Hash entries;
-        
-        public Enumeration keys() throws JSExn { return entries == null ? (Enumeration)EMPTY_ENUMERATION : (Enumeration)new JavaEnumeration(null,entries.keys()); }
-        public JS get(JS key) throws JSExn { return entries == null ? null : (JS)entries.get(key, null); }
-        public void put(JS key, JS val) throws JSExn { (entries==null?entries=new Hash():entries).put(key,null,val); }        
-
-        /** retrieve a trap from the entries hash */
-        final Trap getTrap(JS key) {
-            return entries == null ? null : (Trap)entries.get(key, Trap.class);
-        }
-        
-        /** retrieve a trap from the entries hash */
-        final void putTrap(JS key, Trap value) {
-            if (entries == null) entries = new Hash();
-            entries.put(key, Trap.class, value);
-        }    
-    }
-    
-    public interface Cloneable { }
-        
-    public static class Clone extends O {
-        protected final JS clonee;
-        public Clone(JS clonee) throws JSExn {
-            if(!(clonee instanceof Cloneable)) throw new JSExn("" + clonee.getClass().getName() + " isn't cloneable");
-            this.clonee = clonee;
-        }
-        JS _unclone() { return clonee.unclone(); }
-        boolean jsequals(JS o) { return clonee.jsequals(o); }
-        
-        public Enumeration keys() throws JSExn { return clonee.keys(); }
-        public final JS get(JS key) throws JSExn { return clonee.get(key); }
-        public final void put(JS key, JS val) throws JSExn { clonee.put(key,val); }
-        public final JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-            return clonee.callMethod(method,a0,a1,a2,rest,nargs); 
-        }
-        public JS call(JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-            return clonee.call(a0, a1, a2, rest, nargs);
-        }
-        public InputStream getInputStream() throws IOException { return clonee.getInputStream(); }
-        // FIXME: This shouldn't be necessary (its for Ibex.Blessing)
-        public JS getClonee() { return clonee; }
-    }
-    
-    public static abstract class Enumeration extends JS {
-        final Enumeration parent;
-        boolean done;
-        public Enumeration(Enumeration parent) { this.parent = parent; }
-        protected abstract boolean _hasMoreElements();
-        protected abstract JS _nextElement() throws JSExn;
-        
-        public final boolean hasMoreElements() {
-            if(!done && !_hasMoreElements()) done = true;
-            return !done ? true : parent != null ? parent.hasMoreElements() : false;
-        }
-        public final JS nextElement() throws JSExn { return !done ? _nextElement() : parent != null ? parent.nextElement() : null; }
-        
-        public JS get(JS key) throws JSExn {
-            //#jswitch(key)
-            case "hasMoreElements": return B(hasMoreElements());
-            case "nextElement": return nextElement();
-            //#end
-            return super.get(key);
-        }
-    }
-
-    public static class EmptyEnumeration extends Enumeration {
-        public EmptyEnumeration(Enumeration parent) { super(parent); }
-        protected boolean _hasMoreElements() { return false; }
-        protected JS _nextElement() { return null; }
-    }
-    public static class JavaEnumeration extends Enumeration {
-        private final java.util.Enumeration e;
-        public JavaEnumeration(Enumeration parent, java.util.Enumeration e) { super(parent); this.e = e; }
-        protected boolean _hasMoreElements() { return e.hasMoreElements(); }
-        protected JS _nextElement() { return (JS) e.nextElement(); }
-    }
-    
-    // Static Interpreter Control Methods ///////////////////////////////////////////////////////////////
-
-    /** log a message with the current JavaScript sourceName/line */
-    public static void log(Object message) { info(message); }
-    public static void debug(Object message) { Log.debug(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
-    public static void info(Object message) { Log.info(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
-    public static void warn(Object message) { Log.warn(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
-    public static void error(Object message) { Log.error(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
-
-    public static class NotPauseableException extends Exception { NotPauseableException() { } }
-
-    /** returns a callback which will restart the context; expects a value to be pushed onto the stack when unpaused */
-    public static UnpauseCallback pause() throws NotPauseableException {
-        Interpreter i = Interpreter.current();
-        if (i.pausecount == -1) throw new NotPauseableException();
-        boolean get;
-        switch(i.f.op[i.pc]) {
-            case Tokens.RETURN: case ByteCodes.PUT: get = false; break;
-            case ByteCodes.GET: case ByteCodes.CALL: get = true; break;
-            default: throw new Error("should never happen");
-        }
-        i.pausecount++;
-        return new JS.UnpauseCallback(i,get);
-    }
-
-    public static class UnpauseCallback implements Task {
-        private Interpreter i;
-        private boolean get;
-        UnpauseCallback(Interpreter i, boolean get) { this.i = i; this.get = get; }
-        public void perform() throws JSExn { unpause(); }
-        public JS unpause() throws JSExn { return unpause((JS)null); }
-        public JS unpause(JS o) throws JSExn {
-            if (o == JS.METHOD) throw new JSExn("can't return a method to a paused context");
-            if(get) i.stack.push(o);
-            return i.resume();
-        }
-        public JS unpause(JSExn e) throws JSExn {
-            i.catchException(e);
-            return i.resume();
-        }
-    }
-
-
-
-    // Static Helper Methods ///////////////////////////////////////////////////////////////////////////////////
-
-    /** coerce an object to a Boolean */
-    public static boolean toBoolean(JS o) {
-        if(o == null) return false;
-        if(o instanceof JSNumber) return ((JSNumber)o).toBoolean();
-        if(o instanceof JSString) return ((JSString)o).s.length() != 0;
-        return true;
-    }
-    //#repeat long/int/double/float toLong/toInt/toDouble/toFloat Long/Integer/Double/Float parseLong/parseInt/parseDouble/parseFloat
-    /** coerce an object to a Number */
-    public static long toLong(JS o) throws JSExn {
-        if(o == null) return 0;
-        if(o instanceof JSNumber) return ((JSNumber)o).toLong();
-        if(o instanceof JSString) return Long.parseLong(o.coerceToString());
-        throw new JSExn("can't coerce a " + o.getClass().getName() + " to a number");
-    }
-    //#end
-    
-    public static String toString(JS o) throws JSExn {
-        if(o == null) return "null";
-        return o.coerceToString();
-    }
-    
-    public static String debugToString(JS o) {
-        try { return toString(o); }
-        catch(JSExn e) { return o.toString(); }
-    }
-    
-    public static boolean isInt(JS o) {
-        if(o == null) return true;
-        if(o instanceof JSNumber.I) return true;
-        if(o instanceof JSNumber.B) return false;
-        if(o instanceof JSNumber) {
-            JSNumber n = (JSNumber) o;
-            return n.toInt() == n.toDouble();
-        }
-        if(o instanceof JSString) {
-            String s = ((JSString)o).s;
-            for(int i=0;i<s.length();i++)
-                if(s.charAt(i) < '0' || s.charAt(i) > '9') return false;
-            return true;
-        }
-        return false;
-    }
-    
-    public static boolean isString(JS o) {
-        if(o instanceof JSString) return true;
-        return false;
-    }
-    
-    // Instance Methods ////////////////////////////////////////////////////////////////////
-    public final static JS NaN = new JSNumber.D(Double.NaN);
-    public final static JS ZERO = new JSNumber.I(0);
-    public final static JS ONE = new JSNumber.I(1);
-    public final static JS MATH = new JSMath();
-        
-    public static final JS T = new JSNumber.B(true);
-    public static final JS F = new JSNumber.B(false);
-
-    public static final JS B(boolean b) { return b ? T : F; }
-    public static final JS B(int i) { return i==0 ? F : T; }
-    
-    private static final int CACHE_SIZE = 65536 / 4; // must be a power of two
-    private static final JSString[] stringCache = new JSString[CACHE_SIZE];
-    public static final JS S(String s) {
-        if(s == null) return null;
-        int slot = s.hashCode()&(CACHE_SIZE-1);
-        JSString ret = stringCache[slot];
-        if(ret == null || !ret.s.equals(s)) stringCache[slot] = ret = new JSString(s);
-        return ret;
-    }
-    public static final JS S(String s, boolean intern) { return intern ? JSString.intern(s) : S(s); }
-
-    public static final JS N(double d) { return new JSNumber.D(d); }
-    public static final JS N(long l) { return new JSNumber.L(l); }
-    
-    public static final JS N(Number n) {
-        if(n instanceof Integer) return N(n.intValue());
-        if(n instanceof Long) return N(n.longValue());
-        return N(n.doubleValue());
-    }
-
-    private static final JSNumber.I[] smallIntCache = new JSNumber.I[CACHE_SIZE];
-    private static final JSNumber.I[] largeIntCache = new JSNumber.I[CACHE_SIZE];
-    public static final JS N(int i) {
-        JSNumber.I ret = null;
-        int idx = i + smallIntCache.length / 2;
-        if (idx < CACHE_SIZE && idx > 0) {
-            ret = smallIntCache[idx];
-            if (ret != null) return ret;
-        }
-        else ret = largeIntCache[Math.abs(idx % CACHE_SIZE)];
-        if (ret == null || ret.i != i) {
-            ret = new JSNumber.I(i);
-            if (idx < smallIntCache.length && idx > 0) smallIntCache[idx] = ret;
-            else largeIntCache[Math.abs(idx % CACHE_SIZE)] = ret;
-        }
-        return ret;
-    }
-    
-    private static Enumeration EMPTY_ENUMERATION = new EmptyEnumeration(null);
-    
-    public static JS fromReader(String sourceName, int firstLine, Reader sourceCode) throws IOException {
-        return Parser.fromReader(sourceName, firstLine, sourceCode);
-    }
-
-    public static JS cloneWithNewGlobalScope(JS js, JS s) {
-        if(js instanceof JSFunction)
-            return ((JSFunction)js)._cloneWithNewParentScope(new JSScope.Top(s));
-        else
-            return js;
-    }
-
-
-    // Trap support //////////////////////////////////////////////////////////////////////////////
-
-    /** performs a put, triggering traps if present; traps are run in an unpauseable interpreter */
-    public final void putAndTriggerTraps(JS key, JS value) throws JSExn {
-        Trap t = getTrap(key);
-        if(t == null || (t = t.writeTrap()) == null) put(key,value);
-        else new Interpreter(t,value,false).resume();
-    }
-
-    /** performs a get, triggering traps if present; traps are run in an unpauseable interpreter */
-    public final JS getAndTriggerTraps(JS key) throws JSExn {
-        Trap t = getTrap(key);
-        if (t == null || (t = t.readTrap()) == null) return get(key);
-        else return new Interpreter(t,null,false).resume();
-    }
-    
-    public final JS justTriggerTraps(JS key, JS value) throws JSExn {
-        Trap t = getTrap(key);
-        if(t == null || (t = t.writeTrap()) == null) return value;
-        else return new Interpreter(t,value,true).resume();
-    }
-
-    /** adds a trap, avoiding duplicates */
-    // FIXME: This shouldn't be public, it is needed for a hack in Template.java
-    public void addTrap(JS key, JSFunction f) throws JSExn {
-        if (f.numFormalArgs > 1) throw new JSExn("traps must take either one argument (write) or no arguments (read)");
-        boolean isRead = f.numFormalArgs == 0;
-        for(Trap t = getTrap(key); t != null; t = t.next) if (t.f == f) return;
-        putTrap(key, new Trap(this, key, f, (Trap)getTrap(key)));
-    }
-
-    /** deletes a trap, if present */
-    // FIXME: This shouldn't be public, it is needed for a hack in Template.java
-    public void delTrap(JS key, JSFunction f) throws JSExn {
-        Trap t = (Trap)getTrap(key);
-        if (t == null) return;
-        if (t.f == f) { putTrap(t.target, t.next); return; }
-        for(; t.next != null; t = t.next) if (t.next.f == f) { t.next = t.next.next; return; }
-    }
-
-
-} 
diff --git a/src/org/ibex/js/JSArray.java b/src/org/ibex/js/JSArray.java
deleted file mode 100644 (file)
index a9483d0..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] 
-package org.ibex.js; 
-
-import org.ibex.util.*; 
-import java.util.*;
-
-/** A JavaScript JSArray */
-public class JSArray extends JS.O {
-    private static final Object NULL = new Object();
-    private final BalancedTree bt = new BalancedTree();
-    
-    public JSArray() { }
-    public JSArray(int size) { setSize(size); }
-    
-    /*private static int intVal(Object o) {
-        if (o instanceof Number) {
-            int intVal = ((Number)o).intValue();
-            if (intVal == ((Number)o).doubleValue()) return intVal;
-            return Integer.MIN_VALUE;
-        }
-        if (!(o instanceof String)) return Integer.MIN_VALUE;
-        String s = (String)o;
-        for(int i=0; i<s.length(); i++) if (s.charAt(i) < '0' || s.charAt(i) > '9') return Integer.MIN_VALUE;
-        return Integer.parseInt(s);
-    }*/
-    
-    public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-        //#jswitch(method)
-        case "pop": {
-            int oldSize = size();
-            if(oldSize == 0) return null;
-            return removeElementAt(oldSize-1);
-        }
-        case "reverse": return reverse();
-        case "toString": return join(",");
-        case "shift":
-            if(length() == 0) return null;
-            return removeElementAt(0);
-        case "join":
-            return join(nargs == 0 ? "," : JS.toString(a0));
-        case "sort":
-            return sort(nargs < 1 ? null : a0);
-        case "slice":
-            int start = toInt(nargs < 1 ? null : a0);
-            int end = nargs < 2 ? length() : toInt(a1);
-            return slice(start, end);
-        case "push": {
-            int oldSize = size();
-            for(int i=0; i<nargs; i++) insertElementAt(i==0?a0:i==1?a1:i==2?a2:rest[i-3],oldSize+i);
-            return N(oldSize + nargs);
-        }
-        case "unshift":
-            for(int i=0; i<nargs; i++) insertElementAt(i==0?a0:i==1?a1:i==2?a2:rest[i-3],i);
-            return N(size());
-        case "splice":
-            JSArray array = new JSArray();
-            for(int i=0; i<nargs; i++) array.addElement(i==0?a0:i==1?a1:i==2?a2:rest[i-3]);
-            return splice(array);
-        //#end
-        return super.callMethod(method, a0, a1, a2, rest, nargs);
-    }
-        
-    public JS get(JS key) throws JSExn {
-        if (isInt(key)) {
-            int i = toInt(key);
-            if (i < 0 || i >= size()) return null;
-            return elementAt(i);
-        }
-        //#jswitch(key)
-        case "pop": return METHOD;
-        case "reverse": return METHOD;
-        case "toString": return METHOD;
-        case "shift": return METHOD;
-        case "join": return METHOD;
-        case "sort": return METHOD;
-        case "slice": return METHOD;
-        case "push": return METHOD;
-        case "unshift": return METHOD;
-        case "splice": return METHOD;
-        case "length": return N(size());
-        //#end
-        return super.get(key);
-    }
-
-    public void put(JS key, JS val) throws JSExn {
-        if (isInt(key)) {
-            int i = toInt(key);
-            int oldSize = size();
-            if(i < oldSize) {
-                setElementAt(val,i);
-            } else {
-                if(i > oldSize) setSize(i);
-                insertElementAt(val,i);
-            }
-            return;
-        }
-        if(isString(key)) {
-            if (JS.toString(key).equals("length")) {
-                setSize(JS.toInt(val));
-                return;
-            }
-        }
-        super.put(key,val);
-    }
-
-    public Enumeration keys() throws JSExn {
-        return new Enumeration(super.keys()) {
-                private int n = 0;
-                public boolean _hasMoreElements() { return n < size(); }
-                public JS _nextElement() {
-                    return n >= size() ? null : JS.N(n++);
-                }
-            };
-    }
-
-    public final void setSize(int newSize) {
-        // FEATURE: This could be done a lot more efficiently in BalancedTree
-        int oldSize = size();
-        for(int i=oldSize;i<newSize;i++) insertElementAt(null,i);
-        for(int i=oldSize-1;i>=newSize;i--) removeElementAt(i);
-    }
-    
-    public final int length() { return size(); }
-    public final JS elementAt(int i) { 
-        if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i);
-        Object o = bt.getNode(i);
-        return o == NULL ? (JS)null : (JS)o;
-    }
-    public final void addElement(JS o) { 
-        bt.insertNode(size(),o==null ? NULL : o);
-    }
-    public final void setElementAt(JS o, int i) {
-        if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i);
-        bt.replaceNode(i,o==null ? NULL : o);
-    }
-    public final void insertElementAt(JS o, int i) {
-        if(i < 0 || i > size()) throw new ArrayIndexOutOfBoundsException(i);
-        bt.insertNode(i,o==null ? NULL : o);
-    }
-    public final JS removeElementAt(int i) {
-        if(i < 0 || i >= size()) throw new ArrayIndexOutOfBoundsException(i);
-        Object o = bt.deleteNode(i);
-        return o == NULL ? (JS)null : (JS)o;
-    }
-    
-    public final int size() { return bt.treeSize(); }
-    
-    private JS join(String sep) throws JSExn {
-        int length = size();
-        if(length == 0) return JS.S("");
-        StringBuffer sb = new StringBuffer(64);
-        int i=0;
-        while(true) {
-            JS o = elementAt(i);
-            if(o != null) sb.append(JS.toString(o));
-            if(++i == length) break;
-            sb.append(sep);
-        }
-        return JS.S(sb.toString());
-    }
-    
-    // FEATURE: Implement this more efficiently
-    private JS reverse() {
-        int size = size();
-        if(size < 2) return this;
-        Vec vec = toVec();
-        bt.clear();
-        for(int i=size-1,j=0;i>=0;i--,j++) insertElementAt((JS)vec.elementAt(i),j);
-        return this;
-    }
-    
-    private JS slice(int start, int end) {
-        int length = length();
-        if(start < 0) start = length+start;
-        if(end < 0) end = length+end;
-        if(start < 0) start = 0;
-        if(end < 0) end = 0;
-        if(start > length) start = length;
-        if(end > length) end = length;
-        JSArray a = new JSArray(end-start);
-        for(int i=0;i<end-start;i++)
-            a.setElementAt(elementAt(start+i),i);
-        return a;
-    }
-        
-    private static final Vec.CompareFunc defaultSort = new Vec.CompareFunc() {
-        public int compare(Object a, Object b) {
-            try {
-                return JS.toString((JS)a).compareTo(JS.toString((JS)b));
-            } catch(JSExn e) { throw new JSExn.Wrapper(e); }
-        }
-    };
-    private JS sort(JS tmp) throws JSExn {
-        Vec vec = toVec();
-        try {
-            if(tmp instanceof JS) {
-                final JS jsFunc = (JS) tmp;
-                vec.sort(new Vec.CompareFunc() {
-                    public int compare(Object a, Object b) {
-                        try {
-                            return JS.toInt(jsFunc.call((JS)a, (JS)b, null, null, 2));
-                        } catch(JSExn e) { throw new JSExn.Wrapper(e); }
-                    }
-                });
-            } else {
-                vec.sort(defaultSort);
-            }
-        } catch(JSExn.Wrapper e) {
-            throw e.refill();
-        }
-        setFromVec(vec);
-        return this;
-    }
-    
-    private JS splice(JSArray args) throws JSExn {
-        int oldLength = length();
-        int start = JS.toInt(args.length() < 1 ? null : args.elementAt(0));
-        int deleteCount = JS.toInt(args.length() < 2 ? null : args.elementAt(1));
-        int newCount = args.length() - 2;
-        if(newCount < 0) newCount = 0;
-        if(start < 0) start = oldLength+start;
-        if(start < 0) start = 0;
-        if(start > oldLength) start = oldLength;
-        if(deleteCount < 0) deleteCount = 0;
-        if(deleteCount > oldLength-start) deleteCount = oldLength-start;
-        int newLength = oldLength - deleteCount + newCount;
-        int lengthChange = newLength - oldLength;
-        JSArray ret = new JSArray(deleteCount);
-        for(int i=0;i<deleteCount;i++)
-            ret.setElementAt(elementAt(start+i),i);
-        if(lengthChange > 0) {
-            setSize(newLength);
-            for(int i=newLength-1;i>=start+newCount;i--)
-                setElementAt(elementAt(i-lengthChange),i);
-        } else if(lengthChange < 0) {
-            for(int i=start+newCount;i<newLength;i++)
-                setElementAt(elementAt(i-lengthChange),i);
-            setSize(newLength);
-        }
-        for(int i=0;i<newCount;i++)
-            setElementAt(args.elementAt(i+2),start+i);
-        return ret;
-    }
-    
-    protected Vec toVec() {
-        int count = size();
-        Vec vec = new Vec();
-        vec.setSize(count);
-        for(int i=0;i<count;i++) {
-            Object o = bt.getNode(i);
-            vec.setElementAt(o == NULL ? null : o,i);
-        }
-        return vec;
-    }
-    
-    protected void setFromVec(Vec vec) {
-        int count = vec.size();
-        bt.clear();
-        for(int i=0;i<count;i++) {
-            Object o = vec.elementAt(i);
-            bt.insertNode(i,o==null ? NULL : o);
-        }
-    }
-    
-    String coerceToString() throws JSExn { return JS.toString(join(",")); }
-}
diff --git a/src/org/ibex/js/JSDate.java b/src/org/ibex/js/JSDate.java
deleted file mode 100644 (file)
index 144e868..0000000
+++ /dev/null
@@ -1,1247 +0,0 @@
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * The contents of this file are subject to the Netscape Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/NPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is Rhino code, released
- * May 6, 1999.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation.  Portions created by Netscape are
- * Copyright (C) 1997-1999 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- * Norris Boyd
- * Mike McCabe
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License (the "GPL"), in which case the
- * provisions of the GPL are applicable instead of those above.
- * If you wish to allow use of your version of this file only
- * under the terms of the GPL and not to allow others to use your
- * version of this file under the NPL, indicate your decision by
- * deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL.  If you do not delete
- * the provisions above, a recipient may use your version of this
- * file under either the NPL or the GPL.
- */
-
-package org.ibex.js;
-
-import java.text.DateFormat;
-
-/**
- * This class implements the Date native object.
- * See ECMA 15.9.
- * @author Mike McCabe
- * @author Adam Megacz (many modifications
- */
-public class JSDate extends JS {
-
-    public JSDate() {
-        if (thisTimeZone == null) {
-            // j.u.TimeZone is synchronized, so setting class statics from it
-            // should be OK.
-            thisTimeZone = java.util.TimeZone.getDefault();
-            LocalTZA = thisTimeZone.getRawOffset();
-        }
-    }
-
-    String coerceToString() { return date_format(date, FORMATSPEC_FULL); }
-
-    public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-        switch(nargs) {
-            case 0: {
-                //#jswitch(method)
-                case "toString": return JS.S(date_format(date, FORMATSPEC_FULL));
-                case "toTimeString": return JS.S(date_format(date, FORMATSPEC_TIME));
-                case "toDateString": return JS.S(date_format(date, FORMATSPEC_DATE));
-                case "toLocaleString": return JS.S(toLocaleString(date));
-                case "toLocaleTimeString": return JS.S(toLocaleTimeString(date));
-                case "toLocaleDateString": return JS.S(toLocaleDateString(date));
-                case "toUTCString": return JS.S(toUTCString(date));
-                case "valueOf": return N(this.date);
-                case "getTime": return N(this.date);
-                case "getYear": return N(getYear(date));
-                case "getFullYear": return N(YearFromTime(LocalTime(date)));
-                case "getUTCFullYear": return N(YearFromTime(date));
-                case "getMonth": return N(MonthFromTime(LocalTime(date)));
-                case "getUTCMonth": return N(MonthFromTime(date));
-                case "getDate": return N(DateFromTime(LocalTime(date)));
-                case "getUTCDate": return N(DateFromTime(date));
-                case "getDay": return N(WeekDay(LocalTime(date)));
-                case "getUTCDay": return N(WeekDay(date));
-                case "getHours": return N(HourFromTime(LocalTime(date)));
-                case "getUTCHours": return N(HourFromTime(date));
-                case "getMinutes": return N(MinFromTime(LocalTime(date)));
-                case "getUTCMinutes": return N(MinFromTime(date));
-                case "getSeconds": return N(SecFromTime(LocalTime(date)));
-                case "getUTCSeconds": return N(SecFromTime(date));
-                case "getMilliseconds": return N(msFromTime(LocalTime(date)));
-                case "getUTCMilliseconds": return N(msFromTime(date));
-                case "getTimezoneOffset": return N(getTimezoneOffset(date));
-                //#end
-                return super.callMethod(method, a0, a1, a2, rest, nargs);
-            }
-            case 1: {
-                //#jswitch(method)
-                case "setTime": return N(this.setTime(toDouble(a0)));
-                case "setYear": return N(this.setYear(toDouble(a0)));
-                //#end
-                // fall through
-            }
-            default: {
-                JS[] args = new JS[nargs];
-                for(int i=0; i<nargs; i++) args[i] = i==0 ? a0 : i==1 ? a1 : i==2 ? a2 : rest[i-3];
-                //#jswitch(method)
-                case "setMilliseconds": return N(this.makeTime(args, 1, true));
-                case "setUTCMilliseconds": return N(this.makeTime(args, 1, false));
-                case "setSeconds": return N(this.makeTime(args, 2, true));
-                case "setUTCSeconds": return N(this.makeTime(args, 2, false));
-                case "setMinutes": return N(this.makeTime(args, 3, true));
-                case "setUTCMinutes": return N(this.makeTime(args, 3, false));
-                case "setHours": return N(this.makeTime(args, 4, true));
-                case "setUTCHours": return N(this.makeTime(args, 4, false));
-                case "setDate": return N(this.makeDate(args, 1, true));
-                case "setUTCDate": return N(this.makeDate(args, 1, false));
-                case "setMonth": return N(this.makeDate(args, 2, true));
-                case "setUTCMonth": return N(this.makeDate(args, 2, false));
-                case "setFullYear": return N(this.makeDate(args, 3, true));
-                case "setUTCFullYear": return N(this.makeDate(args, 3, false));
-                //#end
-            }
-        }
-        return super.callMethod(method, a0, a1, a2, rest, nargs);
-    }
-
-    public JS get(JS key) throws JSExn {
-        //#jswitch(key)
-        case "toString": return METHOD;
-        case "toTimeString": return METHOD;
-        case "toDateString": return METHOD;
-        case "toLocaleString": return METHOD;
-        case "toLocaleTimeString": return METHOD;
-        case "toLocaleDateString": return METHOD;
-        case "toUTCString": return METHOD;
-        case "valueOf": return METHOD;
-        case "getTime": return METHOD;
-        case "getYear": return METHOD;
-        case "getFullYear": return METHOD;
-        case "getUTCFullYear": return METHOD;
-        case "getMonth": return METHOD;
-        case "getUTCMonth": return METHOD;
-        case "getDate": return METHOD;
-        case "getUTCDate": return METHOD;
-        case "getDay": return METHOD;
-        case "getUTCDay": return METHOD;
-        case "getHours": return METHOD;
-        case "getUTCHours": return METHOD;
-        case "getMinutes": return METHOD;
-        case "getUTCMinutes": return METHOD;
-        case "getSeconds": return METHOD;
-        case "getUTCSeconds": return METHOD;
-        case "getMilliseconds": return METHOD;
-        case "getUTCMilliseconds": return METHOD;
-        case "getTimezoneOffset": return METHOD;
-        case "setTime": return METHOD;
-        case "setYear": return METHOD;
-        case "setMilliseconds": return METHOD;
-        case "setUTCMilliseconds": return METHOD;
-        case "setSeconds": return METHOD;
-        case "setUTCSeconds": return METHOD;
-        case "setMinutes": return METHOD;
-        case "setUTCMinutes": return METHOD;
-        case "setHours": return METHOD;
-        case "setUTCHours": return METHOD;
-        case "setDate": return METHOD;
-        case "setUTCDate": return METHOD;
-        case "setMonth": return METHOD;
-        case "setUTCMonth": return METHOD;
-        case "setFullYear": return METHOD;
-        case "setUTCFullYear": return METHOD;
-        //#end
-        return super.get(key);
-    }
-
-    /* ECMA helper functions */
-
-    private static final double HalfTimeDomain = 8.64e15;
-    private static final double HoursPerDay    = 24.0;
-    private static final double MinutesPerHour = 60.0;
-    private static final double SecondsPerMinute = 60.0;
-    private static final double msPerSecond    = 1000.0;
-    private static final double MinutesPerDay  = (HoursPerDay * MinutesPerHour);
-    private static final double SecondsPerDay  = (MinutesPerDay * SecondsPerMinute);
-    private static final double SecondsPerHour = (MinutesPerHour * SecondsPerMinute);
-    private static final double msPerDay       = (SecondsPerDay * msPerSecond);
-    private static final double msPerHour      = (SecondsPerHour * msPerSecond);
-    private static final double msPerMinute    = (SecondsPerMinute * msPerSecond);
-
-    private static double Day(double t) {
-        return java.lang.Math.floor(t / msPerDay);
-    }
-
-    private static double TimeWithinDay(double t) {
-        double result;
-        result = t % msPerDay;
-        if (result < 0)
-            result += msPerDay;
-        return result;
-    }
-
-    private static int DaysInYear(int y) {
-        if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
-            return 366;
-        else
-            return 365;
-    }
-
-
-    /* math here has to be f.p, because we need
-     *  floor((1968 - 1969) / 4) == -1
-     */
-    private static double DayFromYear(double y) {
-        return ((365 * ((y)-1970) + java.lang.Math.floor(((y)-1969)/4.0)
-                 - java.lang.Math.floor(((y)-1901)/100.0) + java.lang.Math.floor(((y)-1601)/400.0)));
-    }
-
-    private static double TimeFromYear(double y) {
-        return DayFromYear(y) * msPerDay;
-    }
-
-    private static int YearFromTime(double t) {
-        int lo = (int) java.lang.Math.floor((t / msPerDay) / 366) + 1970;
-        int hi = (int) java.lang.Math.floor((t / msPerDay) / 365) + 1970;
-        int mid;
-
-        /* above doesn't work for negative dates... */
-        if (hi < lo) {
-            int temp = lo;
-            lo = hi;
-            hi = temp;
-        }
-
-        /* Use a simple binary search algorithm to find the right
-           year.  This seems like brute force... but the computation
-           of hi and lo years above lands within one year of the
-           correct answer for years within a thousand years of
-           1970; the loop below only requires six iterations
-           for year 270000. */
-        while (hi > lo) {
-            mid = (hi + lo) / 2;
-            if (TimeFromYear(mid) > t) {
-                hi = mid - 1;
-            } else {
-                if (TimeFromYear(mid) <= t) {
-                    int temp = mid + 1;
-                    if (TimeFromYear(temp) > t) {
-                        return mid;
-                    }
-                    lo = mid + 1;
-                }
-            }
-        }
-        return lo;
-    }
-
-    private static boolean InLeapYear(double t) {
-        return DaysInYear(YearFromTime(t)) == 366;
-    }
-
-    private static int DayWithinYear(double t) {
-        int year = YearFromTime(t);
-        return (int) (Day(t) - DayFromYear(year));
-    }
-    /*
-     * The following array contains the day of year for the first day of
-     * each month, where index 0 is January, and day 0 is January 1.
-     */
-
-    private static double DayFromMonth(int m, boolean leap) {
-        int day = m * 30;
-
-        if (m >= 7) { day += m / 2 - 1; }
-        else if (m >= 2) { day += (m - 1) / 2 - 1; }
-        else { day += m; }
-
-        if (leap && m >= 2) { ++day; }
-
-        return day;
-    }
-
-    private static int MonthFromTime(double t) {
-        int d, step;
-
-        d = DayWithinYear(t);
-
-        if (d < (step = 31))
-            return 0;
-
-        // Originally coded as step += (InLeapYear(t) ? 29 : 28);
-        // but some jits always returned 28!
-        if (InLeapYear(t))
-            step += 29;
-        else
-            step += 28;
-
-        if (d < step)
-            return 1;
-        if (d < (step += 31))
-            return 2;
-        if (d < (step += 30))
-            return 3;
-        if (d < (step += 31))
-            return 4;
-        if (d < (step += 30))
-            return 5;
-        if (d < (step += 31))
-            return 6;
-        if (d < (step += 31))
-            return 7;
-        if (d < (step += 30))
-            return 8;
-        if (d < (step += 31))
-            return 9;
-        if (d < (step += 30))
-            return 10;
-        return 11;
-    }
-
-    private static int DateFromTime(double t) {
-        int d, step, next;
-
-        d = DayWithinYear(t);
-        if (d <= (next = 30))
-            return d + 1;
-        step = next;
-
-        // Originally coded as next += (InLeapYear(t) ? 29 : 28);
-        // but some jits always returned 28!
-        if (InLeapYear(t))
-            next += 29;
-        else
-            next += 28;
-
-        if (d <= next)
-            return d - step;
-        step = next;
-        if (d <= (next += 31))
-            return d - step;
-        step = next;
-        if (d <= (next += 30))
-            return d - step;
-        step = next;
-        if (d <= (next += 31))
-            return d - step;
-        step = next;
-        if (d <= (next += 30))
-            return d - step;
-        step = next;
-        if (d <= (next += 31))
-            return d - step;
-        step = next;
-        if (d <= (next += 31))
-            return d - step;
-        step = next;
-        if (d <= (next += 30))
-            return d - step;
-        step = next;
-        if (d <= (next += 31))
-            return d - step;
-        step = next;
-        if (d <= (next += 30))
-            return d - step;
-        step = next;
-
-        return d - step;
-    }
-
-    private static int WeekDay(double t) {
-        double result;
-        result = Day(t) + 4;
-        result = result % 7;
-        if (result < 0)
-            result += 7;
-        return (int) result;
-    }
-
-    private static double Now() {
-        return (double) System.currentTimeMillis();
-    }
-
-    /* Should be possible to determine the need for this dynamically
-     * if we go with the workaround... I'm not using it now, because I
-     * can't think of any clean way to make toLocaleString() and the
-     * time zone (comment) in toString match the generated string
-     * values.  Currently it's wrong-but-consistent in all but the
-     * most recent betas of the JRE - seems to work in 1.1.7.
-     */
-    private final static boolean TZO_WORKAROUND = false;
-    private static double DaylightSavingTA(double t) {
-        if (!TZO_WORKAROUND) {
-            java.util.Date date = new java.util.Date((long) t);
-            if (thisTimeZone.inDaylightTime(date))
-                return msPerHour;
-            else
-                return 0;
-        } else {
-            /* Use getOffset if inDaylightTime() is broken, because it
-             * seems to work acceptably.  We don't switch over to it
-             * entirely, because it requires (expensive) exploded date arguments,
-             * and the api makes it impossible to handle dst
-             * changeovers cleanly.
-             */
-
-            // Hardcode the assumption that the changeover always
-            // happens at 2:00 AM:
-            t += LocalTZA + (HourFromTime(t) <= 2 ? msPerHour : 0);
-
-            int year = YearFromTime(t);
-            double offset = thisTimeZone.getOffset(year > 0 ? 1 : 0,
-                                                   year,
-                                                   MonthFromTime(t),
-                                                   DateFromTime(t),
-                                                   WeekDay(t),
-                                                   (int)TimeWithinDay(t));
-
-            if ((offset - LocalTZA) != 0)
-                return msPerHour;
-            else
-                return 0;
-            //         return offset - LocalTZA;
-        }
-    }
-
-    private static double LocalTime(double t) {
-        return t + LocalTZA + DaylightSavingTA(t);
-    }
-
-    public static double internalUTC(double t) {
-        return t - LocalTZA - DaylightSavingTA(t - LocalTZA);
-    }
-
-    private static int HourFromTime(double t) {
-        double result;
-        result = java.lang.Math.floor(t / msPerHour) % HoursPerDay;
-        if (result < 0)
-            result += HoursPerDay;
-        return (int) result;
-    }
-
-    private static int MinFromTime(double t) {
-        double result;
-        result = java.lang.Math.floor(t / msPerMinute) % MinutesPerHour;
-        if (result < 0)
-            result += MinutesPerHour;
-        return (int) result;
-    }
-
-    private static int SecFromTime(double t) {
-        double result;
-        result = java.lang.Math.floor(t / msPerSecond) % SecondsPerMinute;
-        if (result < 0)
-            result += SecondsPerMinute;
-        return (int) result;
-    }
-
-    private static int msFromTime(double t) {
-        double result;
-        result =  t % msPerSecond;
-        if (result < 0)
-            result += msPerSecond;
-        return (int) result;
-    }
-
-    private static double MakeTime(double hour, double min,
-                                   double sec, double ms)
-    {
-        return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec)
-            * msPerSecond + ms;
-    }
-
-    private static double MakeDay(double year, double month, double date) {
-        double result;
-        boolean leap;
-        double yearday;
-        double monthday;
-
-        year += java.lang.Math.floor(month / 12);
-
-        month = month % 12;
-        if (month < 0)
-            month += 12;
-
-        leap = (DaysInYear((int) year) == 366);
-
-        yearday = java.lang.Math.floor(TimeFromYear(year) / msPerDay);
-        monthday = DayFromMonth((int) month, leap);
-
-        result = yearday
-            + monthday
-            + date - 1;
-        return result;
-    }
-
-    private static double MakeDate(double day, double time) {
-        return day * msPerDay + time;
-    }
-
-    private static double TimeClip(double d) {
-        if (d != d ||
-            d == Double.POSITIVE_INFINITY ||
-            d == Double.NEGATIVE_INFINITY ||
-            java.lang.Math.abs(d) > HalfTimeDomain)
-        {
-            return Double.NaN;
-        }
-        if (d > 0.0)
-            return java.lang.Math.floor(d + 0.);
-        else
-            return java.lang.Math.ceil(d + 0.);
-    }
-
-    /* end of ECMA helper functions */
-
-    /* find UTC time from given date... no 1900 correction! */
-    public static double date_msecFromDate(double year, double mon,
-                                            double mday, double hour,
-                                            double min, double sec,
-                                            double msec)
-    {
-        double day;
-        double time;
-        double result;
-
-        day = MakeDay(year, mon, mday);
-        time = MakeTime(hour, min, sec, msec);
-        result = MakeDate(day, time);
-        return result;
-    }
-
-
-    private static final int MAXARGS = 7;
-    private static double jsStaticJSFunction_UTC(JS[] args) throws JSExn {
-        double array[] = new double[MAXARGS];
-        int loop;
-        double d;
-
-        for (loop = 0; loop < MAXARGS; loop++) {
-            if (loop < args.length) {
-                d = _toNumber(args[loop]);
-                if (d != d || Double.isInfinite(d)) {
-                    return Double.NaN;
-                }
-                array[loop] = toDouble(args[loop]);
-            } else {
-                array[loop] = 0;
-            }
-        }
-
-        /* adjust 2-digit years into the 20th century */
-        if (array[0] >= 0 && array[0] <= 99)
-            array[0] += 1900;
-
-            /* if we got a 0 for 'date' (which is out of range)
-             * pretend it's a 1.  (So Date.UTC(1972, 5) works) */
-        if (array[2] < 1)
-            array[2] = 1;
-
-        d = date_msecFromDate(array[0], array[1], array[2],
-                              array[3], array[4], array[5], array[6]);
-        d = TimeClip(d);
-        return d;
-        //        return N(d);
-    }
-
-    /*
-     * Use ported code from jsdate.c rather than the locale-specific
-     * date-parsing code from Java, to keep js and rhino consistent.
-     * Is this the right strategy?
-     */
-
-    /* for use by date_parse */
-
-    /* replace this with byte arrays?  Cheaper? */
-    private static String wtb[] = {
-        "am", "pm",
-        "monday", "tuesday", "wednesday", "thursday", "friday",
-        "saturday", "sunday",
-        "january", "february", "march", "april", "may", "june",
-        "july", "august", "september", "october", "november", "december",
-        "gmt", "ut", "utc", "est", "edt", "cst", "cdt",
-        "mst", "mdt", "pst", "pdt"
-        /* time zone table needs to be expanded */
-    };
-
-    private static int ttb[] = {
-        -1, -2, 0, 0, 0, 0, 0, 0, 0,     /* AM/PM */
-        2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
-        10000 + 0, 10000 + 0, 10000 + 0, /* UT/UTC */
-        10000 + 5 * 60, 10000 + 4 * 60,  /* EDT */
-        10000 + 6 * 60, 10000 + 5 * 60,
-        10000 + 7 * 60, 10000 + 6 * 60,
-        10000 + 8 * 60, 10000 + 7 * 60
-    };
-
-    /* helper for date_parse */
-    private static boolean date_regionMatches(String s1, int s1off,
-                                              String s2, int s2off,
-                                              int count)
-    {
-        boolean result = false;
-        /* return true if matches, otherwise, false */
-        int s1len = s1.length();
-        int s2len = s2.length();
-
-        while (count > 0 && s1off < s1len && s2off < s2len) {
-            if (Character.toLowerCase(s1.charAt(s1off)) !=
-                Character.toLowerCase(s2.charAt(s2off)))
-                break;
-            s1off++;
-            s2off++;
-            count--;
-        }
-
-        if (count == 0) {
-            result = true;
-        }
-        return result;
-    }
-
-    private static double date_parseString(String s) {
-        double msec;
-
-        int year = -1;
-        int mon = -1;
-        int mday = -1;
-        int hour = -1;
-        int min = -1;
-        int sec = -1;
-        char c = 0;
-        char si = 0;
-        int i = 0;
-        int n = -1;
-        double tzoffset = -1;
-        char prevc = 0;
-        int limit = 0;
-        boolean seenplusminus = false;
-
-        if (s == null)  // ??? Will s be null?
-            return Double.NaN;
-        limit = s.length();
-        while (i < limit) {
-            c = s.charAt(i);
-            i++;
-            if (c <= ' ' || c == ',' || c == '-') {
-                if (i < limit) {
-                    si = s.charAt(i);
-                    if (c == '-' && '0' <= si && si <= '9') {
-                        prevc = c;
-                    }
-                }
-                continue;
-            }
-            if (c == '(') { /* comments) */
-                int depth = 1;
-                while (i < limit) {
-                    c = s.charAt(i);
-                    i++;
-                    if (c == '(')
-                        depth++;
-                    else if (c == ')')
-                        if (--depth <= 0)
-                            break;
-                }
-                continue;
-            }
-            if ('0' <= c && c <= '9') {
-                n = c - '0';
-                while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {
-                    n = n * 10 + c - '0';
-                    i++;
-                }
-
-                /* allow TZA before the year, so
-                 * 'Wed Nov 05 21:49:11 GMT-0800 1997'
-                 * works */
-
-                /* uses of seenplusminus allow : in TZA, so Java
-                 * no-timezone style of GMT+4:30 works
-                 */
-                if ((prevc == '+' || prevc == '-')/*  && year>=0 */) {
-                    /* make ':' case below change tzoffset */
-                    seenplusminus = true;
-
-                    /* offset */
-                    if (n < 24)
-                        n = n * 60; /* EG. "GMT-3" */
-                    else
-                        n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */
-                    if (prevc == '+')       /* plus means east of GMT */
-                        n = -n;
-                    if (tzoffset != 0 && tzoffset != -1)
-                        return Double.NaN;
-                    tzoffset = n;
-                } else if (n >= 70  ||
-                           (prevc == '/' && mon >= 0 && mday >= 0 && year < 0)) {
-                    if (year >= 0)
-                        return Double.NaN;
-                    else if (c <= ' ' || c == ',' || c == '/' || i >= limit)
-                        year = n < 100 ? n + 1900 : n;
-                    else
-                        return Double.NaN;
-                } else if (c == ':') {
-                    if (hour < 0)
-                        hour = /*byte*/ n;
-                    else if (min < 0)
-                        min = /*byte*/ n;
-                    else
-                        return Double.NaN;
-                } else if (c == '/') {
-                    if (mon < 0)
-                        mon = /*byte*/ n-1;
-                    else if (mday < 0)
-                        mday = /*byte*/ n;
-                    else
-                        return Double.NaN;
-                } else if (i < limit && c != ',' && c > ' ' && c != '-') {
-                    return Double.NaN;
-                } else if (seenplusminus && n < 60) {  /* handle GMT-3:30 */
-                    if (tzoffset < 0)
-                        tzoffset -= n;
-                    else
-                        tzoffset += n;
-                } else if (hour >= 0 && min < 0) {
-                    min = /*byte*/ n;
-                } else if (min >= 0 && sec < 0) {
-                    sec = /*byte*/ n;
-                } else if (mday < 0) {
-                    mday = /*byte*/ n;
-                } else {
-                    return Double.NaN;
-                }
-                prevc = 0;
-            } else if (c == '/' || c == ':' || c == '+' || c == '-') {
-                prevc = c;
-            } else {
-                int st = i - 1;
-                int k;
-                while (i < limit) {
-                    c = s.charAt(i);
-                    if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')))
-                        break;
-                    i++;
-                }
-                if (i <= st + 1)
-                    return Double.NaN;
-                for (k = wtb.length; --k >= 0;)
-                    if (date_regionMatches(wtb[k], 0, s, st, i-st)) {
-                        int action = ttb[k];
-                        if (action != 0) {
-                            if (action < 0) {
-                                /*
-                                 * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as
-                                 * 12:30, instead of blindly adding 12 if PM.
-                                 */
-                                if (hour > 12 || hour < 0) {
-                                    return Double.NaN;
-                                } else {
-                                    if (action == -1 && hour == 12) { // am
-                                        hour = 0;
-                                    } else if (action == -2 && hour != 12) {// pm
-                                        hour += 12;
-                                    }
-                                }
-                            } else if (action <= 13) { /* month! */
-                                if (mon < 0) {
-                                    mon = /*byte*/ (action - 2);
-                                } else {
-                                    return Double.NaN;
-                                }
-                            } else {
-                                tzoffset = action - 10000;
-                            }
-                        }
-                        break;
-                    }
-                if (k < 0)
-                    return Double.NaN;
-                prevc = 0;
-            }
-        }
-        if (year < 0 || mon < 0 || mday < 0)
-            return Double.NaN;
-        if (sec < 0)
-            sec = 0;
-        if (min < 0)
-            min = 0;
-        if (hour < 0)
-            hour = 0;
-        if (tzoffset == -1) { /* no time zone specified, have to use local */
-            double time;
-            time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
-            return internalUTC(time);
-        }
-
-        msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
-        msec += tzoffset * msPerMinute;
-        return msec;
-    }
-
-    private static double jsStaticJSFunction_parse(String s) {
-        return date_parseString(s);
-    }
-
-    private static final int FORMATSPEC_FULL = 0;
-    private static final int FORMATSPEC_DATE = 1;
-    private static final int FORMATSPEC_TIME = 2;
-
-    private static String date_format(double t, int format) {
-        if (t != t)
-            return NaN_date_str;
-
-        StringBuffer result = new StringBuffer(60);
-        double local = LocalTime(t);
-
-        /* offset from GMT in minutes.  The offset includes daylight savings,
-           if it applies. */
-        int minutes = (int) java.lang.Math.floor((LocalTZA + DaylightSavingTA(t))
-                                       / msPerMinute);
-        /* map 510 minutes to 0830 hours */
-        int offset = (minutes / 60) * 100 + minutes % 60;
-
-        String dateStr = Integer.toString(DateFromTime(local));
-        String hourStr = Integer.toString(HourFromTime(local));
-        String minStr = Integer.toString(MinFromTime(local));
-        String secStr = Integer.toString(SecFromTime(local));
-        String offsetStr = Integer.toString(offset > 0 ? offset : -offset);
-        int year = YearFromTime(local);
-        String yearStr = Integer.toString(year > 0 ? year : -year);
-
-        /* Tue Oct 31 09:41:40 GMT-0800 (PST) 2000 */
-        /* Tue Oct 31 2000 */
-        /* 09:41:40 GMT-0800 (PST) */
-
-        if (format != FORMATSPEC_TIME) {
-            result.append(days[WeekDay(local)]);
-            result.append(' ');
-            result.append(months[MonthFromTime(local)]);
-            if (dateStr.length() == 1)
-                result.append(" 0");
-            else
-                result.append(' ');
-            result.append(dateStr);
-            result.append(' ');
-        }
-
-        if (format != FORMATSPEC_DATE) {
-            if (hourStr.length() == 1)
-                result.append('0');
-            result.append(hourStr);
-            if (minStr.length() == 1)
-                result.append(":0");
-            else
-                result.append(':');
-            result.append(minStr);
-            if (secStr.length() == 1)
-                result.append(":0");
-            else
-                result.append(':');
-            result.append(secStr);
-            if (offset > 0)
-                result.append(" GMT+");
-            else
-                result.append(" GMT-");
-            for (int i = offsetStr.length(); i < 4; i++)
-                result.append('0');
-            result.append(offsetStr);
-
-            if (timeZoneFormatter == null)
-                timeZoneFormatter = new java.text.SimpleDateFormat("zzz");
-
-            if (timeZoneFormatter != null) {
-                result.append(" (");
-                java.util.Date date = new java.util.Date((long) t);
-                result.append(timeZoneFormatter.format(date));
-                result.append(')');
-            }
-            if (format != FORMATSPEC_TIME)
-                result.append(' ');
-        }
-
-        if (format != FORMATSPEC_TIME) {
-            if (year < 0)
-                result.append('-');
-            for (int i = yearStr.length(); i < 4; i++)
-                result.append('0');
-            result.append(yearStr);
-        }
-
-        return result.toString();
-    }
-
-    private static double _toNumber(JS o) throws JSExn { return JS.toDouble(o); }
-    private static double _toNumber(JS[] o, int index) throws JSExn { return JS.toDouble(o[index]); }
-    private static double toDouble(double d) { return d; }
-
-    public JSDate(JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-
-        JSDate obj = this;
-        switch (nargs) {
-            case 0: {
-                obj.date = Now();
-                return;
-            }
-            case 1: {
-                double date;
-                if(isString(a0))
-                    date = date_parseString(JS.toString(a0));
-                else
-                    date = _toNumber(a0);
-                obj.date = TimeClip(date);
-                return;
-            }
-            default: {
-                // multiple arguments; year, month, day etc.
-                double array[] = new double[MAXARGS];
-                array[0] = toDouble(a0);
-                array[1] = toDouble(a1);
-                if (nargs >= 2) array[2] = toDouble(a2);
-                for(int i=0; i<nargs; i++) {
-                    double d = _toNumber(i==0?a0:i==1?a1:i==2?a2:rest[i-3]);
-                    if (d != d || Double.isInfinite(d)) {
-                        obj.date = Double.NaN;
-                        return;
-                    }
-                    array[i] = d;
-                }
-                
-                /* adjust 2-digit years into the 20th century */
-                if (array[0] >= 0 && array[0] <= 99)
-                    array[0] += 1900;
-                
-                /* if we got a 0 for 'date' (which is out of range)
-                 * pretend it's a 1 */
-                if (array[2] < 1)
-                    array[2] = 1;
-                
-                double day = MakeDay(array[0], array[1], array[2]);
-                double time = MakeTime(array[3], array[4], array[5], array[6]);
-                time = MakeDate(day, time);
-                time = internalUTC(time);
-                obj.date = TimeClip(time);
-                
-                return;
-            }
-        }
-    }
-
-    /* constants for toString, toUTCString */
-    private static String NaN_date_str = "Invalid Date";
-
-    private static String[] days = {
-        "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
-    };
-
-    private static String[] months = {
-        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-    };
-
-    private static String toLocale_helper(double t,
-                                          java.text.DateFormat formatter)
-    {
-        if (t != t)
-            return NaN_date_str;
-
-        java.util.Date tempdate = new java.util.Date((long) t);
-        return formatter.format(tempdate);
-    }
-
-    private static String toLocaleString(double date) {
-        if (localeDateTimeFormatter == null)
-            localeDateTimeFormatter =
-                DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
-
-        return toLocale_helper(date, localeDateTimeFormatter);
-    }
-
-    private static String toLocaleTimeString(double date) {
-        if (localeTimeFormatter == null)
-            localeTimeFormatter = DateFormat.getTimeInstance(DateFormat.LONG);
-
-        return toLocale_helper(date, localeTimeFormatter);
-    }
-
-    private static String toLocaleDateString(double date) {
-        if (localeDateFormatter == null)
-            localeDateFormatter = DateFormat.getDateInstance(DateFormat.LONG);
-
-        return toLocale_helper(date, localeDateFormatter);
-    }
-
-    private static String toUTCString(double date) {
-        StringBuffer result = new StringBuffer(60);
-
-        String dateStr = Integer.toString(DateFromTime(date));
-        String hourStr = Integer.toString(HourFromTime(date));
-        String minStr = Integer.toString(MinFromTime(date));
-        String secStr = Integer.toString(SecFromTime(date));
-        int year = YearFromTime(date);
-        String yearStr = Integer.toString(year > 0 ? year : -year);
-
-        result.append(days[WeekDay(date)]);
-        result.append(", ");
-        if (dateStr.length() == 1)
-            result.append('0');
-        result.append(dateStr);
-        result.append(' ');
-        result.append(months[MonthFromTime(date)]);
-        if (year < 0)
-            result.append(" -");
-        else
-            result.append(' ');
-        int i;
-        for (i = yearStr.length(); i < 4; i++)
-            result.append('0');
-        result.append(yearStr);
-
-        if (hourStr.length() == 1)
-            result.append(" 0");
-        else
-            result.append(' ');
-        result.append(hourStr);
-        if (minStr.length() == 1)
-            result.append(":0");
-        else
-            result.append(':');
-        result.append(minStr);
-        if (secStr.length() == 1)
-            result.append(":0");
-        else
-            result.append(':');
-        result.append(secStr);
-
-        result.append(" GMT");
-        return result.toString();
-    }
-
-    private static double getYear(double date) {
-        int result = YearFromTime(LocalTime(date));
-        result -= 1900;
-        return result;
-    }
-
-    private static double getTimezoneOffset(double date) {
-        return (date - LocalTime(date)) / msPerMinute;
-    }
-
-    public double setTime(double time) {
-        this.date = TimeClip(time);
-        return this.date;
-    }
-
-    private double makeTime(JS[] args, int maxargs, boolean local) throws JSExn {
-        int i;
-        double conv[] = new double[4];
-        double hour, min, sec, msec;
-        double lorutime; /* Local or UTC version of date */
-
-        double time;
-        double result;
-
-        double date = this.date;
-
-        /* just return NaN if the date is already NaN */
-        if (date != date)
-            return date;
-
-        /* Satisfy the ECMA rule that if a function is called with
-         * fewer arguments than the specified formal arguments, the
-         * remaining arguments are set to undefined.  Seems like all
-         * the Date.setWhatever functions in ECMA are only varargs
-         * beyond the first argument; this should be set to undefined
-         * if it's not given.  This means that "d = new Date();
-         * d.setMilliseconds()" returns NaN.  Blech.
-         */
-        if (args.length == 0)
-            args = new JS[] { null };
-
-        for (i = 0; i < args.length && i < maxargs; i++) {
-            conv[i] = _toNumber(args[i]);
-
-            // limit checks that happen in MakeTime in ECMA.
-            if (conv[i] != conv[i] || Double.isInfinite(conv[i])) {
-                this.date = Double.NaN;
-                return this.date;
-            }
-            conv[i] = toDouble(conv[i]);
-        }
-
-        if (local)
-            lorutime = LocalTime(date);
-        else
-            lorutime = date;
-
-        i = 0;
-        int stop = args.length;
-
-        if (maxargs >= 4 && i < stop)
-            hour = conv[i++];
-        else
-            hour = HourFromTime(lorutime);
-
-        if (maxargs >= 3 && i < stop)
-            min = conv[i++];
-        else
-            min = MinFromTime(lorutime);
-
-        if (maxargs >= 2 && i < stop)
-            sec = conv[i++];
-        else
-            sec = SecFromTime(lorutime);
-
-        if (maxargs >= 1 && i < stop)
-            msec = conv[i++];
-        else
-            msec = msFromTime(lorutime);
-
-        time = MakeTime(hour, min, sec, msec);
-        result = MakeDate(Day(lorutime), time);
-
-        if (local)
-            result = internalUTC(result);
-        date = TimeClip(result);
-
-        this.date = date;
-        return date;
-    }
-
-    private double setHours(JS[] args) throws JSExn {
-        return makeTime(args, 4, true);
-    }
-
-    private double setUTCHours(JS[] args) throws JSExn {
-        return makeTime(args, 4, false);
-    }
-
-    private double makeDate(JS[] args, int maxargs, boolean local) throws JSExn {
-        int i;
-        double conv[] = new double[3];
-        double year, month, day;
-        double lorutime; /* local or UTC version of date */
-        double result;
-
-        double date = this.date;
-
-        /* See arg padding comment in makeTime.*/
-        if (args.length == 0)
-            args = new JS[] { null };
-
-        for (i = 0; i < args.length && i < maxargs; i++) {
-            conv[i] = _toNumber(args[i]);
-
-            // limit checks that happen in MakeDate in ECMA.
-            if (conv[i] != conv[i] || Double.isInfinite(conv[i])) {
-                this.date = Double.NaN;
-                return this.date;
-            }
-            conv[i] = toDouble(conv[i]);
-        }
-
-        /* return NaN if date is NaN and we're not setting the year,
-         * If we are, use 0 as the time. */
-        if (date != date) {
-            if (args.length < 3) {
-                return Double.NaN;
-            } else {
-                lorutime = 0;
-            }
-        } else {
-            if (local)
-                lorutime = LocalTime(date);
-            else
-                lorutime = date;
-        }
-
-        i = 0;
-        int stop = args.length;
-
-        if (maxargs >= 3 && i < stop)
-            year = conv[i++];
-        else
-            year = YearFromTime(lorutime);
-
-        if (maxargs >= 2 && i < stop)
-            month = conv[i++];
-        else
-            month = MonthFromTime(lorutime);
-
-        if (maxargs >= 1 && i < stop)
-            day = conv[i++];
-        else
-            day = DateFromTime(lorutime);
-
-        day = MakeDay(year, month, day); /* day within year */
-        result = MakeDate(day, TimeWithinDay(lorutime));
-
-        if (local)
-            result = internalUTC(result);
-
-        date = TimeClip(result);
-
-        this.date = date;
-        return date;
-    }
-
-    private double setYear(double year) {
-        double day, result;
-        if (year != year || Double.isInfinite(year)) {
-            this.date = Double.NaN;
-            return this.date;
-        }
-
-        if (this.date != this.date) {
-            this.date = 0;
-        } else {
-            this.date = LocalTime(this.date);
-        }
-
-        if (year >= 0 && year <= 99)
-            year += 1900;
-
-        day = MakeDay(year, MonthFromTime(this.date), DateFromTime(this.date));
-        result = MakeDate(day, TimeWithinDay(this.date));
-        result = internalUTC(result);
-
-        this.date = TimeClip(result);
-        return this.date;
-    }
-
-
-    //    private static final int
-    //        Id_toGMTString  =  Id_toUTCString; // Alias, see Ecma B.2.6
-// #/string_id_map#
-
-    /* cached values */
-    private static java.util.TimeZone thisTimeZone;
-    private static double LocalTZA;
-    private static java.text.DateFormat timeZoneFormatter;
-    private static java.text.DateFormat localeDateTimeFormatter;
-    private static java.text.DateFormat localeDateFormatter;
-    private static java.text.DateFormat localeTimeFormatter;
-
-    private double date;
-
-    public long getRawTime() { return (long)this.date; }
-}
-
-
diff --git a/src/org/ibex/js/JSExn.java b/src/org/ibex/js/JSExn.java
deleted file mode 100644 (file)
index 2afcef1..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] 
-package org.ibex.js; 
-
-import org.ibex.util.*; 
-import java.io.*;
-
-/** An exception which can be thrown and caught by JavaScript code */
-public class JSExn extends Exception { 
-    private Vec backtrace = new Vec();
-    private JS js; 
-    public JSExn(String s) { this(JS.S(s)); }
-    public JSExn(JS js) { this(js,null); }
-    public JSExn(JS js, Interpreter cx) { this.js = js; fill(cx); }
-    
-    private void fill(Interpreter cx) {
-        if(cx == null) cx = Interpreter.current();
-        if(cx == null) return;
-        addBacktrace(cx.f.sourceName + ":" + cx.f.line[cx.pc]);
-        cx.stack.backtrace(this);
-    }
-    public void printStackTrace() { printStackTrace(System.err); }
-    public void printStackTrace(PrintWriter pw) {
-        for(int i=0; i<backtrace.size(); i++) pw.println("    at " + (String) backtrace.elementAt(i));
-        super.printStackTrace(pw);
-    }
-    public void printStackTrace(PrintStream ps) {
-        for(int i=0; i<backtrace.size(); i++) ps.println("    at " + (String) backtrace.elementAt(i));
-        super.printStackTrace(ps);
-    }
-    public String toString() { return "JSExn: " + JS.debugToString(js); }
-    public String getMessage() { return toString(); }
-    public JS getObject() { return js; } 
-    
-    void addBacktrace(String line) { backtrace.addElement(line); }
-    
-    public static class Wrapper extends RuntimeException {
-        public final JSExn e;
-        public Wrapper(JSExn e) { this.e = e; }
-        public JSExn refill() {
-            e.addBacktrace("[foreign code]");
-            e.fill(null);
-            return e;
-        }
-    }
-    
-    public static class IO extends JSExn {
-        public IO(java.io.IOException ioe) {
-            super("ibex.io: " + ioe.toString());
-            JS.warn(ioe);
-        }
-    }
-} 
diff --git a/src/org/ibex/js/JSFunction.java b/src/org/ibex/js/JSFunction.java
deleted file mode 100644 (file)
index d50e566..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.js;
-
-import java.io.*;
-import org.ibex.util.*;
-
-/** A JavaScript function, compiled into bytecode */
-// FIXME: This shouldn't be public, needed for public add/delTrap (which is needed for the Template.java hack)
-public class JSFunction extends JS implements ByteCodes, Tokens, Task {
-
-
-    // Fields and Accessors ///////////////////////////////////////////////
-
-    int numFormalArgs = 0;         ///< the number of formal arguments
-
-    String sourceName;             ///< the source code file that this block was drawn from
-    private int firstLine = -1;    ///< the first line of this script
-
-    int[] line = new int[10];      ///< the line numbers
-    int[] op = new int[10];        ///< the instructions
-    Object[] arg = new Object[10]; ///< the arguments to the instructions
-    int size = 0;                  ///< the number of instruction/argument pairs
-
-    JSScope parentScope;           ///< the default scope to use as a parent scope when executing this
-
-
-    // Public //////////////////////////////////////////////////////////////////////////////
-
-    // FEATURE: make sure that this can only be called from the Scheduler...
-    /** if you enqueue a function, it gets invoked in its own pauseable context */
-    public void perform() throws JSExn {
-        Interpreter i = new Interpreter(this, true, new Interpreter.JSArgs(this));
-        i.resume();
-    }
-
-    public JSFunction _cloneWithNewParentScope(JSScope s) {
-        JSFunction ret = new JSFunction(sourceName, firstLine, s);
-        // Reuse the same op, arg, line, and size variables for the new "instance" of the function
-        // NOTE: Neither *this* function nor the new function should be modified after this call
-        ret.op = this.op;
-        ret.arg = this.arg;
-        ret.line = this.line;
-        ret.size = this.size;
-        ret.numFormalArgs = this.numFormalArgs;
-        return ret;
-    }
-
-    /** Note: code gets run in an <i>unpauseable</i> context. */
-    public JS call(JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-        Interpreter cx = new Interpreter(this, false, new Interpreter.JSArgs(a0,a1,a2,rest,nargs,this));
-        return cx.resume();
-    }
-
-    public JSScope getParentScope() { return parentScope; }
-
-    // Adding and Altering Bytecodes ///////////////////////////////////////////////////
-
-    JSFunction(String sourceName, int firstLine, JSScope parentScope) {
-        this.sourceName = sourceName;
-        this.firstLine = firstLine;
-        this.parentScope = parentScope;
-    }
-
-    int get(int pos) { return op[pos]; }
-    Object getArg(int pos) { return arg[pos]; }
-    void set(int pos, int op_, Object arg_) { op[pos] = op_; arg[pos] = arg_; }
-    void set(int pos, Object arg_) { arg[pos] = arg_; }
-    int pop() { size--; arg[size] = null; return op[size]; }
-    void paste(JSFunction other) { for(int i=0; i<other.size; i++) add(other.line[i], other.op[i], other.arg[i]); }
-    JSFunction add(int line, int op_) { return add(line, op_, null); }
-    JSFunction add(int line, int op_, Object arg_) {
-        if (size == op.length - 1) {
-            int[] line2 = new int[op.length * 2]; System.arraycopy(this.line, 0, line2, 0, op.length); this.line = line2;
-            Object[] arg2 = new Object[op.length * 2]; System.arraycopy(arg, 0, arg2, 0, arg.length); arg = arg2;
-            int[] op2 = new int[op.length * 2]; System.arraycopy(op, 0, op2, 0, op.length); op = op2;
-        }
-        this.line[size] = line;
-        op[size] = op_;
-        arg[size] = arg_;
-        size++;
-        return this;
-    }
-    
-
-    // Debugging //////////////////////////////////////////////////////////////////////
-
-    String extendedToString() { return "[" + sourceName + ":" + firstLine + "]"; }
-
-    String dump() { return dump(""); }
-    private  String dump(String prefix) {
-        StringBuffer sb = new StringBuffer(1024);
-        sb.append("\n" + sourceName + ": " + firstLine + "\n");
-        for (int i=0; i < size; i++) {
-            sb.append(prefix);
-            sb.append(i).append(" (").append(line[i]).append("): ");
-            if (op[i] < 0) sb.append(bytecodeToString[-op[i]]);
-            else sb.append(codeToString[op[i]]);
-            sb.append(" ");
-            sb.append(arg[i] == null ? "(no arg)" : arg[i] instanceof JS ? JS.debugToString((JS)arg[i]) : arg[i]);
-            if((op[i] == JF || op[i] == JT || op[i] == JMP) && arg[i] != null && arg[i] instanceof Number) {
-                sb.append(" jump to ").append(i+((Number) arg[i]).intValue());
-            } else  if(op[i] == TRY) {
-                int[] jmps = (int[]) arg[i];
-                sb.append(" catch: ").append(jmps[0] < 0 ? "No catch block" : ""+(i+jmps[0]));
-                sb.append(" finally: ").append(jmps[1] < 0 ? "No finally block" : ""+(i+jmps[1]));
-            } else if(op[i] == NEWFUNCTION) {
-                sb.append(((JSFunction) arg[i]).dump(prefix + "     "));
-            } else if(op[i] == NEWSCOPE) {
-                int n = ((JSNumber)arg[i]).toInt();
-                sb.append(" base: " + (n>>>16) + " size: " + (n&0xffff));
-            }
-            sb.append("\n");
-        }
-        return sb.toString();
-    } 
-
-
-}
-
diff --git a/src/org/ibex/js/JSMath.java b/src/org/ibex/js/JSMath.java
deleted file mode 100644 (file)
index 32d730d..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL ]
-
-package org.ibex.js; 
-
-/** The JavaScript Math object */
-class JSMath extends JS {
-    private static final JS E       = JS.N(java.lang.Math.E);
-    private static final JS PI      = JS.N(java.lang.Math.PI);
-    private static final JS LN10    = JS.N(java.lang.Math.log(10));
-    private static final JS LN2     = JS.N(java.lang.Math.log(2));
-    private static final JS LOG10E  = JS.N(1/java.lang.Math.log(10));
-    private static final JS LOG2E   = JS.N(1/java.lang.Math.log(2));
-    private static final JS SQRT1_2 = JS.N(1/java.lang.Math.sqrt(2));
-    private static final JS SQRT2   = JS.N(java.lang.Math.sqrt(2));
-
-    public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-        switch(nargs) {
-            case 0: {
-                //#jswitch(method)
-                case "random": return JS.N(java.lang.Math.random());
-                //#end
-                break;
-            }
-            case 1: {
-                //#jswitch(method)
-                case "ceil": return JS.N((long)java.lang.Math.ceil(toDouble(a0)));
-                case "floor": return JS.N((long)java.lang.Math.floor(toDouble(a0)));
-                case "round": return JS.N((long)java.lang.Math.round(toDouble(a0)));
-                case "abs": return JS.N(java.lang.Math.abs(toDouble(a0)));
-                case "sin": return JS.N(java.lang.Math.sin(toDouble(a0)));
-                case "cos": return JS.N(java.lang.Math.cos(toDouble(a0)));
-                case "tan": return JS.N(java.lang.Math.tan(toDouble(a0)));
-                case "asin": return JS.N(java.lang.Math.asin(toDouble(a0)));
-                case "acos": return JS.N(java.lang.Math.acos(toDouble(a0)));
-                case "atan": return JS.N(java.lang.Math.atan(toDouble(a0)));
-                case "sqrt": return JS.N(java.lang.Math.sqrt(toDouble(a0)));
-                case "exp": return JS.N(java.lang.Math.exp(toDouble(a0)));
-                case "log": return JS.N(java.lang.Math.log(toDouble(a0)));
-                //#end
-                break;
-            }
-            case 2: {
-                //#jswitch(method)
-                case "min": return JS.N(java.lang.Math.min(toDouble(a0), toDouble(a1)));
-                case "max": return JS.N(java.lang.Math.max(toDouble(a0), toDouble(a1)));
-                case "pow": return JS.N(java.lang.Math.pow(toDouble(a0), toDouble(a1)));
-                case "atan2": return JS.N(java.lang.Math.atan2(toDouble(a0), toDouble(a1)));
-                //#end
-                break;
-            }
-        }
-        return super.callMethod(method, a0, a1, a2, rest, nargs);
-    }
-
-    public JS get(JS key) throws JSExn {
-        //#jswitch(key)
-        case "E": return E;
-        case "LN10": return LN10;
-        case "LN2": return LN2;
-        case "LOG10E": return LOG10E;
-        case "LOG2E": return LOG2E;
-        case "PI": return PI;
-        case "SQRT1_2": return SQRT1_2;
-        case "SQRT2": return SQRT2;
-        case "ceil": return METHOD;
-        case "floor": return METHOD;
-        case "round": return METHOD;
-        case "min": return METHOD;
-        case "max": return METHOD;
-        case "pow": return METHOD;
-        case "atan2": return METHOD;
-        case "abs": return METHOD;
-        case "sin": return METHOD;
-        case "cos": return METHOD;
-        case "tan": return METHOD;
-        case "asin": return METHOD;
-        case "acos": return METHOD;
-        case "atan": return METHOD;
-        case "sqrt": return METHOD;
-        case "exp": return METHOD;
-        case "log": return METHOD;
-        case "random": return METHOD;
-        //#end
-        return super.get(key);
-    }
-}
diff --git a/src/org/ibex/js/JSNumber.java b/src/org/ibex/js/JSNumber.java
deleted file mode 100644 (file)
index 8137cbc..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.ibex.js;
-
-abstract class JSNumber extends JSPrimitive {
-    boolean jsequals(JS o) {
-        if(o == this) return true;
-        if(o instanceof JSNumber) {
-            JSNumber n = (JSNumber) o;
-            if(this instanceof D || n instanceof D) return n.toDouble() == toDouble();
-            return n.toLong() == toLong();
-        } else if(o instanceof JSString) {
-            String s = ((JSString)o).s.trim();
-            try {
-                if(this instanceof D || s.indexOf('.') != -1) return Double.parseDouble(s) == toDouble();
-                return Long.parseLong(s) == toLong();
-            } catch(NumberFormatException e) {
-                return false;
-            }
-        } else {
-            return false;
-        }
-    }
-    // FEATURE: Better hash function? (if d != (int) d then do something double specific)
-    public int hashCode() { return toInt(); }
-    
-    abstract int toInt();
-    long toLong() { return toInt(); }
-    boolean toBoolean() { return toInt() != 0; }
-    double toDouble() { return toLong(); }
-    float toFloat() { return (float) toDouble(); }
-    
-    final static class I extends JSNumber {
-        final int i;
-        I(int i) { this.i = i; }
-        int toInt() { return i; }
-        public String coerceToString() { return Integer.toString(i); }
-    }
-    
-    final static class L extends JSNumber {
-        private final long l;
-        L(long l) { this.l = l; }
-        int toInt() { return (int) l; }
-        long toLong() { return l; }
-        public String coerceToString() { return Long.toString(l); }
-    }
-    
-    final static class D extends JSNumber {
-        private final double d;
-        D(double d) { this.d = d; }
-        int toInt() { return (int) d; }
-        long toLong() { return (long) d; }
-        double toDouble()  { return d; }
-        boolean toBoolean() { return d == d && d != 0.0; }
-        public String coerceToString() { return d == (long) d ? Long.toString((long)d) : Double.toString(d); }
-    }
-    
-    final static class B extends JSNumber {
-        private final boolean b;
-        B(boolean b) { this.b = b; }
-        int toInt() { return b ? 1 : 0; }
-        public String coerceToString() { return b ? "true" : "false"; }
-    }
-}
diff --git a/src/org/ibex/js/JSPrimitive.java b/src/org/ibex/js/JSPrimitive.java
deleted file mode 100644 (file)
index 904a587..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.ibex.js;
-
-class JSPrimitive extends JS {
-    public JS callMethod(JS method, JS arg0, JS arg1, JS arg2, JS[] rest, int alength) throws JSExn {
-        //#jswitch(method)
-        case "toFixed": throw new JSExn("toFixed() not implemented");
-        case "toExponential": throw new JSExn("toExponential() not implemented");
-        case "toPrecision": throw new JSExn("toPrecision() not implemented");
-        case "toString": return this instanceof JSString ? this : JS.S(JS.toString(this));
-        //#end
-            
-        String s = coerceToString();
-        int slength = s.length();
-            
-        //#jswitch(method)
-        case "substring": {
-            int a = alength >= 1 ? JS.toInt(arg0) : 0;
-            int b = alength >= 2 ? JS.toInt(arg1) : slength;
-            if (a > slength) a = slength;
-            if (b > slength) b = slength;
-            if (a < 0) a = 0;
-            if (b < 0) b = 0;
-            if (a > b) { int tmp = a; a = b; b = tmp; }
-            return JS.S(s.substring(a,b));
-        }
-        case "substr": {
-            int start = alength >= 1 ? JS.toInt(arg0) : 0;
-            int len = alength >= 2 ? JS.toInt(arg1) : Integer.MAX_VALUE;
-            if (start < 0) start = slength + start;
-            if (start < 0) start = 0;
-            if (len < 0) len = 0;
-            if (len > slength - start) len = slength - start;
-            if (len <= 0) return JS.S("");
-            return JS.S(s.substring(start,start+len));
-        }
-        case "charAt": {
-            int p = alength >= 1 ? JS.toInt(arg0) : 0;
-            if (p < 0 || p >= slength) return JS.S("");
-            return JS.S(s.substring(p,p+1));
-        }
-        case "charCodeAt": {
-            int p = alength >= 1 ? JS.toInt(arg0) : 0;
-            if (p < 0 || p >= slength) return JS.N(Double.NaN);
-            return JS.N(s.charAt(p));
-        }
-        case "concat": {
-            StringBuffer sb = new StringBuffer(slength*2).append(s);
-            for(int i=0;i<alength;i++) sb.append(i==0?arg0:i==1?arg1:i==2?arg2:rest[i-3]);
-            return JS.S(sb.toString());
-        }
-        case "indexOf": {
-            String search = alength >= 1 ? JS.toString(arg0) : "null";
-            int start = alength >= 2 ? JS.toInt(arg1) : 0;
-            // Java's indexOf handles an out of bounds start index, it'll return -1
-            return JS.N(s.indexOf(search,start));
-        }
-        case "lastIndexOf": {
-            String search = alength >= 1 ? JS.toString(arg0) : "null";
-            int start = alength >= 2 ? JS.toInt(arg1) : 0;
-            // Java's indexOf handles an out of bounds start index, it'll return -1
-            return JS.N(s.lastIndexOf(search,start));            
-        }
-        case "match": return JSRegexp.stringMatch(this,arg0);
-        case "replace": return JSRegexp.stringReplace(this,arg0,arg1);
-        case "search": return JSRegexp.stringSearch(this,arg0);
-        case "split": return JSRegexp.stringSplit(this,arg0,arg1,alength);
-        case "toLowerCase": return JS.S(s.toLowerCase());
-        case "toUpperCase": return JS.S(s.toUpperCase());
-        case "slice": {
-            int a = alength >= 1 ? JS.toInt(arg0) : 0;
-            int b = alength >= 2 ? JS.toInt(arg1) : slength;
-            if (a < 0) a = slength + a;
-            if (b < 0) b = slength + b;
-            if (a < 0) a = 0;
-            if (b < 0) b = 0;
-            if (a > slength) a = slength;
-            if (b > slength) b = slength;
-            if (a > b) return JS.S("");
-            return JS.S(s.substring(a,b));
-        }
-        //#end
-        return super.callMethod(method,arg0,arg1,arg2,rest,alength);
-    }
-    
-    public JS get(JS key) throws JSExn {
-        //#jswitch(key)
-        case "length": return JS.N(JS.toString(this).length());
-        case "substring": return METHOD;
-        case "charAt": return METHOD;
-        case "charCodeAt": return METHOD;
-        case "concat": return METHOD;
-        case "indexOf": return METHOD;
-        case "lastIndexOf": return METHOD; 
-        case "match": return METHOD;
-        case "replace": return METHOD;
-        case "search": return METHOD;
-        case "slice": return METHOD;
-        case "split": return METHOD;
-        case "toLowerCase": return METHOD; 
-        case "toUpperCase": return METHOD; 
-        case "toString": return METHOD; 
-        case "substr": return METHOD;  
-        case "toPrecision": return METHOD;
-        case "toExponential": return METHOD;
-        case "toFixed": return METHOD;
-        //#end
-        return super.get(key);
-    }
-}
diff --git a/src/org/ibex/js/JSReflection.java b/src/org/ibex/js/JSReflection.java
deleted file mode 100644 (file)
index 52f7f9c..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] 
-package org.ibex.js; 
-
-import org.ibex.util.*; 
-import java.io.*;
-import java.util.*;
-import java.lang.reflect.*;
-
-/** Automatic JS-ification via Reflection (not for use in the core) */
-public class JSReflection extends JS {
-
-    public static JS wrap(Object o) throws JSExn {
-        if (o == null) return null;
-        if (o instanceof String) return JS.S((String)o);
-        if (o instanceof Boolean) return JS.B(((Boolean)o).booleanValue());
-        if (o instanceof Number) return JS.N((Number)o);
-        if (o instanceof JS) return (JS)o;
-        if (o instanceof Object[]) {
-            // FIXME: get element type here
-        }
-        throw new JSExn("Reflection object tried to return a " + o.getClass().getName());
-    }
-
-    public static class Array extends JS {
-        final Object[] arr;
-        public Array(Object[] arr) { this.arr = arr; }
-        // FEATURE: Add a JSCounterEnumeration
-        public Enumeration keys() throws JSExn {
-            return new Enumeration(null) {
-                private int n = 0;
-                public boolean _hasMoreElements() { return n < arr.length; }
-                public JS _nextElement() {
-                    return n >= arr.length ? null : JS.N(n++);
-                }
-            };
-        }
-        public JS get(JS key) throws JSExn { return wrap(arr[toInt(key)]); }
-        public void put(JS key, JS val) throws JSExn { throw new JSExn("can't write to org.ibex.js.Reflection.Array's"); }
-    }
-
-    // FIXME public static class Hash { }
-    // FIXME public Enumeration keys() throws JSExn {  }
-
-    public JS get(JS key) throws JSExn {
-        String k = toString(key);
-        try {
-            Field f = this.getClass().getField(k);
-            return wrap(f.get(this));
-        } catch (NoSuchFieldException nfe) {
-        } catch (IllegalAccessException nfe) {
-        } catch (SecurityException nfe) { }
-
-        try {
-            Method[] methods = this.getClass().getMethods();
-            for(int i=0; i<methods.length; i++) if (methods[i].getName().equals(k)) return METHOD;
-        } catch (SecurityException nfe) { }
-        return null;
-    }
-
-    public void put(JS key, JS val) throws JSExn {
-        throw new JSExn("put() not supported yet");
-    }
-
-    public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-        String k = toString(method);
-        try {
-            Method[] methods = this.getClass().getMethods();
-            for(int j=0; j<methods.length; j++) {
-                if (methods[j].getName().equals(k) && methods[j].getParameterTypes().length == nargs) {
-                    Object[] args = new Object[nargs];
-                    for(int i = 0; i<args.length; i++) {
-                        if (i==0) args[i] = a0;
-                        else if (i==1) args[i] = a1;
-                        else if (i==2) args[i] = a2;
-                        else args[i] = rest[i-3];
-                    }
-                    return wrap(methods[j].invoke(this, args));
-                }
-            }
-        } catch (IllegalAccessException nfe) {
-        } catch (InvocationTargetException it) {
-            Throwable ite = it.getTargetException();
-            if (ite instanceof JSExn) throw ((JSExn)ite);
-            JS.warn(ite);
-            throw new JSExn("unhandled reflected exception: " + ite.toString());
-        } catch (SecurityException nfe) { }
-        throw new JSExn("called a reflection method with the wrong number of arguments");
-    }
-} 
diff --git a/src/org/ibex/js/JSRegexp.java b/src/org/ibex/js/JSRegexp.java
deleted file mode 100644 (file)
index 75503ac..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.js;
-
-import gnu.regexp.*;
-
-/** A JavaScript regular expression object */
-public class JSRegexp extends JS {
-    private boolean global;
-    private RE re;
-    private int lastIndex;
-
-    private JS pattern;
-    private int flags;
-    
-    public JSRegexp(JS arg0, JS arg1) throws JSExn {
-        if(arg0 instanceof JSRegexp) {
-            JSRegexp r = (JSRegexp) arg0;
-            this.global = r.global;
-            this.re = r.re;
-            this.lastIndex = r.lastIndex;
-            this.pattern = pattern;
-            this.flags = flags;
-        } else {
-            String pattern = JS.toString(arg0);
-            String sFlags = null;
-            int flags = 0;
-            if(arg1 != null) sFlags = JS.toString(arg1);
-            if(sFlags == null) sFlags = "";
-            for(int i=0;i<sFlags.length();i++) {
-                switch(sFlags.charAt(i)) {
-                    case 'i': flags |= RE.REG_ICASE; break;
-                    case 'm': flags |= RE.REG_MULTILINE; break;
-                    case 'g': global = true; break;
-                    default: throw new JSExn("Invalid flag in regexp \"" + sFlags.charAt(i) + "\"");
-                }
-            }
-            re = newRE(pattern,flags);
-            this.pattern = JS.S(pattern);
-            this.flags = flags;
-        }
-    }
-
-    public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-        switch(nargs) {
-            case 1: {
-                //#jswitch(method)
-                case "exec": {
-                    String s = JS.toString(a0);
-                    int start = global ? lastIndex : 0;
-                    if(start < 0 || start >= s.length()) { lastIndex = 0; return null; }
-                    REMatch match = re.getMatch(s,start);
-                    if(global) lastIndex = match == null ? s.length() : match.getEndIndex();
-                    return match == null ? null : matchToExecResult(match,re,s);
-                }
-                case "test": {
-                    String s = JS.toString(a0);
-                    if (!global) return B(re.getMatch(s) != null);
-                    int start = global ? lastIndex : 0;
-                    if(start < 0 || start >= s.length()) { lastIndex = 0; return null; }
-                    REMatch match = re.getMatch(s,start);
-                    lastIndex = match != null ? s.length() : match.getEndIndex();
-                    return B(match != null);
-                }
-                case "toString": return JS.S(a0.coerceToString());
-                case "stringMatch": return stringMatch(a0,a1);
-                case "stringSearch": return stringSearch(a0,a1);
-                //#end
-                break;
-            }
-            case 2: {
-                //#jswitch(method)
-                case "stringReplace": return stringReplace(a0, a1,a2);
-                //#end
-                break;
-            }
-        }
-        return super.callMethod(method, a0, a1, a2, rest, nargs);
-    }
-    
-    public JS get(JS key) throws JSExn {
-        //#jswitch(key)
-        case "exec": return METHOD;
-        case "test": return METHOD;
-        case "toString": return METHOD;
-        case "lastIndex": return N(lastIndex);
-        case "source": return pattern;
-        case "global": return JS.B(global);
-        case "ignoreCase": return B(flags & RE.REG_ICASE);
-        case "multiline": return B(flags & RE.REG_MULTILINE);
-        //#end
-        return super.get(key);
-    }
-    
-    public void put(JS key, JS value) throws JSExn {
-        if(JS.isString(key)) {
-            if(JS.toString(key).equals("lastIndex")) {
-                lastIndex = JS.toInt(value);
-                return;
-            }
-        }
-        super.put(key,value);
-    }
-  
-    private static JS matchToExecResult(REMatch match, RE re, String s) {
-        try {
-            JS ret = new JS.O();
-            ret.put(JS.S("index"), N(match.getStartIndex()));
-            ret.put(JS.S("input"),JS.S(s));
-            int n = re.getNumSubs();
-            ret.put(JS.S("length"), N(n+1));
-            ret.put(ZERO,JS.S(match.toString()));
-            for(int i=1;i<=n;i++) ret.put(JS.N(i),JS.S(match.toString(i)));
-            return ret;
-        } catch (JSExn e) {
-            throw new Error("this should never happen");
-        }
-    }
-    
-    String coerceToString() {
-        StringBuffer sb = new StringBuffer();
-        sb.append('/');
-        sb.append(pattern);
-        sb.append('/');
-        if(global) sb.append('g');
-        if((flags & RE.REG_ICASE) != 0) sb.append('i');
-        if((flags & RE.REG_MULTILINE) != 0) sb.append('m');
-        return sb.toString();
-    }
-    
-    static JS stringMatch(JS o, JS arg0) throws JSExn {
-        String s = JS.toString(o);
-        RE re;
-        JSRegexp regexp = null;
-        if(arg0 instanceof JSRegexp) {
-            regexp = (JSRegexp) arg0;
-            re = regexp.re;
-        } else {
-            re = newRE(JS.toString(arg0),0);
-        }
-        
-        if(regexp == null) {
-            REMatch match = re.getMatch(s);
-            return matchToExecResult(match,re,s);
-        }
-        if(!regexp.global) return regexp.callMethod(JS.S("exec"), o, null, null, null, 1);
-        
-        JSArray ret = new JSArray();
-        REMatch[] matches = re.getAllMatches(s);
-        for(int i=0;i<matches.length;i++) ret.addElement(JS.S(matches[i].toString()));
-        regexp.lastIndex = matches.length > 0 ? matches[matches.length-1].getEndIndex() : s.length();
-        return ret;
-    }
-    
-    static JS stringSearch(JS o, JS arg0) throws JSExn  {
-        String s = JS.toString(o);
-        RE re = arg0 instanceof JSRegexp ? ((JSRegexp)arg0).re : newRE(JS.toString(arg0),0);
-        REMatch match = re.getMatch(s);
-        return match == null ? N(-1) : N(match.getStartIndex());
-    }
-    
-    static JS stringReplace(JS o, JS arg0, JS arg1) throws JSExn {
-        String s = JS.toString(o);
-        RE re;
-        JSFunction replaceFunc = null;
-        String replaceString = null;
-        JSRegexp regexp = null;
-        if(arg0 instanceof JSRegexp) {
-            regexp = (JSRegexp) arg0;
-            re = regexp.re;
-        } else {
-            re = newRE(arg0.toString(),0);
-        }
-        if(arg1 instanceof JSFunction)
-            replaceFunc = (JSFunction) arg1;
-        else
-            replaceString = JS.toString(arg1);
-        REMatch[] matches;
-        if(regexp != null && regexp.global) {
-            matches = re.getAllMatches(s);
-            if(regexp != null) {
-                if(matches.length > 0)
-                    regexp.lastIndex = matches[matches.length-1].getEndIndex();
-                else
-                    regexp.lastIndex = s.length();
-            }
-        } else {
-            REMatch match = re.getMatch(s);
-            if(match != null)
-                matches = new REMatch[]{ match };
-            else
-                matches = new REMatch[0];
-        }
-        
-        StringBuffer sb = new StringBuffer(s.length());
-        int pos = 0;
-        char[] sa = s.toCharArray();
-        for(int i=0;i<matches.length;i++) {
-            REMatch match = matches[i];
-            sb.append(sa,pos,match.getStartIndex()-pos);
-            pos = match.getEndIndex();
-            if(replaceFunc != null) {
-                int n = (regexp == null ? 0 : re.getNumSubs());
-                int numArgs = 3 + n;
-                JS[] rest = new JS[numArgs - 3];
-                JS a0 = JS.S(match.toString());
-                JS a1 = null;
-                JS a2 = null;
-                for(int j=1;j<=n;j++)
-                    switch(j) {
-                        case 1: a1 = JS.S(match.toString(j)); break;
-                        case 2: a2 = JS.S(match.toString(j)); break;
-                        default: rest[j - 3] = JS.S(match.toString(j)); break;
-                    }
-                switch(numArgs) {
-                    case 3:
-                        a1 = N(match.getStartIndex());
-                        a2 = JS.S(s);
-                        break;
-                    case 4:
-                        a2 = N(match.getStartIndex());
-                        rest[0] = JS.S(s);
-                        break;
-                    default:
-                        rest[rest.length - 2] = N(match.getStartIndex());
-                        rest[rest.length - 1] = JS.S(s);
-                }
-
-                // note: can't perform pausing operations in here
-                sb.append(JS.toString(replaceFunc.call(a0, a1, a2, rest, numArgs)));
-
-            } else {
-                sb.append(mySubstitute(match,replaceString,s));
-            }
-        }
-        int end = matches.length == 0 ? 0 : matches[matches.length-1].getEndIndex();
-        sb.append(sa,end,sa.length-end);
-        return JS.S(sb.toString());
-    }
-    
-    private static String mySubstitute(REMatch match, String s, String source) {
-        StringBuffer sb = new StringBuffer();
-        int i,n;
-        char c,c2;
-        for(i=0;i<s.length()-1;i++) {
-           c = s.charAt(i);
-            if(c != '$') {
-                sb.append(c);
-                continue;
-            }
-            i++;
-            c = s.charAt(i);
-            switch(c) {
-                case '0': case '1': case '2': case '3': case '4':
-                case '5': case '6': case '7': case '8': case '9':
-                    if(i < s.length()-1 && (c2 = s.charAt(i+1)) >= '0' && c2 <= '9') {
-                        n = (c - '0') * 10 + (c2 - '0');
-                        i++;
-                    } else {
-                        n = c - '0';
-                    }
-                    if(n > 0)
-                        sb.append(match.toString(n));
-                    break;
-                case '$':
-                    sb.append('$'); break;
-                case '&':
-                    sb.append(match.toString()); break;
-                case '`':
-                    sb.append(source.substring(0,match.getStartIndex())); break;
-                case '\'':
-                    sb.append(source.substring(match.getEndIndex())); break;
-                default:
-                    sb.append('$');
-                    sb.append(c);
-            }
-        }
-        if(i < s.length()) sb.append(s.charAt(i));
-        return sb.toString();
-    }
-                    
-    
-    static JS stringSplit(JS s_, JS arg0, JS arg1, int nargs) throws JSExn {
-        String s = JS.toString(s_);
-        int limit = nargs < 2 ? Integer.MAX_VALUE : JS.toInt(arg1);
-        if(limit < 0) limit = Integer.MAX_VALUE;
-        if(limit == 0) return new JSArray();
-        
-        RE re = null;
-        JSRegexp regexp = null;
-        String sep = null;
-        JSArray ret = new JSArray();
-        int p = 0;
-        
-        if(arg0 instanceof JSRegexp) {
-            regexp = (JSRegexp) arg0;
-            re = regexp.re;
-        } else {
-            sep = JS.toString(arg0);
-        }
-        
-        // special case this for speed. additionally, the code below doesn't properly handle
-        // zero length strings
-        if(sep != null && sep.length()==0) {
-            int len = s.length();
-            for(int i=0;i<len;i++)
-                ret.addElement(JS.S(s.substring(i,i+1)));
-            return ret;
-        }
-        
-        OUTER: while(p < s.length()) {
-            if(re != null) {
-                REMatch m = re.getMatch(s,p);
-                if(m == null) break OUTER;
-                boolean zeroLength = m.getStartIndex() == m.getEndIndex();
-                ret.addElement(JS.S(s.substring(p,zeroLength ? m.getStartIndex()+1 : m.getStartIndex())));
-                p = zeroLength ? p + 1 : m.getEndIndex();
-                if(!zeroLength) {
-                    for(int i=1;i<=re.getNumSubs();i++) {
-                        ret.addElement(JS.S(m.toString(i)));
-                        if(ret.length() == limit) break OUTER;
-                    }
-                }
-            } else {
-                int x = s.indexOf(sep,p);
-                if(x == -1) break OUTER;
-                ret.addElement(JS.S(s.substring(p,x)));
-                p = x + sep.length();
-            }
-            if(ret.length() == limit) break;
-        }
-        if(p < s.length() && ret.length() != limit)
-            ret.addElement(JS.S(s.substring(p)));
-        return ret;
-    }
-    
-    private static RE newRE(String pattern, int flags) throws JSExn {
-        try {
-            return new RE(pattern,flags,RESyntax.RE_SYNTAX_PERL5);
-        } catch(REException e) {
-            throw new JSExn(e.toString());
-        }
-    }
-}
diff --git a/src/org/ibex/js/JSScope.java b/src/org/ibex/js/JSScope.java
deleted file mode 100644 (file)
index 9b9a3b1..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] 
-package org.ibex.js; 
-
-/** Implementation of a JavaScript Scope */
-class JSScope {
-
-    private final int base;
-    private final JS[] vars;
-    final JSScope parent;
-
-    public static class Top extends JSScope {
-        private final JS global;
-        public Top(JS global) { super(null,0,0); this.global = global; }
-        JS get(int i) throws JSExn { throw new JSExn("scope index out of range"); }
-        void put(int i, JS o) throws JSExn { throw new JSExn("scope index out of range"); }
-        JS getGlobal() { return global; }
-    };
-        
-    // NOTE: We can't just set base to parent.base + parent.vars.length
-    // sometimes we only access part of a parent's scope
-    public JSScope(JSScope parent, int base, int size) {
-        this.parent = parent;
-        this.base = base;
-        this.vars = new JS[size];
-    }
-    
-    final JS get(JS i) throws JSExn {
-        if(i==null) throw new NullPointerException();
-        try {
-            return get(JS.toInt(i));
-        } catch(ArrayIndexOutOfBoundsException e) { 
-            throw new JSExn("scope index out of range");
-        }
-    }
-    final void put(JS i, JS o) throws JSExn {
-        if(i==null) throw new NullPointerException();
-        try {
-            put(JS.toInt(i),o);
-        } catch(ArrayIndexOutOfBoundsException e) { 
-            throw new JSExn("scope index out of range");
-        }
-    }
-    JS get(int i) throws JSExn { return i < base ? parent.get(i) : vars[i-base]; }
-    void put(int i, JS o) throws JSExn { if(i < base) parent.put(i,o); else vars[i-base] = o; }
-    
-    JS getGlobal() { return parent.getGlobal(); }
-    
-    /*private JSScope parentScope;
-
-    private static final JS NULL_PLACEHOLDER = new JS() { };
-
-    public JSScope(JSScope parentScope) { this.parentScope = parentScope; }
-    public void declare(JS s) throws JSExn { super.put(s, NULL_PLACEHOLDER); }
-    public JSScope getParentScope() { return parentScope; }
-
-    public JS get(JS key) throws JSExn {
-        JS o = super.get(key);
-        if (o != null) return o == NULL_PLACEHOLDER ? null : o;
-        else return parentScope == null ? null : parentScope.get(key);
-    }
-
-    public boolean has(JS key) throws JSExn { return super.get(key) != null; }
-    public void put(JS key, JS val) throws JSExn {
-        if (parentScope != null && !has(key)) parentScope.put(key, val);
-        else super.put(key, val == null ? NULL_PLACEHOLDER : val);
-    }
-    
-    public JSScope top() { 
-        JSScope s = this;
-        while(s.parentScope != null) s = s.parentScope;
-        return s;
-    }
-
-    public static class Global extends JSScope {
-        private final static JS NaN = N(Double.NaN);
-        private final static JS POSITIVE_INFINITY = N(Double.POSITIVE_INFINITY);
-
-        public Global() { super(null); }
-        public Global(JSScope p) { super(p); }
-        
-        public void declare(JS k) throws JSExn { throw new JSExn("can't declare variables in the global scope"); }
-        
-        // HACK: "this" gets lost on the way back through the scope chain
-        // We'll have to do something better with this when Scope is rewritten
-        public JS get(JS key) throws JSExn {
-            JS ret = _get(key);
-            if(ret == METHOD) return new Interpreter.Stub(this,key);
-            return ret;
-        }
-        
-        public JS _get(JS key) throws JSExn {
-            //#jswitch(key)
-            case "NaN": return NaN;
-            case "Infinity": return POSITIVE_INFINITY;
-            case "undefined": return null;
-            case "stringFromCharCode": return METHOD;
-            case "parseInt": return METHOD;
-            case "parseFloat": return METHOD;
-            case "isNaN": return METHOD;
-            case "isFinite": return METHOD;
-            case "decodeURI": return METHOD;
-            case "decodeURIComponent": return METHOD;
-            case "encodeURI": return METHOD;
-            case "encodeURIComponent": return METHOD;
-            case "escape": return METHOD;
-            case "unescape": return METHOD;
-            //#end
-            return super.get(key);
-        }
-
-        public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-            //#jswitch(method)
-            case "parseInt": return parseInt(a0, N(0));
-            case "parseFloat": return parseFloat(a0);
-            case "isNaN": { double d = toDouble(a0); return d == d ? F : T; }
-            case "isFinite": { double d = toDouble(a0); return (d == d && !Double.isInfinite(d)) ? T : F; }
-            case "decodeURI": throw new JSExn("unimplemented");
-            case "decodeURIComponent": throw new JSExn("unimplemented");
-            case "encodeURI": throw new JSExn("unimplemented");
-            case "encodeURIComponent": throw new JSExn("unimplemented");
-            case "escape": throw new JSExn("unimplemented");
-            case "unescape": throw new JSExn("unimplemented");
-            case "parseInt": return parseInt(a0, a1);
-            //#end
-            return super.callMethod(method, a0, a1, a2, rest, nargs);
-        }
-
-        private JS parseInt(JS arg, JS r) throws JSExn {
-            int radix = JS.toInt(r);
-            String s = JS.toString(arg);
-            int start = 0;
-            int length = s.length();
-            int sign = 1;
-            long n = 0;
-            if(radix != 0 && (radix < 2 || radix > 36)) return NaN;
-            while(start < length && Character.isWhitespace(s.charAt(start))) start++;
-            if((length >= start+1) && (s.charAt(start) == '+' || s.charAt(start) == '-')) {
-                sign = s.charAt(start) == '+' ? 1 : -1;
-                start++;
-            }
-            if(radix == 0 && length >= start+1 && s.charAt(start) == '0') {
-                start++;
-                if(length >= start+1 && (s.charAt(start) == 'x' || s.charAt(start) == 'X')) {
-                    start++;
-                    radix = 16;
-                } else {
-                    radix = 8;
-                    if(length == start || Character.digit(s.charAt(start+1),8)==-1) return JS.ZERO;
-                }
-            }
-            if(radix == 0) radix = 10;
-            if(length == start || Character.digit(s.charAt(start),radix) == -1) return NaN;
-            // try the fast way first
-            try {
-                String s2 = start == 0 ? s : s.substring(start);
-                return JS.N(sign*Integer.parseInt(s2,radix));
-            } catch(NumberFormatException e) { }
-            // fall through to a slower but emca-compliant method
-            for(int i=start;i<length;i++) {
-                int digit = Character.digit(s.charAt(i),radix);
-                if(digit < 0) break;
-                n = n*radix + digit;
-                if(n < 0) return NaN; // overflow;
-            }
-            if(n <= Integer.MAX_VALUE) return JS.N(sign*(int)n);
-            return JS.N((long)sign*n);
-        }
-
-        private JS parseFloat(JS arg) throws JSExn {
-            String s = JS.toString(arg);
-            int start = 0;
-            int length = s.length();
-            while(start < length && Character.isWhitespace(s.charAt(0))) start++;
-            int end = length;
-            // as long as the string has no trailing garbage,this is fast, its slow with
-            // trailing garbage
-            while(start < end) {
-                try {
-                    return JS.N(new Double(s.substring(start,length)));
-                } catch(NumberFormatException e) { }
-                end--;
-            }
-            return NaN;
-        }
-    }*/
-}
-
diff --git a/src/org/ibex/js/JSString.java b/src/org/ibex/js/JSString.java
deleted file mode 100644 (file)
index 5dc2334..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.ibex.js;
-
-import org.ibex.util.*;
-
-class JSString extends JSPrimitive {
-    final String s;
-    public JSString(String s) { this.s = s; }
-    public int hashCode() { return s.hashCode(); }
-    
-    public boolean jsequals(JS o) {
-        if(o == this) return true;
-        if(o instanceof JSString) {
-            return ((JSString)o).s.equals(s);
-        } else if(o instanceof JSNumber) {
-            return o.jsequals(this);
-        } else {
-            return false;
-        }
-    }
-    
-    private final static Hash internHash = new Hash();
-    static synchronized JS intern(String s) {
-        synchronized(internHash) {
-            JS js = (JS)internHash.get(s);
-            if(js == null) internHash.put(s,js = new Intern(s));
-            return js;
-        }
-    }
-    static class Intern extends JSString {
-        public Intern(String s) { super(s); }
-        protected void finalize() { synchronized(internHash) { internHash.put(s,null); } }
-    }
-    
-    String coerceToString() { return s; }
-}
diff --git a/src/org/ibex/js/Lexer.java b/src/org/ibex/js/Lexer.java
deleted file mode 100644 (file)
index 42ec2c7..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-// Derived from org.mozilla.javascript.TokenStream [NPL]
-
-/**
- * The contents of this file are subject to the Netscape Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/NPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation.
- *
- * Contributor(s): Roger Lawrence, Mike McCabe
- */
-
-package org.ibex.js;
-import java.io.*;
-
-/** Lexes a stream of characters into a stream of Tokens */
-class Lexer implements Tokens {
-
-    /** for debugging */
-    public static void main(String[] s) throws IOException {
-        Lexer l = new Lexer(new InputStreamReader(System.in), "stdin", 0);
-        int tok = 0;
-        while((tok = l.getToken()) != -1) System.out.println(codeToString[tok]);
-    }
-
-    /** the token that was just parsed */
-    protected int op;
-   /** the most recently parsed token, <i>regardless of pushbacks</i> */
-    protected int mostRecentlyReadToken;
-
-    /** if the token just parsed was a NUMBER, this is the numeric value */
-    protected Number number = null;
-
-    /** if the token just parsed was a NAME or STRING, this is the string value */
-    protected String string = null;
-
-    /** the line number of the most recently <i>lexed</i> token */
-    protected int line = 0;
-
-    /** the line number of the most recently <i>parsed</i> token */
-    protected int parserLine = 0;
-
-    /** the column number of the current token */
-    protected int col = 0;
-
-    /** the name of the source code file being lexed */
-    protected String sourceName;
-
-    private SmartReader in;
-    public Lexer(Reader r, String sourceName, int line) throws IOException {
-        this.sourceName = sourceName;
-        this.line = line;
-        this.parserLine = line;
-        in = new SmartReader(r);
-    }
-
-
-    // Predicates ///////////////////////////////////////////////////////////////////////
-
-    private static boolean isAlpha(int c) { return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); }
-    private static boolean isDigit(int c) { return (c >= '0' && c <= '9'); }
-    private static int xDigitToInt(int c) {
-        if ('0' <= c && c <= '9') return c - '0';
-        else if ('a' <= c && c <= 'f') return c - ('a' - 10);
-        else if ('A' <= c && c <= 'F') return c - ('A' - 10);
-        else return -1;
-    }
-
-    
-    // Token Subtype Handlers /////////////////////////////////////////////////////////
-
-    private int getKeyword(String name) throws IOException {
-        //#switch(name)
-        case "if": return IF;
-        case "lt": return LT;
-        case "gt": return GT;
-        case "in": return IN;
-        case "do": return DO;
-        case "and": return AND;
-        case "or": return OR;
-        case "for": return FOR;
-        case "int": return RESERVED;
-        case "new": return RESERVED;
-        case "try": return TRY;
-        case "var": return VAR;
-        case "byte": return RESERVED;
-        case "case": return CASE;
-        case "char": return RESERVED;
-        case "else": return ELSE;
-        case "enum": return RESERVED;
-        case "goto": return RESERVED;
-        case "long": return RESERVED;
-        case "null": return NULL;
-        case "true": return TRUE;
-        case "with": return RESERVED;
-        case "void": return RESERVED;
-        case "class": return RESERVED;
-        case "break": return BREAK;
-        case "while": return WHILE;
-        case "false": return FALSE;
-        case "const": return RESERVED;
-        case "final": return RESERVED;
-        case "super": return RESERVED;
-        case "throw": return THROW;
-        case "catch": return CATCH;
-        case "class": return RESERVED;
-        case "delete": return RESERVED;
-        case "return": return RETURN;
-        case "throws": return RESERVED;
-        case "double": return RESERVED;
-        case "assert": return ASSERT;
-        case "public": return RESERVED;
-        case "switch": return SWITCH;
-        case "typeof": return TYPEOF;
-        case "package": return RESERVED;
-        case "default": return DEFAULT;
-        case "finally": return FINALLY;
-        case "boolean": return RESERVED;
-        case "private": return RESERVED;
-        case "extends": return RESERVED;
-        case "abstract": return RESERVED;
-        case "continue": return CONTINUE;
-        case "debugger": return RESERVED;
-        case "function": return FUNCTION;
-        case "volatile": return RESERVED;
-        case "interface": return RESERVED;
-        case "protected": return RESERVED;
-        case "transient": return RESERVED;
-        case "implements": return RESERVED;
-        case "instanceof": return RESERVED;
-        case "synchronized": return RESERVED;
-        case "cascade": return CASCADE;
-        //#end
-        return -1;
-    }
-
-    private int getIdentifier(int c) throws IOException {
-        in.startString();
-        while (Character.isJavaIdentifierPart((char)(c = in.read())));
-        in.unread();
-        String str = in.getString();
-        int result = getKeyword(str);
-        if (result == RESERVED) throw new LexerException("The reserved word \"" + str + "\" is not permitted in Ibex scripts");
-        if (result != -1) return result;
-        this.string = str.intern();
-        return NAME;
-    }
-    
-    private int getNumber(int c) throws IOException {
-        int base = 10;
-        in.startString();
-        double dval = Double.NaN;
-        long longval = 0;
-        boolean isInteger = true;
-        
-        // figure out what base we're using
-        if (c == '0') {
-            if (Character.toLowerCase((char)(c = in.read())) == 'x') { base = 16; in.startString(); }
-            else if (isDigit(c)) base = 8;
-        }
-        
-        while (0 <= xDigitToInt(c) && !(base < 16 && isAlpha(c))) c = in.read();
-        if (base == 10 && (c == '.' || c == 'e' || c == 'E')) {
-            isInteger = false;
-            if (c == '.') do { c = in.read(); } while (isDigit(c));
-            if (c == 'e' || c == 'E') {
-                c = in.read();
-                if (c == '+' || c == '-') c = in.read();
-                if (!isDigit(c)) throw new LexerException("float listeral did not have an exponent value");
-                do { c = in.read(); } while (isDigit(c));
-            }
-        }
-        in.unread();
-
-        String numString = in.getString();
-        if (base == 10 && !isInteger) {
-            try { dval = (Double.valueOf(numString)).doubleValue(); }
-            catch (NumberFormatException ex) { throw new LexerException("invalid numeric literal: \"" + numString + "\""); }
-        } else {
-            if (isInteger) {
-                longval = Long.parseLong(numString, base);
-                dval = (double)longval;
-            } else {
-                dval = Double.parseDouble(numString);
-                longval = (long) dval;
-                if (longval == dval) isInteger = true;
-            }
-        }
-        
-        if (!isInteger) this.number = new Double(dval);
-        else if(longval >= Integer.MIN_VALUE && longval <= Integer.MAX_VALUE) this.number = new Integer((int)longval);
-        else this.number = new Long(longval);
-        return NUMBER;
-    }
-    
-    private int getString(int c) throws IOException {
-        StringBuffer stringBuf = null;
-        int quoteChar = c;
-        c = in.read();
-        in.startString(); // start after the first "
-        while(c != quoteChar) {
-            if (c == '\n' || c == -1) throw new LexerException("unterminated string literal");
-            if (c == '\\') {
-                if (stringBuf == null) {
-                    in.unread();   // Don't include the backslash
-                    stringBuf = new StringBuffer(in.getString());
-                    in.read();
-                }
-                switch (c = in.read()) {
-                case 'b': c = '\b'; break;
-                case 'f': c = '\f'; break;
-                case 'n': c = '\n'; break;
-                case 'r': c = '\r'; break;
-                case 't': c = '\t'; break;
-                case 'v': c = '\u000B'; break;
-                case '\\': c = '\\'; break;
-                case 'u': {
-                    int v = 0;
-                    for(int i=0; i<4; i++) {
-                        int ci = in.read();
-                        if (!((ci >= '0' && ci <= '9') || (ci >= 'a' && ci <= 'f') || (ci >= 'A' && ci <= 'F')))
-                            throw new LexerException("illegal character '" + ((char)c) + "' in \\u unicode escape sequence");
-                        v = (v << 8) | Integer.parseInt(ci + "", 16);
-                    }
-                    c = (char)v;
-                    break;
-                }
-                default:
-                    // just use the character that was escaped
-                    break;
-                }
-            }
-            if (stringBuf != null) stringBuf.append((char) c);
-            c = in.read();
-        }
-        if (stringBuf != null) this.string = stringBuf.toString().intern();
-        else {
-            in.unread(); // miss the trailing "
-            this.string = in.getString().intern();
-            in.read();
-        }
-        return STRING;
-    }
-
-    private int _getToken() throws IOException {
-        int c;
-        do { c = in.read(); } while (c == '\u0020' || c == '\u0009' || c == '\u000C' || c == '\u000B' || c == '\n' );
-        if (c == -1) return -1;
-        if (c == '\\' || Character.isJavaIdentifierStart((char)c)) return getIdentifier(c);
-        if (isDigit(c) || (c == '.' && isDigit(in.peek()))) return getNumber(c);
-        if (c == '"' || c == '\'') return getString(c);
-        switch (c) {
-        case ';': return SEMI;
-        case '[': return LB;
-        case ']': return RB;
-        case '{': return LC;
-        case '}': return RC;
-        case '(': return LP;
-        case ')': return RP;
-        case ',': return COMMA;
-        case '?': return HOOK;
-        case ':': return !in.match(':') ? COLON : in.match('=') ? GRAMMAR : le(":: is not a valid token");
-        case '.': return DOT;
-        case '|': return in.match('|') ? OR : (in.match('=') ? ASSIGN_BITOR : BITOR);
-        case '^': return in.match('=') ? ASSIGN_BITXOR : BITXOR;
-        case '&': return in.match('&') ? AND : in.match('=') ? ASSIGN_BITAND : BITAND;
-        case '=': return !in.match('=') ? ASSIGN : in.match('=') ? SHEQ : EQ;
-        case '!': return !in.match('=') ? BANG : in.match('=') ? SHNE : NE;
-        case '%': return in.match('=') ? ASSIGN_MOD : MOD;
-        case '~': return BITNOT;
-        case '+': return in.match('=') ? ASSIGN_ADD : in.match('+') ? (in.match('=') ? ADD_TRAP : INC) : ADD;
-        case '-': return in.match('=') ? ASSIGN_SUB: in.match('-') ? (in.match('=') ? DEL_TRAP : DEC) : SUB;
-        case '*': return in.match('=') ? ASSIGN_MUL : MUL;
-        case '<': return !in.match('<') ? (in.match('=') ? LE : LT) : in.match('=') ? ASSIGN_LSH : LSH;
-        case '>': return !in.match('>') ? (in.match('=') ? GE : GT) :
-            in.match('>') ? (in.match('=') ? ASSIGN_URSH : URSH) : (in.match('=') ? ASSIGN_RSH : RSH);
-        case '/':
-            if (in.match('=')) return ASSIGN_DIV;
-            if (in.match('/')) { while ((c = in.read()) != -1 && c != '\n'); in.unread(); return getToken(); }
-            if (!in.match('*')) return DIV;
-            while ((c = in.read()) != -1 && !(c == '*' && in.match('/'))) {
-                if (c == '\n' || c != '/' || !in.match('*')) continue;
-                if (in.match('/')) return getToken();
-                throw new LexerException("nested comments are not permitted");
-            }
-            if (c == -1) throw new LexerException("unterminated comment");
-            return getToken();  // `goto retry'
-        default: throw new LexerException("illegal character: \'" + ((char)c) + "\'");
-        }
-    }
-
-    private int le(String s) throws LexerException { if (true) throw new LexerException(s); return 0; }
-
-    // SmartReader ////////////////////////////////////////////////////////////////
-
-    /** a Reader that tracks line numbers and can push back tokens */
-    private class SmartReader {
-        PushbackReader reader = null;
-        int lastread = -1;
-
-        public SmartReader(Reader r) { reader = new PushbackReader(r); }
-        public void unread() throws IOException { unread((char)lastread); }
-        public void unread(char c) throws IOException {
-            reader.unread(c);
-            if(c == '\n') col = -1;
-            else col--;
-            if (accumulator != null) accumulator.setLength(accumulator.length() - 1);
-        }
-        public boolean match(char c) throws IOException { if (peek() == c) { reader.read(); return true; } else return false; }
-        public int peek() throws IOException {
-            int peeked = reader.read();
-            if (peeked != -1) reader.unread((char)peeked);
-            return peeked;
-        }
-        public int read() throws IOException {
-            lastread = reader.read();
-            if (accumulator != null) accumulator.append((char)lastread);
-            if (lastread != '\n' && lastread != '\r') col++;
-            if (lastread == '\n') {
-                // col is -1 if we just unread a newline, this is sort of ugly
-                if (col != -1) parserLine = ++line;
-                col = 0;
-            }
-            return lastread;
-        }
-
-        // FEATURE: could be much more efficient
-        StringBuffer accumulator = null;
-        public void startString() {
-            accumulator = new StringBuffer();
-            accumulator.append((char)lastread);
-        }
-        public String getString() throws IOException {
-            String ret = accumulator.toString().intern();
-            accumulator = null;
-            return ret;
-        }
-    }
-
-
-    // Token PushBack code ////////////////////////////////////////////////////////////
-
-    private int pushBackDepth = 0;
-    private int[] pushBackInts = new int[10];
-    private Object[] pushBackObjects = new Object[10];
-
-    /** push back a token */
-    public final void pushBackToken(int op, Object obj) {
-        if (pushBackDepth >= pushBackInts.length - 1) {
-            int[] newInts = new int[pushBackInts.length * 2];
-            System.arraycopy(pushBackInts, 0, newInts, 0, pushBackInts.length);
-            pushBackInts = newInts;
-            Object[] newObjects = new Object[pushBackObjects.length * 2];
-            System.arraycopy(pushBackObjects, 0, newObjects, 0, pushBackObjects.length);
-            pushBackObjects = newObjects;
-        }
-        pushBackInts[pushBackDepth] = op;
-        pushBackObjects[pushBackDepth] = obj;
-        pushBackDepth++;
-    }
-
-    /** push back the most recently read token */
-    public final void pushBackToken() { pushBackToken(op, number != null ? (Object)number : (Object)string); }
-
-    /** read a token but leave it in the stream */
-    public final int peekToken() throws IOException {
-        int ret = getToken();
-        pushBackToken();
-        return ret;
-    }
-
-    /** read a token */
-    public final int getToken() throws IOException {
-        number = null;
-        string = null;
-        if (pushBackDepth == 0) {
-            mostRecentlyReadToken = op;
-            return op = _getToken();
-        }
-        pushBackDepth--;
-        op = pushBackInts[pushBackDepth];
-        if (pushBackObjects[pushBackDepth] != null) {
-            number = pushBackObjects[pushBackDepth] instanceof Number ? (Number)pushBackObjects[pushBackDepth] : null;
-            string = pushBackObjects[pushBackDepth] instanceof String ? (String)pushBackObjects[pushBackDepth] : null;
-        }
-        return op;
-    }
-
-    class LexerException extends IOException {
-        public LexerException(String s) { super(sourceName + ":" + line + "," + col + ": " + s); }
-    }
-}
diff --git a/src/org/ibex/js/Parser.java b/src/org/ibex/js/Parser.java
deleted file mode 100644 (file)
index 6293107..0000000
+++ /dev/null
@@ -1,1049 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.js;
-
-import org.ibex.util.*;
-import java.io.*;
-
-/**
- *  Parses a stream of lexed tokens into a tree of JSFunction's.
- *
- *  There are three kinds of things we parse: blocks, statements, and
- *  expressions.
- *
- *  - Expressions are a special type of statement that evaluates to a
- *    value (for example, "break" is not an expression, * but "3+2"
- *    is).  Some tokens sequences start expressions (for * example,
- *    literal numbers) and others continue an expression which * has
- *    already been begun (for example, '+').  Finally, some *
- *    expressions are valid targets for an assignment operation; after
- *    * each of these expressions, continueExprAfterAssignable() is
- *    called * to check for an assignment operation.
- *
- *  - A statement ends with a semicolon and does not return a value.
- *
- *  - A block is a single statement or a sequence of statements
- *    surrounded by curly braces.
- *
- *  Each parsing method saves the parserLine before doing its actual
- *  work and restores it afterwards.  This ensures that parsing a
- *  subexpression does not modify the line number until a token
- *  *after* the subexpression has been consumed by the parent
- *  expression.
- *
- *  Technically it would be a better design for this class to build an
- *  intermediate parse tree and use that to emit bytecode.  Here's the
- *  tradeoff:
- *
- *  Advantages of building a parse tree:
- *  - easier to apply optimizations
- *  - would let us handle more sophisticated languages than JavaScript
- *
- *  Advantages of leaving out the parse tree
- *  - faster compilation
- *  - less load on the garbage collector
- *  - much simpler code, easier to understand
- *  - less error-prone
- *
- *  Fortunately JS is such a simple language that we can get away with
- *  the half-assed approach and still produce a working, complete
- *  compiler.
- *
- *  The bytecode language emitted doesn't really cause any appreciable
- *  semantic loss, and is itself a parseable language very similar to
- *  Forth or a postfix variant of LISP.  This means that the bytecode
- *  can be transformed into a parse tree, which can be manipulated.
- *  So if we ever want to add an optimizer, it could easily be done by
- *  producing a parse tree from the bytecode, optimizing that tree,
- *  and then re-emitting the bytecode.  The parse tree node class
- *  would also be much simpler since the bytecode language has so few
- *  operators.
- *
- *  Actually, the above paragraph is slightly inaccurate -- there are
- *  places where we push a value and then perform an arbitrary number
- *  of operations using it before popping it; this doesn't parse well.
- *  But these cases are clearly marked and easy to change if we do
- *  need to move to a parse tree format.
- */
-class Parser extends Lexer implements ByteCodes {
-
-
-    // Constructors //////////////////////////////////////////////////////
-
-    private Parser(Reader r, String sourceName, int line) throws IOException { super(r, sourceName, line); }
-
-    /** for debugging */
-    public static void main(String[] s) throws IOException {
-        JS block = JS.fromReader("stdin", 0, new InputStreamReader(System.in));
-        if (block == null) return;
-        System.out.println(block);
-    }
-
-    // Statics ////////////////////////////////////////////////////////////
-
-    static byte[] precedence = new byte[MAX_TOKEN + 1];
-    static boolean[] isRightAssociative = new boolean[MAX_TOKEN + 1];
-    // Use this as the precedence when we want anything up to the comma
-    private final static int NO_COMMA = 2;
-    static {
-        isRightAssociative[ASSIGN] =
-            isRightAssociative[ASSIGN_BITOR] =
-            isRightAssociative[ASSIGN_BITXOR] =
-            isRightAssociative[ASSIGN_BITAND] =
-            isRightAssociative[ASSIGN_LSH] =
-            isRightAssociative[ASSIGN_RSH] =
-            isRightAssociative[ASSIGN_URSH] =
-            isRightAssociative[ASSIGN_ADD] =
-            isRightAssociative[ASSIGN_SUB] =
-            isRightAssociative[ASSIGN_MUL] =
-            isRightAssociative[ASSIGN_DIV] =
-            isRightAssociative[ASSIGN_MOD] =
-            isRightAssociative[ADD_TRAP] =
-            isRightAssociative[DEL_TRAP] =
-            true;
-
-        precedence[COMMA] = 1;
-        // 2 is intentionally left unassigned. we use minPrecedence==2 for comma separated lists
-        precedence[ASSIGN] =
-            precedence[ASSIGN_BITOR] =
-            precedence[ASSIGN_BITXOR] =
-            precedence[ASSIGN_BITAND] =
-            precedence[ASSIGN_LSH] =
-            precedence[ASSIGN_RSH] =
-            precedence[ASSIGN_URSH] =
-            precedence[ASSIGN_ADD] =
-            precedence[ASSIGN_SUB] =
-            precedence[ASSIGN_MUL] =
-            precedence[ASSIGN_DIV] =
-            precedence[ADD_TRAP] =
-            precedence[DEL_TRAP] =
-            precedence[ASSIGN_MOD] = 3;
-        precedence[HOOK] = 4;
-        precedence[OR] = 5;
-        precedence[AND] = 6;
-        precedence[BITOR] = 7;
-        precedence[BITXOR] = 8;
-        precedence[BITAND] = 9;
-        precedence[EQ] = precedence[NE] = precedence[SHEQ] = precedence[SHNE] = 10;
-        precedence[LT] = precedence[LE] = precedence[GT] = precedence[GE] = 11;
-        precedence[LSH] = precedence[RSH] = precedence[URSH] = 12;
-        precedence[ADD] = precedence[SUB] = 12;
-        precedence[MUL] = precedence[DIV] = precedence[MOD] = 13;
-        precedence[BITNOT] =  precedence[BANG] = precedence[TYPEOF] = 14;
-        precedence[DOT] = precedence[LB] = precedence[LP] =  precedence[INC] = precedence[DEC] = 15;
-    }
-
-    // Local variable management
-    Vec scopeStack = new Vec();
-    static class ScopeInfo {
-        int base;
-        int end;
-        int newScopeInsn;
-        Hash mapping = new Hash();
-    }
-    Hash globalCache = new Hash();
-    JS scopeKey(String name) {
-        if(globalCache.get(name) != null) return null;
-        for(int i=scopeStack.size()-1;i>=0;i--) {
-            JS key = (JS)((ScopeInfo) scopeStack.elementAt(i)).mapping.get(name);
-            if(key != null) return key;
-        }
-        globalCache.put(name,Boolean.TRUE);
-        return null;
-    }
-    void scopeDeclare(String name) throws IOException {
-        ScopeInfo si = (ScopeInfo) scopeStack.lastElement();
-        if(si.mapping.get(name) != null) throw pe("" + name + " already declared in this scope");
-        si.mapping.put(name,JS.N(si.end++));
-        globalCache.put(name,null);
-    }
-    void scopePush(JSFunction b) {
-        ScopeInfo prev = (ScopeInfo) scopeStack.lastElement();
-        ScopeInfo si = new ScopeInfo();
-        si.base = prev.end;
-        si.end = si.base;
-        si.newScopeInsn = b.size;
-        scopeStack.push(si);
-        b.add(parserLine, NEWSCOPE);
-    }
-    void scopePop(JSFunction b) {
-        ScopeInfo si = (ScopeInfo) scopeStack.pop();
-        b.add(parserLine, OLDSCOPE);
-        b.set(si.newScopeInsn,JS.N((si.base<<16)|((si.end-si.base)<<0))); 
-    }
-    
-    
-    // Parsing Logic /////////////////////////////////////////////////////////
-    
-    /** parse and compile a function */
-    public static JSFunction fromReader(String sourceName, int firstLine, Reader sourceCode) throws IOException {
-        JSFunction ret = new JSFunction(sourceName, firstLine, null);
-        if (sourceCode == null) return ret;
-        Parser p = new Parser(sourceCode, sourceName, firstLine);
-        p.scopeStack.setSize(0);
-        p.scopeStack.push(new ScopeInfo());
-        p.scopePush(ret);
-        while(true) {
-            //int s = ret.size;
-            if(p.peekToken() == -1) break; // FIXME: Check this logic one more time
-            p.parseStatement(ret, null);
-            //if (s == ret.size) break;
-        }
-        p.scopePop(ret);
-        if(p.scopeStack.size() != 1) throw new Error("scopeStack height mismatch");
-        ret.add(-1, LITERAL, null); 
-        ret.add(-1, RETURN);
-        return ret;
-    }
-
-    /** gets a token and throws an exception if it is not <tt>code</tt> */
-    private void consume(int code) throws IOException {
-        if (getToken() != code) {
-            if(code == NAME) switch(op) {
-                case RETURN: case TYPEOF: case BREAK: case CONTINUE: case TRY: case THROW:
-                case ASSERT: case NULL: case TRUE: case FALSE: case IN: case IF: case ELSE:
-                case SWITCH: case CASE: case DEFAULT: case WHILE: case VAR: case WITH:
-                case CATCH: case FINALLY:
-                    throw pe("Bad variable name; '" + codeToString[op].toLowerCase() + "' is a javascript keyword");
-            }
-            throw pe("expected " + codeToString[code] + ", got " + (op == -1 ? "EOF" : codeToString[op]));
-        }
-    }
-
-    /**
-     *  Parse the largest possible expression containing no operators
-     *  of precedence below <tt>minPrecedence</tt> and append the
-     *  bytecodes for that expression to <tt>appendTo</tt>; the
-     *  appended bytecodes MUST grow the stack by exactly one element.
-     */ 
-    private void startExpr(JSFunction appendTo, int minPrecedence) throws IOException {
-        int saveParserLine = parserLine;
-        _startExpr(appendTo, minPrecedence);
-        parserLine = saveParserLine;
-    }
-    private void _startExpr(JSFunction appendTo, int minPrecedence) throws IOException {
-        int tok = getToken();
-        JSFunction b = appendTo;
-
-        switch (tok) {
-        case -1: throw pe("expected expression");
-
-        // all of these simply push values onto the stack
-        case NUMBER: b.add(parserLine, LITERAL, JS.N(number)); break;
-        case STRING: b.add(parserLine, LITERAL, JSString.intern(string)); break;
-        case NULL: b.add(parserLine, LITERAL, null); break;
-        case TRUE: case FALSE: b.add(parserLine, LITERAL, tok == TRUE ? JS.T : JS.F); break;
-
-        // (.foo) syntax
-        case DOT: {
-            consume(NAME);
-            b.add(parserLine, GLOBALSCOPE);
-            b.add(parserLine, GET, JS.S("",true));
-            b.add(parserLine, LITERAL, JS.S(string,true));
-            continueExprAfterAssignable(b,minPrecedence,null);
-            break;
-        }
-
-        case LB: {
-            b.add(parserLine, ARRAY, JS.ZERO);                       // push an array onto the stack
-            int size0 = b.size;
-            int i = 0;
-            if (peekToken() != RB)
-                while(true) {                                               // iterate over the initialization values
-                    b.add(parserLine, LITERAL, JS.N(i++));           // push the index in the array to place it into
-                    if (peekToken() == COMMA || peekToken() == RB)
-                        b.add(parserLine, LITERAL, null);                   // for stuff like [1,,2,]
-                    else
-                        startExpr(b, NO_COMMA);                             // push the value onto the stack
-                    b.add(parserLine, PUT);                                 // put it into the array
-                    b.add(parserLine, POP);                                 // discard the value remaining on the stack
-                    if (peekToken() == RB) break;
-                    consume(COMMA);
-                }
-            b.set(size0 - 1, JS.N(i));                               // back at the ARRAY instruction, write the size of the array
-            consume(RB);
-            break;
-        }
-        case SUB: case ADD: {
-            if(peekToken() == NUMBER) {   // literal
-                consume(NUMBER);
-                b.add(parserLine, LITERAL, JS.N(number.doubleValue() * (tok == SUB ? -1 : 1)));
-            } else { // unary +/- operator
-                if(tok == SUB) b.add(parserLine, LITERAL, JS.ZERO);
-                // BITNOT has the same precedence as the unary +/- operators
-                startExpr(b,precedence[BITNOT]);
-                if(tok == ADD) b.add(parserLine, LITERAL, JS.ZERO); // HACK to force expr into a numeric context
-                b.add(parserLine, SUB);
-            }
-            break;
-        }
-        case LP: {  // grouping (not calling)
-            startExpr(b, -1);
-            consume(RP);
-            break;
-        }
-        case INC: case DEC: {  // prefix (not postfix)
-            startExpr(b, precedence[tok]);
-            int prev = b.size - 1;
-            boolean sg = b.get(prev) == SCOPEGET;
-            if (b.get(prev) == GET && b.getArg(prev) != null)
-                b.set(prev, LITERAL, b.getArg(prev));
-            else if(b.get(prev) == GET)
-                b.pop();
-            else if(!sg)
-                throw pe("prefixed increment/decrement can only be performed on a valid assignment target");
-            if(!sg) b.add(parserLine, GET_PRESERVE, Boolean.TRUE);
-            b.add(parserLine, LITERAL, JS.N(1));
-            b.add(parserLine, tok == INC ? ADD : SUB, JS.N(2));
-            if(sg) {
-                b.add(parserLine, SCOPEPUT, b.getArg(prev));
-            } else {
-                b.add(parserLine, PUT, null);
-                b.add(parserLine, SWAP, null);
-                b.add(parserLine, POP, null);
-            }
-            break;
-        }
-        case BANG: case BITNOT: case TYPEOF: {
-            startExpr(b, precedence[tok]);
-            b.add(parserLine, tok);
-            break;
-        }
-        case LC: { // object constructor
-            b.add(parserLine, OBJECT, null);                                     // put an object on the stack
-            if (peekToken() != RC)
-                while(true) {
-                    if (peekToken() != NAME && peekToken() != STRING)
-                        throw pe("expected NAME or STRING");
-                    getToken();
-                    b.add(parserLine, LITERAL, JSString.intern(string));                          // grab the key
-                    consume(COLON);
-                    startExpr(b, NO_COMMA);                                      // grab the value
-                    b.add(parserLine, PUT);                                      // put the value into the object
-                    b.add(parserLine, POP);                                      // discard the remaining value
-                    if (peekToken() == RC) break;
-                    consume(COMMA);
-                    if (peekToken() == RC) break;                                // we permit {,,} -- I'm not sure if ECMA does
-                }
-            consume(RC);
-            break;
-        }
-        case NAME: {
-            JS varKey = scopeKey(string);
-            if(varKey == null) {
-                b.add(parserLine, GLOBALSCOPE);
-                b.add(parserLine, LITERAL, JSString.intern(string));
-            }
-            continueExprAfterAssignable(b,minPrecedence,varKey);
-            break;
-        }
-        case CASCADE: {
-            if(peekToken() == ASSIGN) {
-                consume(ASSIGN);
-                startExpr(b, precedence[ASSIGN]);
-                b.add(parserLine, CASCADE, JS.T);
-            } else {
-                b.add(parserLine, CASCADE, JS.F);
-            }
-            break;
-        }
-                
-        case FUNCTION: {
-            consume(LP);
-            int numArgs = 0;
-            JSFunction b2 = new JSFunction(sourceName, parserLine, null);
-            b.add(parserLine, NEWFUNCTION, b2);
-
-            // function prelude; arguments array is already on the stack
-            scopePush(b2);
-            scopeDeclare("arguments");
-            b2.add(parserLine, SCOPEPUT,scopeKey("arguments"));
-
-            while(peekToken() != RP) {                                    // run through the list of argument names
-                numArgs++;
-                if (peekToken() == NAME) {
-                    consume(NAME);                                        // a named argument
-                    
-                    b2.add(parserLine, DUP);                              // dup the args array 
-                    b2.add(parserLine, GET, JS.N(numArgs - 1));   // retrieve it from the arguments array
-                    scopeDeclare(string);
-                    b2.add(parserLine, SCOPEPUT, scopeKey(string));
-                    b2.add(parserLine, POP);
-                }
-                if (peekToken() == RP) break;
-                consume(COMMA);
-            }
-            consume(RP);
-
-            b2.numFormalArgs = numArgs;
-            b2.add(parserLine, POP);                                      // pop off the arguments array
-            
-           if(peekToken() != LC)
-                throw pe("JSFunctions must have a block surrounded by curly brackets");
-                
-            parseBlock(b2, null);                                   // the function body
-            
-            scopePop(b2);
-            b2.add(parserLine, LITERAL, null);                        // in case we "fall out the bottom", return NULL
-            b2.add(parserLine, RETURN);
-
-            break;
-        }
-        default: throw pe("expected expression, found " + codeToString[tok] + ", which cannot start an expression");
-        }
-
-        // attempt to continue the expression
-        continueExpr(b, minPrecedence);
-    }
-    /*
-    private Grammar parseGrammar(Grammar g) throws IOException {
-        int tok = getToken();
-        if (g != null)
-            switch(tok) {
-                case BITOR: return new Grammar.Alternative(g, parseGrammar(null));
-                case ADD:   return parseGrammar(new Grammar.Repetition(g, 1, Integer.MAX_VALUE));
-                case MUL:   return parseGrammar(new Grammar.Repetition(g, 0, Integer.MAX_VALUE));
-                case HOOK:  return parseGrammar(new Grammar.Repetition(g, 0, 1));
-            }
-        Grammar g0 = null;
-        switch(tok) {
-            //case NUMBER: g0 = new Grammar.Literal(number); break;
-            case NAME: g0 = new Grammar.Reference(string); break;
-            case STRING:
-                g0 = new Grammar.Literal(string);
-                if (peekToken() == DOT) {
-                    String old = string;
-                    consume(DOT);
-                    consume(DOT);
-                    consume(STRING);
-                    if (old.length() != 1 || string.length() != 1) throw pe("literal ranges must be single-char strings");
-                    g0 = new Grammar.Range(old.charAt(0), string.charAt(0));
-                }
-                break;
-            case LP:     g0 = parseGrammar(null); consume(RP); break;
-            default:     pushBackToken(); return g;
-        }
-        if (g == null) return parseGrammar(g0);
-        return parseGrammar(new Grammar.Juxtaposition(g, g0));
-    }
-    */
-    /**
-     *  Assuming that a complete assignable (lvalue) has just been
-     *  parsed and the object and key are on the stack,
-     *  <tt>continueExprAfterAssignable</tt> will attempt to parse an
-     *  expression that modifies the assignable.  This method always
-     *  decreases the stack depth by exactly one element.
-     */
-    private void continueExprAfterAssignable(JSFunction b,int minPrecedence, JS varKey) throws IOException {
-        int saveParserLine = parserLine;
-        _continueExprAfterAssignable(b,minPrecedence,varKey);
-        parserLine = saveParserLine;
-    }
-    private void _continueExprAfterAssignable(JSFunction b,int minPrecedence, JS varKey) throws IOException {
-        if (b == null) throw new Error("got null b; this should never happen");
-        int tok = getToken();
-        if (minPrecedence != -1 && (precedence[tok] < minPrecedence || (precedence[tok] == minPrecedence && !isRightAssociative[tok])))
-            // force the default case
-            tok = -1;
-        switch(tok) {
-            /*
-        case GRAMMAR: {
-            b.add(parserLine, GET_PRESERVE);
-            Grammar g = parseGrammar(null);
-            if (peekToken() == LC) {
-                g.action = new JSFunction(sourceName, parserLine, null);
-                parseBlock((JSFunction)g.action);
-                ((JSFunction)g.action).add(parserLine, LITERAL, null);         // in case we "fall out the bottom", return NULL              
-                ((JSFunction)g.action).add(parserLine, RETURN);
-            }
-            b.add(parserLine, MAKE_GRAMMAR, g);
-            b.add(parserLine, PUT);
-            break;
-        }
-            */
-        case ASSIGN_BITOR: case ASSIGN_BITXOR: case ASSIGN_BITAND: case ASSIGN_LSH: case ASSIGN_RSH: case ASSIGN_URSH:
-        case ASSIGN_MUL: case ASSIGN_DIV: case ASSIGN_MOD: case ASSIGN_ADD: case ASSIGN_SUB: case ADD_TRAP: case DEL_TRAP: {
-            if (tok != ADD_TRAP && tok != DEL_TRAP) 
-                b.add(parserLine, varKey == null ? GET_PRESERVE : SCOPEGET, varKey);
-            
-            startExpr(b,  precedence[tok]);
-            
-            if (tok != ADD_TRAP && tok != DEL_TRAP) {
-                // tok-1 is always s/^ASSIGN_// (0 is BITOR, 1 is ASSIGN_BITOR, etc) 
-                b.add(parserLine, tok - 1, tok-1==ADD ? JS.N(2) : null);
-                if(varKey == null) {
-                    b.add(parserLine, PUT);
-                    b.add(parserLine, SWAP);
-                    b.add(parserLine, POP);
-                } else {
-                    b.add(parserLine, SCOPEPUT, varKey);
-                }
-            } else {
-                if(varKey != null) throw pe("cannot place traps on local variables");
-                b.add(parserLine, tok);
-            }
-            break;
-        }
-        case INC: case DEC: { // postfix
-            if(varKey == null) {
-                b.add(parserLine, GET_PRESERVE, Boolean.TRUE);
-                b.add(parserLine, LITERAL, JS.N(1));
-                b.add(parserLine, tok == INC ? ADD : SUB, JS.N(2));
-                b.add(parserLine, PUT, null);
-                b.add(parserLine, SWAP, null);
-                b.add(parserLine, POP, null);
-                b.add(parserLine, LITERAL, JS.N(1));
-                b.add(parserLine, tok == INC ? SUB : ADD, JS.N(2));   // undo what we just did, since this is postfix
-            } else {
-                b.add(parserLine, SCOPEGET, varKey);
-                b.add(parserLine, DUP);
-                b.add(parserLine, LITERAL, JS.ONE);
-                b.add(parserLine, tok == INC ? ADD : SUB, JS.N(2));
-                b.add(parserLine, SCOPEPUT, varKey);
-            }
-            break;
-        }
-        case ASSIGN: {
-            startExpr(b, precedence[tok]);
-            if(varKey == null) {
-                b.add(parserLine, PUT);
-                b.add(parserLine, SWAP);
-                b.add(parserLine, POP);
-            } else {
-                b.add(parserLine, SCOPEPUT, varKey);
-            }
-            break;
-        }
-        case LP: {
-            // Method calls are implemented by doing a GET_PRESERVE
-            // first.  If the object supports method calls, it will
-            // return JS.METHOD
-            b.add(parserLine, varKey == null ? GET_PRESERVE : SCOPEGET, varKey);
-            int n = parseArgs(b);
-            b.add(parserLine, varKey == null ? CALLMETHOD : CALL, JS.N(n));
-            break;
-        }
-        default: {
-            pushBackToken();
-            if(varKey != null)
-                b.add(parserLine, SCOPEGET, varKey);
-            else if(b.get(b.size-1) == LITERAL && b.getArg(b.size-1) != null)
-                b.set(b.size-1,GET,b.getArg(b.size-1));
-            else
-                b.add(parserLine, GET);
-            return;
-        }
-        }
-    }
-
-
-    /**
-     *  Assuming that a complete expression has just been parsed,
-     *  <tt>continueExpr</tt> will attempt to extend this expression by
-     *  parsing additional tokens and appending additional bytecodes.
-     *
-     *  No operators with precedence less than <tt>minPrecedence</tt>
-     *  will be parsed.
-     *
-     *  If any bytecodes are appended, they will not alter the stack
-     *  depth.
-     */
-    private void continueExpr(JSFunction b, int minPrecedence) throws IOException {
-        int saveParserLine = parserLine;
-        _continueExpr(b, minPrecedence);
-        parserLine = saveParserLine;
-    }
-    private void _continueExpr(JSFunction b, int minPrecedence) throws IOException {
-        if (b == null) throw new Error("got null b; this should never happen");
-        int tok = getToken();
-        if (tok == -1) return;
-        if (minPrecedence != -1 && (precedence[tok] < minPrecedence || (precedence[tok] == minPrecedence && !isRightAssociative[tok]))) {
-            pushBackToken();
-            return;
-        }
-
-        switch (tok) {
-        case LP: {  // invocation (not grouping)
-            int n = parseArgs(b);
-            b.add(parserLine, CALL, JS.N(n));
-            break;
-        }
-        case BITOR: case BITXOR: case BITAND: case SHEQ: case SHNE: case LSH:
-        case RSH: case URSH: case MUL: case DIV: case MOD:
-        case GT: case GE: case EQ: case NE: case LT: case LE: case SUB: {
-            startExpr(b, precedence[tok]);
-            b.add(parserLine, tok);
-            break;
-        }
-        case ADD: {
-            int count=1;
-            int nextTok;
-            do {
-                startExpr(b,precedence[tok]);
-                count++;
-                nextTok = getToken();
-            } while(nextTok == tok);
-            pushBackToken();
-            b.add(parserLine, tok, JS.N(count));
-            break;
-        }
-        case OR: case AND: {
-            b.add(parserLine, tok == AND ? JSFunction.JF : JSFunction.JT, JS.ZERO);       // test to see if we can short-circuit
-            int size = b.size;
-            startExpr(b, precedence[tok]);                                     // otherwise check the second value
-            b.add(parserLine, JMP, JS.N(2));                            // leave the second value on the stack and jump to the end
-            b.add(parserLine, LITERAL, tok == AND ?
-                  JS.B(false) : JS.B(true));                     // target of the short-circuit jump is here
-            b.set(size - 1, JS.N(b.size - size));                     // write the target of the short-circuit jump
-            break;
-        }
-        case DOT: {
-            // support foo..bar syntax for foo[""].bar
-            if (peekToken() == DOT) {
-                string = "";
-            } else {
-                consume(NAME);
-            }
-            b.add(parserLine, LITERAL, JSString.intern(string));
-            continueExprAfterAssignable(b,minPrecedence,null);
-            break;
-        }
-        case LB: { // subscripting (not array constructor)
-            startExpr(b, -1);
-            consume(RB);
-            continueExprAfterAssignable(b,minPrecedence,null);
-            break;
-        }
-        case HOOK: {
-            b.add(parserLine, JF, JS.ZERO);                // jump to the if-false expression
-            int size = b.size;
-            startExpr(b, minPrecedence);                          // write the if-true expression
-            b.add(parserLine, JMP, JS.ZERO);               // if true, jump *over* the if-false expression     
-            b.set(size - 1, JS.N(b.size - size + 1));    // now we know where the target of the jump is
-            consume(COLON);
-            size = b.size;
-            startExpr(b, minPrecedence);                          // write the if-false expression
-            b.set(size - 1, JS.N(b.size - size + 1));    // this is the end; jump to here
-            break;
-        }
-        case COMMA: {
-            // pop the result of the previous expression, it is ignored
-            b.add(parserLine,POP);
-            startExpr(b,-1);
-            break;
-        }
-        default: {
-            pushBackToken();
-            return;
-        }
-        }
-
-        continueExpr(b, minPrecedence);                           // try to continue the expression
-    }
-    
-    // parse a set of comma separated function arguments, assume LP has already been consumed
-    private int parseArgs(JSFunction b) throws IOException {
-        int i = 0;
-        while(peekToken() != RP) {
-            i++;
-            if (peekToken() != COMMA) {
-                startExpr(b, NO_COMMA);
-                if (peekToken() == RP) break;
-            }
-            consume(COMMA);
-        }
-        consume(RP);
-        return i;
-    }
-    
-    /** Parse a block of statements which must be surrounded by LC..RC. */
-    void parseBlock(JSFunction b) throws IOException { parseBlock(b, null); }
-    void parseBlock(JSFunction b, String label) throws IOException {
-        int saveParserLine = parserLine;
-        _parseBlock(b, label);
-        parserLine = saveParserLine;
-    }
-    void _parseBlock(JSFunction b, String label) throws IOException {
-        if (peekToken() == -1) return;
-        else if (peekToken() != LC) parseStatement(b, null);
-        else {
-            consume(LC);
-            while(peekToken() != RC && peekToken() != -1) parseStatement(b, null);
-            consume(RC);
-        }
-    }
-
-    /** Parse a single statement, consuming the RC or SEMI which terminates it. */
-    void parseStatement(JSFunction b, String label) throws IOException {
-        int saveParserLine = parserLine;
-        _parseStatement(b, label);
-        parserLine = saveParserLine;
-    }
-    void _parseStatement(JSFunction b, String label) throws IOException {
-        int tok = peekToken();
-        if (tok == -1) return;
-        switch(tok = getToken()) {
-            
-        case THROW: case ASSERT: case RETURN: {
-            if (tok == RETURN && peekToken() == SEMI)
-                b.add(parserLine, LITERAL, null);
-            else
-                startExpr(b, -1);
-            b.add(parserLine, tok);
-            consume(SEMI);
-            break;
-        }
-        case BREAK: case CONTINUE: {
-            if (peekToken() == NAME) consume(NAME);
-            b.add(parserLine, tok, string);
-            consume(SEMI);
-            break;
-        }
-        case VAR: {
-            while(true) {
-                consume(NAME);
-                String var = string;
-                scopeDeclare(var);
-                if (peekToken() == ASSIGN) {                     // if there is an '=' after the variable name
-                    consume(ASSIGN);
-                    startExpr(b, NO_COMMA);
-                    b.add(parserLine, SCOPEPUT, scopeKey(var)); // assign it
-                    b.add(parserLine, POP);                      // clean the stack
-                }
-                if (peekToken() != COMMA) break;
-                consume(COMMA);
-            }
-            if ((mostRecentlyReadToken != RC || peekToken() == SEMI) && peekToken() != -1 && mostRecentlyReadToken != SEMI) consume(SEMI);
-            break;
-        }
-        case IF: {
-            consume(LP);
-            startExpr(b, -1);
-            consume(RP);
-            
-            b.add(parserLine, JF, JS.ZERO);                    // if false, jump to the else-block
-            int size = b.size;
-            parseStatement(b, null);
-            
-            if (peekToken() == ELSE) {
-                consume(ELSE);
-                b.add(parserLine, JMP, JS.ZERO);               // if we took the true-block, jump over the else-block
-                b.set(size - 1, JS.N(b.size - size + 1));
-                size = b.size;
-                parseStatement(b, null);
-            }
-            b.set(size - 1, JS.N(b.size - size + 1));        // regardless of which branch we took, b[size] needs to point here
-            break;
-        }
-        case WHILE: {
-            consume(LP);
-            if (label != null) b.add(parserLine, LABEL, label);
-            b.add(parserLine, LOOP);
-            int size = b.size;
-            b.add(parserLine, POP);                                   // discard the first-iteration indicator
-            startExpr(b, -1);
-            b.add(parserLine, JT, JS.N(2));                    // if the while() clause is true, jump over the BREAK
-            b.add(parserLine, BREAK);
-            consume(RP);
-            parseStatement(b, null);
-            b.add(parserLine, CONTINUE);                              // if we fall out of the end, definately continue
-            b.set(size - 1, JS.N(b.size - size + 1));        // end of the loop
-            break;
-        }
-        case SWITCH: {
-            consume(LP);
-            if (label != null) b.add(parserLine, LABEL, label);
-            b.add(parserLine, LOOP);
-            int size0 = b.size;
-            startExpr(b, -1);
-            consume(RP);
-            consume(LC);
-            while(true)
-                if (peekToken() == CASE) {                         // we compile CASE statements like a bunch of if..else's
-                    consume(CASE);
-                    b.add(parserLine, DUP);                        // duplicate the switch() value; we'll consume one copy
-                    startExpr(b, -1);
-                    consume(COLON);
-                    b.add(parserLine, EQ);                         // check if we should do this case-block
-                    b.add(parserLine, JF, JS.ZERO);         // if not, jump to the next one
-                    int size = b.size;
-                    while(peekToken() != CASE && peekToken() != DEFAULT && peekToken() != RC) parseStatement(b, null);
-                    b.set(size - 1, JS.N(1 + b.size - size));
-                } else if (peekToken() == DEFAULT) {
-                    consume(DEFAULT);
-                    consume(COLON);
-                    while(peekToken() != CASE && peekToken() != DEFAULT && peekToken() != RC) parseStatement(b, null);
-                } else if (peekToken() == RC) {
-                    consume(RC);
-                    b.add(parserLine, BREAK);                      // break out of the loop if we 'fall through'
-                    break;
-                } else {
-                    throw pe("expected CASE, DEFAULT, or RC; got " + codeToString[peekToken()]);
-                }
-            b.set(size0 - 1, JS.N(b.size - size0 + 1));      // end of the loop
-            break;
-        }
-            
-        case DO: {
-            if (label != null) b.add(parserLine, LABEL, label);
-            b.add(parserLine, LOOP);
-            int size = b.size;
-            parseStatement(b, null);
-            consume(WHILE);
-            consume(LP);
-            startExpr(b, -1);
-            b.add(parserLine, JT, JS.N(2));                  // check the while() clause; jump over the BREAK if true
-            b.add(parserLine, BREAK);
-            b.add(parserLine, CONTINUE);
-            consume(RP);
-            consume(SEMI);
-            b.set(size - 1, JS.N(b.size - size + 1));      // end of the loop; write this location to the LOOP instruction
-            break;
-        }
-            
-        case TRY: {
-            b.add(parserLine, TRY); // try bytecode causes a TryMarker to be pushed
-            int tryInsn = b.size - 1;
-            // parse the expression to be TRYed
-            parseStatement(b, null); 
-            // pop the try  marker. this is pushed when the TRY bytecode is executed                              
-            b.add(parserLine, POP);
-            // jump forward to the end of the catch block, start of the finally block                             
-            b.add(parserLine, JMP);                                  
-            int successJMPInsn = b.size - 1;
-            
-            if (peekToken() != CATCH && peekToken() != FINALLY)
-                throw pe("try without catch or finally");
-            
-            int catchJMPDistance = -1;
-            if (peekToken() == CATCH) {
-                Vec catchEnds = new Vec();
-                boolean catchAll = false;
-                
-                catchJMPDistance = b.size - tryInsn;
-                
-                while(peekToken() == CATCH && !catchAll) {
-                    String exceptionVar;
-                    getToken();
-                    consume(LP);
-                    consume(NAME);
-                    exceptionVar = string;
-                    int[] writebacks = new int[] { -1, -1, -1 };
-                    if (peekToken() != RP) {
-                        // extended Ibex catch block: catch(e faultCode "foo.bar.baz")
-                        consume(NAME);
-                        b.add(parserLine, DUP);
-                        b.add(parserLine, LITERAL, JSString.intern(string));
-                        b.add(parserLine, GET);
-                        b.add(parserLine, DUP);
-                        b.add(parserLine, LITERAL, null);
-                        b.add(parserLine, EQ);
-                        b.add(parserLine, JT);
-                        writebacks[0] = b.size - 1;
-                        if (peekToken() == STRING) {
-                            consume(STRING);
-                            b.add(parserLine, DUP);
-                            b.add(parserLine, LITERAL, string);
-                            b.add(parserLine, LT);
-                            b.add(parserLine, JT);
-                            writebacks[1] = b.size - 1;
-                            b.add(parserLine, DUP);
-                            b.add(parserLine, LITERAL, string + "/");   // (slash is ASCII after dot)
-                            b.add(parserLine, GE);
-                            b.add(parserLine, JT);
-                            writebacks[2] = b.size - 1;
-                        } else {
-                            consume(NUMBER);
-                            b.add(parserLine, DUP);
-                            b.add(parserLine, LITERAL, number);
-                            b.add(parserLine, EQ);
-                            b.add(parserLine, JF);
-                            writebacks[1] = b.size - 1;
-                        }
-                        b.add(parserLine, POP);  // pop the element thats on the stack from the compare
-                    } else {
-                        catchAll = true;
-                    }
-                    consume(RP);
-                    // the exception is on top of the stack; put it to the chosen name
-                    scopePush(b);
-                    scopeDeclare(exceptionVar);
-                    b.add(parserLine, SCOPEPUT, scopeKey(exceptionVar));
-                    b.add(parserLine, POP);
-                    parseBlock(b, null);
-                    scopePop(b);
-                    
-                    b.add(parserLine, JMP);
-                    catchEnds.addElement(new Integer(b.size-1));
-                    
-                    for(int i=0; i<3; i++) if (writebacks[i] != -1) b.set(writebacks[i], JS.N(b.size-writebacks[i]));
-                    b.add(parserLine, POP); // pop the element thats on the stack from the compare
-                }
-                
-                if(!catchAll)
-                    b.add(parserLine, THROW);
-                
-                for(int i=0;i<catchEnds.size();i++) {
-                    int n = ((Integer)catchEnds.elementAt(i)).intValue();
-                    b.set(n, JS.N(b.size-n));
-                }
-                
-                // pop the try and catch markers
-                b.add(parserLine,POP);
-                b.add(parserLine,POP);
-            }
-                        
-            // jump here if no exception was thrown
-            b.set(successJMPInsn, JS.N(b.size - successJMPInsn)); 
-                        
-            int finallyJMPDistance = -1;
-            if (peekToken() == FINALLY) {
-                b.add(parserLine, LITERAL, null); // null FinallyData
-                finallyJMPDistance = b.size - tryInsn;
-                consume(FINALLY);
-                parseStatement(b, null);
-                b.add(parserLine,FINALLY_DONE); 
-            }
-            
-            // setup the TRY arguments
-            b.set(tryInsn, new int[] { catchJMPDistance, finallyJMPDistance });
-            
-            break;
-        }
-            
-        case FOR: {
-            consume(LP);
-            
-            tok = getToken();
-            boolean hadVar = false;                                      // if it's a for..in, we ignore the VAR
-            if (tok == VAR) { hadVar = true; tok = getToken(); }
-            String varName = string;
-            boolean forIn = peekToken() == IN;                           // determine if this is a for..in loop or not
-            pushBackToken(tok, varName);
-            
-            if (forIn) {
-                consume(NAME);
-                consume(IN);
-                startExpr(b,-1);
-                consume(RP);
-                
-                b.add(parserLine, PUSHKEYS);
-                
-                int size = b.size;
-                b.add(parserLine, LOOP);
-                b.add(parserLine, POP);
-                
-                b.add(parserLine,SWAP); // get the keys enumeration object on top
-                b.add(parserLine,DUP);
-                b.add(parserLine,GET,JS.S("hasMoreElements"));
-                int size2 = b.size;
-                b.add(parserLine,JT);
-                b.add(parserLine,SWAP);
-                b.add(parserLine,BREAK);
-                b.set(size2, JS.N(b.size - size2));
-                b.add(parserLine,DUP);
-                b.add(parserLine,GET,JS.S("nextElement"));
-
-                scopePush(b);
-                
-                if(hadVar) scopeDeclare(varName);
-                JS varKey = scopeKey(varName);
-                
-                if(varKey == null) {
-                    b.add(parserLine,GLOBALSCOPE);
-                    b.add(parserLine,SWAP);
-                    b.add(parserLine, LITERAL, JSString.intern(varName));
-                    b.add(parserLine,SWAP);
-                    b.add(parserLine,PUT);
-                    b.add(parserLine,POP);
-                } else {
-                    b.add(parserLine, SCOPEPUT, varKey);
-                }
-                b.add(parserLine,POP);  // pop the put'ed value
-                b.add(parserLine,SWAP); // put CallMarker back into place
-                
-                parseStatement(b, null);
-                
-                scopePop(b);
-                b.add(parserLine, CONTINUE);
-                // jump here on break
-                b.set(size, JS.N(b.size - size));
-                
-                b.add(parserLine, POP);
-            } else {
-                if (hadVar) pushBackToken(VAR, null);                    // yeah, this actually matters
-                scopePush(b);                             // grab a fresh scope
-                    
-                parseStatement(b, null);                                 // initializer
-                JSFunction e2 =                                    // we need to put the incrementor before the test
-                    new JSFunction(sourceName, parserLine, null);  // so we save the test here
-                if (peekToken() != SEMI)
-                    startExpr(e2, -1);
-                else
-                    e2.add(parserLine, JSFunction.LITERAL, JS.T);         // handle the for(foo;;foo) case
-                consume(SEMI);
-                if (label != null) b.add(parserLine, LABEL, label);
-                b.add(parserLine, LOOP);
-                int size2 = b.size;
-                    
-                b.add(parserLine, JT, JS.ZERO);                   // if we're on the first iteration, jump over the incrementor
-                int size = b.size;
-                if (peekToken() != RP) {                                 // do the increment thing
-                    startExpr(b, -1);
-                    b.add(parserLine, POP);
-                }
-                b.set(size - 1, JS.N(b.size - size + 1));
-                consume(RP);
-                    
-                b.paste(e2);                                             // ok, *now* test if we're done yet
-                b.add(parserLine, JT, JS.N(2));                   // break out if we don't meet the test
-                b.add(parserLine, BREAK);
-                parseStatement(b, null);
-                b.add(parserLine, CONTINUE);                             // if we fall out the bottom, CONTINUE
-                b.set(size2 - 1, JS.N(b.size - size2 + 1));     // end of the loop
-                    
-                scopePop(b);                            // get our scope back
-            }
-            break;
-        }
-                
-        case NAME: {  // either a label or an identifier; this is the one place we're not LL(1)
-            String possiblyTheLabel = string;
-            if (peekToken() == COLON) {      // label
-                consume(COLON);
-                parseStatement(b, possiblyTheLabel);
-                break;
-            } else {                         // expression
-                pushBackToken(NAME, possiblyTheLabel);  
-                startExpr(b, -1);
-                b.add(parserLine, POP);
-                if ((mostRecentlyReadToken != RC || peekToken() == SEMI) && peekToken() != -1 && mostRecentlyReadToken != SEMI) consume(SEMI);
-                break;
-            }
-        }
-
-        case SEMI: return;                                               // yep, the null statement is valid
-
-        case LC: {  // blocks are statements too
-            pushBackToken();
-            scopePush(b);
-            parseBlock(b, label);
-            scopePop(b);
-            break;
-        }
-
-        default: {  // hope that it's an expression
-            pushBackToken();
-            startExpr(b, -1);
-            b.add(parserLine, POP);
-            if ((mostRecentlyReadToken != RC || peekToken() == SEMI) && peekToken() != -1 && mostRecentlyReadToken != SEMI) consume(SEMI);
-            break;
-        }
-        }
-    }
-
-
-    // ParserException //////////////////////////////////////////////////////////////////////
-    private IOException pe(String s) { return new IOException(sourceName + ":" + line + " " + s); }
-    
-}
-
diff --git a/src/org/ibex/js/PropertyFile.java b/src/org/ibex/js/PropertyFile.java
deleted file mode 100644 (file)
index ee7be2e..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] 
-package org.ibex.js; 
-
-import org.ibex.util.*; 
-import java.util.*;
-import java.io.*;
-
-// FEATURE: Update for new api
-
-/** A JS interface to a Java '.properties' file; very crude */
-public class PropertyFile extends JS {
-
-    /*private final Properties p = new Properties();
-    private final Hash cache = new Hash(10, 3);
-    private File f;
-
-    private class Minion extends JS {
-        private final String prefix;
-        Minion(String prefix) { this.prefix = prefix; }
-        public Number coerceToNumber()  { return N(coerceToString()); }
-        public Boolean coerceToBoolean() { return B(coerceToString().equals("true")); }
-        public String coerceToString()  { return (String)p.get(prefix.substring(0, prefix.length() - 1)); }
-        public Enumeration keys() throws JSExn { throw new JSExn("PropertyFile.keys() not supported"); }
-        public Object get(Object key) throws JSExn {
-            if (toString(key).equals("")) return coerceToString();
-            Object ret = p.get(prefix + escape(toString(key)));
-            if (ret != null) return ret;
-            return new Minion(prefix + escape(toString(key)) + ".");
-        }
-        public void put(Object key, Object val) throws JSExn {
-            try {
-                p.put(prefix + (prefix.equals("") ? "" : ".") + escape(toString(key)), toString(val));
-                File fnew = new File(f.getName() + ".new");
-                FileOutputStream fo = new FileOutputStream(fnew);
-                p.save(fo, "");
-                fo.close();
-                fnew.renameTo(f);
-                f = fnew;
-            } catch (IOException e) { throw new JSExn(e); }
-        }
-    }
-
-    public static String escape(String s) {
-        return s.replaceAll("\\\\", "\\\\\\\\").replaceAll("\\.", "\\\\.").replaceAll("=","\\\\="); }
-    public PropertyFile(File f) throws IOException { this.f = f; this.p.load(new FileInputStream(f)); }
-    public void put(Object key, Object val) throws JSExn { new Minion("").put(key, val); }
-    public Enumeration keys() throws JSExn { return new Minion("").keys(); }
-    public Object get(Object key) throws JSExn {
-        Object ret = p.get(toString(key));
-        if (ret != null) return ret;
-        return new Minion(escape(toString(key)));
-    }*/
-}
diff --git a/src/org/ibex/js/Stream.java b/src/org/ibex/js/Stream.java
deleted file mode 100644 (file)
index 685f990..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.js;
-
-import java.io.*;
-import java.util.zip.*;
-import org.ibex.util.*;
-import org.ibex.plat.*;
-import org.ibex.net.*;
-
-/**
- *   Essentiall an InputStream "factory".  You can repeatedly ask a
- *   Stream for an InputStream, and each InputStream you get back will
- *   be totally independent of the others (ie separate stream position
- *   and state) although they draw from the same data source.
- */
-// FEATURE: Should this be in org.ibex.js?
-public abstract class Stream extends JS implements JS.Cloneable {
-
-    // Public Interface //////////////////////////////////////////////////////////////////////////////
-
-    /*public static InputStream getInputStream(JS js) throws IOException { return ((Stream)js.unclone()).getInputStream();}*/
-    public static class NotCacheableException extends Exception { }
-
-    private Cache getCache = new Cache(100);
-    public abstract JS _get(String key);
-    public final JS get(JS key) throws JSExn {
-        JS ret = (JS) getCache.get(key);
-        if (ret == null) getCache.put(key, ret = _get(JS.toString(key)));
-        return ret;
-    }
-
-    // Private Interface //////////////////////////////////////////////////////////////////////////////
-
-    static String getCacheKey(JS s) throws NotCacheableException {
-        if(s instanceof Stream) return ((Stream)s).getCacheKey();
-        throw new NotCacheableException();
-    }
-    
-    public abstract InputStream getInputStream() throws IOException;
-    protected String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); }
-
-    /** HTTP or HTTPS resource */
-    // FEATURE: Only instansiate only ibex.net.HTTP, share with all substreams
-    public static class HTTP extends Stream {
-        private String url;
-        public HTTP(String url) { while (url.endsWith("/")) url = url.substring(0, url.length() - 1); this.url = url; }
-        public JS _get(String key) { return new HTTP(url + "/" + key); }
-        public String getCacheKey(Vec path) throws NotCacheableException { return url; }
-        public InputStream getInputStream() throws IOException { return new org.ibex.net.HTTP(url).GET(); }
-    }
-
-    /** byte arrays */
-    public static class ByteArray extends Stream {
-        private byte[] bytes;
-        private String cacheKey;
-        public ByteArray(byte[] bytes, String cacheKey) { this.bytes = bytes; this.cacheKey = cacheKey; }
-        public String getCacheKey() throws NotCacheableException {
-            if (cacheKey == null) throw new NotCacheableException(); return cacheKey; }
-        public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(bytes); }
-        public JS _get(String key) { return null; }
-    }
-
-    /** a file */
-    public static class File extends Stream {
-        private String path;
-        public File(String path) { this.path = path; }
-        public String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); /* already on disk */ }
-        public InputStream getInputStream() throws IOException { return new FileInputStream(path); }
-        public JS _get(String key) { return new File(path + java.io.File.separatorChar + key); }
-    }
-
-    /** "unwrap" a Zip archive */
-    public static class Zip extends Stream {
-        private JS parent;
-        private String path;
-        public Zip(JS parent) { this(parent, null); }
-        public Zip(JS parent, String path) {
-            while(path != null && path.startsWith("/")) path = path.substring(1);
-            this.parent = parent;
-            this.path = path;
-        }
-        public String getCacheKey() throws NotCacheableException { return getCacheKey(parent) + "!zip:"; }
-        public JS _get(String key) { return new Zip(parent, path==null?key:path+'/'+key); }
-        public InputStream getInputStream() throws IOException {
-            InputStream pis = parent.getInputStream();
-            ZipInputStream zis = new ZipInputStream(pis);
-            ZipEntry ze = zis.getNextEntry();
-            while(ze != null && !ze.getName().equals(path)) ze = zis.getNextEntry();
-            if (ze == null) throw new IOException("requested file (" + path + ") not found in archive");
-            return new KnownLength.KnownLengthInputStream(zis, (int)ze.getSize());
-        }
-    }
-
-    /** "unwrap" a Cab archive */
-    public static class Cab extends Stream {
-        private JS parent;
-        private String path;
-        public Cab(JS parent) { this(parent, null); }
-        public Cab(JS parent, String path) { this.parent = parent; this.path = path; }
-        public String getCacheKey() throws NotCacheableException { return getCacheKey(parent) + "!cab:"; }
-        public JS _get(String key) { return new Cab(parent, path==null?key:path+'/'+key); }
-        public InputStream getInputStream() throws IOException { return new MSPack(parent.getInputStream()).getInputStream(path); }
-    }
-
-    /** the Builtin resource */
-    public static class Builtin extends Stream {
-        public String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); }
-        public InputStream getInputStream() throws IOException { return Platform.getBuiltinInputStream(); }
-        public JS _get(String key) { return null; }
-    }
-
-    /** shadow resource which replaces the graft */
-    public static class ProgressWatcher extends Stream {
-        final JS watchee;
-        JS callback;
-        public ProgressWatcher(JS watchee, JS callback) { this.watchee = watchee; this.callback = callback; }
-        public String getCacheKey() throws NotCacheableException { return getCacheKey(watchee); }
-        public InputStream getInputStream() throws IOException {
-            final InputStream is = watchee.getInputStream();
-            return new FilterInputStream(is) {
-                    int bytesDownloaded = 0;
-                    public int read() throws IOException {
-                        int ret = super.read();
-                        if (ret != -1) bytesDownloaded++;
-                        return ret;
-                    }
-                    public int read(byte[] b, int off, int len) throws IOException {
-                        int ret = super.read(b, off, len);
-                        if (ret != 1) bytesDownloaded += ret;
-                        Scheduler.add(new Task() { public void perform() throws IOException, JSExn {
-                            callback.call(N(bytesDownloaded),
-                                          N(is instanceof KnownLength ? ((KnownLength)is).getLength() : 0), null, null, 2);
-                        } });
-                        return ret;
-                    }
-                };
-        }
-        public JS _get(String s) { return null; }
-    }
-
-    /** subclass from this if you want a CachedInputStream for each path */
-    public static class CachedStream extends Stream {
-        private JS parent;
-        private boolean disk = false;
-        private String key;
-        private String s;
-        public String getCacheKey() throws NotCacheableException { return key; }
-        CachedInputStream cis = null;
-        public CachedStream(JS p, String s, boolean d) throws NotCacheableException {
-            this.parent = p; this.s = s; this.disk = d; this.key = getCacheKey(p);
-        }
-        public InputStream getInputStream() throws IOException {
-            if (cis != null) return cis.getInputStream();
-            if (!disk) {
-                cis = new CachedInputStream(parent.getInputStream());
-            } else {
-                // FEATURE: Move LocalStorage into org.ibex.js or move this out
-                java.io.File f = org.ibex.core.LocalStorage.Cache.getCacheFileForKey(key);
-                if (f.exists()) return new FileInputStream(f);
-                cis = new CachedInputStream(parent.getInputStream(), f);
-            }
-            return cis.getInputStream();
-        }
-        public JS _get(String s) { return null; }
-    }
-}
diff --git a/src/org/ibex/js/Test.java b/src/org/ibex/js/Test.java
deleted file mode 100644 (file)
index 1bf62e1..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.ibex.js;
-
-import java.io.*;
-
-public class Test extends JS {
-    static JS.UnpauseCallback up = null;
-    static String action;
-    
-    public static void main(String[] args) throws Exception {
-        if(args.length == 0) { System.err.println("Usage Test filename"); System.exit(1); }
-        JS f = JS.fromReader(args[0],1,new FileReader(args[0]));
-        System.out.println(((JSFunction)f).dump());
-        JS s = new JS.O();
-        s.put(JS.S("sys"),new Test());
-        f = JS.cloneWithNewGlobalScope(f,s);
-        //JS ret = f.call(null,null,null,null,0);
-        Interpreter i = new Interpreter((JSFunction)f, true, new Interpreter.JSArgs(f));
-        JS ret = i.resume();
-        while(up != null) {
-            JS.UnpauseCallback up = Test.up; Test.up = null;
-            if("throw".equals(action)) ret = up.unpause(new JSExn("this was thrown to a paused context"));
-            else if("bgget".equals(action)) ret = up.unpause(JS.S("I'm returning this from a get request"));
-            else {
-                System.out.println("got a background put " + action);
-                ret = up.unpause();
-            }
-        }
-        System.out.println("Script returned: " + JS.toString(ret));
-    }
-    
-    public JS get(JS key) throws JSExn {
-        if(!JS.isString(key)) return null;
-        if("print".equals(JS.toString(key))) return METHOD;
-        if("clone".equals(JS.toString(key))) return METHOD;
-        if("firethis".equals(JS.toString(key))) return METHOD;
-        if("bgget".equals(JS.toString(key))) {
-            action = "bgget";
-            try {
-                up = JS.pause();
-            } catch(NotPauseableException e) {
-                throw new Error("should never happen");
-            }
-            return null;
-        }
-        return super.get(key);
-    }
-        
-    public void put(JS key, JS val) throws JSExn {
-        if("bgput".equals(JS.toString(key))) {
-            action = JS.toString(val);
-            try {
-                up = JS.pause();
-            } catch(NotPauseableException e) {
-                throw new Error("should never happen");
-            }
-            return;
-        }   
-        if("exit".equals(JS.toString(key))) {
-            System.exit(JS.toInt(val));
-            return;
-        }
-        super.put(key,val);
-    }
-    
-    public JS callMethod(JS method, JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-        if(!JS.isString(method)) return null;
-        if("print".equals(JS.toString(method))) {
-            System.out.println(JS.debugToString(a0));
-            return null;
-        }
-        if("clone".equals(JS.toString(method))) return a0 == null ? null : a0.jsclone();
-        if("firethis".equals(JS.toString(method))) {
-            String action = JS.toString(a0);
-            JS target = a1;
-            JS key = a2;
-            if(action.equals("get")) return a1.getAndTriggerTraps(key);
-            else if(action.equals("put")) a1.putAndTriggerTraps(key,JS.S("some value"));
-            else if(action.equals("trigger")) return target.justTriggerTraps(key,JS.S("some trigger value"));
-            return null;
-        }
-        return null;
-    }
-}
diff --git a/src/org/ibex/js/Tokens.java b/src/org/ibex/js/Tokens.java
deleted file mode 100644 (file)
index 126a10b..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.js;
-
-/** this class contains a <tt>public static final int</tt> for each valid token */
-interface Tokens {
-
-    // Token Constants //////////////////////////////////////////////////////////
-
-    // arithmetic operations; also valid as bytecodes
-    public static final int BITOR         = 0;   // |
-    public static final int ASSIGN_BITOR  = 1;   // |=
-    public static final int BITXOR        = 2;   // ^
-    public static final int ASSIGN_BITXOR = 3;   // ^=
-    public static final int BITAND        = 4;   // &
-    public static final int ASSIGN_BITAND = 5;   // &=
-    public static final int LSH           = 6;   // <<
-    public static final int ASSIGN_LSH    = 7;   // <<=
-    public static final int RSH           = 8;   // >>
-    public static final int ASSIGN_RSH    = 9;   // >>=
-    public static final int URSH          = 10;  // >>>
-    public static final int ASSIGN_URSH   = 11;  // >>>=
-    public static final int ADD           = 12;  // +
-    public static final int ASSIGN_ADD    = 13;  // +=
-    public static final int SUB           = 14;  // -
-    public static final int ASSIGN_SUB    = 15;  // -=
-    public static final int MUL           = 16;  // *
-    public static final int ASSIGN_MUL    = 17;  // *=
-    public static final int DIV           = 18;  // /
-    public static final int ASSIGN_DIV    = 19;  // /=
-    public static final int MOD           = 20;  // %
-    public static final int ASSIGN_MOD    = 21;  // %=
-    public static final int BITNOT        = 22;  // ~
-    public static final int ASSIGN_BITNOT = 23;  // ~=
-
-    // logical operations; also valid as bytecodes
-    public static final int OR            = 24;  // ||
-    public static final int AND           = 25;  // &&
-    public static final int BANG          = 26;  // !
-
-    // equality operations; also valid as bytecodes
-    public static final int EQ            = 27;  // ==
-    public static final int NE            = 28;  // !=
-    public static final int LT            = 29;  // <
-    public static final int LE            = 30;  // <=
-    public static final int GT            = 31;  // >
-    public static final int GE            = 32;  // >=
-    public static final int SHEQ          = 33;  // ===
-    public static final int SHNE          = 34;  // !==
-
-    // other permissible bytecode tokens
-    public static final int RETURN        = 35;  // return
-    public static final int TYPEOF        = 36;  // typeof
-    public static final int BREAK         = 37;  // break keyword
-    public static final int CONTINUE      = 38;  // continue keyword
-    public static final int TRY           = 39;  // try
-    public static final int THROW         = 40;  // throw
-    public static final int ASSERT        = 41;  // assert keyword
-
-    public static final int NAME          = 42;  // *** identifiers ***
-    public static final int NUMBER        = 43;  // *** numeric literals ***
-    public static final int STRING        = 44;  // *** string literals ***
-    public static final int NULL          = 45;  // null
-    public static final int THIS          = 46;  // this
-    public static final int FALSE         = 47;  // false
-    public static final int TRUE          = 48;  // true
-    public static final int IN            = 49;  // in
-
-    public static final int SEMI          = 50;  // ;
-    public static final int LB            = 51;  // [
-    public static final int RB            = 52;  // ]
-    public static final int LC            = 53;  // {
-    public static final int RC            = 54;  // }
-    public static final int LP            = 55;  // (
-    public static final int RP            = 56;  // )
-    public static final int COMMA         = 57;  // ,
-    public static final int ASSIGN        = 58;  // =
-    public static final int HOOK          = 59;  // ?
-    public static final int COLON         = 60;  // :
-    public static final int INC           = 61;  // ++
-    public static final int DEC           = 62;  // --
-    public static final int DOT           = 63;  // .
-    public static final int FUNCTION      = 64;  // function
-    public static final int IF            = 65;  // if keyword
-    public static final int ELSE          = 66;  // else keyword
-    public static final int SWITCH        = 67;  // switch keyword
-    public static final int CASE          = 68;  // case keyword
-    public static final int DEFAULT       = 69;  // default keyword
-    public static final int WHILE         = 70;  // while keyword
-    public static final int DO            = 71;  // do keyword
-    public static final int FOR           = 72;  // for keyword
-    public static final int VAR           = 73;  // var keyword
-    public static final int WITH          = 74;  // with keyword
-    public static final int CATCH         = 75;  // catch keyword
-    public static final int FINALLY       = 76;  // finally keyword
-    public static final int RESERVED      = 77;  // reserved keyword
-    public static final int GRAMMAR       = 78;  // the grammar-definition operator (::=)
-    public static final int ADD_TRAP      = 79;  // the add-trap operator (++=)
-    public static final int DEL_TRAP      = 80;  // the del-trap operator (--=)
-    public static final int CASCADE       = 81;  // cascade expression - arg==true for write cascade
-    public static final int MAX_TOKEN = DEL_TRAP;
-
-    public final static String[] codeToString = new String[] {
-        "BITOR", "ASSIGN_BITOR", "BITXOR", "ASSIGN_BITXOR", "BITAND",
-        "ASSIGN_BITAND", "LSH", "ASSIGN_LSH", "RSH", "ASSIGN_RSH",
-        "URSH", "ASSIGN_URSH", "ADD", "ASSIGN_ADD", "SUB",
-        "ASSIGN_SUB", "MUL", "ASSIGN_MUL", "DIV", "ASSIGN_DIV", "MOD",
-        "ASSIGN_MOD", "BITNOT", "ASSIGN_BITNOT", "OR", "AND", "BANG",
-        "EQ", "NE", "LT", "LE", "GT", "GE", "SHEQ", "SHNE", "RETURN",
-        "TYPEOF", "BREAK", "CONTINUE", "TRY", "THROW", "ASSERT", "NAME",
-        "NUMBER", "STRING", "NULL", "THIS", "FALSE", "TRUE", "IN",
-        "SEMI", "LB", "RB", "LC", "RC", "LP", "RP", "COMMA", "ASSIGN",
-        "HOOK", "COLON", "INC", "DEC", "DOT", "FUNCTION", "IF",
-        "ELSE", "SWITCH", "CASE", "DEFAULT", "WHILE", "DO", "FOR",
-        "VAR", "WITH", "CATCH", "FINALLY", "RESERVED", "GRAMMAR",
-        "ADD_TRAP", "DEL_TRAP", "CASCADE"
-    };
-
-}
-
-
diff --git a/src/org/ibex/js/Trap.java b/src/org/ibex/js/Trap.java
deleted file mode 100644 (file)
index 580ed69..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.js;
-
-/**
- *  This class encapsulates a single trap placed on a given node. The
- *  traps for a given property name on a given box are maintained as a
- *  linked list stack, with the most recently placed trap at the head
- *  of the list.
- */
-final class Trap {
-
-    final JS target;          ///< the box on which this trap was placed
-    final JS key;             ///< the property that the trap was placed on
-
-    final JSFunction f;       ///< the function for this trap
-    Trap next;                ///< the next trap down the trap stack
-
-    Trap(JS b, JS n, JSFunction f, Trap nx) {
-        target = b; key = n; this.f = f; this.next = nx;
-    }
-    
-    boolean isReadTrap()  { return f.numFormalArgs == 0; }
-    boolean isWriteTrap() { return f.numFormalArgs != 0; }
-    Trap readTrap()  { Trap t = this; while(t!=null && t.isWriteTrap()) t = t.next; return t; }
-    Trap writeTrap() { Trap t = this; while(t!=null && t.isReadTrap())  t = t.next; return t; }
-    Trap nextReadTrap()  { return next == null ? null : next.readTrap();  }
-    Trap nextWriteTrap() { return next == null ? null : next.writeTrap(); }
-}
diff --git a/src/org/ibex/net/HTTP.java b/src/org/ibex/net/HTTP.java
deleted file mode 100644 (file)
index da94713..0000000
+++ /dev/null
@@ -1,1304 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.net;
-
-import java.net.*;
-import java.io.*;
-import java.util.*;
-import org.ibex.js.*;
-import org.ibex.util.*;
-import org.ibex.plat.*;
-import org.ibex.core.*;
-import org.ibex.crypto.*;
-
-/**
- *  This object encapsulates a *single* HTTP connection. Multiple requests may be pipelined over a connection (thread-safe),
- *  although any IOException encountered in a request will invalidate all later requests.
- */
-public class HTTP {
-
-
-    // Public Methods ////////////////////////////////////////////////////////////////////////////////////////
-
-    public HTTP(String url) { this(url, false); }
-    public HTTP(String url, boolean skipResolveCheck) { originalUrl = url; this.skipResolveCheck = skipResolveCheck; }
-
-    /** Performs an HTTP GET request */
-    public InputStream GET() throws IOException { return makeRequest(null, null); }
-
-    /** Performs an HTTP POST request; content is additional headers, blank line, and body */
-    public InputStream POST(String contentType, String content) throws IOException { return makeRequest(contentType, content); }
-
-    public static class HTTPException extends IOException { public HTTPException(String s) { super(s); } }
-
-    public static HTTP stdio = new HTTP("stdio:");
-
-
-    // Statics ///////////////////////////////////////////////////////////////////////////////////////////////
-
-    static Hash resolvedHosts = new Hash();            ///< cache for resolveAndCheckIfFirewalled()
-    private static Hash authCache = new Hash();        ///< cache of userInfo strings, keyed on originalUrl
-
-
-    // Instance Data ///////////////////////////////////////////////////////////////////////////////////////////////
-
-    final String originalUrl;              ///< the URL as passed to the original constructor; this is never changed
-    String url = null;                     ///< the URL to connect to; this is munged when the url is parsed */
-    String host = null;                    ///< the host to connect to
-    int port = -1;                         ///< the port to connect on
-    boolean ssl = false;                   ///< true if SSL (HTTPS) should be used
-    String path = null;                    ///< the path (URI) to retrieve on the server
-    Socket sock = null;                    ///< the socket
-    InputStream in = null;                 ///< the socket's inputstream
-    String userInfo = null;                ///< the username and password portions of the URL
-    boolean firstRequest = true;           ///< true iff this is the first request to be made on this socket
-    boolean skipResolveCheck = false;      ///< allowed to skip the resolve check when downloading PAC script
-    boolean proxied = false;               ///< true iff we're using a proxy
-
-    /** this is null if the current request is the first request on
-     *  this HTTP connection; otherwise it is a Semaphore which will be
-     *  released once the request ahead of us has recieved its response
-     */
-    Semaphore okToRecieve = null;
-
-    /**
-     *  This method isn't synchronized; however, only one thread can be in the inner synchronized block at a time, and the rest of
-     *  the method is protected by in-order one-at-a-time semaphore lock-steps
-     */
-    private InputStream makeRequest(String contentType, String content) throws IOException {
-
-        // Step 1: send the request and establish a semaphore to stop any requests that pipeline after us
-        Semaphore blockOn = null;
-        Semaphore releaseMe = null;
-        synchronized(this) {
-            try {
-                connect();
-                sendRequest(contentType, content);
-            } catch (IOException e) {
-                reset();
-                throw e;
-            }
-            blockOn = okToRecieve;
-            releaseMe = okToRecieve = new Semaphore();
-        }
-        
-        // Step 2: wait for requests ahead of us to complete, then read the reply off the stream
-        boolean doRelease = true;
-        try {
-            if (blockOn != null) blockOn.block();
-            
-            // previous call wrecked the socket connection, but we already sent our request, so we can't just retry --
-            // this could cause the server to receive the request twice, which could be bad (think of the case where the
-            // server call causes Amazon.com to ship you an item with one-click purchasing).
-            if (in == null)
-                throw new HTTPException("a previous pipelined call messed up the socket");
-            
-            Hashtable h = in == null ? null : parseHeaders(in);
-            if (h == null) {
-                if (firstRequest) throw new HTTPException("server closed the socket with no response");
-                // sometimes the server chooses to close the stream between requests
-                reset();
-                releaseMe.release();
-                return makeRequest(contentType, content);
-            }
-
-            String reply = h.get("STATUSLINE").toString();
-            
-            if (reply.startsWith("407") || reply.startsWith("401")) {
-                
-                if (reply.startsWith("407")) doProxyAuth(h, content == null ? "GET" : "POST");
-                else doWebAuth(h, content == null ? "GET" : "POST");
-                
-                if (h.get("HTTP").equals("1.0") && h.get("content-length") == null) {
-                    if (Log.on) Log.info(this, "proxy returned an HTTP/1.0 reply with no content-length...");
-                    reset();
-                } else {
-                    int cl = h.get("content-length") == null ? -1 : Integer.parseInt(h.get("content-length").toString());
-                    new HTTPInputStream(in, cl, releaseMe).close();
-                }
-                releaseMe.release();
-                return makeRequest(contentType, content);
-                
-            } else if (reply.startsWith("2")) {
-                if (h.get("HTTP").equals("1.0") && h.get("content-length") == null)
-                    throw new HTTPException("Ibex does not support HTTP/1.0 servers which fail to return the Content-Length header");
-                int cl = h.get("content-length") == null ? -1 : Integer.parseInt(h.get("content-length").toString());
-                InputStream ret = new HTTPInputStream(in, cl, releaseMe);
-                if ("gzip".equals(h.get("content-encoding"))) ret = new java.util.zip.GZIPInputStream(ret);
-                doRelease = false;
-                return ret;
-                
-            } else {
-                throw new HTTPException("HTTP Error: " + reply);
-                
-            }
-            
-        } catch (IOException e) { reset(); throw e;
-        } finally { if (doRelease) releaseMe.release();
-        }
-    }
-
-
-    // Safeguarded DNS Resolver ///////////////////////////////////////////////////////////////////////////
-
-    /**
-     *  resolves the hostname and returns it as a string in the form "x.y.z.w"
-     *  @throws HTTPException if the host falls within a firewalled netblock
-     */
-    private void resolveAndCheckIfFirewalled(String host) throws HTTPException {
-
-        // cached
-        if (resolvedHosts.get(host) != null) return;
-
-        // if all scripts are trustworthy (local FS), continue
-        if (Main.originAddr == null) return;
-
-        // resolve using DNS
-        try {
-            InetAddress addr = InetAddress.getByName(host);
-            byte[] quadbyte = addr.getAddress();
-            if ((quadbyte[0] == 10 ||
-                 (quadbyte[0] == 192 && quadbyte[1] == 168) ||
-                 (quadbyte[0] == 172 && (quadbyte[1] & 0xF0) == 16)) && !addr.equals(Main.originAddr))
-                throw new HTTPException("security violation: " + host + " [" + addr.getHostAddress() +
-                                        "] is in a firewalled netblock");
-            return;
-        } catch (UnknownHostException uhe) { }
-
-        if (Platform.detectProxy() == null)
-            throw new HTTPException("could not resolve hostname \"" + host + "\" and no proxy configured");
-    }
-
-
-    // Methods to attempt socket creation /////////////////////////////////////////////////////////////////
-
-    private Socket getSocket(String host, int port, boolean ssl, boolean negotiate) throws IOException {
-        Socket ret = ssl ? new SSL(host, port, negotiate) : new Socket(java.net.InetAddress.getByName(host), port);
-        ret.setTcpNoDelay(true);
-        return ret;
-    }
-
-    /** Attempts a direct connection */
-    private Socket attemptDirect() {
-        try {
-            Log.info(this, "attempting to create unproxied socket to " +
-                     host + ":" + port + (ssl ? " [ssl]" : ""));
-            return getSocket(host, port, ssl, true);
-        } catch (IOException e) {
-            if (Log.on) Log.info(this, "exception in attemptDirect(): " + e);
-            return null;
-        }
-    }
-
-    /** Attempts to use an HTTP proxy, employing the CONNECT method if HTTPS is requested */
-    private Socket attemptHttpProxy(String proxyHost, int proxyPort) {
-        try {
-            if (Log.verbose) Log.info(this, "attempting to create HTTP proxied socket using proxy " + proxyHost + ":" + proxyPort);
-            Socket sock = getSocket(proxyHost, proxyPort, ssl, false);
-
-            if (!ssl) {
-                if (!path.startsWith("http://")) path = "http://" + host + ":" + port + path;
-                return sock;
-            }
-
-            PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
-            BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
-            pw.print("CONNECT " + host + ":" + port + " HTTP/1.1\r\n\r\n");
-            pw.flush();
-            String s = br.readLine();
-            if (s.charAt(9) != '2') throw new HTTPException("proxy refused CONNECT method: \"" + s + "\"");
-            while (br.readLine().length() > 0) { };
-            ((SSL)sock).negotiate();
-            return sock;
-
-        } catch (IOException e) {
-            if (Log.on) Log.info(this, "exception in attemptHttpProxy(): " + e);
-            return null;
-        }
-    }
-
-    /**
-     *  Implements SOCKSv4 with v4a DNS extension
-     *  @see http://www.socks.nec.com/protocol/socks4.protocol
-     *  @see http://www.socks.nec.com/protocol/socks4a.protocol
-     */
-    private Socket attemptSocksProxy(String proxyHost, int proxyPort) {
-
-        // even if host is already a "x.y.z.w" string, we use this to parse it into bytes
-        InetAddress addr = null;
-        try { addr = InetAddress.getByName(host); } catch (Exception e) { }
-
-        if (Log.verbose) Log.info(this, "attempting to create SOCKSv4" + (addr == null ? "" : "a") +
-                                 " proxied socket using proxy " + proxyHost + ":" + proxyPort);
-
-        try {
-            Socket sock = getSocket(proxyHost, proxyPort, ssl, false);
-            
-            DataOutputStream dos = new DataOutputStream(sock.getOutputStream());
-            dos.writeByte(0x04);                         // SOCKSv4(a)
-            dos.writeByte(0x01);                         // CONNECT
-            dos.writeShort(port & 0xffff);               // port
-            if (addr == null) dos.writeInt(0x00000001);  // bogus IP
-            else dos.write(addr.getAddress());           // actual IP
-            dos.writeByte(0x00);                         // no userid
-            if (addr == null) {
-                PrintWriter pw = new PrintWriter(new OutputStreamWriter(dos));
-                pw.print(host);
-                pw.flush();
-                dos.writeByte(0x00);                     // hostname null terminator
-            }
-            dos.flush();
-
-            DataInputStream dis = new DataInputStream(sock.getInputStream());
-            dis.readByte();                              // reply version
-            byte success = dis.readByte();               // success/fail
-            dis.skip(6);                                 // ip/port
-            
-            if ((int)(success & 0xff) == 90) {
-                if (ssl) ((SSL)sock).negotiate();
-                return sock;
-            }
-            if (Log.on) Log.info(this, "SOCKS server denied access, code " + (success & 0xff));
-            return null;
-
-        } catch (IOException e) {
-            if (Log.on) Log.info(this, "exception in attemptSocksProxy(): " + e);
-            return null;
-        }
-    }
-
-    /** executes the PAC script and dispatches a call to one of the other attempt methods based on the result */
-    private Socket attemptPAC(org.ibex.js.JS pacFunc) {
-        if (Log.verbose) Log.info(this, "evaluating PAC script");
-        String pac = null;
-        try {
-            JS obj = pacFunc.call(JS.S(url), JS.S(host), null, null, 2);
-            if (Log.verbose) Log.info(this, "  PAC script returned \"" + JS.debugToString(obj) + "\"");
-            pac = JS.toString(obj);
-        } catch (Throwable e) {
-            if (Log.on) Log.info(this, "PAC script threw exception " + e);
-            return null;
-        }
-
-        StringTokenizer st = new StringTokenizer(pac, ";", false);
-        while (st.hasMoreTokens()) {
-            String token = st.nextToken().trim();
-            if (Log.verbose) Log.info(this, "  trying \"" + token + "\"...");
-            try {
-                Socket ret = null;
-                if (token.startsWith("DIRECT"))
-                    ret = attemptDirect();
-                else if (token.startsWith("PROXY"))
-                    ret = attemptHttpProxy(token.substring(token.indexOf(' ') + 1, token.indexOf(':')),
-                                           Integer.parseInt(token.substring(token.indexOf(':') + 1)));
-                else if (token.startsWith("SOCKS"))
-                    ret = attemptSocksProxy(token.substring(token.indexOf(' ') + 1, token.indexOf(':')),
-                                            Integer.parseInt(token.substring(token.indexOf(':') + 1)));
-                if (ret != null) return ret;
-            } catch (Throwable e) {
-                if (Log.on) Log.info(this, "attempt at \"" + token + "\" failed due to " + e + "; trying next token");
-            }
-        }
-        if (Log.on) Log.info(this, "all PAC results exhausted");
-        return null;
-    }
-
-
-    // Everything Else ////////////////////////////////////////////////////////////////////////////
-
-    private synchronized void connect() throws IOException {
-        if (originalUrl.equals("stdio:")) { in = new BufferedInputStream(System.in); return; }
-        if (sock != null) {
-            if (in == null) in = new BufferedInputStream(sock.getInputStream());
-            return;
-        }
-        // grab the userinfo; gcj doesn't have java.net.URL.getUserInfo()
-        String url = originalUrl;
-        userInfo = url.substring(url.indexOf("://") + 3);
-        userInfo = userInfo.indexOf('/') == -1 ? userInfo : userInfo.substring(0, userInfo.indexOf('/'));
-        if (userInfo.indexOf('@') != -1) {
-            userInfo = userInfo.substring(0, userInfo.indexOf('@'));
-            url = url.substring(0, url.indexOf("://") + 3) + url.substring(url.indexOf('@') + 1);
-        } else {
-            userInfo = null;
-        }
-
-        if (url.startsWith("https:")) {
-            ssl = true;
-        } else if (!url.startsWith("http:")) {
-            throw new IOException("HTTP only supports http/https urls");
-        }
-        if (url.indexOf("://") == -1) throw new IOException("URLs must contain a ://");
-        String temphost = url.substring(url.indexOf("://") + 3);
-        path = temphost.substring(temphost.indexOf('/'));
-        temphost = temphost.substring(0, temphost.indexOf('/'));
-        if (temphost.indexOf(':') != -1) {
-            port = Integer.parseInt(temphost.substring(temphost.indexOf(':')+1));
-            temphost = temphost.substring(0, temphost.indexOf(':'));
-        } else {
-            port = ssl ? 443 : 80;
-        }
-        if (!skipResolveCheck) resolveAndCheckIfFirewalled(temphost);
-        host = temphost;
-        if (Log.verbose) Log.info(this, "creating HTTP object for connection to " + host + ":" + port);
-
-        Proxy pi = Platform.detectProxy();
-        OUTER: do {
-            if (pi != null) {
-                for(int i=0; i<pi.excluded.length; i++) if (host.equals(pi.excluded[i])) break OUTER;
-                if (sock == null && pi.proxyAutoConfigFunction != null) sock = attemptPAC(pi.proxyAutoConfigFunction);
-                if (sock == null && ssl && pi.httpsProxyHost != null) sock = attemptHttpProxy(pi.httpsProxyHost,pi.httpsProxyPort);
-                if (sock == null && pi.httpProxyHost != null) sock = attemptHttpProxy(pi.httpProxyHost, pi.httpProxyPort);
-                if (sock == null && pi.socksProxyHost != null) sock = attemptSocksProxy(pi.socksProxyHost, pi.socksProxyPort);
-            }
-        } while (false);
-        proxied = sock != null;
-        if (sock == null) sock = attemptDirect();
-        if (sock == null) throw new HTTPException("unable to contact host " + host);
-        if (in == null) in = new BufferedInputStream(sock.getInputStream());
-    }
-
-    private void sendRequest(String contentType, String content) throws IOException {
-        PrintWriter pw = new PrintWriter(new OutputStreamWriter(originalUrl.equals("stdio:") ?
-                                                                System.out : sock.getOutputStream()));
-        if (content != null) {
-            pw.print("POST " + path + " HTTP/1.0\r\n"); // FIXME chunked encoding
-            int contentLength = content.substring(0, 2).equals("\r\n") ?
-                content.length() - 2 :
-                (content.length() - content.indexOf("\r\n\r\n") - 4);
-            pw.print("Content-Length: " + contentLength + "\r\n");
-            if (contentType != null) pw.print("Content-Type: " + contentType + "\r\n");
-        } else {
-            pw.print("GET " + path + " HTTP/1.1\r\n");
-        }
-        
-        pw.print("User-Agent: Ibex\r\n");
-        pw.print("Accept-encoding: gzip\r\n");
-        pw.print("Host: " + (host + (port == 80 ? "" : (":" + port))) + "\r\n");
-        if (proxied) pw.print("X-RequestOrigin: " + Main.originHost + "\r\n");
-
-        if (Proxy.Authorization.authorization != null) pw.print("Proxy-Authorization: "+Proxy.Authorization.authorization2+"\r\n");
-        if (authCache.get(originalUrl) != null) pw.print("Authorization: " + authCache.get(originalUrl) + "\r\n");
-
-        pw.print(content == null ? "\r\n" : content);
-        pw.flush();
-    }
-
-    private void doWebAuth(Hashtable h0, String method) throws IOException {
-        if (userInfo == null) throw new HTTPException("web server demanded username/password, but none were supplied");
-        Hashtable h = parseAuthenticationChallenge(h0.get("www-authenticate").toString());
-        
-        if (h.get("AUTHTYPE").equals("Basic")) {
-            if (authCache.get(originalUrl) != null) throw new HTTPException("username/password rejected");
-            authCache.put(originalUrl, "Basic " + new String(Base64.encode(userInfo.getBytes("UTF8"))));
-            
-        } else if (h.get("AUTHTYPE").equals("Digest")) {
-            if (authCache.get(originalUrl) != null && !"true".equals(h.get("stale")))
-                throw new HTTPException("username/password rejected");
-            String path2 = path;
-            if (path2.startsWith("http://") || path2.startsWith("https://")) {
-                path2 = path2.substring(path2.indexOf("://") + 3);
-                path2 = path2.substring(path2.indexOf('/'));
-            }
-            String A1 = userInfo.substring(0, userInfo.indexOf(':')) + ":" + h.get("realm") + ":" +
-                userInfo.substring(userInfo.indexOf(':') + 1);
-            String A2 = method + ":" + path2;
-            authCache.put(originalUrl,
-                          "Digest " +
-                          "username=\"" + userInfo.substring(0, userInfo.indexOf(':')) + "\", " +
-                          "realm=\"" + h.get("realm") + "\", " +
-                          "nonce=\"" + h.get("nonce") + "\", " +
-                          "uri=\"" + path2 + "\", " +
-                          (h.get("opaque") == null ? "" : ("opaque=\"" + h.get("opaque") + "\", ")) + 
-                          "response=\"" + H(H(A1) + ":" + h.get("nonce") + ":" + H(A2)) + "\", " +
-                          "algorithm=MD5"
-                          );
-            
-        } else {
-            throw new HTTPException("unknown authentication type: " + h.get("AUTHTYPE"));
-        }
-    }
-
-    private void doProxyAuth(Hashtable h0, String method) throws IOException {
-        if (Log.on) Log.info(this, "Proxy AuthChallenge: " + h0.get("proxy-authenticate"));
-        Hashtable h = parseAuthenticationChallenge(h0.get("proxy-authenticate").toString());
-        String style = h.get("AUTHTYPE").toString();
-        String realm = (String)h.get("realm");
-
-        if (style.equals("NTLM") && Proxy.Authorization.authorization2 == null) {
-            Log.info(this, "Proxy identified itself as NTLM, sending Type 1 packet");
-            Proxy.Authorization.authorization2 = "NTLM " + Base64.encode(Proxy.NTLM.type1);
-            return;
-        }
-
-        if (!realm.equals("Digest") || Proxy.Authorization.authorization2 == null || !"true".equals(h.get("stale")))
-            Proxy.Authorization.getPassword(realm, style, sock.getInetAddress().getHostAddress(),
-                                            Proxy.Authorization.authorization);
-
-        if (style.equals("Basic")) {
-            Proxy.Authorization.authorization2 =
-                "Basic " + new String(Base64.encode(Proxy.Authorization.authorization.getBytes("UTF8")));
-            
-        } else if (style.equals("Digest")) {
-            String A1 = Proxy.Authorization.authorization.substring(0, userInfo.indexOf(':')) + ":" + h.get("realm") + ":" +
-                Proxy.Authorization.authorization.substring(Proxy.Authorization.authorization.indexOf(':') + 1);
-            String A2 = method + ":" + path;
-            Proxy.Authorization.authorization2 = 
-                "Digest " +
-                "username=\"" + Proxy.Authorization.authorization.substring(0, Proxy.Authorization.authorization.indexOf(':')) +
-                "\", " +
-                "realm=\"" + h.get("realm") + "\", " +
-                "nonce=\"" + h.get("nonce") + "\", " +
-                "uri=\"" + path + "\", " +
-                (h.get("opaque") == null ? "" : ("opaque=\"" + h.get("opaque") + "\", ")) + 
-                "response=\"" + H(H(A1) + ":" + h.get("nonce") + ":" + H(A2)) + "\", " +
-                "algorithm=MD5";
-
-        } else if (style.equals("NTLM")) {
-            Log.info(this, "Proxy identified itself as NTLM, got Type 2 packet");
-            byte[] type2 = Base64.decode(((String)h0.get("proxy-authenticate")).substring(5).trim());
-            for(int i=0; i<type2.length; i += 4) {
-                String log = "";
-                if (i<type2.length) log += Integer.toString(type2[i] & 0xff, 16) + " ";
-                if (i+1<type2.length) log += Integer.toString(type2[i+1] & 0xff, 16) + " ";
-                if (i+2<type2.length) log += Integer.toString(type2[i+2] & 0xff, 16) + " ";
-                if (i+3<type2.length) log += Integer.toString(type2[i+3] & 0xff, 16) + " ";
-                Log.info(this, log);
-            }
-            // FEATURE: need to keep the connection open between type1 and type3
-            // FEATURE: finish this
-            //byte[] type3 = Proxy.NTLM.getResponse(
-            //Proxy.Authorization.authorization2 = "NTLM " + Base64.encode(type3));
-        }            
-    }
-
-
-    // HTTPInputStream ///////////////////////////////////////////////////////////////////////////////////
-
-    /** An input stream that represents a subset of a longer input stream. Supports HTTP chunking as well */
-    public class HTTPInputStream extends FilterInputStream implements KnownLength {
-
-        private int length = 0;              ///< if chunking, numbytes left in this subset; else the remainder of the chunk
-        private Semaphore releaseMe = null;  ///< this semaphore will be released when the stream is closed
-        boolean chunkedDone = false;         ///< indicates that we have encountered the zero-length terminator chunk
-        boolean firstChunk = true;           ///< if we're on the first chunk, we don't pre-read a CRLF
-        private int contentLength = 0;       ///< the length of the entire content body; -1 if chunked
-
-        HTTPInputStream(InputStream in, int length, Semaphore releaseMe) throws IOException {
-            super(in);
-            this.releaseMe = releaseMe;
-            this.contentLength = length;
-            this.length = length == -1 ? 0 : length;
-        }
-
-        public int getLength() { return contentLength; }
-        public boolean markSupported() { return false; }
-        public int read(byte[] b) throws IOException { return read(b, 0, b.length); }
-        public long skip(long n) throws IOException { return read(null, -1, (int)n); }
-        public int available() throws IOException {
-            if (contentLength == -1) return java.lang.Math.min(super.available(), length);
-            return super.available();
-        }
-
-        public int read() throws IOException {
-            byte[] b = new byte[1];
-            int ret = read(b, 0, 1);
-            return ret == -1 ? -1 : b[0] & 0xff;
-        }
-
-        private void readChunk() throws IOException {
-            if (chunkedDone) return;
-            if (!firstChunk) super.skip(2); // CRLF
-            firstChunk = false;
-            String chunkLen = "";
-            while(true) {
-                int i = super.read();
-                if (i == -1) throw new HTTPException("encountered end of stream while reading chunk length");
-
-                // FEATURE: handle chunking extensions
-                if (i == '\r') {
-                    super.read();    // LF
-                    break;
-                } else {
-                    chunkLen += (char)i;
-                }
-            }
-            length = Integer.parseInt(chunkLen.trim(), 16);
-            if (length == 0) chunkedDone = true;
-        }
-
-        public int read(byte[] b, int off, int len) throws IOException {
-            boolean good = false;
-            try {
-                if (length == 0 && contentLength == -1) {
-                    readChunk();
-                    if (chunkedDone) { good = true; return -1; }
-                } else {
-                    if (length == 0) { good = true; return -1; }
-                }
-                if (len > length) len = length;
-                int ret = b == null ? (int)super.skip(len) : super.read(b, off, len);
-                if (ret >= 0) {
-                    length -= ret;
-                    good = true;
-                }
-                return ret;
-            } finally {
-                if (!good) reset();
-            }
-        }
-
-        public void close() throws IOException {
-            if (contentLength == -1) {
-                while(!chunkedDone) {
-                    if (length != 0) skip(length);
-                    readChunk();
-                }
-                skip(2);
-            } else {
-                if (length != 0) skip(length);
-            }
-            if (releaseMe != null) releaseMe.release();
-        }
-    }
-
-    void reset() {
-        firstRequest = true;
-        in = null;
-        sock = null;
-    }
-
-
-    // Misc Helpers ///////////////////////////////////////////////////////////////////////////////////
-
-    /** reads a set of HTTP headers off of the input stream, returning null if the stream is already at its end */
-    private Hashtable parseHeaders(InputStream in) throws IOException {
-        Hashtable ret = new Hashtable();
-
-        // we can't use a BufferedReader directly on the input stream, since it will buffer past the end of the headers
-        byte[] buf = new byte[4096];
-        int buflen = 0;
-        while(true) {
-            int read = in.read();
-            if (read == -1 && buflen == 0) return null;
-            if (read == -1) throw new HTTPException("stream closed while reading headers");
-            buf[buflen++] = (byte)read;
-            if (buflen >= 4 && buf[buflen - 4] == '\r' && buf[buflen - 3] == '\n' &&
-                buf[buflen - 2] == '\r' && buf[buflen - 1] == '\n')
-                break;
-            if (buflen >=2 && buf[buflen - 1] == '\n' && buf[buflen - 2] == '\n')
-                break;  // nice for people using stdio
-            if (buflen == buf.length) {
-                byte[] newbuf = new byte[buf.length * 2];
-                System.arraycopy(buf, 0, newbuf, 0, buflen);
-                buf = newbuf;
-            }
-        }
-
-        BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf, 0, buflen)));
-        String s = br.readLine();
-        if (!s.startsWith("HTTP/")) throw new HTTPException("Expected reply to start with \"HTTP/\", got: " + s);
-        ret.put("STATUSLINE", s.substring(s.indexOf(' ') + 1));
-        ret.put("HTTP", s.substring(5, s.indexOf(' ')));
-
-        while((s = br.readLine()) != null && s.length() > 0) {
-            String front = s.substring(0, s.indexOf(':')).toLowerCase();
-            String back = s.substring(s.indexOf(':') + 1).trim();
-            // ugly hack: we never replace a Digest-auth with a Basic-auth (proxy + www)
-            if (front.endsWith("-authenticate") && ret.get(front) != null && !back.equals("Digest")) continue;
-            ret.put(front, back);
-        }
-        return ret;
-    }
-
-    private Hashtable parseAuthenticationChallenge(String s) {
-        Hashtable ret = new Hashtable();
-
-        s = s.trim();
-        ret.put("AUTHTYPE", s.substring(0, s.indexOf(' ')));
-        s = s.substring(s.indexOf(' ')).trim();
-
-        while (s.length() > 0) {
-            String val = null;
-            String key = s.substring(0, s.indexOf('='));
-            s = s.substring(s.indexOf('=') + 1);
-            if (s.charAt(0) == '\"') {
-                s = s.substring(1);
-                val = s.substring(0, s.indexOf('\"'));
-                s = s.substring(s.indexOf('\"') + 1);
-            } else {
-                val = s.indexOf(',') == -1 ? s : s.substring(0, s.indexOf(','));
-                s = s.indexOf(',') == -1 ? "" : s.substring(s.indexOf(',') + 1);
-            }
-            if (s.length() > 0 && s.charAt(0) == ',') s = s.substring(1);
-            s = s.trim();
-            ret.put(key, val);
-        }
-        return ret;
-    }
-
-    private String H(String s) throws IOException {
-        byte[] b = s.getBytes("UTF8");
-        MD5 md5 = new MD5();
-        md5.update(b, 0, b.length);
-        byte[] out = new byte[md5.getDigestSize()];
-        md5.doFinal(out, 0);
-        String ret = "";
-        for(int i=0; i<out.length; i++) {
-            ret += "0123456789abcdef".charAt((out[i] & 0xf0) >> 4);
-            ret += "0123456789abcdef".charAt(out[i] & 0x0f);
-        }
-        return ret;
-    }
-
-
-    // Proxy ///////////////////////////////////////////////////////////
-
-    /** encapsulates most of the proxy logic; some is shared in HTTP.java */
-    public static class Proxy {
-        
-        public String httpProxyHost = null;                  ///< the HTTP Proxy host to use
-        public int httpProxyPort = -1;                       ///< the HTTP Proxy port to use
-        public String httpsProxyHost = null;                 ///< seperate proxy for HTTPS
-        public int httpsProxyPort = -1;
-        public String socksProxyHost = null;                 ///< the SOCKS Proxy Host to use
-        public int socksProxyPort = -1;                      ///< the SOCKS Proxy Port to use
-        public String[] excluded = new String[] { };         ///< hosts to be excluded from proxy use; wildcards permitted
-        public JS proxyAutoConfigFunction = null;  ///< the PAC script
-    
-        public static Proxy detectProxyViaManual() {
-            Proxy ret = new Proxy();
-        
-            ret.httpProxyHost = Platform.getEnv("http_proxy");
-            if (ret.httpProxyHost != null) {
-                if (ret.httpProxyHost.startsWith("http://")) ret.httpProxyHost = ret.httpProxyHost.substring(7);
-                if (ret.httpProxyHost.endsWith("/"))
-                    ret.httpProxyHost = ret.httpProxyHost.substring(0, ret.httpProxyHost.length() - 1);
-                if (ret.httpProxyHost.indexOf(':') != -1) {
-                    ret.httpProxyPort = Integer.parseInt(ret.httpProxyHost.substring(ret.httpProxyHost.indexOf(':') + 1));
-                    ret.httpProxyHost = ret.httpProxyHost.substring(0, ret.httpProxyHost.indexOf(':'));
-                } else {
-                    ret.httpProxyPort = 80;
-                }
-            }
-        
-            ret.httpsProxyHost = Platform.getEnv("https_proxy");
-            if (ret.httpsProxyHost != null) {
-                if (ret.httpsProxyHost.startsWith("https://")) ret.httpsProxyHost = ret.httpsProxyHost.substring(7);
-                if (ret.httpsProxyHost.endsWith("/"))
-                    ret.httpsProxyHost = ret.httpsProxyHost.substring(0, ret.httpsProxyHost.length() - 1);
-                if (ret.httpsProxyHost.indexOf(':') != -1) {
-                    ret.httpsProxyPort = Integer.parseInt(ret.httpsProxyHost.substring(ret.httpsProxyHost.indexOf(':') + 1));
-                    ret.httpsProxyHost = ret.httpsProxyHost.substring(0, ret.httpsProxyHost.indexOf(':'));
-                } else {
-                    ret.httpsProxyPort = 80;
-                }
-            }
-        
-            ret.socksProxyHost = Platform.getEnv("socks_proxy");
-            if (ret.socksProxyHost != null) {
-                if (ret.socksProxyHost.startsWith("socks://")) ret.socksProxyHost = ret.socksProxyHost.substring(7);
-                if (ret.socksProxyHost.endsWith("/"))
-                    ret.socksProxyHost = ret.socksProxyHost.substring(0, ret.socksProxyHost.length() - 1);
-                if (ret.socksProxyHost.indexOf(':') != -1) {
-                    ret.socksProxyPort = Integer.parseInt(ret.socksProxyHost.substring(ret.socksProxyHost.indexOf(':') + 1));
-                    ret.socksProxyHost = ret.socksProxyHost.substring(0, ret.socksProxyHost.indexOf(':'));
-                } else {
-                    ret.socksProxyPort = 80;
-                }
-            }
-        
-            String noproxy = Platform.getEnv("no_proxy");
-            if (noproxy != null) {
-                StringTokenizer st = new StringTokenizer(noproxy, ",");
-                ret.excluded = new String[st.countTokens()];
-                for(int i=0; st.hasMoreTokens(); i++) ret.excluded[i] = st.nextToken();
-            }
-        
-            if (ret.httpProxyHost == null && ret.socksProxyHost == null) return null;
-            return ret;
-        }
-    
-        public static JS proxyAutoConfigRootScope = /*new ProxyAutoConfigRootScope();*/ null; // JS:FIXME: New api
-        public static JS getProxyAutoConfigFunction(String url) {
-            try { 
-                BufferedReader br = new BufferedReader(new InputStreamReader(new HTTP(url, true).GET()));
-                String s = null;
-                String script = "";
-                while((s = br.readLine()) != null) script += s + "\n";
-                if (Log.on) Log.info(Proxy.class, "successfully retrieved WPAD PAC:");
-                if (Log.on) Log.info(Proxy.class, script);
-            
-                // MS CARP hack
-                Vector carpHosts = new Vector();
-                for(int i=0; i<script.length(); i++)
-                    if (script.regionMatches(i, "new Node(", 0, 9)) {
-                        String host = script.substring(i + 10, script.indexOf('\"', i + 11));
-                        if (Log.on) Log.info(Proxy.class, "Detected MS Proxy Server CARP Script, Host=" + host);
-                        carpHosts.addElement(host);
-                    }
-                if (carpHosts.size() > 0) {
-                    script = "function FindProxyForURL(url, host) {\nreturn \"";
-                    for(int i=0; i<carpHosts.size(); i++)
-                        script += "PROXY " + carpHosts.elementAt(i) + "; ";
-                    script += "\";\n}";
-                    if (Log.on) Log.info(Proxy.class, "DeCARPed PAC script:");
-                    if (Log.on) Log.info(Proxy.class, script);
-                }
-
-                JS scr = JS.fromReader("PAC script at " + url, 0, new StringReader(script));
-                JS.cloneWithNewGlobalScope(scr, proxyAutoConfigRootScope).call(null, null, null, null, 0);
-                return (JS)proxyAutoConfigRootScope.get(JS.S("FindProxyForURL"));
-            } catch (Exception e) {
-                if (Log.on) {
-                    Log.info(Platform.class, "WPAD detection failed due to:");
-                    // I have no idea what this was supposed to do
-                    /*if (e instanceof JSExn) {
-                        try {
-                            org.ibex.js.JSArray arr = new org.ibex.js.JSArray();
-                            arr.addElement(((JSExn)e).getObject());
-                        } catch (Exception e2) {
-                            Log.info(Platform.class, e);
-                        }
-                    }*/
-                    Log.info(Platform.class, e);
-                }
-                return null;
-            }
-        }
-
-
-        // Authorization ///////////////////////////////////////////////////////////////////////////////////
-
-        public static class Authorization {
-
-            static public String authorization = null;
-            static public String authorization2 = null;
-            static public Semaphore waitingForUser = new Semaphore();
-
-            public static synchronized void getPassword(final String realm, final String style,
-                                                        final String proxyIP, String oldAuth) throws IOException {
-
-                // this handles cases where multiple threads hit the proxy auth at the same time -- all but one will block on the
-                // synchronized keyword. If 'authorization' changed while the thread was blocked, it means that the user entered
-                // a password, so we should reattempt authorization.
-
-                if (authorization != oldAuth) return;
-                if (Log.on) Log.info(Authorization.class, "displaying proxy authorization dialog");
-                Scheduler.add(new Task() {
-                        public void perform() throws IOException, JSExn {
-                            Box b = new Box();
-                            Template t = null;
-                            // FIXME
-                            //Template.buildTemplate("org/ibex/builtin/proxy_authorization.ibex", Stream.getInputStream((JS)Main.builtin.get("org/ibex/builtin/proxy_authorization.ibex")), new Ibex(null));
-                            t.apply(b);
-                            b.put(JS.S("realm"), JS.S(realm));
-                            b.put(JS.S("proxyIP"), JS.S(proxyIP));
-                        }
-                    });
-
-                waitingForUser.block();
-                if (Log.on) Log.info(Authorization.class, "got proxy authorization info; re-attempting connection");
-            }
-        }
-
-
-        // ProxyAutoConfigRootJSScope ////////////////////////////////////////////////////////////////////
-
-        // FIXME: JS Update for new API
-        /*public static class ProxyAutoConfigRootScope extends JSScope.Global {
-
-            public ProxyAutoConfigRootScope() { super(); }
-        
-            public Object get(Object name) throws JSExn {
-                //#switch(name)
-                case "isPlainHostName": return METHOD;
-                case "dnsDomainIs": return METHOD;
-                case "localHostOrDomainIs": return METHOD;
-                case "isResolvable": return METHOD;
-                case "isInNet": return METHOD;
-                case "dnsResolve": return METHOD;
-                case "myIpAddress": return METHOD;
-                case "dnsDomainLevels": return METHOD;
-                case "shExpMatch": return METHOD;
-                case "weekdayRange": return METHOD;
-                case "dateRange": return METHOD;
-                case "timeRange": return METHOD;
-                case "ProxyConfig": return ProxyConfig;
-                //#end
-                return super.get(name);
-            }
-        
-            private static final JS proxyConfigBindings = new JS.O();
-            private static final JS ProxyConfig = new JS() {
-                    public Object get(Object name) {
-                        if (name.equals("bindings")) return proxyConfigBindings;
-                        return null;
-                    }
-                };
-
-            public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
-                //#switch(method)
-                case "isPlainHostName": return (a0.toString().indexOf('.') == -1) ? Boolean.TRUE : Boolean.FALSE;
-                case "dnsDomainIs": return (a0.toString().endsWith(a1.toString())) ? Boolean.TRUE : Boolean.FALSE;
-                case "localHostOrDomainIs":
-                    return (a0.equals(a1) || (a0.toString().indexOf('.') == -1 && a1.toString().startsWith(a0.toString()))) ? T:F;
-                case "isResolvable": try {
-                    return (InetAddress.getByName(a0.toString()) != null) ? Boolean.TRUE : Boolean.FALSE;
-                } catch (UnknownHostException e) { return F; }
-                case "isInNet":
-                    if (nargs != 3) return Boolean.FALSE;
-                    try {
-                        byte[] host = InetAddress.getByName(a0.toString()).getAddress();
-                        byte[] net = InetAddress.getByName(a1.toString()).getAddress();
-                        byte[] mask = InetAddress.getByName(a2.toString()).getAddress();
-                        return ((host[0] & mask[0]) == net[0] &&
-                                (host[1] & mask[1]) == net[1] &&
-                                (host[2] & mask[2]) == net[2] &&
-                                (host[3] & mask[3]) == net[3]) ?
-                            Boolean.TRUE : Boolean.FALSE;
-                    } catch (Exception e) {
-                        throw new JSExn("exception in isInNet(): " + e);
-                    }
-                case "dnsResolve":
-                    try {
-                        return InetAddress.getByName(a0.toString()).getHostAddress();
-                    } catch (UnknownHostException e) {
-                        return null;
-                    }
-                case "myIpAddress":
-                    try {
-                        return InetAddress.getLocalHost().getHostAddress();
-                    } catch (UnknownHostException e) {
-                        if (Log.on) Log.info(this, "strange... host does not know its own address");
-                        return null;
-                    }
-                case "dnsDomainLevels":
-                    String s = a0.toString();
-                    int i = 0;
-                    while((i = s.indexOf('.', i)) != -1) i++;
-                    return new Integer(i);
-                case "shExpMatch":
-                    StringTokenizer st = new StringTokenizer(a1.toString(), "*", false);
-                    String[] arr = new String[st.countTokens()];
-                    String s = a0.toString();
-                    for (int i=0; st.hasMoreTokens(); i++) arr[i] = st.nextToken();
-                    return match(arr, s, 0) ? Boolean.TRUE : Boolean.FALSE;
-                case "weekdayRange":
-                    TimeZone tz = (nargs < 3 || a2 == null || !a2.equals("GMT")) ?
-                        TimeZone.getTimeZone("UTC") : TimeZone.getDefault();
-                    Calendar c = new GregorianCalendar();
-                    c.setTimeZone(tz);
-                    c.setTime(new java.util.Date());
-                    java.util.Date d = c.getTime();
-                    int day = d.getDay();
-                    String d1s = a0.toString().toUpperCase();
-                    int d1 = 0, d2 = 0;
-                    for(int i=0; i<days.length; i++) if (days[i].equals(d1s)) d1 = i;
-                    
-                    if (nargs == 1)
-                        return d1 == day ? Boolean.TRUE : Boolean.FALSE;
-                    
-                    String d2s = a1.toString().toUpperCase();
-                    for(int i=0; i<days.length; i++) if (days[i].equals(d2s)) d2 = i;
-                    
-                    return ((d1 <= d2 && day >= d1 && day <= d2) || (d1 > d2 && (day >= d1 || day <= d2))) ? T : F;
-                    
-                case "dateRange": throw new JSExn("Ibex does not support dateRange() in PAC scripts");
-                case "timeRange": throw new JSExn("Ibex does not support timeRange() in PAC scripts");
-                //#end
-                return super.callMethod(method, a0, a1, a2, rest, nargs);
-            }       
-            private static boolean match(String[] arr, String s, int index) {
-                if (index >= arr.length) return true;
-                for(int i=0; i<s.length(); i++) {
-                    String s2 = s.substring(i);
-                    if (s2.startsWith(arr[index]) && match(arr, s2.substring(arr[index].length()), index + 1)) return true;
-                }
-                return false;
-            }
-            public static String[] days = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
-        }*/
-
-
-        /**
-         *  An implementation of Microsoft's proprietary NTLM authentication protocol.  This code was derived from Eric
-         *  Glass's work, and is copyright as follows:
-         *
-         *  Copyright (c) 2003 Eric Glass     (eglass1 at comcast.net). 
-         *
-         *  Permission to use, copy, modify, and distribute this document for any purpose and without any fee is hereby
-         *  granted, provided that the above copyright notice and this list of conditions appear in all copies.
-         *  The most current version of this document may be obtained from http://davenport.sourceforge.net/ntlm.html .
-         */ 
-        public static class NTLM {
-            
-            public static final byte[] type1 = new byte[] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01,
-                                                            0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00 };
-            
-            /**
-             * Calculates the NTLM Response for the given challenge, using the
-             * specified password.
-             *
-             * @param password The user's password.
-             * @param challenge The Type 2 challenge from the server.
-             *
-             * @return The NTLM Response.
-             */
-            public static byte[] getNTLMResponse(String password, byte[] challenge)
-                throws UnsupportedEncodingException {
-                byte[] ntlmHash = ntlmHash(password);
-                return lmResponse(ntlmHash, challenge);
-            }
-
-            /**
-             * Calculates the LM Response for the given challenge, using the specified
-             * password.
-             *
-             * @param password The user's password.
-             * @param challenge The Type 2 challenge from the server.
-             *
-             * @return The LM Response.
-             */
-            public static byte[] getLMResponse(String password, byte[] challenge)
-                {
-                byte[] lmHash = lmHash(password);
-                return lmResponse(lmHash, challenge);
-            }
-
-            /**
-             * Calculates the NTLMv2 Response for the given challenge, using the
-             * specified authentication target, username, password, target information
-             * block, and client challenge.
-             *
-             * @param target The authentication target (i.e., domain).
-             * @param user The username. 
-             * @param password The user's password.
-             * @param targetInformation The target information block from the Type 2
-             * message.
-             * @param challenge The Type 2 challenge from the server.
-             * @param clientChallenge The random 8-byte client challenge. 
-             *
-             * @return The NTLMv2 Response.
-             */
-            public static byte[] getNTLMv2Response(String target, String user,
-                                                   String password, byte[] targetInformation, byte[] challenge,
-                                                   byte[] clientChallenge) throws UnsupportedEncodingException {
-                byte[] ntlmv2Hash = ntlmv2Hash(target, user, password);
-                byte[] blob = createBlob(targetInformation, clientChallenge);
-                return lmv2Response(ntlmv2Hash, blob, challenge);
-            }
-
-            /**
-             * Calculates the LMv2 Response for the given challenge, using the
-             * specified authentication target, username, password, and client
-             * challenge.
-             *
-             * @param target The authentication target (i.e., domain).
-             * @param user The username.
-             * @param password The user's password.
-             * @param challenge The Type 2 challenge from the server.
-             * @param clientChallenge The random 8-byte client challenge.
-             *
-             * @return The LMv2 Response. 
-             */
-            public static byte[] getLMv2Response(String target, String user,
-                                                 String password, byte[] challenge, byte[] clientChallenge)
-                throws UnsupportedEncodingException {
-                byte[] ntlmv2Hash = ntlmv2Hash(target, user, password);
-                return lmv2Response(ntlmv2Hash, clientChallenge, challenge);
-            }
-
-            /**
-             * Calculates the NTLM2 Session Response for the given challenge, using the
-             * specified password and client challenge.
-             *
-             * @param password The user's password.
-             * @param challenge The Type 2 challenge from the server.
-             * @param clientChallenge The random 8-byte client challenge.
-             *
-             * @return The NTLM2 Session Response.  This is placed in the NTLM
-             * response field of the Type 3 message; the LM response field contains
-             * the client challenge, null-padded to 24 bytes.
-             */
-            public static byte[] getNTLM2SessionResponse(String password,
-                                                         byte[] challenge, byte[] clientChallenge) throws UnsupportedEncodingException {
-                byte[] ntlmHash = ntlmHash(password);
-                MD5 md5 = new MD5();
-                md5.update(challenge, 0, challenge.length);
-                md5.update(clientChallenge, 0, clientChallenge.length);
-                byte[] sessionHash = new byte[8];
-                byte[] md5_out = new byte[md5.getDigestSize()];
-                md5.doFinal(md5_out, 0);
-                System.arraycopy(md5_out, 0, sessionHash, 0, 8);
-                return lmResponse(ntlmHash, sessionHash);
-            }
-
-            /**
-             * Creates the LM Hash of the user's password.
-             *
-             * @param password The password.
-             *
-             * @return The LM Hash of the given password, used in the calculation
-             * of the LM Response.
-             */
-            private static byte[] lmHash(String password) {
-                /*
-                byte[] oemPassword = password.toUpperCase().getBytes("UTF8");
-                int length = java.lang.Math.min(oemPassword.length, 14);
-                byte[] keyBytes = new byte[14];
-                System.arraycopy(oemPassword, 0, keyBytes, 0, length);
-                Key lowKey = createDESKey(keyBytes, 0);
-                Key highKey = createDESKey(keyBytes, 7);
-                byte[] magicConstant = "KGS!@#$%".getBytes("UTF8");
-                Cipher des = Cipher.getInstance("DES/ECB/NoPadding");
-                des.init(Cipher.ENCRYPT_MODE, lowKey);
-                byte[] lowHash = des.doFinal(magicConstant);
-                des.init(Cipher.ENCRYPT_MODE, highKey);
-                byte[] highHash = des.doFinal(magicConstant);
-                byte[] lmHash = new byte[16];
-                System.arraycopy(lowHash, 0, lmHash, 0, 8);
-                System.arraycopy(highHash, 0, lmHash, 8, 8);
-                return lmHash;
-                */
-                return null;
-            }
-
-            /**
-             * Creates the NTLM Hash of the user's password.
-             *
-             * @param password The password.
-             *
-             * @return The NTLM Hash of the given password, used in the calculation
-             * of the NTLM Response and the NTLMv2 and LMv2 Hashes.
-             */
-            private static byte[] ntlmHash(String password) throws UnsupportedEncodingException {
-                // FIXME
-                /*
-                byte[] unicodePassword = password.getBytes("UnicodeLittleUnmarked");
-                MD4 md4 = new MD4();
-                md4.update(unicodePassword, 0, unicodePassword.length);
-                byte[] ret = new byte[md4.getDigestSize()];
-                return ret;
-                */
-                return null;
-            }
-
-            /**
-             * Creates the NTLMv2 Hash of the user's password.
-             *
-             * @param target The authentication target (i.e., domain).
-             * @param user The username.
-             * @param password The password.
-             *
-             * @return The NTLMv2 Hash, used in the calculation of the NTLMv2
-             * and LMv2 Responses. 
-             */
-            private static byte[] ntlmv2Hash(String target, String user,
-                                             String password) throws UnsupportedEncodingException {
-                byte[] ntlmHash = ntlmHash(password);
-                String identity = user.toUpperCase() + target.toUpperCase();
-                return hmacMD5(identity.getBytes("UnicodeLittleUnmarked"), ntlmHash);
-            }
-
-            /**
-             * Creates the LM Response from the given hash and Type 2 challenge.
-             *
-             * @param hash The LM or NTLM Hash.
-             * @param challenge The server challenge from the Type 2 message.
-             *
-             * @return The response (either LM or NTLM, depending on the provided
-             * hash).
-             */
-            private static byte[] lmResponse(byte[] hash, byte[] challenge)
-                {
-                /*
-                byte[] keyBytes = new byte[21];
-                System.arraycopy(hash, 0, keyBytes, 0, 16);
-                Key lowKey = createDESKey(keyBytes, 0);
-                Key middleKey = createDESKey(keyBytes, 7);
-                Key highKey = createDESKey(keyBytes, 14);
-                Cipher des = Cipher.getInstance("DES/ECB/NoPadding");
-                des.init(Cipher.ENCRYPT_MODE, lowKey);
-                byte[] lowResponse = des.doFinal(challenge);
-                des.init(Cipher.ENCRYPT_MODE, middleKey);
-                byte[] middleResponse = des.doFinal(challenge);
-                des.init(Cipher.ENCRYPT_MODE, highKey);
-                byte[] highResponse = des.doFinal(challenge);
-                byte[] lmResponse = new byte[24];
-                System.arraycopy(lowResponse, 0, lmResponse, 0, 8);
-                System.arraycopy(middleResponse, 0, lmResponse, 8, 8);
-                System.arraycopy(highResponse, 0, lmResponse, 16, 8);
-                return lmResponse;
-                */
-                return null;
-            }
-
-            /**
-             * Creates the LMv2 Response from the given hash, client data, and
-             * Type 2 challenge.
-             *
-             * @param hash The NTLMv2 Hash.
-             * @param clientData The client data (blob or client challenge).
-             * @param challenge The server challenge from the Type 2 message.
-             *
-             * @return The response (either NTLMv2 or LMv2, depending on the
-             * client data).
-             */
-            private static byte[] lmv2Response(byte[] hash, byte[] clientData,
-                                               byte[] challenge) {
-                byte[] data = new byte[challenge.length + clientData.length];
-                System.arraycopy(challenge, 0, data, 0, challenge.length);
-                System.arraycopy(clientData, 0, data, challenge.length,
-                                 clientData.length);
-                byte[] mac = hmacMD5(data, hash);
-                byte[] lmv2Response = new byte[mac.length + clientData.length];
-                System.arraycopy(mac, 0, lmv2Response, 0, mac.length);
-                System.arraycopy(clientData, 0, lmv2Response, mac.length,
-                                 clientData.length);
-                return lmv2Response;
-            }
-
-            /**
-             * Creates the NTLMv2 blob from the given target information block and
-             * client challenge.
-             *
-             * @param targetInformation The target information block from the Type 2
-             * message.
-             * @param clientChallenge The random 8-byte client challenge.
-             *
-             * @return The blob, used in the calculation of the NTLMv2 Response.
-             */
-            private static byte[] createBlob(byte[] targetInformation,
-                                             byte[] clientChallenge) {
-                byte[] blobSignature = new byte[] {
-                    (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00
-                };
-                byte[] reserved = new byte[] {
-                    (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00
-                };
-                byte[] unknown1 = new byte[] {
-                    (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00
-                };
-                byte[] unknown2 = new byte[] {
-                    (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00
-                };
-                long time = System.currentTimeMillis();
-                time += 11644473600000l; // milliseconds from January 1, 1601 -> epoch.
-                time *= 10000; // tenths of a microsecond.
-                // convert to little-endian byte array.
-                byte[] timestamp = new byte[8];
-                for (int i = 0; i < 8; i++) {
-                    timestamp[i] = (byte) time;
-                    time >>>= 8;
-                }
-                byte[] blob = new byte[blobSignature.length + reserved.length +
-                                       timestamp.length + clientChallenge.length +
-                                       unknown1.length + targetInformation.length +
-                                       unknown2.length];
-                int offset = 0;
-                System.arraycopy(blobSignature, 0, blob, offset, blobSignature.length);
-                offset += blobSignature.length;
-                System.arraycopy(reserved, 0, blob, offset, reserved.length);
-                offset += reserved.length;
-                System.arraycopy(timestamp, 0, blob, offset, timestamp.length);
-                offset += timestamp.length;
-                System.arraycopy(clientChallenge, 0, blob, offset,
-                                 clientChallenge.length);
-                offset += clientChallenge.length;
-                System.arraycopy(unknown1, 0, blob, offset, unknown1.length);
-                offset += unknown1.length;
-                System.arraycopy(targetInformation, 0, blob, offset,
-                                 targetInformation.length);
-                offset += targetInformation.length;
-                System.arraycopy(unknown2, 0, blob, offset, unknown2.length);
-                return blob;
-            }
-
-            /**
-             * Calculates the HMAC-MD5 hash of the given data using the specified
-             * hashing key.
-             *
-             * @param data The data for which the hash will be calculated. 
-             * @param key The hashing key.
-             *
-             * @return The HMAC-MD5 hash of the given data.
-             */
-            private static byte[] hmacMD5(byte[] data, byte[] key) {
-                byte[] ipad = new byte[64];
-                byte[] opad = new byte[64];
-                for (int i = 0; i < 64; i++) {
-                    ipad[i] = (byte) 0x36;
-                    opad[i] = (byte) 0x5c;
-                }
-                for (int i = key.length - 1; i >= 0; i--) {
-                    ipad[i] ^= key[i];
-                    opad[i] ^= key[i];
-                }
-                byte[] content = new byte[data.length + 64];
-                System.arraycopy(ipad, 0, content, 0, 64);
-                System.arraycopy(data, 0, content, 64, data.length);
-                MD5 md5 = new MD5();
-                md5.update(content, 0, content.length);
-                data = new byte[md5.getDigestSize()];
-                md5.doFinal(data, 0);
-                content = new byte[data.length + 64];
-                System.arraycopy(opad, 0, content, 0, 64);
-                System.arraycopy(data, 0, content, 64, data.length);
-                md5 = new MD5();
-                md5.update(content, 0, content.length);
-                byte[] ret = new byte[md5.getDigestSize()];
-                md5.doFinal(ret, 0);
-                return ret;
-            }
-
-            /**
-             * Creates a DES encryption key from the given key material.
-             *
-             * @param bytes A byte array containing the DES key material.
-             * @param offset The offset in the given byte array at which
-             * the 7-byte key material starts.
-             *
-             * @return A DES encryption key created from the key material
-             * starting at the specified offset in the given byte array.
-             */
-                /*
-            private static Key createDESKey(byte[] bytes, int offset) {
-                byte[] keyBytes = new byte[7];
-                System.arraycopy(bytes, offset, keyBytes, 0, 7);
-                byte[] material = new byte[8];
-                material[0] = keyBytes[0];
-                material[1] = (byte) (keyBytes[0] << 7 | (keyBytes[1] & 0xff) >>> 1);
-                material[2] = (byte) (keyBytes[1] << 6 | (keyBytes[2] & 0xff) >>> 2);
-                material[3] = (byte) (keyBytes[2] << 5 | (keyBytes[3] & 0xff) >>> 3);
-                material[4] = (byte) (keyBytes[3] << 4 | (keyBytes[4] & 0xff) >>> 4);
-                material[5] = (byte) (keyBytes[4] << 3 | (keyBytes[5] & 0xff) >>> 5);
-                material[6] = (byte) (keyBytes[5] << 2 | (keyBytes[6] & 0xff) >>> 6);
-                material[7] = (byte) (keyBytes[6] << 1);
-                oddParity(material);
-                return new SecretKeySpec(material, "DES");
-            }
-                */
-
-            /**
-             * Applies odd parity to the given byte array.
-             *
-             * @param bytes The data whose parity bits are to be adjusted for
-             * odd parity.
-             */
-            private static void oddParity(byte[] bytes) {
-                for (int i = 0; i < bytes.length; i++) {
-                    byte b = bytes[i];
-                    boolean needsParity = (((b >>> 7) ^ (b >>> 6) ^ (b >>> 5) ^
-                                            (b >>> 4) ^ (b >>> 3) ^ (b >>> 2) ^
-                                            (b >>> 1)) & 0x01) == 0;
-                    if (needsParity) {
-                        bytes[i] |= (byte) 0x01;
-                    } else {
-                        bytes[i] &= (byte) 0xfe;
-                    }
-                }
-            }
-
-        }
-    }
-}
diff --git a/src/org/ibex/net/SOAP.java b/src/org/ibex/net/SOAP.java
deleted file mode 100644 (file)
index d54ebce..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.net;
-
-import java.io.*;
-import java.util.*;
-import org.ibex.js.*;
-import org.ibex.util.*;
-import org.ibex.crypto.*;
-
-/**
- *  A partial RPC-style SOAP 1.1 client. Implemented from the SOAP 1.1
- *  Spec and Dave Winer's "SOAP for Busy Developers". This class
- *  extends XMLRPC in order to share some networking logic.
- *
- *  Currently unsupported features/hacks:
- *  <ul><li> Multi-ref data and circular references
- *      <li> 'Document Style'
- *      <li> WSDL support
- *  </ul>
- */
-public class SOAP extends XMLRPC {
-
-    /** the desired content of the SOAPAction header */
-    String action = null;
-
-    /** the namespace to use */
-    String nameSpace = null;
-
-    /** When you get a property from an SOAP, it just returns another SOAP with the property name tacked onto methodname. */
-    public Object get(Object name) {
-        return new SOAP(url, (method.equals("") ? "" : method + ".") + name.toString(), this, action, nameSpace); }
-
-
-    // Methods to Recieve and parse SOAP Responses ////////////////////////////////////////////////////
-
-    public void startElement(String name, String[] keys, Object[] vals, int line, int col) {
-
-        content.reset();
-        if (name.equals("SOAP-ENV:Envelope")) return;
-        if (name.equals("SOAP-ENV:Body")) return;
-        if (name.equals("SOAP-ENV:Fault")) fault = true;
-        // add a generic struct; we'll change this if our type is different
-        objects.addElement(new JS.O());
-
-        for(int i=0; i<keys.length; i++) {
-            String key = keys[i];
-            String value = vals[i].toString();
-            if (key.endsWith("ype")) {
-                if (value.endsWith("boolean")) {
-                    objects.removeElementAt(objects.size() - 1);
-                    objects.addElement(Boolean.FALSE);
-                } else if (value.endsWith("int")) {
-                    objects.removeElementAt(objects.size() - 1);
-                    objects.addElement(new Integer(0));
-                } else if (value.endsWith("double")) {
-                    objects.removeElementAt(objects.size() - 1);
-                    objects.addElement(new Double(0.0));
-                } else if (value.endsWith("string")) {
-                    objects.removeElementAt(objects.size() - 1);
-                    objects.addElement("");
-                } else if (value.endsWith("base64")) {
-                    objects.removeElementAt(objects.size() - 1);
-                    objects.addElement(new byte[] { });
-                } else if (value.endsWith("null")) {
-                    objects.removeElementAt(objects.size() - 1);
-                    objects.addElement(null);
-                } else if (value.endsWith("arrayType") || value.endsWith("JSArray") || key.endsWith("arrayType")) {
-                    objects.removeElementAt(objects.size() - 1);
-                    objects.addElement(new JSArray());
-                }
-            }
-        }
-    }
-
-    public void endElement(String name, int line, int col) {
-
-        if (name.equals("SOAP-ENV:Envelope")) return;
-        if (name.equals("SOAP-ENV:Body")) return;
-
-        if (content.size() > 0 && content.toString().trim().length() > 0) {
-
-            // remove ourselves
-            Object me = objects.elementAt(objects.size() - 1);
-
-            if (fault || me instanceof String) {
-                objects.removeElementAt(objects.size() - 1);
-                objects.addElement(new String(content.getBuf(), 0, content.size()).intern());
-                content.reset();
-
-            } else if (me instanceof byte[]) {
-                objects.removeElementAt(objects.size() - 1);
-                objects.addElement(new Stream.ByteArray(Base64.decode(new String(content.getBuf(), 0, content.size())), null));
-                content.reset();                
-
-            } else if (me instanceof Integer) {
-                objects.removeElementAt(objects.size() - 1);
-                objects.addElement(new Integer(new String(content.getBuf(), 0, content.size())));
-                content.reset();
-                
-            } else if (me instanceof Boolean) {
-                objects.removeElementAt(objects.size() - 1);
-                String s = new String(content.getBuf(), 0, content.size()).trim();
-                if (s.equals("1") || s.equals("true")) objects.addElement(Boolean.TRUE);
-                else objects.addElement(Boolean.FALSE);
-                content.reset();
-                
-            } else if (me instanceof Double) {
-                objects.removeElementAt(objects.size() - 1);
-                objects.addElement(new Double(new String(content.getBuf(), 0, content.size())));
-                content.reset();
-                
-            } else {
-                // okay, we got PCDATA for what is supposedly a
-                // struct... somebody's not adding their type info...
-                String s = new String(content.getBuf(), 0, content.size()).trim();
-                boolean hasdot = false;
-                for(int i=0; i<s.length(); i++) {
-                    if (s.charAt(i) == '.') hasdot = true;
-                    if (!Character.isDigit(s.charAt(i))) {
-                        objects.removeElementAt(objects.size() - 1);
-                        objects.addElement(s);
-                        return;
-                    }
-                }
-                if (hasdot) {
-                    objects.removeElementAt(objects.size() - 1);
-                    objects.addElement(new Double(s));
-                } else {
-                    objects.removeElementAt(objects.size() - 1);
-                    objects.addElement(new Integer(s));
-                }
-                content.reset();
-            }
-
-        }
-        
-        // remove ourselves
-        JS me = (JS) objects.elementAt(objects.size() - 1);
-
-        // find our parent
-        Object parent = objects.size() > 1 ? objects.elementAt(objects.size() - 2) : null;
-
-        // we want to fold stuff back into the fault object
-        if (objects.size() < 2) return;
-
-        // our parent "should" be an aggregate type -- add ourselves to it.
-        // FIXME: Can we get away without JSArray being public?
-        /*if (parent != null && parent instanceof JSArray) {
-            objects.removeElementAt(objects.size() - 1);
-            ((JSArray)parent).addElement(me);
-
-        } else */ if (parent != null && parent instanceof JS) {
-            objects.removeElementAt(objects.size() - 1);
-            try {
-                ((JS)parent).put(JS.S(name), me);
-            } catch (JSExn e) {
-                throw new Error("this should never happen");
-            }
-
-        }
-
-    }
-
-    /** Appends the SOAP representation of <code>o</code> to <code>sb</code> */
-    void appendObject(String name, JS o, StringBuffer sb) throws JSExn {
-        // JS:FIXME: Update for new api
-        /*
-        if (o instanceof Number) {
-            if ((double)((Number)o).intValue() == ((Number)o).doubleValue()) {
-                sb.append("                <" + name + " xsi:type=\"xsd:int\">");
-                sb.append(((Number)o).intValue());
-                sb.append("</" + name + ">\r\n");
-            } else {
-                sb.append("                <" + name + " xsi:type=\"xsd:double\">");
-                sb.append(o);
-                sb.append("</" + name + ">\r\n");
-            }
-
-        } else if (o instanceof Boolean) {
-            sb.append("                <" + name + " xsi:type=\"xsd:boolean\">");
-            sb.append(((Boolean)o).booleanValue() ? "true" : "false");
-            sb.append("</" + name + ">\r\n");
-
-        } else if (o instanceof Stream) {
-            try {
-                sb.append("                <" + name + " xsi:type=\"SOAP-ENC:base64\">\r\n");
-                InputStream is = ((Stream)o).getInputStream();
-                byte[] buf = new byte[54];
-                while(true) {
-                    int numread = is.read(buf, 0, 54);
-                    if (numread == -1) break;
-                    byte[] writebuf = buf;
-                    if (numread < buf.length) {
-                        writebuf = new byte[numread];
-                        System.arraycopy(buf, 0, writebuf, 0, numread);
-                    }
-                    sb.append("              ");
-                    sb.append(new String(Base64.encode(writebuf)));
-                    sb.append("\r\n");
-                }
-                sb.append(((Boolean)o).booleanValue() ? "1" : "0");
-                sb.append("</" + name + ">\r\n");
-            } catch (IOException e) {
-                if (Log.on) Log.info(this, "caught IOException while attempting to send a ByteStream via SOAP");
-                if (Log.on) Log.info(this, e);
-                throw new JSExn("caught IOException while attempting to send a ByteStream via SOAP");
-            }
-
-        } else if (o instanceof String) {
-            sb.append("                <" + name + " xsi:type=\"xsd:string\">");
-            String s = (String)o;
-            if (s.indexOf('<') == -1 && s.indexOf('&') == -1) {
-                sb.append(s);
-            } else {
-                char[] cbuf = s.toCharArray();
-                while(true) {
-                    int oldi = 0, i=0;
-                    while(i < cbuf.length && cbuf[i] != '<' && cbuf[i] != '&') i++;
-                    sb.append(cbuf, oldi, i);
-                    if (i == cbuf.length) break;
-                    if (cbuf[i] == '<') sb.append("&lt;");
-                    else if (cbuf[i] == '&') sb.append("&amp;");
-                    i = oldi = i + 1;
-                }
-            }
-            sb.append("</" + name + ">\r\n");
-
-        } else if (o instanceof JSArray) {
-            JSArray a = (JSArray)o;
-            sb.append("                <" + name + " SOAP-ENC:arrayType=\"xsd:ur-type[" + a.length() + "]\">");
-            for(int i=0; i<a.length(); i++) appendObject("item", a.elementAt(i), sb);
-            sb.append("</" + name + ">\r\n");
-
-        } else if (o instanceof JS) {
-            JS j = (JS)o;
-            sb.append("                <" + name + ">");
-            Enumeration e = j.keys();
-            while(e.hasMoreElements()) {
-                Object key = e.nextElement();
-                appendObject((String)key, j.get(key), sb);
-            }
-            sb.append("</" + name + ">\r\n");
-
-        }*/
-    }
-
-    protected String buildRequest(JS[] args) throws JSExn, IOException {
-        // build up the request
-        StringBuffer content = new StringBuffer();
-        content.append("SOAPAction: " + action + "\r\n\r\n");
-        content.append("<?xml version=\"1.0\"?>\r\n");
-        content.append("<SOAP-ENV:Envelope SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"\r\n");
-        content.append("                   xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\r\n");
-        content.append("                   xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\r\n");
-        content.append("                   xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\r\n");
-        content.append("                   xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\">\r\n");
-        content.append("<SOAP-ENV:Body>\r\n");
-        content.append("    <");
-        content.append(method);
-        content.append(nameSpace != null ? " xmlns=\"" + nameSpace + "\"" : "");
-        content.append(">\r\n");
-        if (args.length > 0) {
-            Enumeration e = args[0].keys();
-            while(e.hasMoreElements()) {
-                JS key = e.nextElement();
-                appendObject(JS.toString(key), args[0].get(key), content);
-            }
-        }
-        content.append("    </" + method + "></SOAP-ENV:Body></SOAP-ENV:Envelope>\r\n");
-        return content.toString();
-    }
-
-    public SOAP(String url, String methodname, String action, String nameSpace) {
-        super(url, methodname);
-        this.action = action;
-        this.nameSpace = nameSpace;
-    }
-    public SOAP(String url, String methodname, SOAP httpSource, String action, String nameSpace) {
-        super(url, methodname, httpSource);
-        this.action = action;
-        this.nameSpace = nameSpace;
-    }
-
-}
diff --git a/src/org/ibex/net/XMLRPC.java b/src/org/ibex/net/XMLRPC.java
deleted file mode 100644 (file)
index 72a2c76..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.net;
-
-import java.io.*;
-import java.util.*;
-import org.ibex.js.*;
-import org.ibex.util.*;
-import org.ibex.crypto.*;
-
-/**
- *  An XML-RPC client implemented as a JavaScript Host Object. See the
- *  Ibex spec for information on its behavior.
- *
- *  NOTE: this client is EXTREMELY lenient in the responses it will
- *  accept; there are many, many invalid responses that it will
- *  successfully parse and return. Do NOT use this to determine the
- *  validity of your server.
- *
- *  This client conforms to <a href="http://www.xmlrpc.com/spec">The
- *  XML-RPC Spec</a>, subject to these limitations:
- *  <ol>
- *    <li> XMLRPC cannot invoke methods that require a <base64/> argument
- *    <li> if a return value contains a <base64/>, it will be returned as a string
- *    <li> The decision to pass a number as <i4/> or <double/> is based
- *         entirely on whether or not the argument is fractional. Thus, it
- *         is impossible to pass a non-fractional number to an xmlrpc
- *         method that insists on being called with a <double/> element. We
- *         hope that most xml-rpc servers will be able to automatically
- *         convert.
- *  </ol>
- */
-public class XMLRPC extends JS {
-
-    public XMLRPC(String url, String method) {
-        this.http = url.startsWith("stdio:") ? HTTP.stdio : new HTTP(url);
-        this.url = url;
-        this.method = method;
-    }
-    public XMLRPC(String url, String method, XMLRPC httpSource) {
-        this.http = httpSource.http; this.url = url; this.method = method; }
-    public Object get(Object name) {
-        return new XMLRPC(url, (method.equals("") ? "" : method + ".") + name.toString(), this); }
-
-
-    /** this holds character content as we read it in -- since there is only one per instance, we don't support mixed content */
-    protected AccessibleCharArrayWriter content = new AccessibleCharArrayWriter(100);
-    protected String url = null;         ///< the url to connect to
-    protected String method = null;      ///< the method name to invoke on the remove server
-    protected HTTP http = null;          ///< the HTTP connection to use
-    private Hash tracker;                ///< used to detect multi-ref data
-    protected boolean fault = false;     ///< True iff the return value is a fault (and should be thrown as an exception)
-
-
-    /** The object stack. As we process xml elements, pieces of the
-     *  return value are pushed onto and popped off of this stack.
-     *
-     *  The general protocol is that any time a &lt;value&gt; tag is
-     *  encountered, an empty String ("") is pushed onto the stack. If
-     *  the &lt;value/&gt; node has content (either an anonymous
-     *  string or some other XML node), that content replaces the
-     *  empty string.
-     *
-     *  If an &lt;array&gt; tag is encountered, a null is pushed onto the
-     *  stack. When a &lt;/data&gt; is encountered, we search back on the
-     *  stack to the last null, replace it with a NativeJSArray, and
-     *  insert into it all elements above it on the stack.
-     *
-     *  If a &lt;struct&gt; tag is encountered, a JSect is pushed
-     *  onto the stack. If a &lt;name&gt; tag is encountered, its CDATA is
-     *  pushed onto the stack. When a &lt;/member&gt; is encountered, the
-     *  name (second element on stack) and value (top of stack) are
-     *  popped off the stack and inserted into the struct (third
-     *  element on stack).
-     */
-    protected Vec objects = null;
-
-
-    // Recieve ////////////////////////////////////////////////////////////////
-
-    private class Helper extends XML {
-        public Helper() { super(BUFFER_SIZE); }
-
-        public void startElement(XML.Element c) {
-            content.reset();
-            //#switch(c.getLocalName())
-            case "fault": fault = true;
-            case "struct": objects.setElementAt(new JS.O(), objects.size() - 1);
-            case "array": objects.setElementAt(null, objects.size() - 1);
-            case "value": objects.addElement("");
-            //#end
-        }
-        
-        public void endElement(XML.Element c) {
-            //#switch(c.getLocalName())
-            case "int": objects.setElementAt(JS.N(Integer.parseInt(new String(content.getBuf(), 0, content.size()))), objects.size() - 1);
-            case "i4": objects.setElementAt(JS.N(Integer.parseInt(new String(content.getBuf(), 0, content.size()))), objects.size() - 1);
-            case "boolean": objects.setElementAt(content.getBuf()[0] == '1' ? JS.T : JS.F, objects.size() - 1);
-            case "string": objects.setElementAt(JS.S(new String(content.getBuf(), 0, content.size())), objects.size() - 1);
-            case "double": objects.setElementAt(JS.N(Double.parseDouble(new String(content.getBuf(), 0, content.size()))), objects.size() - 1);
-            case "base64":
-                objects.setElementAt(new Stream.ByteArray(Base64.decode(new String(content.getBuf(), 0, content.size())),
-                                                          null), objects.size() - 1);
-            case "name": objects.addElement(JS.S(new String(content.getBuf(), 0, content.size())));
-            case "value": if ("".equals(objects.lastElement()))
-                objects.setElementAt(JS.S(new String(content.getBuf(), 0, content.size())), objects.size() - 1);
-            case "dateTime.iso8601":
-                String s = new String(content.getBuf(), 0, content.size());
-                
-                // strip whitespace
-                int i=0;
-                while(Character.isWhitespace(s.charAt(i))) i++;
-                if (i > 0) s = s.substring(i);
-                
-                try {
-                    JSDate nd = new JSDate();
-                    double date = JSDate.date_msecFromDate(Double.valueOf(s.substring(0, 4)).doubleValue(),
-                                                           Double.valueOf(s.substring(4, 6)).doubleValue() - 1,
-                                                           Double.valueOf(s.substring(6, 8)).doubleValue(),
-                                                           Double.valueOf(s.substring(9, 11)).doubleValue(),
-                                                           Double.valueOf(s.substring(12, 14)).doubleValue(),
-                                                           Double.valueOf(s.substring(15, 17)).doubleValue(),
-                                                           (double)0
-                                                           );
-                    nd.setTime(JSDate.internalUTC(date));
-                    objects.setElementAt(nd, objects.size() - 1);
-                    
-                } catch (Exception e) {
-                    throw new RuntimeException("ibex.net.rpc.xml.recieve.malformedDateTag" +
-                                    "the server sent a <dateTime.iso8601> tag which was malformed: " + s);
-                }
-            case "member":
-                JS memberValue = (JS) objects.elementAt(objects.size() - 1);
-                String memberName = (String)objects.elementAt(objects.size() - 2);
-                JS struct = (JS)objects.elementAt(objects.size() - 3);
-                try {
-                    struct.put(JS.S(memberName), memberValue);
-                } catch (JSExn e) {
-                    throw new Error("this should never happen");
-                }
-                objects.setSize(objects.size() - 2);
-            case "data":
-                int i;
-                for(i=objects.size() - 1; objects.elementAt(i) != null; i--);
-                JS arr = new JSArray();
-                try {
-                    for(int j = i + 1; j<objects.size(); j++) arr.put(JS.N(j - i - 1), (JS)objects.elementAt(j));
-                } catch (JSExn e) {
-                    throw new Error("this should never happen");
-                }
-                objects.setElementAt(arr, i);
-                objects.setSize(i + 1);
-            //#end            
-            content.reset();
-        }
-        
-        public void characters(char[] ch, int start, int length) {
-            try { content.write(ch, start, length); }
-            catch (Exception e) { 
-                if (Log.on) Log.info(this, "Exception in XMLRPC.content() -- this should never happen");
-                if (Log.on) Log.info(this, e);
-            }
-        }
-        
-        public void whitespace(char[] ch, int start, int length) {}
-    }
-
-    // Send ///////////////////////////////////////////////////////////////////////////
-
-    protected String buildRequest(JS[] args) throws JSExn, IOException {
-        StringBuffer content = new StringBuffer();
-        content.append("\r\n");
-        content.append("<?xml version=\"1.0\"?>\n");
-        content.append("    <methodCall>\n");
-        content.append("        <methodName>");
-        content.append(method);
-        content.append("</methodName>\n");
-        content.append("        <params>\n");
-        for(int i=0; i<args.length; i++) {
-            content.append("            <param>\n");
-            appendObject(args[i], content);
-            content.append("            </param>\n");
-        }
-        content.append("        </params>\n");
-        content.append("    </methodCall>");
-        return content.toString();
-    }
-
-    /** Appends the XML-RPC representation of <code>o</code> to <code>sb</code> */
-    void appendObject(JS o, StringBuffer sb) throws JSExn {
-        // JS:FIXME: Update for new api
-        throw new Error("FIXME");
-        /*if (o == null) {
-            throw new JSExn("attempted to send a null value via XML-RPC");
-
-        } else if (o instanceof Number) {
-            if ((double)((Number)o).intValue() == ((Number)o).doubleValue()) {
-                sb.append("                <value><i4>");
-                sb.append(((Number)o).intValue());
-                sb.append("</i4></value>\n");
-            } else {
-                sb.append("                <value><double>");
-                sb.append(o);
-                sb.append("</double></value>\n");
-            }
-
-        } else if (o instanceof Boolean) {
-            sb.append("                <value><boolean>");
-            sb.append(((Boolean)o).booleanValue() ? "1" : "0");
-            sb.append("</boolean></value>\n");
-
-        } else if (o instanceof Stream) {
-            try {
-                sb.append("                <value><base64>\n");
-                InputStream is = ((Stream)o).getInputStream();
-                byte[] buf = new byte[54];
-                while(true) {
-                    int numread = is.read(buf, 0, 54);
-                    if (numread == -1) break;
-                    byte[] writebuf = buf;
-                    if (numread < buf.length) {
-                        writebuf = new byte[numread];
-                        System.arraycopy(buf, 0, writebuf, 0, numread);
-                    }
-                    sb.append("              ");
-                    sb.append(new String(Base64.encode(writebuf)));
-                    sb.append("\n");
-                }
-                sb.append("\n              </base64></value>\n");
-            } catch (IOException e) {
-                if (Log.on) Log.info(this, "caught IOException while attempting to send a ByteStream via XML-RPC");
-                if (Log.on) Log.info(this, e);
-                throw new JSExn("caught IOException while attempting to send a ByteStream via XML-RPC");
-            }
-
-        } else if (o instanceof String) {
-            sb.append("                <value><string>");
-            String s = (String)o;
-            if (s.indexOf('<') == -1 && s.indexOf('&') == -1) {
-                sb.append(s);
-            } else {
-                char[] cbuf = s.toCharArray();
-                int oldi = 0, i=0;
-                while(true) {
-                    while(i < cbuf.length && cbuf[i] != '<' && cbuf[i] != '&') i++;
-                    sb.append(cbuf, oldi, i - oldi);
-                    if (i >= cbuf.length) break;
-                    if (cbuf[i] == '<') sb.append("&lt;");
-                    else if (cbuf[i] == '&') sb.append("&amp;");
-                    i = oldi = i + 1;
-                    if (i >= cbuf.length) break;
-                }
-            }
-            sb.append("</string></value>\n");
-
-        } else if (o instanceof JSDate) {
-            sb.append("                <value><dateTime.iso8601>");
-            java.util.Date d = new java.util.Date(((JSDate)o).getRawTime());
-            sb.append(d.getYear() + 1900);
-            if (d.getMonth() + 1 < 10) sb.append('0');
-            sb.append(d.getMonth() + 1);
-            if (d.getDate() < 10) sb.append('0');
-            sb.append(d.getDate());
-            sb.append('T');
-            if (d.getHours() < 10) sb.append('0');
-            sb.append(d.getHours());
-            sb.append(':');
-            if (d.getMinutes() < 10) sb.append('0');
-            sb.append(d.getMinutes());
-            sb.append(':');
-            if (d.getSeconds() < 10) sb.append('0');
-            sb.append(d.getSeconds());
-            sb.append("</dateTime.iso8601></value>\n");
-
-        } else if (o instanceof JSArray) {
-            if (tracker.get(o) != null) throw new JSExn("attempted to send multi-ref data structure via XML-RPC");
-            tracker.put(o, Boolean.TRUE);
-            sb.append("                <value><array><data>\n");
-            JSArray a = (JSArray)o;
-            for(int i=0; i<a.length(); i++) appendObject(a.elementAt(i), sb);
-            sb.append("                </data></array></value>\n");
-
-        } else if (o instanceof JS) {
-            if (tracker.get(o) != null) throw new JSExn("attempted to send multi-ref data structure via XML-RPC");
-            tracker.put(o, Boolean.TRUE);
-            JS j = (JS)o;
-            sb.append("                <value><struct>\n");
-            Enumeration e = j.keys();
-            while(e.hasMoreElements()) {
-                Object key = e.nextElement();
-                sb.append("                <member><name>" + key + "</name>\n");
-                appendObject(j.get(key), sb);
-                sb.append("                </member>\n");
-            }
-            sb.append("                </struct></value>\n");
-
-        } else {
-            throw new JSExn("attempt to send object of type " + o.getClass().getName() + " via XML-RPC");
-
-        }*/
-    }
-
-
-    // Call Sequence //////////////////////////////////////////////////////////////////////////
-
-    public final JS call(JS a0, JS a1, JS a2, JS[] rest, int nargs) throws JSExn {
-        final JS[] args = new JS[nargs];
-        for(int i=0;i<nargs;i++) args[i]= i==0?a0:i==1?a1:i==2?a2:rest[i-3];
-        try {
-            final JS.UnpauseCallback callback = JS.pause();
-            new java.lang.Thread() { public void run() { call(callback,args); }  }.start();
-            return null; // doesn't matter since we paused
-        } catch (NotPauseableException npe) {
-            throw new JSExn("cannot invoke an XML-RPC call in the foreground thread");
-        }
-    }
-
-    final void call(final JS.UnpauseCallback callback, JS[] args) {
-        try {
-            if (Log.rpc) Log.info(this, "call to " + url + " : " + method);
-            if (tracker == null) tracker = new Hash();
-            if (objects == null) objects = new Vec();
-            String request = buildRequest(args);
-            if (Log.rpc) Log.info(this, "send:\n" + request);
-            InputStream is = http.POST("text/xml", request);
-            BufferedReader br = new BufferedReader(new InputStreamReader(is));
-            try {
-                new Helper().parse(br);
-                final JSExn exn = fault ? new JSExn(objects.elementAt(0).toString()) : null;
-                final JS result = fault ? null : objects.size() == 0 ? null : (JS) objects.elementAt(0);
-                Scheduler.add(new Task() { public void perform() throws JSExn { if(fault) callback.unpause(exn); else callback.unpause(result); }});
-            } finally {
-                tracker.clear();
-                objects.setSize(0);
-            }
-        } catch (final JSExn e) {
-            Scheduler.add(new Task() { public void perform() throws JSExn { callback.unpause(e); }});
-        } catch (final IOException e) {
-            final Exception e2 = e;
-            Scheduler.add(new Task() { public void perform() throws JSExn { callback.unpause(new JSExn(e2.toString())); }});
-        } catch (final XML.Exn e) {
-            final Exception e2 = e;
-            Scheduler.add(new Task() { public void perform() throws JSExn { callback.unpause(new JSExn(e2.toString())); }});
-        }
-    }
-}
index 3a4ec12..2735182 100644 (file)
@@ -96,7 +96,7 @@ public class Darwin extends POSIX {
     
     protected Scheduler _getScheduler() { return new DarwinScheduler(); }
     protected native void runApplicationEventLoop();
     
     protected Scheduler _getScheduler() { return new DarwinScheduler(); }
     protected native void runApplicationEventLoop();
-    private class DarwinScheduler extends org.ibex.util.Scheduler {
+    private class DarwinScheduler extends org.ibex.core.Scheduler {
         public void run() {
             new Thread() { public void run() { defaultRun(); } }.start();
             runApplicationEventLoop();
         public void run() {
             new Thread() { public void run() { defaultRun(); } }.start();
             runApplicationEventLoop();
index 959ba5d..5e5ebb3 100644 (file)
@@ -8,7 +8,7 @@ import org.ibex.net.*;
 /** Linux with an X11 display */
 public class Linux extends X11 {
 
 /** Linux with an X11 display */
 public class Linux extends X11 {
 
-    public static void main(String[] args) throws Exception { org.ibex.Main.main(args); }
+    public static void main(String[] args) throws Exception { org.ibex.core.Main.main(args); }
     private native void fixEnvironment();
 
     public Linux() {
     private native void fixEnvironment();
 
     public Linux() {
index e4ef29a..586b675 100644 (file)
@@ -85,7 +85,8 @@ public class Win32 extends GCJ {
 
         HTTP.Proxy ret = new HTTP.Proxy();
         if (container[2] != null) {
 
         HTTP.Proxy ret = new HTTP.Proxy();
         if (container[2] != null) {
-            ret.proxyAutoConfigFunction = HTTP.Proxy.getProxyAutoConfigFunction(container[2]);
+           // FIXME!!!
+            //ret.proxyAutoConfigFunction = HTTP.Proxy.getProxyAutoConfigFunction(container[2]);
             if (ret.proxyAutoConfigFunction != null) return ret;
         }
 
             if (ret.proxyAutoConfigFunction != null) return ret;
         }
 
@@ -259,7 +260,7 @@ public class Win32 extends GCJ {
             ((Win32Picture)source).init();
             drawPicture(source, dx, dy, cx1, cy1, cx2, cy2, 0, false);
         }
             ((Win32Picture)source).init();
             drawPicture(source, dx, dy, cx1, cy1, cx2, cy2, 0, false);
         }
-        public void drawGlyph(org.ibex.Font.Glyph source, int dx, int dy, int cx1, int cy1, int cx2, int cy2, int rgb) {
+        public void drawGlyph(org.ibex.graphics.Font.Glyph source, int dx, int dy, int cx1, int cy1, int cx2, int cy2, int rgb) {
             Win32Picture p = ((Win32Picture)((Platform.DefaultGlyph)source).getPicture());
             p.init();
             drawPicture(p, dx, dy, cx1, cy1, cx2, cy2, rgb, true);
             Win32Picture p = ((Win32Picture)((Platform.DefaultGlyph)source).getPicture());
             p.init();
             drawPicture(p, dx, dy, cx1, cy1, cx2, cy2, rgb, true);
diff --git a/src/org/ibex/util/AccessibleCharArrayWriter.java b/src/org/ibex/util/AccessibleCharArrayWriter.java
deleted file mode 100644 (file)
index 62e436a..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.ibex.util;
-
-import java.io.*;
-
-public class AccessibleCharArrayWriter extends CharArrayWriter {
-    public char[] getBuf() { return buf; }
-    public AccessibleCharArrayWriter(int i) { super(i); }
-}
-
diff --git a/src/org/ibex/util/BalancedTree.java b/src/org/ibex/util/BalancedTree.java
deleted file mode 100644 (file)
index dd993a0..0000000
+++ /dev/null
@@ -1,433 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-// FEATURE: private void intersection() { }
-// FEATURE: private void union() { }
-// FEATURE: private void subset() { }
-// FEATURE: grow if we run out of slots
-
-// FEATURE: Add the cached_index stuff back in 
-
-/** a weight-balanced tree with fake leaves */
-public class BalancedTree {
-    // Instance Variables ///////////////////////////////////////////////////////////////////
-
-    private int root = 0;                         ///< the slot of the root element
-
-    private int cached_index = -1;
-    private int cached_slot = -1;
-    
-    // Public API //////////////////////////////////////////////////////////////////////////
-
-    /** the number of elements in the tree */
-    public final int treeSize() {
-        synchronized(BalancedTree.class) {
-            return root == 0 ? 0 : size[root];
-        }
-    }
-
-    /** clamps index to [0..treeSize()] and inserts object o *before* the specified index */
-    public final void insertNode(int index, Object o) {
-        synchronized(BalancedTree.class) {
-        if(o == null) throw new Error("can't insert nulls in the balanced tree");
-        cached_slot = cached_index = -1;
-        if (index < 0) index = 0;
-        if (index > treeSize()) index = treeSize();
-        int arg = allocateSlot(o);
-        if (root != 0) {
-            insert(index, arg, root, 0, false, false);
-        } else {
-            root = arg;
-            left[arg] = right[arg] = parent[arg] = 0;
-            size[arg] = 1;
-        }
-        }
-    }
-
-    /** clamps index to [0..treeSize()-1] and replaces the object at that index with object o */
-    public final void replaceNode(int index, Object o) {
-        synchronized(BalancedTree.class) {
-        if(o == null) throw new Error("can't insert nulls in the balanced tree");
-        cached_slot = cached_index = -1;
-        if(root == 0) throw new Error("called replaceNode() on an empty tree");
-        if (index < 0) index = 0;
-        if (index >= treeSize()) index = treeSize() - 1;
-        int arg = allocateSlot(o);
-        insert(index, arg, root, 0, true, false);
-        }
-    }
-
-    /** returns the index of o; runs in O((log n)^2) time unless cache hit */
-    public final int indexNode(Object o) { 
-        synchronized(BalancedTree.class) {
-        if(o == null) return -1;
-        if (cached_slot != -1 && objects[cached_slot] == o) return cached_index;
-
-        int slot = getSlot(o);
-        if(slot == -1) return -1;
-        
-        int index = 0;
-        while(true) {
-            // everything to the left is before us so add that to the index
-            index += sizeof(left[slot]);
-            // we are before anything on the right
-            while(left[parent[slot]] == slot) slot = parent[slot];
-            // we end of the first node who isn't on the left, go to the node that has as its child
-            slot = parent[slot];
-            // if we just processed the root we're done
-            if(slot == 0) break;
-            // count the node we're currently on towards the index
-            index++;
-        }
-        return index;
-        }
-    }
-
-    /** returns the object at index; runs in O(log n) time unless cache hit */
-    public final Object getNode(int index) {
-        synchronized(BalancedTree.class) {
-        if (index == cached_index) return objects[cached_slot];
-
-        if (cached_index != -1) {
-            int distance = Math.abs(index - cached_index);
-            // if the in-order distance between the cached node and the
-            // target node is less than log(n), it's probably faster to
-            // search directly.
-            if ((distance < 16) && ((2 << distance) < treeSize())) {
-                while(cached_index > index) { cached_slot = prev(cached_slot); cached_index--; }
-                while(cached_index < index) { cached_slot = next(cached_slot); cached_index++; }
-                return objects[cached_slot];
-            }
-        }
-        /*
-        cached_index = index;
-        cached_slot = get(index, root);
-        return objects[cached_slot];
-        */
-        return objects[get(index, root)];
-        }
-    }
-
-    /** deletes the object at index, returning the deleted object */
-    public final Object deleteNode(int index) {
-        synchronized(BalancedTree.class) {
-        cached_slot = cached_index = -1;
-        // FIXME: left[], right[], size[], and parent[] aren't getting cleared properly somewhere in here where a node had two children
-        int del = delete(index, root, 0);
-        left[del] = right[del] = size[del] = parent[del] = 0;
-        Object ret = objects[del];
-        objects[del] = null;
-        return ret;
-        }
-    }
-    
-    public final void clear() {
-        synchronized(BalancedTree.class) {
-        if(root == 0) return;
-        int i = leftmost(root);
-        do {
-            int next = next(i);
-            objects[i] = null;
-            left[i] = right[i] = size[i] = parent[i] = 0;
-            i = next;
-        } while(i != 0);
-        root = 0;
-        }
-    }
-
-    // Node Data /////////////////////////////////////////////////////////////////////////
-
-    private final static int NUM_SLOTS = 64 * 1024;
-    // FEATURE: GROW - private final static int MAX_SLOT_DISTANCE = 32;
-
-    /**
-     * Every object inserted into *any* tree gets a "slot" in this
-     * array.  The slot is determined by hashcode modulo the length of
-     * the array, with quadradic probing to resolve collisions.  NOTE
-     * that the "slot" of a node is NOT the same as its index.
-     * Furthermore, if an object is inserted into multiple trees, that
-     * object will have multiple slots.
-     */
-    private static Object[] objects = new Object[NUM_SLOTS];
-
-    /// These two arrays hold the left and right children of each
-    /// slot; in other words, left[x] is the *slot* of the left child
-    /// of the node in slot x.
-    ///
-    /// If x has no left child, then left[x] is -1 multiplied by the
-    /// slot of the node that precedes x; if x is the first node, then
-    /// left[x] is 0.  The right[] array works the same way.
-    ///
-    private static int[] left = new int[NUM_SLOTS];
-    private static int[] right = new int[NUM_SLOTS];
-    
-    /// The parent of this node (0 if it is the root node)
-    private static int[] parent = new int[NUM_SLOTS];
-
-    ///< the number of descendants of this node *including the node itself*
-    private static int[] size = new int[NUM_SLOTS];
-
-
-    // Slot Management //////////////////////////////////////////////////////////////////////
-    
-    /** if alloc == false returns the slot holding object o. if alloc is true returns a new slot for obejct o */
-    private int getSlot(Object o, boolean alloc) {
-        // we XOR with our own hashcode so that we don't get tons of
-        // collisions when a single Object is inserted into multiple
-        // trees
-        int dest = Math.abs(o.hashCode() ^ this.hashCode()) % objects.length;
-        Object search = alloc ? null : o;
-        int odest = dest;
-        boolean plus = true;
-        int tries = 1;
-        if(dest == 0) dest=1;
-        while (objects[dest] != search || !(alloc || root(dest) == root)) {
-            dest = Math.abs((odest + (plus ? 1 : -1) * tries * tries) % objects.length);
-            if (dest == 0) dest=1;
-            if (plus) tries++;
-            plus = !plus;
-            // FEATURE: GROW - if(tries > MAX_SLOT_DISTANCE) return -1;
-        }
-        return dest;
-    }
-
-    /** returns the slots holding object o */
-    private int getSlot(Object o) { return getSlot(o,false); }
-    
-    /** allocates a new slot holding object o*/
-    private int allocateSlot(Object o) {
-        int slot = getSlot(o, true);
-        // FEATURE: GROW - if(slot == -1) throw new Error("out of slots");
-        objects[slot] = o;
-        return slot;
-    }
-
-
-
-    // Helpers /////////////////////////////////////////////////////////////////////////
-
-    // FEATURE: These might be faster if they aren't recursive
-    private final int leftmost(int slot) { return left[slot] <= 0 ? slot : leftmost(left[slot]); }
-    private final int rightmost(int slot) { return right[slot] <= 0 ? slot : rightmost(right[slot]); }
-    private final int sizeof(int slot) { return slot <= 0 ? 0 : size[slot]; }
-    private final int root(int slot) { return parent[slot] == 0 ? slot : root(parent[slot]); }
-
-    private int next(int node) {
-        if(right[node] > 0) {
-            node = right[node];
-            while(left[node] > 0) node = left[node];
-            return node;
-        } else {
-            int p = parent[node];
-            while(right[p] == node) { node = p; p = parent[node]; };
-            return p;
-        }
-    }
-    
-    private int prev(int node) {
-        if(left[node] > 0) {
-            node = left[node];
-            while(right[node] > 0) node = right[node];
-            return node;
-        } else {
-            int p = parent[node];
-            while(left[p] == node) { node = p; p = parent[node]; }
-            return p;
-        }
-    }
-
-    // Rotation and Balancing /////////////////////////////////////////////////////////////
-
-    //      p                  p
-    //      |                  |
-    //      b                  d 
-    //     / \                / \
-    //    a   d    < == >    b   e
-    //       / \            / \
-    //      c   e          a   c
-    // FIXME might be doing too much work here
-    private void rotate(boolean toTheLeft, int b, int p) {
-        int[] left = toTheLeft ? BalancedTree.left : BalancedTree.right;
-        int[] right = toTheLeft ? BalancedTree.right : BalancedTree.left;
-        int d = right[b];
-        int c = left[d];
-        if (d == 0) throw new Error("rotation error");
-        left[d] = b;
-        right[b] = c;
-        
-        parent[b] = d;
-        parent[d] = p;
-        if(c != 0) parent[c] = b;
-        
-        if (p == 0)              root = d;
-        else if (left[p] == b)   left[p] = d;
-        else if (right[p] == b)  right[p] = d;
-        else throw new Error("rotate called with invalid parent");
-        size[b] = 1 + sizeof(left[b]) + sizeof(right[b]);
-        size[d] = 1 + sizeof(left[d]) + sizeof(right[d]);        
-    }
-
-    private void balance(int slot, int p) {
-        if (slot <= 0) return;
-        size[slot] = 1 + sizeof(left[slot]) + sizeof(right[slot]);
-        if (sizeof(left[slot]) - 1 > 2 * sizeof(right[slot])) rotate(false, slot, p);
-        else if (sizeof(left[slot]) * 2 < sizeof(right[slot]) - 1) rotate(true, slot, p);
-    }
-
-
-
-    // Insert /////////////////////////////////////////////////////////////////////////
-
-    private void insert(int index, int arg, int slot, int p, boolean replace, boolean wentLeft) {
-        int diff = slot == 0 ? 0 : index - sizeof(left[slot]);
-        if (slot != 0 && diff != 0) {
-            if (diff < 0) insert(index, arg, left[slot], slot, replace, true);
-            else insert(index - sizeof(left[slot]) - 1, arg, right[slot], slot, replace, false);
-            balance(slot, p);
-            return;
-        }
-
-        if (size[arg] != 0) throw new Error("double insertion");
-
-        // we are replacing an existing node
-        if (replace) {
-            if (diff != 0) throw new Error("this should never happen"); // since we already clamped the index
-            if (p == 0)                 root = arg;
-            else if (left[p] == slot)   left[p] = arg;
-            else if (right[p] == slot)  right[p] = arg;
-            else throw new Error("should never happen");
-            left[arg] = left[slot];
-            right[arg] = right[slot];
-            size[arg] = size[slot];
-            parent[arg] = parent[slot];
-            if(left[slot] != 0) parent[left[slot]] = arg;
-            if(right[slot] != 0) parent[right[slot]] = arg;
-            objects[slot] = null;
-            left[slot] = right[slot] = size[slot] = parent[slot] = 0;
-            
-        // we become the child of a former leaf
-        } else if (slot == 0) {
-            int[] left = wentLeft ? BalancedTree.left : BalancedTree.right;
-            int[] right = wentLeft ? BalancedTree.right : BalancedTree.left;
-            // FEATURE: Might be doing too much work here
-            left[arg] = slot;
-            right[arg] = 0;
-            parent[arg] = p;
-            left[p] = arg;
-            balance(arg, p);
-
-        // we take the place of a preexisting node
-        } else {
-            left[arg] = left[slot];   // steal slot's left subtree
-            left[slot] = 0;
-            right[arg] = slot;        // make slot our right subtree
-            parent[arg] = parent[slot];
-            parent[slot] = arg;
-            if(left[arg] != 0) parent[left[arg]] = arg;
-            if (slot == root) {
-                root = arg;
-                balance(slot, arg);
-                balance(arg, 0);
-            } else {
-                if (left[p] == slot)        left[p] = arg;
-                else if (right[p] == slot)  right[p] = arg;
-                else throw new Error("should never happen");
-                balance(slot, arg);
-                balance(arg, p);
-            }
-        }
-    }
-
-
-    // Retrieval //////////////////////////////////////////////////////////////////////
-
-    private int get(int index, int slot) {
-        int diff = index - sizeof(left[slot]);
-        if (diff > 0) return get(diff - 1, right[slot]);
-        else if (diff < 0) return get(index, left[slot]);
-        else return slot;
-    }
-
-
-    // Deletion //////////////////////////////////////////////////////////////////////
-
-    private int delete(int index, int slot, int p) {
-        int diff = index - sizeof(left[slot]);
-        if (diff < 0) {
-            int ret = delete(index, left[slot], slot);
-            balance(slot, p);
-            return ret;
-
-        } else if (diff > 0) {
-            int ret = delete(diff - 1, right[slot], slot);
-            balance(slot, p);
-            return ret;
-
-        // we found the node to delete
-        } else {
-
-            // fast path: it has no children
-            if (left[slot] == 0 && right[slot] == 0) {
-                if (p == 0) root = 0;
-                else {
-                    int[] side = left[p] == slot ? left : right;
-                    side[p] = side[slot];      // fix parent's pointer
-                }
-                
-            // fast path: it has no left child, so we replace it with its right child
-            } else if (left[slot] == 0) {
-                if (p == 0) root = right[slot];
-                else (left[p] == slot ? left : right)[p] = right[slot];     // fix parent's pointer
-                parent[right[slot]] = p;
-                left[leftmost(right[slot])] = left[slot];                             // fix our successor-leaf's fake right ptr
-                balance(right[slot], p);
-
-            // fast path; it has no right child, so we replace it with its left child
-            } else if (right[slot] == 0) {
-                if (p == 0) root = left[slot];
-                else (left[p] == slot ? left : right)[p] = left[slot];      // fix parent's pointer
-                parent[left[slot]] = p;
-                right[rightmost(left[slot])] = right[slot];                           // fix our successor-leaf's fake right ptr
-                balance(left[slot], p);
-
-            // node to be deleted has two children, so we replace it with its left child's rightmost descendant
-            } else {
-                int left_childs_rightmost = delete(sizeof(left[slot]) - 1, left[slot], slot);
-                left[left_childs_rightmost] = left[slot];
-                right[left_childs_rightmost] = right[slot];
-                if(left[slot] != 0) parent[left[slot]] = left_childs_rightmost;
-                if(right[slot] != 0) parent[right[slot]] = left_childs_rightmost;
-                parent[left_childs_rightmost] = parent[slot];
-                if (p == 0) root = left_childs_rightmost;
-                else (left[p] == slot ? left : right)[p] = left_childs_rightmost;     // fix parent's pointer
-                balance(left_childs_rightmost, p);
-            }
-
-            return slot;
-        }
-    }
-
-    protected void finalize() { clear(); }
-
-    public void printTree() {
-        if(root == 0) System.err.println("Tree is empty");
-        else printTree(root,0,false);
-    }
-    
-    private void printTree(int node,int indent,boolean l) {
-        for(int i=0;i<indent;i++) System.err.print("   ");
-        if(node == 0) System.err.println("None");
-        else {
-            System.err.print("" + node + ": " + objects[node]);
-            System.err.println(" Parent: " + parent[node] + " Size: " + size[node]);
-            printTree(left[node],indent+1,true);
-            printTree(right[node],indent+1,false);
-        }
-    }
-}
diff --git a/src/org/ibex/util/CAB.java b/src/org/ibex/util/CAB.java
deleted file mode 100644 (file)
index a8d7e0b..0000000
+++ /dev/null
@@ -1,501 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-import java.io.*;
-import java.util.*;
-import java.util.zip.*;
-
-/** Reads a CAB file structure */
-public class CAB {
-
-    /** reads a CAB file, parses it, and returns an InputStream representing the named file */
-    public static InputStream getFileInputStream(InputStream is, String fileName) throws IOException, EOFException {
-      return getFileInputStream(is, 0, fileName);
-    }
-
-    public static InputStream getFileInputStream(InputStream is, int skipHeaders, String fileName) throws IOException, EOFException {
-        DataInputStream dis = new DataInputStream(is);
-        CFHEADER h = new CFHEADER();
-
-        while (skipHeaders > 0) { CFHEADER.seekMSCF(dis); skipHeaders--; }
-
-        try {
-         h.read(dis);
-        } catch (CFHEADER.BogusHeaderException bhe) {
-         throw new EOFException();
-        }
-
-        for(int i=0; i<h.folders.length; i++) {
-            CFFOLDER f = new CFFOLDER(h);
-            try {
-               f.read(dis);
-            } catch (CFFOLDER.UnsupportedCompressionTypeException ucte) {
-               throw ucte;
-            }
-        }
-
-        for(int i=0; i<h.files.length; i++) {
-            CFFILE f = new CFFILE(h);
-            f.read(dis);
-        }
-        
-        for(int i=0; i<h.folders.length; i++) {
-            InputStream is2 = new CFFOLDERInputStream(h.folders[i], dis);
-            for(int j=0; j<h.folders[i].files.size(); j++) {
-                CFFILE file = (CFFILE)h.folders[i].files.elementAt(j);
-                if (file.fileName.equals(fileName)) return new LimitStream(is2, file.fileSize);
-                byte[] b = new byte[file.fileSize];
-            }
-        }
-
-        return null;
-    }
-
-    private static class LimitStream extends FilterInputStream {
-        int limit;
-        public LimitStream(InputStream is, int limit) {
-            super(is);
-            this.limit = limit;
-        }
-        public int read() throws IOException {
-            if (limit == 0) return -1;
-            int ret = super.read();
-            if (ret != -1) limit--;
-            return ret;
-        }
-        public int read(byte[] b, int off, int len) throws IOException {
-            if (len > limit) len = limit;
-            if (limit == 0) return -1;
-            int ret = super.read(b, off, len);
-            limit -= ret;
-            return ret;
-        }
-    }
-    
-    /** Encapsulates a CFHEADER entry */
-    public static class CFHEADER {
-        byte[]   reserved1 = new byte[4];       // reserved
-        int      fileSize = 0;                  // size of this cabinet file in bytes
-        byte[]   reserved2 = new byte[4];       // reserved
-        int      offsetOfFirstCFFILEEntry;      // offset of the first CFFILE entry
-        byte[]   reserved3 = new byte[4];       // reserved
-        byte     versionMinor = 3;              // cabinet file format version, minor
-        byte     versionMajor = 1;              // cabinet file format version, major
-        boolean  prevCAB = false;               // true iff there is a cabinet before this one in a sequence
-        boolean  nextCAB = false;               // true iff there is a cabinet after this one in a sequence
-        boolean  hasReserved = false;           // true iff the cab has per-{cabinet, folder, block} reserved areas
-        int      setID = 0;                     // must be the same for all cabinets in a set
-        int      indexInCabinetSet = 0;         // number of this cabinet file in a set
-        byte     perCFFOLDERReservedSize = 0;   // (optional) size of per-folder reserved area
-        byte     perDatablockReservedSize = 0;  // (optional) size of per-datablock reserved area
-        byte[]   perCabinetReservedArea = null; // per-cabinet reserved area
-        String   previousCabinet = null;        // name of previous cabinet file in a set
-        String   previousDisk = null;           // name of previous disk in a set
-        String   nextCabinet = null;            // name of next cabinet in a set
-        String   nextDisk = null;               // name of next disk in a set
-
-        CFFOLDER[] folders = new CFFOLDER[0];
-        CFFILE[] files = new CFFILE[0];
-
-        int readCFFOLDERs = 0;                    // the number of folders read in so far
-        int readCFFILEs = 0;                      // the number of folders read in so far
-
-        public void print(PrintStream ps) {
-            ps.println("CAB CFFILE CFHEADER v" + ((int)versionMajor) + "." + ((int)versionMinor));
-            ps.println("    total file size               = " + fileSize);
-            ps.println("    offset of first file          = " + offsetOfFirstCFFILEEntry);
-            ps.println("    total folders                 = " + folders.length);
-            ps.println("    total files                   = " + files.length);
-            ps.println("    flags                         = 0x" +
-                       Integer.toString((prevCAB ? 0x1 : 0x0) |
-                                        (nextCAB ? 0x2 : 0x0) |
-                                        (hasReserved ? 0x4 : 0x0), 16) + " [ " +
-                       (prevCAB ? "prev " : "") + 
-                       (nextCAB ? "next " : "") + 
-                       (hasReserved ? "reserve_present " : "") + "]");
-            ps.println("    set id                        = " + setID);
-            ps.println("    index in set                  = " + indexInCabinetSet);
-            ps.println("    header reserved area #1       =" +
-                       " 0x" + Integer.toString(reserved1[0], 16) +
-                       " 0x" + Integer.toString(reserved1[1], 16) +
-                       " 0x" + Integer.toString(reserved1[2], 16) +
-                       " 0x" + Integer.toString(reserved1[3], 16));
-            ps.println("    header reserved area #2       =" +
-                       " 0x" + Integer.toString(reserved2[0], 16) +
-                       " 0x" + Integer.toString(reserved2[1], 16) +
-                       " 0x" + Integer.toString(reserved2[2], 16) +
-                       " 0x" + Integer.toString(reserved2[3], 16));
-            ps.println("    header reserved area #3       =" +
-                       " 0x" + Integer.toString(reserved3[0], 16) +
-                       " 0x" + Integer.toString(reserved3[1], 16) +
-                       " 0x" + Integer.toString(reserved3[2], 16) +
-                       " 0x" + Integer.toString(reserved3[3], 16));
-            if (hasReserved) {
-                if (perCabinetReservedArea != null) {
-                    ps.print("    per-cabinet reserved area     = ");
-                    for(int i=0; i<perCabinetReservedArea.length; i++)
-                        ps.print(((perCabinetReservedArea[i] & 0xff) < 16 ? "0" : "") +
-                                 Integer.toString(perCabinetReservedArea[i] & 0xff, 16) + " ");
-                    ps.println();
-                }
-                ps.println("    per folder  reserved area     = " + perCFFOLDERReservedSize + " bytes");
-                ps.println("    per block   reserved area     = " + perDatablockReservedSize + " bytes");
-            }
-        }
-
-        public String toString() {
-            return
-                "[ CAB CFFILE CFHEADER v" +
-                ((int)versionMajor) + "." + ((int)versionMinor) + ", " +
-                fileSize + " bytes, " +
-                folders.length + " folders, " +
-                files.length + " files] ";
-        }
-
-        /** fills in all fields in the header and positions the stream at the first folder */
-        public void read(DataInputStream dis) throws IOException, BogusHeaderException {
-            seekMSCF(dis);
-            dis.readFully(reserved1);
-
-            byte[] headerHashable = new byte[28];
-            dis.readFully(headerHashable);
-            DataInputStream hhis = new DataInputStream(new ByteArrayInputStream(headerHashable));
-
-            fileSize = readLittleInt(hhis);
-            hhis.readFully(reserved2);
-            offsetOfFirstCFFILEEntry = readLittleInt(hhis);
-            hhis.readFully(reserved3);
-            versionMinor = hhis.readByte();
-            versionMajor = hhis.readByte();
-            folders = new CFFOLDER[readLittleShort(hhis)];
-            files = new CFFILE[readLittleShort(hhis)];
-            int flags = readLittleShort(hhis);
-            prevCAB = (flags & 0x0001) != 0;
-            nextCAB = (flags & 0x0002) != 0;
-            hasReserved = (flags & 0x0004) != 0;
-            setID = readLittleShort(hhis);
-            indexInCabinetSet = readLittleShort(hhis);
-
-            if (offsetOfFirstCFFILEEntry < 0 || fileSize < 0) {
-               throw new BogusHeaderException();
-            }
-
-            if (hasReserved) {
-                perCabinetReservedArea = new byte[readLittleShort(dis)];
-                perCFFOLDERReservedSize = dis.readByte();
-                perDatablockReservedSize = dis.readByte();
-                if (perCabinetReservedArea.length > 0)
-                    dis.readFully(perCabinetReservedArea);
-            }
-
-            try {
-               if (prevCAB) {
-                   previousCabinet = readZeroTerminatedString(dis);
-                   previousDisk = readZeroTerminatedString(dis);
-               }
-               if (nextCAB) {
-                   nextCabinet = readZeroTerminatedString(dis);
-                   nextDisk = readZeroTerminatedString(dis);
-               }
-            } catch (ArrayIndexOutOfBoundsException e) {
-               throw new BogusHeaderException();
-            }
-        }
-
-        public static void seekMSCF(DataInputStream dis) throws EOFException, IOException
-        {
-           int state;
-           // skip up to and including the 'MSCF' signature
-           state = 0;
-           while (state != 4) {
-              // M
-              while (state == 0 && dis.readByte() != 0x4D) { }
-              state = 1;
-              // S
-              switch (dis.readByte()) {
-                 case 0x53 : state = 2; break;
-                 case 0x4D : state = 1; continue;
-                 default :   state = 0; continue;
-              }
-              // C
-              if (dis.readByte() == 0x43) { state = 3; }
-              else { state = 0; continue; }
-              // F
-              if (dis.readByte() == 0x46) { state = 4; }
-              else { state = 0; }
-           }
-        }
-
-        public static class BogusHeaderException extends IOException {}
-    }
-
-    /** Encapsulates a CFFOLDER entry */
-    public static class CFFOLDER {
-        public static final int COMPRESSION_NONE      = 0;
-        public static final int COMPRESSION_MSZIP     = 1;
-        public static final int COMPRESSION_QUANTUM   = 2;
-        public static final int COMPRESSION_LZX       = 3;
-
-        int      firstBlockOffset = 0;          // offset of first data block within this folder
-        int      numBlocks = 0;                 // number of data blocks
-        int      compressionType = 0;           // compression type for this folder
-        byte[]   reservedArea = null;           // per-folder reserved area
-        int      indexInCFHEADER = 0;           // our index in CFHEADER.folders
-        Vector   files = new Vector();
-
-        private CFHEADER header = null;
-
-        public CFFOLDER(CFHEADER header) { this.header = header; }
-
-        public String toString() {
-            return "[ CAB CFFOLDER, " + numBlocks + " data blocks, compression type " +
-                compressionName(compressionType) +
-                ", " + reservedArea.length + " bytes of reserved data ]";
-        }
-
-        public void read(DataInputStream dis) throws IOException, UnsupportedCompressionTypeException {
-            firstBlockOffset = readLittleInt(dis);
-            numBlocks = readLittleShort(dis);
-            compressionType = readLittleShort(dis) & 0x000F;
-            if (compressionType != COMPRESSION_MSZIP) {
-               throw new UnsupportedCompressionTypeException(compressionType);
-            }
-            reservedArea = new byte[header.perCFFOLDERReservedSize];
-            if (reservedArea.length > 0) dis.readFully(reservedArea);
-            indexInCFHEADER = header.readCFFOLDERs++;
-            header.folders[indexInCFHEADER] = this;
-        }
-
-        public static String compressionName(int type) {
-            switch (type) {
-               case COMPRESSION_NONE:
-                  return "NONE";
-               case COMPRESSION_MSZIP:
-                  return "MSZIP";
-               case COMPRESSION_QUANTUM:
-                  return "QUANTUM";
-               case COMPRESSION_LZX:
-                  return "LZX";
-               default:
-                  return "<Unknown type " + type + ">";
-            }
-        }
-
-        public static class UnsupportedCompressionTypeException extends IOException {
-            private int compressionType;
-
-            UnsupportedCompressionTypeException(int type) {
-               compressionType = type;
-            }
-            public String toString() {
-               return "UnsupportedCompressionTypeException: no support for compression type " + compressionName(compressionType);
-            }
-        }
-    }
-
-    /** Encapsulates a CFFILE entry */
-    public static class CFFILE {
-        int fileSize = 0;                       // size of this file
-        int uncompressedOffsetInCFFOLDER = 0;   // offset of this file within the folder, not accounting for compression
-        int folderIndex = 0;                    // index of the CFFOLDER we belong to
-        Date date = null;                       // modification date
-        int attrs = 0;                          // attrs
-        boolean readOnly = false;               // read-only flag
-        boolean hidden = false;                 // hidden flag
-        boolean system = false;                 // system flag
-        boolean arch = false;                   // archive flag
-        boolean runAfterExec = false;           // true if file should be run during extraction
-        boolean UTFfileName = false;            // true if filename is UTF-encoded
-        String fileName = null;                 // filename
-        int indexInCFHEADER = 0;                // our index in CFHEADER.files
-        CFFOLDER folder = null;                 // the folder we belong to
-        private CFHEADER header = null;
-        File myFile;
-
-        public CFFILE(CFHEADER header) { this.header = header; }
-
-        public CFFILE(File f, String pathName) throws IOException {
-            fileSize = (int)f.length();
-            folderIndex = 0;
-            date = new java.util.Date(f.lastModified());
-            fileName = pathName;
-            myFile = f;
-        }
-
-        public String toString() {
-            return "[ CAB CFFILE: " + fileName + ", " + fileSize + " bytes [ " +
-                (readOnly ? "readonly " : "") +
-                (system ? "system " : "") +
-                (hidden ? "hidden " : "") +
-                (arch ? "arch " : "") +
-                (runAfterExec ? "run_after_exec " : "") +
-                (UTFfileName ? "UTF_filename " : "") +
-                "]";
-        }
-
-        public void read(DataInputStream dis) throws IOException {
-            fileSize = readLittleInt(dis);
-            uncompressedOffsetInCFFOLDER = readLittleInt(dis);
-            folderIndex = readLittleShort(dis);
-            readLittleShort(dis);   // date
-            readLittleShort(dis);   // time
-            attrs = readLittleShort(dis);
-            readOnly = (attrs & 0x1) != 0;
-            hidden = (attrs & 0x2) != 0;
-            system = (attrs & 0x4) != 0;
-            arch = (attrs & 0x20) != 0;
-            runAfterExec = (attrs & 0x40) != 0;
-            UTFfileName = (attrs & 0x80) != 0;
-            fileName = readZeroTerminatedString(dis);
-
-            indexInCFHEADER = header.readCFFILEs++;
-            header.files[indexInCFHEADER] = this;
-            folder = header.folders[folderIndex];
-            folder.files.addElement(this);
-        }
-    }
-
-
-
-
-    // Compressing Input and Output Streams ///////////////////////////////////////////////
-
-    /** an InputStream that decodes CFDATA blocks belonging to a CFFOLDER */
-    private static class CFFOLDERInputStream extends InputStream {
-        CFFOLDER folder;
-        DataInputStream dis;
-        InputStream iis = null;
-
-        byte[] compressed = new byte[128 * 1024];
-        byte[] uncompressed = new byte[256 * 1024];
-
-        public CFFOLDERInputStream(CFFOLDER f, DataInputStream dis) {
-            this.folder = f;
-            this.dis = dis;
-        }
-
-        InputStream readBlock() throws IOException {
-            int compressedBytes = readLittleShort(dis);
-            int unCompressedBytes = readLittleShort(dis);
-            byte[] reserved = new byte[/*folder.header.perDatablockReservedSize*/0];
-            if (reserved.length > 0) dis.readFully(reserved);
-            if (dis.readByte() != 0x43) throw new CABException("malformed block header");
-            if (dis.readByte() != 0x4B) throw new CABException("malformed block header");
-
-            dis.readFully(compressed, 0, compressedBytes - 2);
-
-            Inflater i = new Inflater(true);
-            i.setInput(compressed, 0, compressedBytes - 2);
-            
-            if (unCompressedBytes > uncompressed.length) uncompressed = new byte[unCompressedBytes];
-            try { i.inflate(uncompressed, 0, uncompressed.length);
-            } catch (DataFormatException dfe) {
-                dfe.printStackTrace();
-                throw new CABException(dfe.toString());
-            }
-            return new ByteArrayInputStream(uncompressed, 0, unCompressedBytes);
-        }
-
-        public int available() throws IOException { return iis == null ? 0 : iis.available(); }
-        public void close() throws IOException { iis.close(); }
-        public void mark(int i) { }
-        public boolean markSupported() { return false; }
-        public void reset() { }
-
-        public long skip(long l) throws IOException {
-            if (iis == null) iis = readBlock();
-            int ret = 0;
-            while (l > ret) {
-                long numread = iis.skip(l - ret);
-                if (numread == 0 || numread == -1) iis = readBlock();
-                else ret += numread;
-            }
-            return ret;
-        }
-        
-        public int read(byte[] b, int off, int len) throws IOException {
-            if (iis == null) iis = readBlock();
-            int ret = 0;
-            while (len > ret) {
-                int numread = iis.read(b, off + ret, len - ret);
-                if (numread == 0 || numread == -1) iis = readBlock();
-                else ret += numread;
-            }
-            return ret;
-        }
-
-        public int read() throws IOException {
-            if (iis == null) iis = readBlock();
-            int ret = iis.read();
-            if (ret == -1) {
-                iis = readBlock();
-                ret = iis.read();
-            }
-            return ret;
-        }
-    }
-
-
-
-    // Misc Stuff //////////////////////////////////////////////////////////////
-
-    public static String readZeroTerminatedString(DataInputStream dis) throws IOException {
-        int numBytes = 0;
-        byte[] b = new byte[256];
-        while(true) {
-            byte next = dis.readByte();
-            if (next == 0x0) return new String(b, 0, numBytes);
-            b[numBytes++] = next;
-        }
-    }
-    
-    public static int readLittleInt(DataInputStream dis) throws IOException {
-        int lowest = (int)(dis.readByte() & 0xff);
-        int low = (int)(dis.readByte() & 0xff);
-        int high = (int)(dis.readByte() & 0xff);
-        int highest = (int)(dis.readByte() & 0xff);
-        return (highest << 24) | (high << 16) | (low << 8) | lowest;
-    }
-
-    public static int readLittleShort(DataInputStream dis) throws IOException {
-        int low = (int)(dis.readByte() & 0xff);
-        int high = (int)(dis.readByte() & 0xff);
-        return (high << 8) | low;
-    }
-
-    public static class CABException extends IOException {
-        public CABException(String s) { super(s); }
-    }
-
-
-    /** scratch space for isToByteArray() */
-    static byte[] workspace = new byte[16 * 1024];
-
-    /** Trivial method to completely read an InputStream */
-    public static synchronized byte[] isToByteArray(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/org/ibex/util/Cache.java b/src/org/ibex/util/Cache.java
deleted file mode 100644 (file)
index af88c88..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-/*
-
-Bug report from a user:
-
-I looked at your Cache.java and tried to make good use of it, but I was
-out of luck - it wouldn't run here. Digging deeper into the code, I came
-across something that might be considered a bug. But maybe it's just a
-feature :-)
-
-
-Starting with an empty cache, Cache.put() immediately followed by
-Cache.get() on same keys / same object will set Node lru back to null in
-Node.remove() which is called in get().
-
-Assuming this put()-get() sequence is fixed, it will fill the cache, but
-lru will remain null.
-
-When cache is filled 100%, we have, at the end of the get(), where
-size>maxSize is checked, a state that mru == lru == n (from
-if(lru==null) thus deleteting the newly inserted object. Oops.
-
-
-Hope I made this clear enough. Maybe it's not a problem in xwt due to a
-different usage scheme of the cache.
-
-
-
-*/
-
-package org.ibex.util;
-
-// FIXME needs to be a weak hash
-
-/**
- *  A Hash table with a fixed size; drops extraneous elements.  Uses
- *  LRU strategy.
- */
-public class Cache extends Hash {
-
-    /** head of list is the mru; tail is the lru */
-    Node mru = null;
-    Node lru = null;
-
-    private int maxSize;
-    private Cache() { }
-    public Cache(int maxSize) {
-        super(maxSize * 2, 3);
-        this.maxSize = maxSize;
-    }
-
-    /** A doubly-linked list */
-    private class Node {
-        final Object val;
-        final Object k1;
-        final Object k2;
-        public Node(Object k1, Object k2, Object val) { this.k1 = k1; this.k2 = k2; this.val = val; }
-        Node next = null;
-        Node prev = null;
-        void remove() {
-            if (this == lru) lru = prev;
-            if (this == mru) mru = next;
-            if (next != null) next.prev = prev;
-            if (prev != null) prev.next = next;
-            next = prev = null;
-        }
-        void placeAfter(Node n) {
-            remove();
-            if (n == null) return;
-            next = n.next;
-            if (n.next != null) n.next.prev = this;
-            n.next = this;
-            prev = n;
-        }
-        void placeBefore(Node n) {
-            remove();
-            if (n == null) return;
-            next = n;
-            prev = n.prev;
-            n.prev = this;
-            if (prev != null) prev.next = this;
-        }
-    }
-
-    public void clear() {
-        lru = null;
-        super.clear();
-    }
-
-    public void remove(Object k1, Object k2) {
-        Object o = super.get(k1, k2);
-        if (o != null) ((Node)o).remove();
-        super.remove(k1, k2);
-    }
-
-    public Object get(Object k1, Object k2) {
-        Node n = (Node)super.get(k1, k2);
-        if (n == null) return null;
-        n.remove();
-        n.placeBefore(mru);
-        mru = n;
-        return n.val;
-    }
-
-    public void put(Object k1, Object k2, Object v) {
-        Node n = new Node(k1, k2, v);
-        if (lru == null) {
-            lru = mru = n;
-        } else {
-            n.placeBefore(mru);
-            mru = n;
-        }
-        if (super.get(k1, k2) != null) remove(k1, k2);
-        super.put(k1, k2, n);
-        if (size > maxSize) remove(lru.k1, lru.k2);
-    }
-
-}
-
-
diff --git a/src/org/ibex/util/CachedInputStream.java b/src/org/ibex/util/CachedInputStream.java
deleted file mode 100644 (file)
index a712f84..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-import java.io.*;
-
-// FEATURE: don't use a byte[] if we have a diskCache file
-/**
- *  Wraps around an InputStream, caching the stream in a byte[] as it
- *  is read and permitting multiple simultaneous readers
- */
-public class CachedInputStream {
-
-    boolean filling = false;               ///< true iff some thread is blocked on us waiting for input
-    boolean eof = false;                   ///< true iff end of stream has been reached
-    byte[] cache = new byte[1024 * 128];
-    int size = 0;
-    final InputStream is;
-    File diskCache;
-
-    public CachedInputStream(InputStream is) { this(is, null); }
-    public CachedInputStream(InputStream is, File diskCache) {
-        this.is = is;
-        this.diskCache = diskCache;
-    }
-    public InputStream getInputStream() throws IOException {
-        if (diskCache != null && diskCache.exists()) return new FileInputStream(diskCache);
-        return new SubStream();
-    }
-
-    public void grow(int newLength) {
-        if (newLength < cache.length) return;
-        byte[] newCache = new byte[cache.length + 2 * (newLength - cache.length)];
-        System.arraycopy(cache, 0, newCache, 0, size);
-        cache = newCache;
-    }
-
-    synchronized void fillCache(int howMuch) throws IOException {
-        if (filling) { try { wait(); } catch (InterruptedException e) { }; return; }
-        filling = true;
-        grow(size + howMuch);
-        int ret = is.read(cache, size, howMuch);
-        if (ret == -1) {
-            eof = true;
-            // FIXME: probably a race here
-            if (diskCache != null && !diskCache.exists())
-                try {
-                    File cacheFile = new File(diskCache + ".incomplete");
-                    FileOutputStream cacheFileStream = new FileOutputStream(cacheFile);
-                    cacheFileStream.write(cache, 0, size);
-                    cacheFileStream.close();
-                    cacheFile.renameTo(diskCache);
-                } catch (IOException e) {
-                    Log.info(this, "exception thrown while writing disk cache");
-                    Log.info(this, e);
-                }
-        }
-        else size += ret;
-        filling = false;
-        notifyAll();
-    }
-
-    private class SubStream extends InputStream implements KnownLength {
-        int pos = 0;
-        public int available() { return Math.max(0, size - pos); }
-        public long skip(long n) throws IOException { pos += (int)n; return n; }     // FEATURE: don't skip past EOF
-        public int getLength() { return eof ? size : is instanceof KnownLength ? ((KnownLength)is).getLength() : 0; }
-        public int read() throws IOException {                                       // FEATURE: be smarter here
-            byte[] b = new byte[1];
-            int ret = read(b, 0, 1);
-            return ret == -1 ? -1 : b[0]&0xff;
-        }
-        public int read(byte[] b, int off, int len) throws IOException {
-            synchronized(CachedInputStream.this) {
-                while (pos >= size && !eof) fillCache(pos + len - size);
-                if (eof && pos == size) return -1;
-                int count = Math.min(size - pos, len);
-                System.arraycopy(cache, pos, b, off, count);
-                pos += count;
-                return count;
-            }
-        }
-    }
-}
diff --git a/src/org/ibex/util/Callback.java b/src/org/ibex/util/Callback.java
deleted file mode 100644 (file)
index 471df9b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-/** a simple interface for callbacks*/
-public interface Callback {
-
-    public abstract Object call(Object arg);
-
-}
diff --git a/src/org/ibex/util/CounterEnumeration.java b/src/org/ibex/util/CounterEnumeration.java
deleted file mode 100644 (file)
index 5a01f3e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (C) 2004 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-package org.ibex.util;
-import java.util.*;
-
-public class CounterEnumeration implements Enumeration {
-    public final int max;
-    private int cur = 0;
-    public CounterEnumeration(int i) { max = i; }
-    public void reset() { cur = 0; }
-    public boolean hasMoreElements() { return cur < max; }
-    public Object nextElement() { return new Integer(cur++); }
-}
diff --git a/src/org/ibex/util/DirtyList.java b/src/org/ibex/util/DirtyList.java
deleted file mode 100644 (file)
index 0a77a94..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-/** 
- *  A general-purpose data structure for holding a list of rectangular
- *  regions that need to be repainted, with intelligent coalescing.
- *
- *  DirtyList will unify two regions A and B if the smallest rectangle
- *  enclosing both A and B occupies no more than epsilon + Area_A +
- *  Area_B. Failing this, if two corners of A fall within B, A will be
- *  shrunk to exclude the union of A and B.
- */
-public class DirtyList {
-
-    /** The dirty regions (each one is an int[4]). */
-    private int[][] dirties = new int[10][];
-
-    /** The number of dirty regions */
-    private int numdirties = 0;
-
-    /** See class comment */
-    private static final int epsilon = 50 * 50;
-
-    public int num() { return numdirties; }
-    
-    /** grows the array */
-    private void grow() {
-        int[][] newdirties = new int[dirties.length * 2][];
-        System.arraycopy(dirties, 0, newdirties, 0, numdirties);
-        dirties = newdirties;
-    }
-
-    /** Add a new rectangle to the dirty list; returns false if the
-     *  region fell completely within an existing rectangle or set of
-     *  rectangles (ie did not expand the dirty area)
-     */
-    public synchronized boolean dirty(int x, int y, int w, int h) {
-        if (numdirties == dirties.length) grow();
-
-        // we attempt the "lossless" combinations first
-        for(int i=0; i<numdirties; i++) {
-            int[] cur = dirties[i];
-
-            // new region falls completely within existing region
-            if (x >= cur[0] && y >= cur[1] && x + w <= cur[0] + cur[2] && y + h <= cur[1] + cur[3]) {
-                return false;
-
-            // existing region falls completely within new region
-            } else if (x <= cur[0] && y <= cur[1] && x + w >= cur[0] + cur[2] && y + h >= cur[1] + cur[3]) {
-                dirties[i][2] = 0;
-                dirties[i][3] = 0;
-
-            // left end of new region falls within existing region
-            } else if (x >= cur[0] && x < cur[0] + cur[2] && y >= cur[1] && y + h <= cur[1] + cur[3]) {
-                w = x + w - (cur[0] + cur[2]);
-                x = cur[0] + cur[2];
-                i = -1; continue;
-                
-            // right end of new region falls within existing region
-            } else if (x + w > cur[0] && x + w <= cur[0] + cur[2] && y >= cur[1] && y + h <= cur[1] + cur[3]) {
-                w = cur[0] - x;
-                i = -1; continue;
-                
-            // top end of new region falls within existing region
-            } else if (x >= cur[0] && x + w <= cur[0] + cur[2] && y >= cur[1] && y < cur[1] + cur[3]) {
-                h = y + h - (cur[1] + cur[3]);
-                y = cur[1] + cur[3];
-                i = -1; continue;
-                
-            // bottom end of new region falls within existing region
-            } else if (x >= cur[0] && x + w <= cur[0] + cur[2] && y + h > cur[1] && y + h <= cur[1] + cur[3]) {
-                h = cur[1] - y;
-                i = -1; continue;
-                
-            // left end of existing region falls within new region
-            } else if (dirties[i][0] >= x && dirties[i][0] < x + w && dirties[i][1] >= y && dirties[i][1] + dirties[i][3] <= y + h) {
-                dirties[i][2] = dirties[i][2] - (x + w - dirties[i][0]);
-                dirties[i][0] = x + w;
-                i = -1; continue;
-                
-            // right end of existing region falls within new region
-            } else if (dirties[i][0] + dirties[i][2] > x && dirties[i][0] + dirties[i][2] <= x + w &&
-                       dirties[i][1] >= y && dirties[i][1] + dirties[i][3] <= y + h) {
-                dirties[i][2] = x - dirties[i][0];
-                i = -1; continue;
-                
-            // top end of existing region falls within new region
-            } else if (dirties[i][0] >= x && dirties[i][0] + dirties[i][2] <= x + w && dirties[i][1] >= y && dirties[i][1] < y + h) {
-                dirties[i][3] = dirties[i][3] - (y + h - dirties[i][1]);
-                dirties[i][1] = y + h;
-                i = -1; continue;
-                
-            // bottom end of existing region falls within new region
-            } else if (dirties[i][0] >= x && dirties[i][0] + dirties[i][2] <= x + w &&
-                       dirties[i][1] + dirties[i][3] > y && dirties[i][1] + dirties[i][3] <= y + h) {
-                dirties[i][3] = y - dirties[i][1];
-                i = -1; continue;
-            }
-
-        }
-
-        // then we attempt the "lossy" combinations
-        for(int i=0; i<numdirties; i++) {
-            int[] cur = dirties[i];
-            if (w > 0 && h > 0 && cur[2] > 0 && cur[3] > 0 &&
-                ((max(x + w, cur[0] + cur[2]) - min(x, cur[0])) *
-                 (max(y + h, cur[1] + cur[3]) - min(y, cur[1])) <
-                 w * h + cur[2] * cur[3] + epsilon)) {
-                int a = min(cur[0], x);
-                int b = min(cur[1], y);
-                int c = max(x + w, cur[0] + cur[2]) - min(cur[0], x);
-                int d = max(y + h, cur[1] + cur[3]) - min(cur[1], y);
-                dirties[i][2] = 0;
-                dirties[i][3] = 0;
-                return dirty(a, b, c, d);
-            }
-        }
-
-        dirties[numdirties++] = new int[] { x, y, w, h };
-        return true;
-    }
-
-    /** Returns true if there are no regions that need repainting */
-    public boolean empty() { return (numdirties == 0); }
-    
-    /**
-     *  Atomically returns the list of dirty rectangles as an array of
-     *  four-int arrays and clears the internal dirty-rectangle
-     *  list. Note that some of the regions returned may be null, or
-     *  may have zero height or zero width, and do not need to be
-     *  repainted.
-     */
-    public synchronized int[][] flush() {
-        if (numdirties == 0) return null;
-        int[][] ret = dirties;
-        for(int i=numdirties; i<ret.length; i++) ret[i] = null;
-        dirties = new int[dirties.length][];
-        numdirties = 0;
-        return ret;
-    }
-
-    /** included here so that it can be inlined */
-    private static final int min(int a, int b) {
-        if (a<b) return a;
-        else return b;
-    }
-    
-    /** included here so that it can be inlined */
-    private static final int max(int a, int b) {
-        if (a>b) return a;
-        else return b;
-    }
-    
-    /** included here so that it can be inlined */
-    private static final int min(int a, int b, int c) {
-        if (a<=b && a<=c) return a;
-        else if (b<=c && b<=a) return b;
-        else return c;
-    }
-    
-    /** included here so that it can be inlined */
-    private static final int max(int a, int b, int c) {
-        if (a>=b && a>=c) return a;
-        else if (b>=c && b>=a) return b;
-        else return c;
-    }
-    
-    /** included here so that it can be inlined */
-    private static final int bound(int a, int b, int c) {
-        if (a > b) return a;
-        if (c < b) return c;
-        return b;
-    }
-
-}
diff --git a/src/org/ibex/util/EjAlbertBrowserLauncher.java b/src/org/ibex/util/EjAlbertBrowserLauncher.java
deleted file mode 100644 (file)
index cf46138..0000000
+++ /dev/null
@@ -1,589 +0,0 @@
-package org.ibex.util;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * BrowserLauncher is a class that provides one static method, openURL, which opens the default
- * web browser for the current user of the system to the given URL.  It may support other
- * protocols depending on the system -- mailto, ftp, etc. -- but that has not been rigorously
- * tested and is not guaranteed to work.
- * <p>
- * Yes, this is platform-specific code, and yes, it may rely on classes on certain platforms
- * that are not part of the standard JDK.  What we're trying to do, though, is to take something
- * that's frequently desirable but inherently platform-specific -- opening a default browser --
- * and allow programmers (you, for example) to do so without worrying about dropping into native
- * code or doing anything else similarly evil.
- * <p>
- * Anyway, this code is completely in Java and will run on all JDK 1.1-compliant systems without
- * modification or a need for additional libraries.  All classes that are required on certain
- * platforms to allow this to run are dynamically loaded at runtime via reflection and, if not
- * found, will not cause this to do anything other than returning an error when opening the
- * browser.
- * <p>
- * There are certain system requirements for this class, as it's running through Runtime.exec(),
- * which is Java's way of making a native system call.  Currently, this requires that a Macintosh
- * have a Finder which supports the GURL event, which is true for Mac OS 8.0 and 8.1 systems that
- * have the Internet Scripting AppleScript dictionary installed in the Scripting Additions folder
- * in the Extensions folder (which is installed by default as far as I know under Mac OS 8.0 and
- * 8.1), and for all Mac OS 8.5 and later systems.  On Windows, it only runs under Win32 systems
- * (Windows 95, 98, and NT 4.0, as well as later versions of all).  On other systems, this drops
- * back from the inherently platform-sensitive concept of a default browser and simply attempts
- * to launch Netscape via a shell command.
- * <p>
- * This code is Copyright 1999-2001 by Eric Albert (ejalbert@cs.stanford.edu) and may be
- * redistributed or modified in any form without restrictions as long as the portion of this
- * comment from this paragraph through the end of the comment is not removed.  The author
- * requests that he be notified of any application, applet, or other binary that makes use of
- * this code, but that's more out of curiosity than anything and is not required.  This software
- * includes no warranty.  The author is not repsonsible for any loss of data or functionality
- * or any adverse or unexpected effects of using this software.
- * <p>
- * Credits:
- * <br>Steven Spencer, JavaWorld magazine (<a href="http://www.javaworld.com/javaworld/javatips/jw-javatip66.html">Java Tip 66</a>)
- * <br>Thanks also to Ron B. Yeh, Eric Shapiro, Ben Engber, Paul Teitlebaum, Andrea Cantatore,
- * Larry Barowski, Trevor Bedzek, Frank Miedrich, and Ron Rabakukk
- *
- * @author Eric Albert (<a href="mailto:ejalbert@cs.stanford.edu">ejalbert@cs.stanford.edu</a>)
- * @version 1.4b1 (Released June 20, 2001)
- */
-public class EjAlbertBrowserLauncher {
-
-       /**
-        * The Java virtual machine that we are running on.  Actually, in most cases we only care
-        * about the operating system, but some operating systems require us to switch on the VM. */
-       private static int jvm;
-
-       /** The browser for the system */
-       private static Object browser;
-
-       /**
-        * Caches whether any classes, methods, and fields that are not part of the JDK and need to
-        * be dynamically loaded at runtime loaded successfully.
-        * <p>
-        * Note that if this is <code>false</code>, <code>openURL()</code> will always return an
-        * IOException.
-        */
-       private static boolean loadedWithoutErrors;
-
-       /** The com.apple.mrj.MRJFileUtils class */
-       private static Class mrjFileUtilsClass;
-
-       /** The com.apple.mrj.MRJOSType class */
-       private static Class mrjOSTypeClass;
-
-       /** The com.apple.MacOS.AEDesc class */
-       private static Class aeDescClass;
-       
-       /** The <init>(int) method of com.apple.MacOS.AETarget */
-       private static Constructor aeTargetConstructor;
-       
-       /** The <init>(int, int, int) method of com.apple.MacOS.AppleEvent */
-       private static Constructor appleEventConstructor;
-       
-       /** The <init>(String) method of com.apple.MacOS.AEDesc */
-       private static Constructor aeDescConstructor;
-       
-       /** The findFolder method of com.apple.mrj.MRJFileUtils */
-       private static Method findFolder;
-
-       /** The getFileCreator method of com.apple.mrj.MRJFileUtils */
-       private static Method getFileCreator;
-       
-       /** The getFileType method of com.apple.mrj.MRJFileUtils */
-       private static Method getFileType;
-       
-       /** The openURL method of com.apple.mrj.MRJFileUtils */
-       private static Method openURLm;
-       
-       /** The makeOSType method of com.apple.MacOS.OSUtils */
-       private static Method makeOSType;
-       
-       /** The putParameter method of com.apple.MacOS.AppleEvent */
-       private static Method putParameter;
-       
-       /** The sendNoReply method of com.apple.MacOS.AppleEvent */
-       private static Method sendNoReply;
-       
-       /** Actually an MRJOSType pointing to the System Folder on a Macintosh */
-       private static Object kSystemFolderType;
-
-       /** The keyDirectObject AppleEvent parameter type */
-       private static Integer keyDirectObject;
-
-       /** The kAutoGenerateReturnID AppleEvent code */
-       private static Integer kAutoGenerateReturnID;
-       
-       /** The kAnyTransactionID AppleEvent code */
-       private static Integer kAnyTransactionID;
-
-       /** The linkage object required for JDirect 3 on Mac OS X. */
-       private static Object linkage;
-       
-       /** The framework to reference on Mac OS X */
-       private static final String JDirect_MacOSX = "/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox";
-
-       /** JVM constant for MRJ 2.0 */
-       private static final int MRJ_2_0 = 0;
-       
-       /** JVM constant for MRJ 2.1 or later */
-       private static final int MRJ_2_1 = 1;
-
-       /** JVM constant for Java on Mac OS X 10.0 (MRJ 3.0) */
-       private static final int MRJ_3_0 = 3;
-       
-       /** JVM constant for MRJ 3.1 */
-       private static final int MRJ_3_1 = 4;
-
-       /** JVM constant for any Windows NT JVM */
-       private static final int WINDOWS_NT = 5;
-       
-       /** JVM constant for any Windows 9x JVM */
-       private static final int WINDOWS_9x = 6;
-
-       /** JVM constant for any other platform */
-       private static final int OTHER = -1;
-
-       /**
-        * The file type of the Finder on a Macintosh.  Hardcoding "Finder" would keep non-U.S. English
-        * systems from working properly.
-        */
-       private static final String FINDER_TYPE = "FNDR";
-
-       /**
-        * The creator code of the Finder on a Macintosh, which is needed to send AppleEvents to the
-        * application.
-        */
-       private static final String FINDER_CREATOR = "MACS";
-
-       /** The name for the AppleEvent type corresponding to a GetURL event. */
-       private static final String GURL_EVENT = "GURL";
-
-       /**
-        * The first parameter that needs to be passed into Runtime.exec() to open the default web
-        * browser on Windows.
-        */
-    private static final String FIRST_WINDOWS_PARAMETER = "/c";
-    
-    /** The second parameter for Runtime.exec() on Windows. */
-    private static final String SECOND_WINDOWS_PARAMETER = "start";
-    
-    /**
-     * The third parameter for Runtime.exec() on Windows.  This is a "title"
-     * parameter that the command line expects.  Setting this parameter allows
-     * URLs containing spaces to work.
-     */
-    private static final String THIRD_WINDOWS_PARAMETER = "\"\"";
-       
-       /**
-        * The shell parameters for Netscape that opens a given URL in an already-open copy of Netscape
-        * on many command-line systems.
-        */
-       private static final String NETSCAPE_REMOTE_PARAMETER = "-remote";
-       private static final String NETSCAPE_OPEN_PARAMETER_START = "'openURL(";
-       private static final String NETSCAPE_OPEN_PARAMETER_END = ")'";
-       
-       /**
-        * The message from any exception thrown throughout the initialization process.
-        */
-       private static String errorMessage;
-
-       /**
-        * An initialization block that determines the operating system and loads the necessary
-        * runtime data.
-        */
-       static {
-               loadedWithoutErrors = true;
-               String osName = System.getProperty("os.name");
-               if (osName.startsWith("Mac OS")) {
-                       String mrjVersion = System.getProperty("mrj.version");
-                       String majorMRJVersion = mrjVersion.substring(0, 3);
-                       try {
-                               double version = Double.valueOf(majorMRJVersion).doubleValue();
-                               if (version == 2) {
-                                       jvm = MRJ_2_0;
-                               } else if (version >= 2.1 && version < 3) {
-                                       // Assume that all 2.x versions of MRJ work the same.  MRJ 2.1 actually
-                                       // works via Runtime.exec() and 2.2 supports that but has an openURL() method
-                                       // as well that we currently ignore.
-                                       jvm = MRJ_2_1;
-                               } else if (version == 3.0) {
-                                       jvm = MRJ_3_0;
-                               } else if (version >= 3.1) {
-                                       // Assume that all 3.1 and later versions of MRJ work the same.
-                                       jvm = MRJ_3_1;
-                               } else {
-                                       loadedWithoutErrors = false;
-                                       errorMessage = "Unsupported MRJ version: " + version;
-                               }
-                       } catch (NumberFormatException nfe) {
-                               loadedWithoutErrors = false;
-                               errorMessage = "Invalid MRJ version: " + mrjVersion;
-                       }
-               } else if (osName.startsWith("Windows")) {
-                       if (osName.indexOf("9") != -1) {
-                               jvm = WINDOWS_9x;
-                       } else {
-                               jvm = WINDOWS_NT;
-                       }
-               } else {
-                       jvm = OTHER;
-               }
-               
-               if (loadedWithoutErrors) {      // if we haven't hit any errors yet
-                       loadedWithoutErrors = loadClasses();
-               }
-       }
-
-       /**
-        * This class should be never be instantiated; this just ensures so.
-        */
-       private EjAlbertBrowserLauncher() { }
-       
-       /**
-        * Called by a static initializer to load any classes, fields, and methods required at runtime
-        * to locate the user's web browser.
-        * @return <code>true</code> if all intialization succeeded
-        *                      <code>false</code> if any portion of the initialization failed
-        */
-       private static boolean loadClasses() {
-               switch (jvm) {
-                       case MRJ_2_0:
-                               try {
-                                       Class aeTargetClass = Class.forName("com.apple.MacOS.AETarget");
-                                       Class osUtilsClass = Class.forName("com.apple.MacOS.OSUtils");
-                                       Class appleEventClass = Class.forName("com.apple.MacOS.AppleEvent");
-                                       Class aeClass = Class.forName("com.apple.MacOS.ae");
-                                       aeDescClass = Class.forName("com.apple.MacOS.AEDesc");
-
-                                       aeTargetConstructor = aeTargetClass.getDeclaredConstructor(new Class [] { int.class });
-                                       appleEventConstructor = appleEventClass.getDeclaredConstructor(new Class[] { int.class, int.class, aeTargetClass, int.class, int.class });
-                                       aeDescConstructor = aeDescClass.getDeclaredConstructor(new Class[] { String.class });
-
-                                       makeOSType = osUtilsClass.getDeclaredMethod("makeOSType", new Class [] { String.class });
-                                       putParameter = appleEventClass.getDeclaredMethod("putParameter", new Class[] { int.class, aeDescClass });
-                                       sendNoReply = appleEventClass.getDeclaredMethod("sendNoReply", new Class[] { });
-
-                                       Field keyDirectObjectField = aeClass.getDeclaredField("keyDirectObject");
-                                       keyDirectObject = (Integer) keyDirectObjectField.get(null);
-                                       Field autoGenerateReturnIDField = appleEventClass.getDeclaredField("kAutoGenerateReturnID");
-                                       kAutoGenerateReturnID = (Integer) autoGenerateReturnIDField.get(null);
-                                       Field anyTransactionIDField = appleEventClass.getDeclaredField("kAnyTransactionID");
-                                       kAnyTransactionID = (Integer) anyTransactionIDField.get(null);
-                               } catch (ClassNotFoundException cnfe) {
-                                       errorMessage = cnfe.getMessage();
-                                       return false;
-                               } catch (NoSuchMethodException nsme) {
-                                       errorMessage = nsme.getMessage();
-                                       return false;
-                               } catch (NoSuchFieldException nsfe) {
-                                       errorMessage = nsfe.getMessage();
-                                       return false;
-                               } catch (IllegalAccessException iae) {
-                                       errorMessage = iae.getMessage();
-                                       return false;
-                               }
-                               break;
-                       case MRJ_2_1:
-                               try {
-                                       mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
-                                       mrjOSTypeClass = Class.forName("com.apple.mrj.MRJOSType");
-                                       Field systemFolderField = mrjFileUtilsClass.getDeclaredField("kSystemFolderType");
-                                       kSystemFolderType = systemFolderField.get(null);
-                                       findFolder = mrjFileUtilsClass.getDeclaredMethod("findFolder", new Class[] { mrjOSTypeClass });
-                                       getFileCreator = mrjFileUtilsClass.getDeclaredMethod("getFileCreator", new Class[] { File.class });
-                                       getFileType = mrjFileUtilsClass.getDeclaredMethod("getFileType", new Class[] { File.class });
-                               } catch (ClassNotFoundException cnfe) {
-                                       errorMessage = cnfe.getMessage();
-                                       return false;
-                               } catch (NoSuchFieldException nsfe) {
-                                       errorMessage = nsfe.getMessage();
-                                       return false;
-                               } catch (NoSuchMethodException nsme) {
-                                       errorMessage = nsme.getMessage();
-                                       return false;
-                               } catch (SecurityException se) {
-                                       errorMessage = se.getMessage();
-                                       return false;
-                               } catch (IllegalAccessException iae) {
-                                       errorMessage = iae.getMessage();
-                                       return false;
-                               }
-                               break;
-                       case MRJ_3_0:
-                           try {
-                                       Class linker = Class.forName("com.apple.mrj.jdirect.Linker");
-                                       Constructor constructor = linker.getConstructor(new Class[]{ Class.class });
-                                       linkage = constructor.newInstance(new Object[] { EjAlbertBrowserLauncher.class });
-                               } catch (ClassNotFoundException cnfe) {
-                                       errorMessage = cnfe.getMessage();
-                                       return false;
-                               } catch (NoSuchMethodException nsme) {
-                                       errorMessage = nsme.getMessage();
-                                       return false;
-                               } catch (InvocationTargetException ite) {
-                                       errorMessage = ite.getMessage();
-                                       return false;
-                               } catch (InstantiationException ie) {
-                                       errorMessage = ie.getMessage();
-                                       return false;
-                               } catch (IllegalAccessException iae) {
-                                       errorMessage = iae.getMessage();
-                                       return false;
-                               }
-                               break;
-                       case MRJ_3_1:
-                               try {
-                                       mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
-                                       openURLm = mrjFileUtilsClass.getDeclaredMethod("openURL", new Class[] { String.class });
-                               } catch (ClassNotFoundException cnfe) {
-                                       errorMessage = cnfe.getMessage();
-                                       return false;
-                               } catch (NoSuchMethodException nsme) {
-                                       errorMessage = nsme.getMessage();
-                                       return false;
-                               }
-                               break;
-                       default:
-                           break;
-               }
-               return true;
-       }
-
-       /**
-        * Attempts to locate the default web browser on the local system.  Caches results so it
-        * only locates the browser once for each use of this class per JVM instance.
-        * @return The browser for the system.  Note that this may not be what you would consider
-        *                      to be a standard web browser; instead, it's the application that gets called to
-        *                      open the default web browser.  In some cases, this will be a non-String object
-        *                      that provides the means of calling the default browser.
-        */
-       private static Object locateBrowser() {
-               if (browser != null) {
-                       return browser;
-               }
-               switch (jvm) {
-                       case MRJ_2_0:
-                               try {
-                                       Integer finderCreatorCode = (Integer) makeOSType.invoke(null, new Object[] { FINDER_CREATOR });
-                                       Object aeTarget = aeTargetConstructor.newInstance(new Object[] { finderCreatorCode });
-                                       Integer gurlType = (Integer) makeOSType.invoke(null, new Object[] { GURL_EVENT });
-                                       Object appleEvent = appleEventConstructor.newInstance(new Object[] { gurlType, gurlType, aeTarget, kAutoGenerateReturnID, kAnyTransactionID });
-                                       // Don't set browser = appleEvent because then the next time we call
-                                       // locateBrowser(), we'll get the same AppleEvent, to which we'll already have
-                                       // added the relevant parameter. Instead, regenerate the AppleEvent every time.
-                                       // There's probably a way to do this better; if any has any ideas, please let
-                                       // me know.
-                                       return appleEvent;
-                               } catch (IllegalAccessException iae) {
-                                       browser = null;
-                                       errorMessage = iae.getMessage();
-                                       return browser;
-                               } catch (InstantiationException ie) {
-                                       browser = null;
-                                       errorMessage = ie.getMessage();
-                                       return browser;
-                               } catch (InvocationTargetException ite) {
-                                       browser = null;
-                                       errorMessage = ite.getMessage();
-                                       return browser;
-                               }
-                       case MRJ_2_1:
-                               File systemFolder;
-                               try {
-                                       systemFolder = (File) findFolder.invoke(null, new Object[] { kSystemFolderType });
-                               } catch (IllegalArgumentException iare) {
-                                       browser = null;
-                                       errorMessage = iare.getMessage();
-                                       return browser;
-                               } catch (IllegalAccessException iae) {
-                                       browser = null;
-                                       errorMessage = iae.getMessage();
-                                       return browser;
-                               } catch (InvocationTargetException ite) {
-                                       browser = null;
-                                       errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage();
-                                       return browser;
-                               }
-                               String[] systemFolderFiles = systemFolder.list();
-                               // Avoid a FilenameFilter because that can't be stopped mid-list
-                               for(int i = 0; i < systemFolderFiles.length; i++) {
-                                       try {
-                                               File file = new File(systemFolder, systemFolderFiles[i]);
-                                               if (!file.isFile()) {
-                                                       continue;
-                                               }
-                                               // We're looking for a file with a creator code of 'MACS' and
-                                               // a type of 'FNDR'.  Only requiring the type results in non-Finder
-                                               // applications being picked up on certain Mac OS 9 systems,
-                                               // especially German ones, and sending a GURL event to those
-                                               // applications results in a logout under Multiple Users.
-                                               Object fileType = getFileType.invoke(null, new Object[] { file });
-                                               if (FINDER_TYPE.equals(fileType.toString())) {
-                                                       Object fileCreator = getFileCreator.invoke(null, new Object[] { file });
-                                                       if (FINDER_CREATOR.equals(fileCreator.toString())) {
-                                                               browser = file.toString();      // Actually the Finder, but that's OK
-                                                               return browser;
-                                                       }
-                                               }
-                                       } catch (IllegalArgumentException iare) {
-                                               browser = browser;
-                                               errorMessage = iare.getMessage();
-                                               return null;
-                                       } catch (IllegalAccessException iae) {
-                                               browser = null;
-                                               errorMessage = iae.getMessage();
-                                               return browser;
-                                       } catch (InvocationTargetException ite) {
-                                               browser = null;
-                                               errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage();
-                                               return browser;
-                                       }
-                               }
-                               browser = null;
-                               break;
-                       case MRJ_3_0:
-                       case MRJ_3_1:
-                               browser = "";   // Return something non-null
-                               break;
-                       case WINDOWS_NT:
-                               browser = "cmd.exe";
-                               break;
-                       case WINDOWS_9x:
-                               browser = "command.com";
-                               break;
-                       case OTHER:
-                       default:
-                               browser = "netscape";
-                               break;
-               }
-               return browser;
-       }
-
-       /**
-        * Attempts to open the default web browser to the given URL.
-        * @param url The URL to open
-        * @throws IOException If the web browser could not be located or does not run
-        */
-       public static void openURL(String url) throws IOException {
-               if (!loadedWithoutErrors) {
-                       throw new IOException("Exception in finding browser: " + errorMessage);
-               }
-               Object browser = locateBrowser();
-               if (browser == null) {
-                       throw new IOException("Unable to locate browser: " + errorMessage);
-               }
-               
-               switch (jvm) {
-                       case MRJ_2_0:
-                               Object aeDesc = null;
-                               try {
-                                       aeDesc = aeDescConstructor.newInstance(new Object[] { url });
-                                       putParameter.invoke(browser, new Object[] { keyDirectObject, aeDesc });
-                                       sendNoReply.invoke(browser, new Object[] { });
-                               } catch (InvocationTargetException ite) {
-                                       throw new IOException("InvocationTargetException while creating AEDesc: " + ite.getMessage());
-                               } catch (IllegalAccessException iae) {
-                                       throw new IOException("IllegalAccessException while building AppleEvent: " + iae.getMessage());
-                               } catch (InstantiationException ie) {
-                                       throw new IOException("InstantiationException while creating AEDesc: " + ie.getMessage());
-                               } finally {
-                                       aeDesc = null;  // Encourage it to get disposed if it was created
-                                       browser = null; // Ditto
-                               }
-                               break;
-                       case MRJ_2_1:
-                               Runtime.getRuntime().exec(new String[] { (String) browser, url } );
-                               break;
-                       case MRJ_3_0:
-                               int[] instance = new int[1];
-                               int result = ICStart(instance, 0);
-                               if (result == 0) {
-                                       int[] selectionStart = new int[] { 0 };
-                                       byte[] urlBytes = url.getBytes();
-                                       int[] selectionEnd = new int[] { urlBytes.length };
-                                       result = ICLaunchURL(instance[0], new byte[] { 0 }, urlBytes,
-                                                                                       urlBytes.length, selectionStart,
-                                                                                       selectionEnd);
-                                       if (result == 0) {
-                                               // Ignore the return value; the URL was launched successfully
-                                               // regardless of what happens here.
-                                               ICStop(instance);
-                                       } else {
-                                               throw new IOException("Unable to launch URL: " + result);
-                                       }
-                               } else {
-                                       throw new IOException("Unable to create an Internet Config instance: " + result);
-                               }
-                               break;
-                       case MRJ_3_1:
-                               try {
-                                       openURLm.invoke(null, new Object[] { url });
-                               } catch (InvocationTargetException ite) {
-                                       throw new IOException("InvocationTargetException while calling openURL: " + ite.getMessage());
-                               } catch (IllegalAccessException iae) {
-                                       throw new IOException("IllegalAccessException while calling openURL: " + iae.getMessage());
-                               }
-                               break;
-                   case WINDOWS_NT:
-                   case WINDOWS_9x:
-                       // Add quotes around the URL to allow ampersands and other special
-                       // characters to work.
-                               Process process = Runtime.getRuntime().exec(new String[] { (String) browser,
-                                                                                                                               FIRST_WINDOWS_PARAMETER,
-                                                                                                                               SECOND_WINDOWS_PARAMETER,
-                                                                                                                               THIRD_WINDOWS_PARAMETER,
-                                                                                                                               '"' + url + '"' });
-                               // This avoids a memory leak on some versions of Java on Windows.
-                               // That's hinted at in <http://developer.java.sun.com/developer/qow/archive/68/>.
-                               try {
-                                       process.waitFor();
-                                       process.exitValue();
-                               } catch (InterruptedException ie) {
-                                       throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
-                               }
-                               break;
-                       case OTHER:
-                               // Assume that we're on Unix and that Netscape is installed
-                               
-                               // First, attempt to open the URL in a currently running session of Netscape
-                               process = Runtime.getRuntime().exec(new String[] { (String) browser,
-                                                                                                       NETSCAPE_REMOTE_PARAMETER,
-                                                                                                       NETSCAPE_OPEN_PARAMETER_START +
-                                                                                                       url +
-                                                                                                       NETSCAPE_OPEN_PARAMETER_END });
-                               try {
-                                       int exitCode = process.waitFor();
-                                       if (exitCode != 0) {    // if Netscape was not open
-                                               Runtime.getRuntime().exec(new String[] { (String) browser, url });
-                                       }
-                               } catch (InterruptedException ie) {
-                                       throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
-                               }
-                               break;
-                       default:
-                               // This should never occur, but if it does, we'll try the simplest thing possible
-                               Runtime.getRuntime().exec(new String[] { (String) browser, url });
-                               break;
-               }
-       }
-
-       /**
-        * Methods required for Mac OS X.  The presence of native methods does not cause
-        * any problems on other platforms.
-        */
-    /*
-       private native static int ICStart(int[] instance, int signature);
-       private native static int ICStop(int[] instance);
-       private native static int ICLaunchURL(int instance, byte[] hint, byte[] data, int len,
-                                                                                       int[] selectionStart, int[] selectionEnd);
-    */
-    private static int ICStart(int[] instance, int signature) { return 0; }
-    private static int ICStop(int[] instance) { return 0; }
-    private static int ICLaunchURL(int instance, byte[] hint, byte[] data, int len,
-        int[] selectionStart, int[] selectionEnd) { return 0; }
-}
diff --git a/src/org/ibex/util/FileNameEncoder.java b/src/org/ibex/util/FileNameEncoder.java
deleted file mode 100644 (file)
index e68bba2..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-import java.util.*;
-import java.io.*;
-
-/** provides commands to urlencode and urldecode strings, making sure
- *  to escape sequences which have special meanings in filenames */
-public class FileNameEncoder {
-
-    private static final char[] hex =
-        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
-
-    public static String encode(String s) {
-        StringBuffer sb = new StringBuffer();
-        try {
-            byte[] b = s.getBytes("UTF-8");
-            for(int i=0; i<b.length; i++) {
-                char c = (char)(b[i] & 0xff);
-                if (c == File.separatorChar || c < 32 || c > 126 || c == '%' || (i == 0 && c == '.'))
-                    sb.append("%" + hex[(b[i] & 0xf0) >> 8] + hex[b[i] & 0xf]);
-                else sb.append(c);
-            }
-            return sb.toString();
-        } catch (UnsupportedEncodingException uee) {
-            throw new Error("this should never happen; Java spec mandates UTF-8 support");
-        }
-    }
-
-    public static String decode(String s) {
-        StringBuffer sb = new StringBuffer();
-        byte[] b = new byte[s.length() * 2];
-        int bytes = 0;
-        for(int i=0; i<s.length(); i++) {
-            char c = s.charAt(i);
-            if (c == '%') b[bytes++] = (byte)Integer.parseInt(("" + s.charAt(++i) + s.charAt(++i)), 16);
-            else b[bytes++] = (byte)c;
-        }
-        try {
-            return new String(b, 0, bytes, "UTF-8");
-        } catch (UnsupportedEncodingException uee) {
-            throw new Error("this should never happen; Java spec mandates UTF-8 support");
-        }
-    }
-}
diff --git a/src/org/ibex/util/Grammar.java b/src/org/ibex/util/Grammar.java
deleted file mode 100644 (file)
index 683c118..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.ibex.util;
-
-import org.ibex.js.*;
-
-public abstract class Grammar extends JS {
-
-    public JS action = null;
-
-    // FIXME: Updae for new api
-    
-    // means we call()ed a Grammar that hasn't been bound to a scope yet
-    /*public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
-        throw new Error("this should never happen");
-    }
-
-    private static Object NULL = new Object();
-    
-    public abstract int match(String s, int start, Hash v, JSScope scope) throws JSExn;
-    public int matchAndWrite(final String s, final int start, Hash v, JSScope scope, String key) throws JSExn {
-        final Hash v2 = new Hash();
-        final int ret = match(s, start, v2, scope);
-        Object result = ret == -1 ? NULL : action == null ?
-            s.substring(start, ret) :
-            JS.cloneWithNewParentScope(action, new JSScope(scope) {
-                    public Object get(Object key) throws JSExn {
-                        Object val = v2.get(key);
-                        if (val == NULL) return null;
-                        if (val != null) return val;
-                        if (key.equals("whole")) return s.substring(start, ret);
-                        return super.get(key);
-                    }
-                }).call(null, null, null, null, 0);
-        if (key != null) {
-            Object old = v.get(key);
-            if (old == null || old == NULL) { }
-            else if (old instanceof JSArray) { if (result != NULL) { ((JSArray)old).addElement(result); result = old; } }
-            else if (result != NULL) { JSArray j = new JSArray(); j.addElement(old); j.addElement(result); result = j; }
-            v.put(key, result);
-        }
-        return ret;
-    }
-
-    public static class Alternative extends Grammar {
-        private Grammar r1, r2;
-        public Alternative(Grammar r1, Grammar r2) { this.r1 = r1; this.r2 = r2; }
-        public int match(String s, int start, Hash v, JSScope r) throws JSExn {
-            int s1 = r1.match(s, start, v, r);
-            if (s1 != -1) return s1;
-            int s2 = r2.match(s, start, v, r);
-            if (s2 != -1) return s2;
-            return -1;
-        }
-    }
-
-    public static class Juxtaposition extends Grammar {
-        private Grammar r1, r2;
-        public Juxtaposition(Grammar r1, Grammar r2) { this.r1 = r1; this.r2 = r2; }
-        public int match(String s, int start, Hash v, JSScope r) throws JSExn {
-            int s1 = r1.match(s, start, v, r);
-            if (s1 == -1) return -1;
-            int s2 = r2.match(s, s1, v, r);
-            if (s2 == -1) return -1;
-            return s2;
-        }
-    }
-
-    public static class Repetition extends Grammar {
-        private Grammar r1;
-        private int min, max;
-        public Repetition(Grammar r1, int min, int max) { this.r1 = r1; this.min = min; this.max = max; }
-        public int match(String s, int start, Hash v, JSScope r) throws JSExn {
-            int i;
-            for(i=0; i<max; i++) {
-                start = r1.match(s, start, v, r);
-                if (start == -1) return -1;
-            }
-            if (i < min) return -1;
-            return start;
-        }
-    }
-
-    public static class Literal extends Grammar {
-        String str;
-        public Literal(String str) { this.str = str; }
-        public int match(String s, int start, Hash v, JSScope r) {
-            if (!s.regionMatches(start, str, 0, str.length())) return -1;
-            return start + str.length();
-        }
-    }
-
-    public static class Range extends Grammar {
-        char min, max;
-        public Range(char min, char max) { this.min = min; this.max = max; }
-        public int match(String s, int start, Hash v, JSScope r) throws JSExn {
-            if (!(s.charAt(start) >= min && s.charAt(start) <= max)) return -1;
-            return start + 1;
-        }
-    }
-
-    public static class Reference extends Grammar {
-        String key;
-        public Reference(String key) { this.key = key; }
-        public int match(String s, int start, Hash v, JSScope scope) throws JSExn {
-            return ((Grammar)scope.get(key)).matchAndWrite(s, start, v, scope, key);
-        }
-    }*/
-}
diff --git a/src/org/ibex/util/Hash.java b/src/org/ibex/util/Hash.java
deleted file mode 100644 (file)
index 11fe4d8..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-import java.util.*;
-
-/** Implementation of an unsynchronized hash table, with one or two
- *  keys, using Radke's quadradic residue linear probing instead of
- *  buckets to minimize object count (less allocations, faster GC).
- *  See C. Radke, Communications of the ACM, 1970, 103-105
- *
- *  Not threadsafe.
- */
-public class Hash {
-    /** this object is inserted as key in a slot when the
-     *  corresponding value is removed -- this ensures that the
-     *  probing sequence for any given key remains the same even if
-     *  other keys are removed.
-     */
-    private static Object placeholder = new Object();
-
-    /** the number of entries with at least one non-null key */
-    private int usedslots = 0;
-
-    /** the number of entries with non-null values */
-    protected int size = 0;
-
-    /** when num_slots < loadFactor * size, rehash into a bigger table */
-    private final int loadFactor;
-
-    /** primary keys */
-    private Object[] keys1 = null;
-
-    /** secondary keys; null if no secondary key has ever been added */
-    private Object[] keys2 = null;
-
-    /** the values for the table */
-    private Object[] vals = null;
-    
-    /** the number of entries with a non-null value */
-    public int size() { return size; }
-
-    /** empties the table */
-    public void clear() {
-        size = 0;
-        usedslots = 0;
-        for(int i=0; i<vals.length; i++) {
-            vals[i] = null;
-            keys1[i] = null;
-            if (keys2 != null) keys2[i] = null;
-        }
-    }
-
-    /** returns all the primary keys in the table */
-    public Enumeration keys() { return new HashEnum(); }
-
-    public Hash() { this(25, 3); }
-    public Hash(int initialcapacity, int loadFactor) {
-        // using a pseudoprime in the form 4x+3 ensures full coverage
-        initialcapacity = initialcapacity / 4;
-        initialcapacity = 4 * initialcapacity + 3;
-        keys1 = new Object[initialcapacity];
-        vals = new Object[initialcapacity];
-        this.loadFactor = loadFactor;
-    }
-    
-    public void remove(Object k1) { remove(k1, null); }
-    public void remove(Object k1, Object k2) { put_(k1, k2, null); }
-
-    private void rehash() {
-        Object[] oldkeys1 = keys1;
-        Object[] oldkeys2 = keys2;
-        Object[] oldvals = vals;
-        keys1 = new Object[oldvals.length * 2];
-        keys2 = oldkeys2 == null ? null : new Object[oldvals.length * 2];
-        vals = new Object[oldvals.length * 2];
-        size = 0;
-        usedslots = 0;
-        for(int i=0; i<oldvals.length; i++)
-            if (((oldkeys1[i] != null && oldkeys1[i] != placeholder) || (oldkeys2 != null && oldkeys2[i] != null)) && oldvals[i] != null)
-                put_(oldkeys1[i], oldkeys2 == null ? null : oldkeys2[i], oldvals[i]);
-    }
-
-    public Object get(Object k1) { return get(k1, null); }
-    public Object get(Object k1, Object k2) {
-        if (k2 != null && keys2 == null) return null;
-        int hash = (k1 == null ? 0 : k1.hashCode()) ^ (k2 == null ? 0 : k2.hashCode());
-        int dest = Math.abs(hash) % vals.length;
-        int odest = dest;
-        int tries = 1;
-        boolean plus = true;
-        while (keys1[dest] != null || (keys2 != null && keys2[dest] != null)) {
-            Object hk1 = keys1[dest];
-            Object hk2 = keys2 == null ? null : keys2[dest];
-            if ((k1 == hk1 || (k1 != null && hk1 != null && k1.equals(hk1))) &&
-                (k2 == hk2 || (k2 != null && hk2 != null && k2.equals(hk2)))) {
-                return vals[dest];
-            }
-            dest = Math.abs((odest + (plus ? 1 : -1 ) * tries * tries) % vals.length);
-            if (plus) tries++;
-            plus = !plus;
-        }
-        return null;
-    }
-
-    public void put(Object k1, Object v) { put(k1, null, v); }
-    public void put(Object k1, Object k2, Object v) { put_(k1, k2, v); }
-    private void put_(Object k1, Object k2, Object v) {
-        if (usedslots * loadFactor > vals.length) rehash();
-        int hash = (k1 == null ? 0 : k1.hashCode()) ^ (k2 == null ? 0 : k2.hashCode());
-        int dest = Math.abs(hash) % vals.length;
-        int odest = dest;
-        boolean plus = true;
-        int tries = 1;
-        while (true) {
-            Object hk1 = keys1[dest];
-            Object hk2 = keys2 == null ? null : keys2[dest];
-            if (hk1 == null && hk2 == null) {                                         // empty slot
-                if (v == null) return;
-                size++;
-                usedslots++;
-                break;
-            }
-
-            if ((k1 == hk1 || (k1 != null && hk1 != null && k1.equals(hk1))) &&       // replacing former entry
-                (k2 == hk2 || (k2 != null && hk2 != null && k2.equals(hk2)))) {
-
-                // we don't actually remove things from the table; rather, we insert a placeholder
-                if (v == null) {
-                    k1 = placeholder;
-                    k2 = null;
-                    size--;
-                }
-                break;
-            }
-
-            dest = Math.abs((odest + (plus ? 1 : -1 ) * tries * tries) % vals.length);
-            if (plus) tries++;
-            plus = !plus;
-        }
-
-        keys1[dest] = k1;
-        if (k2 != null && keys2 == null) keys2 = new Object[keys1.length];
-        if (keys2 != null) keys2[dest] = k2;
-        vals[dest] = v;
-    }
-
-    private class HashEnum implements java.util.Enumeration {
-        private int iterator;
-        
-        public HashEnum() { findNext(); }
-        
-        private void findNext() {
-            while(iterator < keys1.length && (keys1[iterator] == null || keys1[iterator] == placeholder)) iterator++;
-        }
-        
-        public boolean hasMoreElements() {
-            return iterator < keys1.length;
-        }
-
-        public Object nextElement() {
-            if (iterator == keys1.length) throw new NoSuchElementException();
-            Object o = keys1[iterator];
-            iterator++;
-            findNext();
-            return o;
-        }
-    }
-}
-
-
diff --git a/src/org/ibex/util/InputStreamToByteArray.java b/src/org/ibex/util/InputStreamToByteArray.java
deleted file mode 100644 (file)
index 7e19644..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-import java.io.*;
-
-public 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/org/ibex/util/KnownLength.java b/src/org/ibex/util/KnownLength.java
deleted file mode 100644 (file)
index 06118bb..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-import java.io.*;
-
-/** a generic interface for things that "know" their length */
-public interface KnownLength {
-
-    public abstract int getLength();
-
-    public static class KnownLengthInputStream extends FilterInputStream implements KnownLength {
-        int length;
-        public int getLength() { return length; }
-        public KnownLengthInputStream(java.io.InputStream parent, int length) {
-            super(parent);
-            this.length = length;
-        }
-    }
-
-}
diff --git a/src/org/ibex/util/LineReader.java b/src/org/ibex/util/LineReader.java
deleted file mode 100644 (file)
index 429c218..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.ibex.util;
-import java.io.*;
-
-public class LineReader {
-
-    private int MAXBUF = 1024 * 16;
-    char[] buf = new char[MAXBUF];
-    int buflen = 0;
-    Reader r;
-    Vec pushback = new Vec();
-
-    public LineReader(Reader r) { this.r = r; }
-
-    public void pushback(String s) { pushback.push(s); }
-
-    public String readLine() throws IOException {
-        while(true) {
-            if (pushback.size() > 0) return (String)pushback.pop();
-            for(int i=0; i<buflen; i++) {
-                if (buf[i] == '\n') {
-                    String ret;
-                    if (buf[i-1] == '\r') ret = new String(buf, 0, i-1);
-                    else ret = new String(buf, 0, i);
-                    System.arraycopy(buf, i+1, buf, 0, buflen - (i+1));
-                    buflen -= i+1;
-                    return ret;
-                }
-            }
-           if (buflen == MAXBUF) {
-               char[] buf2 = new char[MAXBUF*2];
-               System.arraycopy(buf, 0, buf2, 0, buflen);
-               buf = buf2;
-               MAXBUF *= 2;
-           }
-            int numread = r.read(buf, buflen, MAXBUF - buflen);
-            if (numread == -1) {
-                if (buflen == 0) return null;
-                String ret = new String(buf, 0, buflen);
-                buflen = 0;
-                return ret;
-            } else {
-                buflen += numread;
-            }
-        }
-    }
-}
diff --git a/src/org/ibex/util/Log.java b/src/org/ibex/util/Log.java
deleted file mode 100644 (file)
index 467a339..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-import org.ibex.js.*;
-import java.io.*;
-import java.util.*;
-import java.net.*;
-
-/** easy to use logger */
-public class Log {
-
-    public static boolean on            = System.getProperty("ibex.log.on", "true").equals("true");
-    public static boolean color         = System.getProperty("ibex.log.color", "true").equals("true");
-    public static boolean verbose       = System.getProperty("ibex.log.verbose", "false").equals("true");
-    public static boolean logDates      = System.getProperty("ibex.log.dates", "false").equals("true");
-    public static boolean notes         = System.getProperty("ibex.log.notes.on", "true").equals("true");
-    public static int maximumNoteLength = Integer.parseInt(System.getProperty("ibex.log.notes.maximumLength", (1024 * 32)+""));
-    public static boolean rpc           = false;
-    public static Date lastDate = null;
-
-    public static PrintStream logstream = System.err;
-
-    public static void flush() { logstream.flush(); }
-    public static void email(String address) { throw new Error("FIXME not supported"); }
-    public static void file(String filename) throws IOException {
-        // FIXME security
-        logstream = new PrintStream(new FileOutputStream(filename));
-    }
-    public static void tcp(String host, int port) throws IOException {
-        // FIXME security
-        logstream = new PrintStream(new Socket(InetAddress.getByName(host), port).getOutputStream());
-    }
-
-    private static Hashtable threadAnnotations = new Hashtable();
-    public static void setThreadAnnotation(String s) { threadAnnotations.put(Thread.currentThread(), s); }
-
-    /** 
-     *  Notes can be used to attach log messages to the current thread
-     *  if you're not sure you want them in the log just yet.
-     *  Originally designed for retroactively logging socket-level
-     *  conversations only if an error is encountered
-     */
-    public static void note(String s) {
-        if (!notes) return;
-        StringBuffer notebuf = notebuf();
-        notebuf.append(s);
-        if (notebuf.length() > maximumNoteLength) {
-            notebuf.reverse();
-            notebuf.setLength(maximumNoteLength * 3 / 4);
-            notebuf.reverse();
-        }
-    }
-    public static void clearnotes() { if (!notes) return; notebuf().setLength(0); }
-    private static Hashtable notebufs = new Hashtable();
-    private static StringBuffer notebuf() {
-        StringBuffer ret = (StringBuffer)notebufs.get(Thread.currentThread());
-        if (ret == null) {
-            ret = new StringBuffer(16 * 1024);
-            notebufs.put(Thread.currentThread(), ret);
-        }
-        return ret;
-    }
-
-    /** true iff nothing has yet been logged */
-    public static boolean firstMessage = true;
-
-    /** message can be a String or a Throwable */
-    public static synchronized void echo(Object o, Object message) { log(o, message, ECHO); }
-    public static synchronized void diag(Object o, Object message) { log(o, message, DIAGNOSTIC); }
-    public static synchronized void debug(Object o, Object message) { log(o, message, DEBUG); }
-    public static synchronized void info(Object o, Object message) { log(o, message, INFO); }
-    public static synchronized void warn(Object o, Object message) { log(o, message, WARN); }
-    public static synchronized void error(Object o, Object message) { log(o, message, ERROR); }
-
-    // these two logging levels serve ONLY to change the color; semantically they are the same as DEBUG
-    private static final int DIAGNOSTIC = -2;
-    private static final int ECHO = -1;
-
-    // the usual log4j levels, minus FAIL (we just throw an Error in that case)
-    public static final int DEBUG = 0;
-    public static final int INFO = 1;
-    public static final int WARN = 2;
-    public static final int ERROR = 3;
-    public static final int SILENT = Integer.MAX_VALUE;
-    public static int level = INFO;
-
-    private static final int BLUE = 34;
-    private static final int GREEN = 32;
-    private static final int CYAN = 36;
-    private static final int RED = 31;
-    private static final int PURPLE = 35;
-    private static final int BROWN = 33;
-    private static final int GRAY = 37;
-    
-    private static String colorize(int color, boolean bright, String s) {
-        if (!Log.color) return s;
-        return
-            "\033[40;" + (bright?"1;":"") + color + "m" +
-            s +
-            "\033[0m";
-    }
-
-    private static String lastClassName = null;
-    private static synchronized void log(Object o, Object message, int level) {
-        if (level < Log.level) return;
-        if (firstMessage && !logDates) {
-            firstMessage = false;
-            logstream.println(colorize(GREEN, false, "==========================================================================="));
-
-            // FIXME later: causes problems with method pruning
-            //diag(Log.class, "Logging enabled at " + new java.util.Date());
-
-            if (color) diag(Log.class, "logging messages in " +
-                colorize(BLUE, true, "c") +
-                colorize(RED, true, "o") +
-                colorize(CYAN, true, "l") +
-                colorize(GREEN, true, "o") +
-                colorize(PURPLE, true, "r"));
-        }
-
-        String classname;
-        if (o instanceof Class) {
-            classname = ((Class)o).getName();
-            if (classname.indexOf('.') != -1) classname = classname.substring(classname.lastIndexOf('.') + 1);
-        }
-        else if (o instanceof String) classname = (String)o;
-        else classname = o.getClass().getName();
-
-        if (classname.equals(lastClassName)) classname = "";
-        else lastClassName = classname;
-        
-        if (classname.length() > (logDates ? 14 : 20)) classname = classname.substring(0, (logDates ? 14 : 20));
-        while (classname.length() < (logDates ? 14 : 20)) classname = " " + classname;
-        classname = classname + (classname.trim().length() == 0 ? "  " : ": ");
-        classname = colorize(GRAY, true, classname);
-        classname = classname.replace('$', '.');
-
-        if (logDates) {
-            Date d = new Date();
-            if (lastDate == null || d.getYear() != lastDate.getYear() || d.getMonth() != lastDate.getMonth() || d.getDay() != lastDate.getDay()) {
-                String now = new java.text.SimpleDateFormat("EEE dd MMM yyyy").format(d);
-                logstream.println();
-                logstream.println(colorize(GRAY, false, "=== " + now + " =========================================================="));
-            }
-            java.text.DateFormat df = new java.text.SimpleDateFormat("[EEE HH:mm:ss] ");
-            classname = df.format(d) + classname;
-            lastDate = d;
-        }
-
-        String annot = (String)threadAnnotations.get(Thread.currentThread());
-        if (annot != null) classname += annot;
-
-        if (message instanceof Throwable) {
-            if (level < ERROR) level = WARN;
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            ((Throwable)message).printStackTrace(new PrintStream(baos));
-            if (notes && notebuf().length() > 0) {
-                PrintWriter pw = new PrintWriter(baos);
-                pw.println();
-                pw.println("Thread notes:");
-                pw.println(notebuf().toString());
-                clearnotes();
-                pw.flush();
-            }
-            byte[] b = baos.toByteArray();
-            BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(b)));
-            String s = null;
-            try {
-                String m = "";
-                while((s = br.readLine()) != null) m += s + "\n";
-                if (m.length() > 0) log(o, m.substring(0, m.length() - 1), level);
-            } catch (IOException e) {
-                // FEATURE: use org.ibex.io.Stream's here
-                logstream.println(colorize(RED, true, "Logger: exception thrown by ByteArrayInputStream; this should not happen"));
-            }
-            lastClassName = "";
-            return;
-        }
-
-        String str = message.toString();
-        if (str.indexOf('\n') != -1) lastClassName = "";
-        while(str.indexOf('\t') != -1)
-            str = str.substring(0, str.indexOf('\t')) + "    " + str.substring(str.indexOf('\t') + 1);
-
-        classname = colorize(GRAY, false, classname);
-        int levelcolor = GRAY;
-        boolean bright = true;
-        switch (level) {
-            case DIAGNOSTIC:  levelcolor = GREEN; bright = false; break;
-            case ECHO:        levelcolor = BLUE;  bright = true;  break;
-            case DEBUG:       levelcolor = BROWN; bright = true;  break;
-            case INFO:        levelcolor = GRAY;  bright = false; break;
-            case WARN:        levelcolor = BROWN; bright = false; break;
-            case ERROR:       levelcolor = RED;   bright = true;  break;
-        }
-
-        while(str.indexOf('\n') != -1) {
-            logstream.println(classname + colorize(levelcolor, bright, str.substring(0, str.indexOf('\n'))));
-            classname = logDates ? "                " : "                      ";
-            classname = colorize(GRAY,false,classname);
-            str = str.substring(str.indexOf('\n') + 1);
-        }
-        logstream.println(classname + colorize(levelcolor, bright, str));
-    }
-
-    // FIXME: Update for new api
-    /*public static void recursiveLog(String indent, String name, Object o) throws JSExn {
-        if (!name.equals("")) name += " : ";
-
-        if (o == null) {
-            JS.log(indent + name + "<null>");
-
-        } else if (o instanceof JSArray) {
-            JS.log(indent + name + "<array>");
-            JSArray na = (JSArray)o;
-            for(int i=0; i<na.length(); i++)
-                recursiveLog(indent + "  ", i + "", na.elementAt(i));
-
-        } else if (o instanceof JS) {
-            JS.log(indent + name + "<object>");
-            JS s = (JS)o;
-            Enumeration e = s.keys();
-            while(e.hasMoreElements()) {
-                Object key = e.nextElement();
-                if (key != null)
-                    recursiveLog(indent + "  ", key.toString(),
-                                 (key instanceof Integer) ?
-                                 s.get(((Integer)key)) : s.get(key.toString()));
-            }
-        } else {
-            JS.log(indent + name + o);
-
-        }
-    }*/
-
-}
diff --git a/src/org/ibex/util/MSPack.c b/src/org/ibex/util/MSPack.c
deleted file mode 100644 (file)
index f09cf35..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
-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) {
-                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;
-}
-
-// FEATURE: Remove this to possibly avoid pulling in stdio from libc 
-// (it may be getting pulled in anyway from malloc or something)
-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
-};
-
-extern char *user_info[1024];
-
-int mspack_main() {
-    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);
-        
-    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;
-    
-    return 0;
-}
diff --git a/src/org/ibex/util/MSPack.java b/src/org/ibex/util/MSPack.java
deleted file mode 100644 (file)
index 6236df6..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.ibex.util;
-
-import org.ibex.core.Main;
-import org.ibex.util.*;
-import java.io.*;
-import org.ibex.nestedvm.*;
-import org.ibex.nestedvm.Runtime;
-
-public class MSPack {
-    private static byte[] image;
-    
-    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 {
-        try {
-            Runtime vm = (Runtime)Class.forName("org.ibex.util.MIPSApps").newInstance();
-            byte[] cab = InputStreamToByteArray.convert(cabIS);
-            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"} );
-            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");
-        } catch(Exception e) {
-            throw new MSPackException(e.toString());
-        }
-    }
-    
-    public String[] getFileNames() { return fileNames; }
-    public int[] getLengths() { return lengths; }
-    public InputStream getInputStream(int index) {
-        return new KnownLength.KnownLengthInputStream(new ByteArrayInputStream(data[index]), data[index].length);
-    }
-    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();
-    }
-}
-
diff --git a/src/org/ibex/util/NanoGoat.java b/src/org/ibex/util/NanoGoat.java
deleted file mode 100644 (file)
index 2b5b772..0000000
+++ /dev/null
@@ -1,475 +0,0 @@
-package org.ibex.util;
-import java.util.*;
-import java.io.*;
-import java.util.zip.*;
-import org.apache.bcel.*;
-import org.apache.bcel.generic.*;
-import org.apache.bcel.classfile.*;
-import org.apache.bcel.util.*;
-
-public class NanoGoat {
-
-    public static final boolean deleteMethods = false;
-    public static SyntheticRepository repo = null;
-    public static HashSet dest = new HashSet();
-    public static HashSet constructed = new HashSet();
-    public static String outdir = ".";
-    public static Hashtable subclasses = new Hashtable();
-    public static Hashtable uponconstruction = new Hashtable();
-    public static Hashtable mark_if_constructed = new Hashtable();
-    public static int level = 0;
-
-    public NanoGoat() { }
-
-    public void loadAllMethods(String classname) throws Exception {
-        visitJavaClass(repo.loadClass(classname));
-        Method[] meths = getMethods(repo.loadClass(classname));
-        for(int i=0; i<meths.length; i++)
-            visitJavaMethod(repo.loadClass(classname), meths[i]);
-    }
-
-    public void loadAllStaticMethods(String classname) throws Exception {
-        visitJavaClass(repo.loadClass(classname));
-        Method[] meths = getMethods(repo.loadClass(classname));
-        for(int i=0; i<meths.length; i++)
-            if (meths[i].isStatic())
-                visitJavaMethod(repo.loadClass(classname), meths[i]);
-    }
-
-    public void loadMethod(String classAndMethodName) throws Exception {
-        String classname = classAndMethodName.substring(0, classAndMethodName.lastIndexOf('.'));
-        String methodname = classAndMethodName.substring(classAndMethodName.lastIndexOf('.') + 1);
-        if (classname.endsWith("." + methodname)) methodname = "<init>";
-        visitJavaClass(repo.loadClass(classname));
-        Method[] meths = getMethods(repo.loadClass(classname));
-        for(int i=0; i<meths.length; i++)
-            if (meths[i].getName().equals(methodname))
-                visitJavaMethod(repo.loadClass(classname), meths[i]);
-    }
-    public static void main(String[] args) throws Exception {
-        int start = 1;
-        repo = SyntheticRepository.getInstance(new ClassPath(args[0]));
-
-        NanoGoat bcp = new NanoGoat();
-        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
-        for(String s = br.readLine(); s != null; s = br.readLine()) {
-            s = s.trim();
-            if (s.length() == 0) continue;
-            try {
-                if (s.endsWith("$")) s = s.substring(0, s.length() - 1);
-                if (s.endsWith(".class")) {
-                    bcp.visitJavaClass(repo.loadClass(s.substring(0, s.length() - 6)));
-                } else {
-                    JavaClass cl = repo.loadClass(s.substring(0, s.lastIndexOf('.')));;
-                    bcp.visitJavaClass(cl);
-                    bcp.loadMethod(s);
-                    Field[] fields = cl.getFields();
-                    for(int j=0; j<fields.length; j++) {
-                        if (fields[j].getName().equals(s.substring(s.lastIndexOf('.') + 1)))
-                            bcp.visitJavaField(fields[j], cl);
-                    }
-                }
-            } catch (Exception e) {
-                System.out.println("WARNING: couldn't load class for " + s);
-                e.printStackTrace();
-            }
-        }
-
-        System.out.println("\n\n======================================================================\n");
-
-        // we call start(), but the VM calls run()...
-        bcp.loadMethod("java.lang.Thread.run");
-        bcp.loadAllMethods("java.lang.SecurityContext");
-        bcp.loadAllMethods("java.lang.ThreadDeath");
-        bcp.loadMethod("java.lang.Thread.run");                  // we call start(), but the VM calls run()...
-        bcp.loadMethod("java.lang.ref.Reference.enqueue");       // the GC calls this directly
-        bcp.loadAllMethods("gnu.gcj.runtime.StringBuffer");      // the compiler emits calls directly to this class
-        bcp.loadAllMethods("gnu.gcj.convert.Input_UTF8");        // retrieved via reflection
-        bcp.loadAllMethods("gnu.gcj.convert.Output_UTF8");       // retrieved via reflection
-        bcp.loadMethod("gnu.gcj.convert.BytesToUnicode.done");   // called by natString
-        bcp.loadAllStaticMethods("java.lang.reflect.Modifier");        // used all over natClass...
-
-        // the Interpreter.run() method's switchblock is too complex...
-        bcp.loadAllMethods("org.ibex.js.Interpreter$TryMarker");
-        bcp.loadAllMethods("org.ibex.js.Interpreter$CatchMarker");
-        bcp.loadAllMethods("org.ibex.js.Interpreter$LoopMarker");
-        bcp.loadAllMethods("org.ibex.js.Interpreter$FinallyData");
-        bcp.loadAllMethods("org.ibex.js.Interpreter$CallMarker");
-        bcp.loadAllMethods("org.ibex.js.Interpreter");
-        bcp.loadAllMethods("org.ibex.js.Interpreter$1");
-        bcp.loadAllMethods("org.ibex.js.Interpreter$Stub");
-        bcp.loadAllMethods("org.ibex.js.Trap$TrapScope");
-        bcp.loadMethod("org.ibex.js.JSScope.top");
-        bcp.loadAllMethods("org.ibex.Picture$1");
-        bcp.loadAllMethods("org.ibex.Ibex$Blessing");
-        bcp.loadAllMethods("org.ibex.util.SSL$entropySpinner");
-        bcp.loadAllMethods("org.ibex.HTTP$HTTPInputStream");
-        bcp.visitJavaClass(repo.loadClass("org.ibex.util.SSL"));
-
-        bcp.loadAllMethods("java.util.Hashtable$HashIterator");
-        bcp.loadMethod("java.util.SimpleTimeZone.useDaylightTime");
-        bcp.visitJavaClass(repo.loadClass("gnu.gcj.runtime.FinalizerThread"));
-        bcp.visitJavaClass(repo.loadClass("gnu.gcj.runtime.FirstThread"));
-
-        // to ensure we get all the stuff that might be called from CNI
-        bcp.loadAllMethods("org.ibex.plat.Linux");
-        bcp.loadAllMethods("org.ibex.plat.X11");
-        bcp.loadAllMethods("org.ibex.plat.GCJ");
-        bcp.loadAllMethods("org.ibex.plat.POSIX");
-        bcp.loadAllMethods("org.ibex.plat.X11$X11Surface");
-        bcp.loadAllMethods("org.ibex.plat.X11$X11PixelBuffer");
-        bcp.loadAllMethods("org.ibex.plat.X11$X11Picture");
-        bcp.loadAllMethods("org.ibex.Surface");
-        bcp.loadAllMethods("org.ibex.Picture");
-        bcp.loadAllMethods("org.ibex.PixelBuffer");
-
-        // primary entry point
-        bcp.loadMethod("org.ibex.plat.Linux.main");
-        System.out.println();
-
-        System.out.println("Dumping...");
-        ZipFile zf = new ZipFile(args[0]);
-        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(args[0] + ".tmp"));
-        Enumeration e = zf.entries();
-        while(e.hasMoreElements()) {
-            ZipEntry ze = ((ZipEntry)e.nextElement());
-            String ss = ze.getName();
-            if (!ss.endsWith(".class")) continue;
-            ss = ss.substring(0, ss.length() - 6);
-            ss = ss.replace('/', '.');
-            dump(repo.loadClass(ss), zos);
-        }
-        zos.close();
-        zf.close();
-        new File(args[0] + ".tmp").renameTo(new File(args[0] + ".pruned"));
-    }
-
-    public static void dump(JavaClass clazz, ZipOutputStream zos) throws Exception {
-        if (!dest.contains(clazz)) return;
-
-        ConstantPoolGen newcpg = new ConstantPoolGen(clazz.getConstantPool());
-        ClassGen cg = new ClassGen(clazz);
-        InstructionFactory factory = new InstructionFactory(cg, newcpg);
-        cg.setMajor(46);
-        cg.setMinor(0);
-        cg.setConstantPool(newcpg);
-
-        boolean isconstructed = false;
-        Method[] methods = getMethods(clazz);
-        for(int i=0; i<methods.length; i++)
-            if (dest.contains(methods[i]) && methods[i].getName().equals("<init>"))
-                isconstructed = true;
-
-        // we can only prune static fields (to avoid altering object layout, which is hardcoded into
-        // CNI code), but that's okay since instance fields don't contribute to binary size
-        Field[] fields = clazz.getFields();
-        for(int i=0; i<fields.length; i++) {
-            if ((!dest.contains(fields[i]) && fields[i].isStatic()) ||
-                ((!(constructed.contains(clazz))) && !fields[i].isStatic())) { 
-                System.out.println("  pruning field " + clazz.getClassName() + "." + fields[i].getName());
-                // FIXME this confuses gcj in jar-at-a-time mode
-                //cg.removeField(fields[i]);
-            }
-        }
-
-        int numMethods = 0;
-        boolean good = false;
-        for(int i=0; i<methods.length; i++) {
-            if (dest.contains(methods[i]) && (isconstructed || methods[i].isStatic())) {
-                good = true;
-            } else {
-                if (methods[i].getCode() == null) {
-                    System.out.println("  empty codeblock: " + clazz.getClassName() + "." + methods[i].getName());
-                } else {
-                    System.out.println("  pruning " +(isconstructed?"":"unconstructed")+ " method " +
-                                       clazz.getClassName() + "." + methods[i].getName());
-                    if (deleteMethods) { cg.removeMethod(methods[i]); continue; }
-                    MethodGen mg = new MethodGen(methods[i], clazz.getClassName(), newcpg);
-                    mg.removeExceptions();
-                    InstructionList il = new InstructionList();
-                    mg.setInstructionList(il);
-                    InstructionHandle ih_0 = il.append(factory.createNew("java.lang.UnsatisfiedLinkError"));
-                    il.append(InstructionConstants.DUP);
-                    il.append(factory.createInvoke("java.lang.UnsatisfiedLinkError",
-                                                   "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
-                    il.append(InstructionConstants.ATHROW);
-                    mg.setMaxStack();
-                    mg.setMaxLocals();
-                    mg.removeExceptions();
-                    mg.removeLocalVariables();
-                    mg.removeExceptionHandlers();
-                    mg.removeLineNumbers();
-                    cg.replaceMethod(methods[i], mg.getMethod());
-                    il.dispose();
-                }
-            }
-        }
-
-        // FIXME: chain up to superclass' <clinit>... that might remove the need for this hack
-        // FIXME: gcj compiling in jar-at-a-time mode can't be convinced to let classes outside the jar override
-        //        the ones inside the jar
-        good = true;
-
-        if (!good && !clazz.isAbstract() && !clazz.isInterface()) {
-            System.out.println("DROPPING " + clazz.getClassName());
-            JavaClass[] ifaces = clazz.getInterfaces();
-            String[] ifacestrings = new String[ifaces.length];
-            for(int i=0; i<ifaces.length; i++) ifacestrings[i] = ifaces[i].getClassName();
-            cg = new ClassGen(clazz.getClassName(),
-                              clazz.getSuperClass().getClassName(),
-                              clazz.getFileName(),
-                              clazz.getAccessFlags(),
-                              ifacestrings,
-                              newcpg);
-        } else {
-            System.out.println("dumping " + clazz.getClassName());
-        }
-        FilterOutputStream noclose = new FilterOutputStream(zos) { public void close() throws IOException { flush(); } };
-        zos.putNextEntry(new ZipEntry(clazz.getClassName().replace('.', '/')+".class"));
-        cg.getJavaClass().dump(noclose);
-        noclose.flush();
-    }
-
-    public JavaClass sig2class(String sig) throws Exception {
-        if (sig == null) return null;
-        while (sig.length() > 0 && (sig.charAt(0) == 'L' || sig.charAt(0) == '[')) {
-            if (sig.charAt(0) == 'L') sig = sig.substring(1, sig.length() - 1);
-            else if (sig.charAt(0) == '[') sig = sig.substring(1, sig.length());
-        }
-        if (sig.length() <= 1) return null;
-        if (sig.equals("<null object>")) return null;
-        if (sig.startsWith("<return address")) return null;
-        return repo.loadClass(sig);
-    }
-    public void load(String sig) throws Exception {
-        if (sig == null) return;
-        while (sig.length() > 0 && (sig.charAt(0) == 'L' || sig.charAt(0) == '[')) {
-            if (sig.charAt(0) == 'L') sig = sig.substring(1, sig.length() - 1);
-            else if (sig.charAt(0) == '[') sig = sig.substring(1, sig.length());
-        }
-        if (sig.length() <= 1) return;
-        if (sig.equals("<null object>")) return;
-        if (sig.startsWith("<return address")) return;
-        visitJavaClass(repo.loadClass(sig));
-    }
-    public void load(Type t) throws Exception {
-        if (t == null) return;
-        if (t instanceof ArrayType) load(((ArrayType)t).getElementType());
-        if (!(t instanceof ObjectType)) return;
-        load(((ObjectType)t).getClassName());
-    }
-
-    public String getMethodSignature(Method m, ConstantPoolGen cpg) throws Exception { return m.getName() + m.getSignature(); }
-    public String getMethodSignature(InvokeInstruction ii, ConstantPoolGen cpg) throws Exception {
-        String sig = "";
-        Type[] argtypes = ii.getArgumentTypes(cpg);
-        for(int j=0; j<argtypes.length; j++) sig += argtypes[j].getSignature();
-        return ii.getMethodName(cpg) + "(" + sig + ")" + ii.getReturnType(cpg).getSignature();
-    }
-
-    public void visitJavaMethod(JavaClass jc, Method method) throws Exception {
-        visitJavaClass(jc);
-        if (jc.getClassName().indexOf("SharedLib") != -1) return;
-        if (jc.getClassName().indexOf("Datagram") != -1) return;
-        if (jc.getClassName().startsWith("java.io.Object")) return;
-        if (jc.getClassName().startsWith("java.util.jar.")) return;
-        if (jc.getClassName().startsWith("java.net.Inet6")) return;
-
-        // gcj bug; gcj can't compile this method from a .class file input; I have no idea why
-        if (jc.getClassName().equals("java.lang.System") && method.getName().equals("runFinalizersOnExit")) return;
-
-        // we know these can't be constructed
-        if (method.getName().equals("<init>") && jc.getClassName().startsWith("java.lang.reflect.")) return;
-
-        if (dest.contains(method)) return;
-        dest.add(method);
-
-        if (method.getName().equals("<clinit>") && jc.getSuperClass() != null)
-            loadMethod(jc.getSuperClass().getClassName() + ".<clinit>");
-
-        if (method.isStatic() || method.getName().equals("<init>")) loadMethod(jc.getClassName() + ".<clinit>");
-        if (method.getName().equals("<init>")) {
-            // FIXME: generalize to all perinstancemethods
-            constructed.add(jc);
-            HashSet hs = (HashSet)uponconstruction.get(jc);
-            if (hs != null) {
-                Iterator it = hs.iterator();
-                while(it.hasNext()) visitJavaMethod(jc, (Method)it.next());
-            }
-            loadMethod(jc.getClassName() + ".equals");
-            loadMethod(jc.getClassName() + ".hashCode");
-            loadMethod(jc.getClassName() + ".toString");
-            loadMethod(jc.getClassName() + ".finalize");
-            loadMethod(jc.getClassName() + ".clone");
-        }
-
-        ConstantPoolGen cpg = new ConstantPoolGen(method.getConstantPool());
-        if (!method.isStatic() && !constructed.contains(jc)) {
-            HashSet hs = (HashSet)uponconstruction.get(jc);
-            if (hs == null) uponconstruction.put(jc, hs = new HashSet());
-            hs.add(method);
-            markMethodInSubclasses(jc, method, cpg);
-            dest.remove(method);
-            return;
-        }
-
-        level += 2;
-        for(int i=0; i<level; i++) System.out.print(" ");
-        System.out.print(jc.getClassName() + "." + getMethodSignature(method, cpg));
-        markMethodInSubclasses(jc, method, cpg);
-        if (method.getCode() == null) { System.out.println(); level -= 2; return; }
-        byte[] code = method.getCode().getCode();
-        InstructionList il = new InstructionList(code);
-        InstructionHandle[] instructions = il.getInstructionHandles();
-        System.out.println(" [" + instructions.length + " instructions]");
-        for(int i=0; i<instructions.length; i++){ 
-            Instruction instr = instructions[i].getInstruction();;
-            if (instr instanceof Select) {
-                InstructionHandle[] ih2 = ((Select)instr).getTargets();
-                InstructionHandle[] ih3 = new InstructionHandle[instructions.length + ih2.length];
-                System.arraycopy(instructions, 0, ih3, 0, instructions.length);
-                System.arraycopy(ih2, 0, ih3, instructions.length, ih2.length);
-                instructions = ih3;
-            }
-            if (instr instanceof LoadClass) {
-                ObjectType ot = (ObjectType)((LoadClass)instr).getLoadClassType(cpg);
-                if (ot != null) loadMethod(ot.getClassName() + ".<clinit>");
-            }
-            if (instr instanceof CPInstruction) load(((CPInstruction)instr).getType(cpg));
-            if (instr instanceof TypedInstruction) load(((TypedInstruction)instr).getType(cpg));
-            if (instr instanceof NEW) loadMethod(((NEW)instr).getLoadClassType(cpg).getClassName() + ".<init>");
-            if (instr instanceof org.apache.bcel.generic.FieldOrMethod)
-                load(((org.apache.bcel.generic.FieldOrMethod)instr).getClassType(cpg));
-            if (instr instanceof org.apache.bcel.generic.FieldInstruction) {
-                load(((org.apache.bcel.generic.FieldInstruction)instr).getFieldType(cpg));
-                load(((org.apache.bcel.generic.FieldInstruction)instr).getType(cpg));
-                String fieldName = ((org.apache.bcel.generic.FieldInstruction)instr).getFieldName(cpg);
-                JavaClass jc2 = repo.loadClass(((ObjectType)((org.apache.bcel.generic.FieldInstruction)instr).
-                                                getLoadClassType(cpg)).getClassName());
-                Field[] fields = jc2.getFields();
-                for(int j=0; j<fields.length; j++) if (fields[j].getName().equals(fieldName)) visitJavaField(fields[j], jc2);
-            }
-            if (instr instanceof InvokeInstruction) {
-                InvokeInstruction ii = (InvokeInstruction)instr;
-                String ii_sig = getMethodSignature(ii, cpg);
-                JavaClass c = sig2class(ii.getLoadClassType(cpg).getSignature());
-
-                load(ii.getType(cpg));
-                Method[] meths = getMethods(c);
-                boolean good = false;
-                for(int i2=0; i2<meths.length; i2++) {
-                    if (getMethodSignature(meths[i2], cpg).equals(ii_sig)) {
-                        visitJavaMethod(c, meths[i2]);
-                        good = true;
-                        break;
-                    }
-                } 
-                if (!good) throw new Exception("couldn't find method " + getMethodSignature(ii, cpg) + " in " + c.getClassName());
-            }
-        }
-        Type[] argtypes = method.getArgumentTypes();
-        for(int i=0; i<argtypes.length; i++) load(argtypes[i]);
-        if (method.getExceptionTable() != null) {
-            String[] exntypes = method.getExceptionTable().getExceptionNames();
-            for(int i=0; i<exntypes.length; i++) load(exntypes[i]);
-        }
-        level -= 2;
-    }
-
-    public void visitJavaField(Field field, JavaClass clazz) throws Exception {
-        if (dest.contains(field)) return;
-        dest.add(field);
-        if (field.isStatic()) loadMethod(clazz.getClassName() + ".<clinit>");
-    }
-
-    public void visitJavaClass(JavaClass clazz) throws Exception {
-        if (dest.contains(clazz)) return;
-        dest.add(clazz);
-
-        ConstantPoolGen cpg = new ConstantPoolGen(clazz.getConstantPool());
-        level += 2;
-        for(int i=0; i<level; i++) System.out.print(" ");
-        System.out.println(clazz.getClassName() + ".class");
-
-        JavaClass superclass = clazz.getSuperClass();
-        for(JavaClass sup = superclass; sup != null; sup = sup.getSuperClass()) {
-            if (subclasses.get(sup) == null) subclasses.put(sup, new HashSet());
-            ((HashSet)subclasses.get(sup)).add(clazz);
-        }
-        JavaClass[] interfaces = clazz.getAllInterfaces();
-        for(int i=0; i<interfaces.length; i++) {
-            if (subclasses.get(interfaces[i]) == null) subclasses.put(interfaces[i], new HashSet());
-            ((HashSet)subclasses.get(interfaces[i])).add(clazz);
-        }
-
-        for(JavaClass sup = superclass; sup != null; sup = sup.getSuperClass()) {
-            visitJavaClass(sup);
-            remarkMethods(sup, clazz, cpg);
-        }
-        for(int i=0; i<interfaces.length; i++) {
-            visitJavaClass(interfaces[i]);
-            remarkMethods(interfaces[i], clazz, cpg);
-        }
-
-        Field[] fields = clazz.getFields();
-        for(int i=0; i<fields.length; i++) {
-            if (!fields[i].isStatic()) visitJavaField(fields[i], clazz);
-            else {
-                Type t = fields[i].getType();
-                if (t instanceof ObjectType) load(t);
-            }
-        }
-        level -= 2;
-    }
-
-    public void markMethodInSubclasses(JavaClass c, Method m, JavaClass subclass, ConstantPoolGen cpg) throws Exception {
-        if (m.isStatic()) return;
-        if (m.getName().equals("<init>")) return;
-        if (m.getName().equals("equals")) return;
-        if (m.getName().equals("hashCode")) return;
-        if (m.getName().equals("clone")) return;
-        if (m.getName().equals("finalize")) return;
-        if (m.getName().equals("toString")) return;
-        String sig = getMethodSignature(m, cpg);
-        Method[] submethods = getMethods(subclass);
-        for(int j=0; j<submethods.length; j++)
-            if (getMethodSignature(submethods[j], cpg).equals(sig))
-                visitJavaMethod(subclass, submethods[j]);
-    }
-    public void markMethodInSubclasses(JavaClass c, Method m, ConstantPoolGen cpg) throws Exception {
-        if (m.isStatic()) return;
-        if (m.getName().equals("<init>")) return;
-        HashSet s = (HashSet)subclasses.get(c);
-        if (s == null) return;
-        Object[] subclasses = s.toArray();
-        for(int i=0; i<subclasses.length; i++) {
-            JavaClass subclass = (JavaClass)subclasses[i];
-            if (subclass == c) continue;
-            markMethodInSubclasses(c, m, subclass, cpg);
-        }
-    }
-        
-    public void remarkMethods(JavaClass c, ConstantPoolGen cpg) throws Exception {
-        Method[] meths =getMethods(c);
-        for(int j=0; j<meths.length; j++)
-            if (dest.contains(meths[j]) ||
-                (uponconstruction.get(c) != null && ((HashSet)uponconstruction.get(c)).contains(meths[j])))
-                markMethodInSubclasses(c, meths[j], cpg);
-    }
-
-    public void remarkMethods(JavaClass c, JavaClass target, ConstantPoolGen cpg) throws Exception {
-        Method[] meths = getMethods(c);
-        for(int j=0; j<meths.length; j++)
-            if (dest.contains(meths[j]) ||
-                (uponconstruction.get(c) != null && ((HashSet)uponconstruction.get(c)).contains(meths[j])))
-                markMethodInSubclasses(c, meths[j], target, cpg);
-    }
-
-    public static Hashtable methodsHashtable = new Hashtable();
-    public static Method[] getMethods(JavaClass c) {
-        Method[] ret = (Method[])methodsHashtable.get(c);
-        if (ret == null) methodsHashtable.put(c, ret = c.getMethods());
-        return ret;
-    }
-
-}
diff --git a/src/org/ibex/util/PackBytesIntoString.java b/src/org/ibex/util/PackBytesIntoString.java
deleted file mode 100644 (file)
index 1e07e86..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-/** packs 8-bit bytes into a String of 7-bit chars (to avoid the UTF-8 non-ASCII penalty) */
-public class PackBytesIntoString {
-
-    public static String pack(byte[] b, int off, int len) throws IllegalArgumentException {
-        if (len % 7 != 0) throw new IllegalArgumentException("len must be a multiple of 7");
-        StringBuffer ret = new StringBuffer();
-        for(int i=off; i<off+len; i += 7) {
-            long l = 0;
-            for(int j=6; j>=0; j--) {
-                l <<= 8;
-                l |= (b[i + j] & 0xff);
-            }
-            for(int j=0; j<8; j++) {
-                ret.append((char)(l & 0x7f));
-                l >>= 7;
-            }
-        }
-        return ret.toString();
-    }
-
-    public static byte[] unpack(String s) throws IllegalArgumentException {
-        if (s.length() % 8 != 0) throw new IllegalArgumentException("string length must be a multiple of 8");
-        byte[] ret = new byte[(s.length() / 8) * 7];
-        for(int i=0; i<s.length(); i += 8) {
-            long l = 0;
-            for(int j=7; j>=0; j--) {
-                l <<= 7;
-                l |= (s.charAt(i + j) & 0x7fL);
-            }
-            for(int j=0; j<7; j++) {
-                ret[(i / 8) * 7 + j] = (byte)(l & 0xff);
-                l >>= 8;
-            }
-        }
-        return ret;
-    }
-}
diff --git a/src/org/ibex/util/Preprocessor.java b/src/org/ibex/util/Preprocessor.java
deleted file mode 100644 (file)
index 4698fdc..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-import gnu.regexp.*;
-import java.util.*;
-import java.io.*;
-
-/**
- *   A VERY crude, inefficient Java preprocessor
- *
- *   //#define FOO bar baz       -- replace all instances of token FOO with "bar baz"
- *   //#replace foo/bar baz/bop  -- DUPLICATE everything between here and //#end,
- *                                  replacing foo with bar and baz with bop in the *second* copy
- *   //#switch(EXPR)             -- switch on strings
- *       case "case1":
- *   //#end
- *
- *   Replacements are done on a token basis.  Tokens are defined as a
- *   sequence of characters which all belong to a single class.  The
- *   two character classes are:
- *
- *     - [a-zA-Z0-9_]
- *     - all other non-whitespace characters
- */
-public class Preprocessor {
-
-    public static String replaceAll(String source, String regexp, String replaceWith) {
-        try {
-            RE re = new RE(regexp, 0, RESyntax.RE_SYNTAX_PERL5);
-            return (String)re.substituteAll(source, replaceWith);
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    public static void main(String[] args) throws Exception {
-        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
-        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
-
-        // process stdin to stdout
-        Preprocessor cc = new Preprocessor(br, bw);
-        Vector err = cc.process();
-        bw.flush();
-
-        // handle errors
-        boolean errors = false;
-        for (int i=0; i < err.size(); i++) { if (err.get(i) instanceof Error) errors = true; System.err.println(err.get(i)); }
-        if (errors) throw new Exception();
-    }
-
-    private Reader r;
-    private Writer w;
-    private LineNumberReader in;
-    private PrintWriter out;
-
-    private Hashtable replace = new Hashtable();
-    private Hashtable[] repeatreplaces = null;
-    private Vector sinceLastRepeat = null;
-    private Vector err = new Vector();
-
-    private int enumSwitch = 0; // number appended to variable used in switch implementation
-
-   
-    public Preprocessor(Reader reader, Writer writer) {
-        setReader(reader);
-        setWriter(writer);
-    }
-
-    public void setReader(Reader reader) { r = reader; if (r != null) in = new LineNumberReader(r); }
-    public Reader getReader() { return r; }
-
-    public void setWriter(Writer writer) { w = writer; if (w != null) out = new PrintWriter(w); }
-    public Writer getWriter() { return w; }
-
-
-    /** process data from reader, write to writer, return vector of errors */
-    public Vector process() throws IOException {
-        err.clear();
-
-        String s = null;
-PROCESS:
-        while((s = in.readLine()) != null) {
-            if (sinceLastRepeat != null) sinceLastRepeat.addElement(s);
-            String trimmed = s.trim();
-
-            if (trimmed.startsWith("//#define ")) {
-                if (trimmed.length() == 9 || trimmed.charAt(9) != ' ') {
-                    err.add(new Error("#define badly formed, ignored")); continue PROCESS;
-                }
-                int keyStart = indexOfNotWS(trimmed, 9);
-                if (keyStart == -1) {
-                    err.add(new Error("#define requires KEY")); continue PROCESS;
-                }
-                int keyEnd = indexOfWS(trimmed, keyStart);
-
-                int macroStart = trimmed.indexOf('(');
-                int macroEnd = trimmed.indexOf(')');
-                if (macroStart > keyEnd) {
-                    // no macro is defined, just make sure something dumb like KEYNA)ME hasn't been done
-                    if (macroEnd < keyEnd) { err.add(new Error("#define key contains invalid char: ')'")); continue PROCESS; }
-                    macroStart = macroEnd = -1;
-                }
-
-                if (macroStart == 0) {
-                    err.add(new Error("#define macro requires name")); continue PROCESS;
-                } else if (macroStart > 0) {
-                    if (macroStart > macroEnd) { err.add(new Error("#define macro badly formed")); continue PROCESS; }
-                    if (macroStart+1 == macroEnd) { err.add(new Error("#define macro requires property name")); continue PROCESS; }
-
-                    JSFunctionMacro fm = new JSFunctionMacro();
-                    String key = trimmed.substring(keyStart, macroStart);
-                    String unbound = trimmed.substring(macroStart +1, macroEnd);
-                    int unboundDiv = unbound.indexOf(',');
-                    if (unboundDiv == -1) {
-                        fm.unbound1 = unbound;
-                    } else {
-                        fm.unbound1 = unbound.substring(0, unboundDiv);
-                        fm.unbound2 = unbound.substring(unboundDiv +1);
-                        if (fm.unbound1.length() == 0) { err.add(new Error("#define macro property 1 requires name")); continue PROCESS; }
-                        if (fm.unbound2.length() == 0) { err.add(new Error("#define macro property 1 requires name")); continue PROCESS; }
-                    }
-                    fm.expression = trimmed.substring(keyEnd).trim();
-                    replace.put(key, fm);
-                } else {
-                    String key = trimmed.substring(keyStart, keyEnd);
-                    String val = trimmed.substring(keyEnd).trim();
-                    replace.put(key, val);
-                }
-                out.print("\n"); // preserve line numbers
-                
-            } else if (trimmed.startsWith("//#repeat ")) {
-                trimmed = trimmed.substring(9);
-                while(trimmed.charAt(trimmed.length() - 1) == '\\') {
-                    String s2 = in.readLine().trim();
-                    if (s2.startsWith("//")) s2 = s2.substring(2).trim();
-                    trimmed = trimmed.substring(0, trimmed.length() - 1) + " " + s2;
-                    out.print("\n");  // preserve line numbers
-                }
-                StringTokenizer st = new StringTokenizer(trimmed, " ");
-                repeatreplaces = null;
-                while (st.hasMoreTokens()) {
-                    String tok = st.nextToken().trim();
-                    String key = tok.substring(0, tok.indexOf('/'));
-                    String vals = tok.substring(tok.indexOf('/') + 1);
-                    StringTokenizer st2 = new StringTokenizer(vals,"/");
-                    if(repeatreplaces == null) {
-                        repeatreplaces = new Hashtable[st2.countTokens()];
-                        for(int i=0;i<repeatreplaces.length;i++) repeatreplaces[i] = (Hashtable) replace.clone();
-                    }
-                    for(int i=0;st2.hasMoreTokens() && i<repeatreplaces.length;i++)
-                        repeatreplaces[i].put(key, st2.nextToken());
-                }
-                sinceLastRepeat = new Vector();
-                out.print("\n"); // preserve line numbers
-
-            } else if (trimmed.startsWith("//#end")) {
-                if (sinceLastRepeat == null) { err.add(new Warning("#end orphaned")); continue PROCESS; }
-                Hashtable save = replace;
-                out.print("\n");
-                for(int i=0;i<repeatreplaces.length;i++) {
-                    replace = repeatreplaces[i];
-                    for(int j=0; j<sinceLastRepeat.size() - 1; j++) out.print(processLine((String)sinceLastRepeat.elementAt(j), true));
-                }
-                sinceLastRepeat = null;
-                replace = save;
-
-            } else if (trimmed.startsWith("//#switch") || trimmed.startsWith("//#jswitch")) {
-                boolean jswitch =  trimmed.startsWith("//#jswitch");
-                int expStart = trimmed.indexOf('(') +1;
-                if (expStart < 1) { err.add(new Error("expected ( in #switch")); continue PROCESS; }
-                int expEnd = trimmed.lastIndexOf(')');
-                if (expEnd == -1) { err.add(new Error("expected ) in #switch")); continue PROCESS; }
-                if (expEnd - expStart <= 1) { err.add(new Error("badly formed #switch statement")); continue PROCESS; }
-                String expr = trimmed.substring(expStart, expEnd);
-
-                if(jswitch) {
-                    out.print("final org.ibex.js.JS ccSwitchExpr"+enumSwitch+" = " + expr + ";");
-                    out.print("if(org.ibex.js.JS.isString(ccSwitchExpr"+enumSwitch+")) {");
-                    out.print("final String ccSwitch"+enumSwitch+" = org.ibex.js.JS.toString(ccSwitchExpr"+enumSwitch+");");
-                } else {
-                    out.print("final String ccSwitch"+enumSwitch+" = "+expr+";  ");
-                }
-                out.print("SUCCESS:do { switch(ccSwitch"+enumSwitch+".length()) {\n");
-
-                Hashtable[] byLength = new Hashtable[255];
-                String key = null;
-                String Default = null;
-                for(trimmed = in.readLine().trim(); !trimmed.startsWith("//#end"); trimmed = in.readLine().trim()) {
-                    if (trimmed.startsWith("default:")) {
-                        Default = processLine(trimmed.substring(8), false);
-                        continue;
-                    }
-                    if (trimmed.startsWith("case ")) {
-                        // find key
-                        int strStart = trimmed.indexOf('\"') +1;
-                        if (strStart < 1) { err.add(new Error("expected opening of String literal")); continue PROCESS; }
-                        int strEnd = trimmed.indexOf('\"', strStart);
-                        if (strEnd == -1) { err.add(new Error("expected closing of String literal")); continue PROCESS; }
-                        key = trimmed.substring(strStart, strEnd);
-
-                        Hashtable thisCase = (Hashtable)byLength[key.length()];
-                        if (thisCase == null) byLength[key.length()] = thisCase = new Hashtable();
-                        thisCase.put(key, "");
-
-                        // find end of case definition
-                        int caseEnd = trimmed.indexOf(':', strEnd) +1;
-                        if (caseEnd < 1) { err.add(new Error("expected :")); continue PROCESS; }
-                        trimmed = trimmed.substring(caseEnd);
-                    }
-
-                    if (key != null) {
-                        Hashtable hash = byLength[key.length()];
-                        hash.put(key, (String)hash.get(key) + replaceAll(processLine(trimmed, false), "//[^\"]*$", "").trim() + "\n");
-                    } else {
-                        out.print(processLine(trimmed, false));
-                    }
-                }
-
-                for(int i=0; i<255; i++) {
-                    if (byLength[i] == null) continue;
-                    out.print("case " + i + ": { switch(ccSwitch"+enumSwitch+".charAt(0)) { ");
-                    buildTrie("", byLength[i]);
-                    out.print("}; break; }  ");
-                }
-                out.print("} "); /* switch */
-                if (Default != null) out.print(" " + Default);
-                out.print(" } while(false);\n"); /* OUTER */
-                if(jswitch) out.print("}");
-                enumSwitch++;
-
-            } else {
-                out.print(processLine(s, false));
-            }
-        }
-
-        return err;
-    }
-
-    private void buildTrie(String prefix, Hashtable cases) {
-        Enumeration caseKeys = cases.keys();
-        Vec keys = new Vec();
-        while(caseKeys.hasMoreElements()) keys.addElement(caseKeys.nextElement());
-        keys.sort(new Vec.CompareFunc() { public int compare(Object a, Object b) {
-            return ((String)a).compareTo((String)b);
-        } } );
-
-        for(int i=0; i<keys.size(); i++) {
-            if (!((String)keys.elementAt(i)).startsWith(prefix)) continue;
-            String prefixPlusOne = ((String)keys.elementAt(i)).substring(0, prefix.length() + 1);
-            if (i<keys.size()-1 && prefixPlusOne.equals((((String)keys.elementAt(i + 1)).substring(0, prefix.length() + 1)))) {
-                out.print("case \'" + prefixPlusOne.charAt(prefixPlusOne.length() - 1) + "\': { ");
-                out.print("switch(ccSwitch"+enumSwitch+".charAt(" + (prefix.length()+1) + ")) { ");
-                buildTrie(prefixPlusOne, cases);
-                out.print("} break; } ");
-                while(i<keys.size() && prefixPlusOne.equals(((String)keys.elementAt(i)).substring(0, prefix.length() + 1))) i++;
-                if (i<keys.size()) { i--; continue; }
-            } else {
-                out.print("case \'" + prefixPlusOne.charAt(prefixPlusOne.length() - 1) + "\': ");
-                String code = (String)cases.get(keys.elementAt(i));
-                code = code.substring(0, code.length());
-                String key = (String)keys.elementAt(i);
-                out.print("if (\""+key+"\".equals(ccSwitch"+enumSwitch+")) { if (true) do { " + code + " } while(false); break SUCCESS; } break;  ");
-            }
-        }
-    }
-
-    private String processLine(String s, boolean deleteLineEndings) throws IOException {
-        if (deleteLineEndings && s.indexOf("//") != -1) s = s.substring(0, s.indexOf("//"));
-        String ret = "";
-        for(int i=0; i<s.length(); i++) {
-            char c = s.charAt(i);
-            if (!Character.isLetter(c) && !Character.isDigit(c) && c != '_') {
-                ret += c;
-                continue;
-            }
-            int j;
-            for(j = i; j < s.length(); j++) {
-                c = s.charAt(j);
-                if (!Character.isLetter(c) && !Character.isDigit(c) && c != '_') break;
-            }
-            String tok = s.substring(i, j);
-            Object val = replace.get(tok);
-            if (val == null) {
-                ret += tok;
-                i = j - 1;
-            } else if (val instanceof JSFunctionMacro) {
-                if (s.charAt(j) != '(') { ret += tok; i = j - 1; continue; }
-                ret += ((JSFunctionMacro)val).process(s.substring(j+1, s.indexOf(')', j)));
-                i = s.indexOf(')', j);
-            } else {
-                ret += val;
-                i = j - 1;
-            }
-        }
-        if (!deleteLineEndings) ret += "\n";
-        return ret;
-    }
-
-    private static int indexOfWS(String s) { return indexOfWS(s, 0); }
-    private static int indexOfWS(String s, int beginIndex) {
-        if (s == null || beginIndex >= s.length()) return -1;
-        for (; beginIndex < s.length(); beginIndex++) {
-            if (s.charAt(beginIndex) == ' ') return beginIndex;
-        }
-        return s.length();
-    }
-
-    private static int indexOfNotWS(String s) { return indexOfWS(s, 0); }
-    private static int indexOfNotWS(String s, int beginIndex) {
-        if (s == null || beginIndex >= s.length()) return -1;
-        for (; beginIndex < s.length(); beginIndex++) {
-            if (s.charAt(beginIndex) != ' ') return beginIndex;
-        }
-        return -1;
-    }
-
-    public class Warning {
-        protected String msg;
-        protected int line;
-
-        public Warning() { msg = ""; }
-        public Warning(String m) { msg = m; if (in != null) line = in.getLineNumber(); }
-
-        public String toString() { return "WARNING Line "+line+": "+msg; }
-    }
-
-    public class Error extends Warning {
-        public Error() { super(); }
-        public Error(String m) { super(m); }
-        public String toString() { return "ERROR Line "+line+": "+msg; }
-    }
-
-    public static class JSFunctionMacro {
-        public String unbound1 = null;
-        public String unbound2 = null;
-        public String expression = null;
-        public String process(String args) {
-            String bound1 = null;
-            String bound2 = null;
-            if (unbound2 == null) {
-                bound1 = args;
-                return replaceAll(expression, unbound1, bound1);
-            } else {
-                bound1 = args.substring(0, args.indexOf(','));
-                bound2 = args.substring(args.indexOf(',') + 1);
-                return replaceAll(replaceAll(expression, unbound1, bound1), unbound2, bound2);
-            }
-        }
-    }
-}
-
diff --git a/src/org/ibex/util/Queue.java b/src/org/ibex/util/Queue.java
deleted file mode 100644 (file)
index 91b9b29..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-/** A simple synchronized queue, implemented as an array */
-public class Queue {
-
-    public Queue(int initiallength) { vec = new Object[initiallength]; }
-    
-    /** The store */
-    private Object[] vec;
-    
-    /** The index of the first node in the queue */
-    private int first = 0;
-    
-    /** The number of elements in the queue; INVARAINT: size <= vec.length */
-    private int size = 0;
-    
-    /** Grow the queue, if needed */
-    private void grow(int newlength) {
-        Object[] newvec = new Object[newlength];
-        if (first + size > vec.length) {
-            System.arraycopy(vec, first, newvec, 0, vec.length - first);
-            System.arraycopy(vec, 0, newvec, vec.length - first, size - (vec.length - first));
-        } else {
-            System.arraycopy(vec, first, newvec, 0, size);
-        }
-        first = 0;
-        vec = newvec;
-    }
-
-    /** The number of elements in the queue */    
-    public int size() { return size; }
-    
-    /** Empties the queue */
-    public synchronized void flush() {
-        first = 0;
-        size = 0;
-        for(int i=0; i<vec.length; i++) vec[i] = null;
-    }
-
-    /** Add an element to the front of the queue */
-    public synchronized void prepend(Object o) {
-        if (size == vec.length) grow(vec.length * 2);
-        first--;
-        if (first < 0) first += vec.length;
-        vec[first] = o;
-        size++;
-        if (size == 1) notify();
-    }
-    
-    /** Add an element to the back of the queue */
-    public synchronized void append(Object o) {
-        if (size == vec.length) grow(vec.length * 2);
-        if (first + size >= vec.length) vec[first + size - vec.length] = o;
-        else vec[first + size] = o;
-        size++;
-        if (size == 1) notify();
-    }
-    
-    /** Remove and return and element from the queue, blocking if empty. */
-    public Object remove() { return remove(true); }
-
-    /** Remove and return an element from the queue, blocking if
-        <tt>block</tt> is true and the queue is empty. */
-    public synchronized Object remove(boolean block) {
-
-        while (size == 0 && block) {
-            try { wait(); } catch (InterruptedException e) { }
-        }
-        
-        if (!block && size == 0) return null;
-        Object ret = vec[first];
-        first++;
-        size--;
-        if (first >= vec.length) first = 0;
-        return ret;
-    }
-
-    /** Returns the top element in the queue without removing it */
-    public synchronized Object peek() {
-        if (size == 0) return null;
-        return vec[first];
-    }
-
-}
diff --git a/src/org/ibex/util/Scheduler.java b/src/org/ibex/util/Scheduler.java
deleted file mode 100644 (file)
index a2ce69c..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.util;
-
-import java.io.IOException;
-
-import org.ibex.js.*;
-import org.ibex.util.*;
-import org.ibex.graphics.*;
-import org.ibex.plat.*;
-
-/** Implements cooperative multitasking */
-public class Scheduler {
-
-    // Public API Exposed to org.ibex /////////////////////////////////////////////////
-
-    private static Scheduler singleton;
-    private static String taskDesc(Task t) { return t instanceof JS ? JS.debugToString((JS)t) : t.toString(); }    
-    public static void add(Task t) { Log.debug(Scheduler.class, "scheduling " + taskDesc(t)); Scheduler.runnable.append(t); }
-    public static void init() { if (singleton == null) (singleton = Platform.getScheduler()).run(); }
-
-    private static Task current = null;
-
-    private static volatile boolean rendering = false;
-    private static volatile boolean again = false;
-
-    /** synchronizd so that we can safely call it from an event-delivery thread, in-context */
-    public static void renderAll() {
-        if (rendering) { again = true; return; }
-        synchronized(Scheduler.class) {
-            try {
-                rendering = true;
-                do {
-                    // FEATURE: this could be cleaner
-                    again = false;
-                    for(int i=0; i<Surface.allSurfaces.size(); i++) {
-                        Surface s = ((Surface)Surface.allSurfaces.elementAt(i));
-                        do { s.render(); } while(s.abort);
-                    }
-                } while(again);
-            } finally {
-                rendering = false;
-            }
-        }
-    }
-
-    
-
-    // API which must be supported by subclasses /////////////////////////////////////
-
-    /**
-     *  SCHEDULER INVARIANT: all scheduler implementations MUST invoke
-     *  Surface.renderAll() after performing a Task if no tasks remain
-     *  in the queue.  A scheduler may choose to invoke
-     *  Surface.renderAll() more often than that if it so chooses.
-     */
-    public void run() { defaultRun(); }
-    public Scheduler() { }
-
-
-    // Default Implementation //////////////////////////////////////////////////////
-
-    protected static Queue runnable = new Queue(50);
-    public void defaultRun() {
-        while(true) {
-            current = (Task)runnable.remove(true);
-            try {
-                // FIXME hideous
-                synchronized(this) {
-                    for(int i=0; i<Surface.allSurfaces.size(); i++) {
-                        Surface s = (Surface)Surface.allSurfaces.elementAt(i);
-                        if (current instanceof JS) {
-                            s._mousex = Integer.MAX_VALUE;
-                            s._mousey = Integer.MAX_VALUE;
-                        } else {
-                            s._mousex = s.mousex;
-                            s._mousey = s.mousey;
-                        }
-                    }
-                    Log.debug(Scheduler.class, "performing " + taskDesc(current));
-                    current.perform();
-                }
-                renderAll();
-            } catch (JSExn e) {
-                Log.info(Scheduler.class, "a JavaScript thread spawned with ibex.thread() threw an exception:");
-                Log.info(Scheduler.class,e);
-            } catch (Exception e) {
-                Log.info(Scheduler.class, "a Task threw an exception which was caught by the scheduler:");
-                Log.info(Scheduler.class, e);
-            } catch (Throwable t) {
-                t.printStackTrace();
-            }
-            // if an Error is thrown it will cause the engine to quit
-        }
-    }
-}
diff --git a/src/org/ibex/util/Semaphore.java b/src/org/ibex/util/Semaphore.java
deleted file mode 100644 (file)
index ad8376f..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-/** Simple implementation of a blocking, counting semaphore. */
-public class Semaphore {
-    
-    private int val = 0;
-
-    /** Decrement the counter, blocking if zero. */
-    public synchronized void block() {
-        while(val == 0) {
-            try {
-                wait();
-            } catch (InterruptedException e) {
-            } catch (Throwable e) {
-                if (Log.on) Log.info(this, "Exception in Semaphore.block(); this should never happen");
-                if (Log.on) Log.info(this, e);
-            }
-        }
-        val--;
-    }
-    
-    /** Incremenet the counter. */
-    public synchronized void release() {
-        val++;
-        notify();
-    }
-
-}
diff --git a/src/org/ibex/util/Simplex.java b/src/org/ibex/util/Simplex.java
deleted file mode 100644 (file)
index 2ae314a..0000000
+++ /dev/null
@@ -1,1345 +0,0 @@
-package org.ibex.util;
-import java.io.* ;
-import java.util.* ;
-
-public class Simplex {
-
-    public final static short FAIL = -1;
-    
-    public final static short NULL = 0;
-    public final static short FALSE = 0;
-    public final static short TRUE = 1;
-    
-    public final static short DEFNUMINV = 50;
-    
-    /* solve status values */
-    public final static short OPTIMAL = 0;
-    public final static short MILP_FAIL = 1;
-    public final static short INFEASIBLE = 2;
-    public final static short UNBOUNDED = 3;
-    public final static short FAILURE = 4;
-    public final static short RUNNING = 5;
-    
-    /* lag_solve extra status values */
-    public final static short FEAS_FOUND = 6;
-    public final static short NO_FEAS_FOUND = 7;
-    public final static short BREAK_BB = 8;
-    
-    public final static short FIRST_NI =       0;
-    public final static short RAND_NI = 1;
-    
-    public final static short LE = 0;
-    public final static short EQ = 1;
-    public final static short GE = 2;
-    public final static short OF = 3;
-    
-    public final static short MAX_WARN_COUNT = 20;
-    
-    public final static float DEF_INFINITE = (float)1e24; /* limit for dynamic range */
-    public final static float DEF_EPSB = (float)5.01e-7; /* for rounding RHS values to 0 determine     
-                                               infeasibility basis */
-    public final static float DEF_EPSEL = (float)1e-8; /* for rounding other values (vectors) to 0 */
-    public final static float DEF_EPSD  = (float)1e-6; /* for rounding reduced costs to zero */
-    public final static float DEF_EPSILON = (float)1e-3; /* to determine if a float value is integer */
-    
-    public final static float PREJ = (float)1e-3;  /* pivot reject (try others first) */
-    
-    public final static int ETA_START_SIZE = 10000; /* start size of array Eta. Realloced if needed */
-
-    static class Ref {
-        float value;
-        public Ref(float v) { value = v; }
-    }
-
-    //public static class Simplex {
-        /* Globals used by solver */
-        short JustInverted;
-        short Status;
-        short Doiter;
-        short DoInvert;
-        short Break_bb;
-
-        public short active;           /*TRUE if the globals point to this structure*/
-        public short debug;           /* ## Print B&B information */
-        public short trace;           /* ## Print information on pivot selection */
-        public int         rows;               /* Nr of constraint rows in the problem */
-        int       rows_alloc;          /* The allocated memory for Rows sized data */
-        int       columns_alloc;  
-        int       sum;                /* The size of the variables + the slacks */
-        int       sum_alloc;
-        int       non_zeros;          /* The number of elements in the sparce matrix*/
-        int       mat_alloc;           /* The allocated size for matrix sized 
-                                           structures */
-        MatrixArray  mat;                /* mat_alloc :The sparse matrix */
-        MatrixArray  alternate_mat;                /* mat_alloc :The sparse matrix */
-        int[]     col_end;            /* columns_alloc+1 :Cend[i] is the index of the
-                                         first element after column i.
-                                         column[i] is stored in elements 
-                                         col_end[i-1] to col_end[i]-1 */
-        int[]     col_no;             /* mat_alloc :From Row 1 on, col_no contains the
-                                         column nr. of the
-                                         nonzero elements, row by row */
-        short     row_end_valid;       /* true if row_end & col_no are valid */
-        int[]     row_end;            /* rows_alloc+1 :row_end[i] is the index of the 
-                                         first element in Colno after row i */
-        float[]  orig_rh;            /* rows_alloc+1 :The RHS after scaling & sign 
-                                         changing, but before `Bound transformation' */
-        float[]  rh;                   /* rows_alloc+1 :As orig_rh, but after Bound 
-                                           transformation */
-        float[]  rhs;          /* rows_alloc+1 :The RHS of the curent simplex  
-                                  tableau */
-        float[]  orig_upbo;          /* sum_alloc+1 :Bound before transformations */
-        float[]  orig_lowbo;           /*  "       "                   */
-        float[]  upbo;               /*  "       "  :Upper bound after transformation 
-                                          & B&B work*/
-        float[]  lowbo;              /*  "       "  :Lower bound after transformation
-                                          & B&B work */
-
-        short     basis_valid;        /* TRUE is the basis is still valid */
-        int[]     bas;                /* rows_alloc+1 :The basis column list */
-        short[]   basis;              /* sum_alloc+1 : basis[i] is TRUE if the column
-                                         is in the basis */
-        short[]   lower;              /*  "       "  :TRUE is the variable is at its 
-                                          lower bound (or in the basis), it is FALSE
-                                          if the variable is at its upper bound */
-
-        short     eta_valid;          /* TRUE if current Eta structures are valid */
-        int       eta_alloc;          /* The allocated memory for Eta */
-        int       eta_size;           /* The number of Eta columns */
-        int       num_inv;            /* The number of float pivots */
-        int       max_num_inv;        /* ## The number of float pivots between 
-                                         reinvertions */
-        float[]  eta_value;          /* eta_alloc :The Structure containing the
-                                         values of Eta */
-        int[]     eta_row_nr;         /*  "     "  :The Structure containing the Row
-                                          indexes of Eta */
-        int[]     eta_col_end;        /* rows_alloc + MaxNumInv : eta_col_end[i] is
-                                         the start index of the next Eta column */
-
-        short      bb_rule;            /* what rule for selecting B&B variables */
-
-        short     break_at_int;       /* TRUE if stop at first integer better than
-                                         break_value */
-        float    break_value;        
-
-        float    obj_bound;          /* ## Objective function bound for speedup of 
-                                         B&B */
-        int       iter;               /* The number of iterations in the simplex
-                                         solver () */
-        int       total_iter;         /* The total number of iterations (B&B) (ILP)*/ 
-        int       max_level;          /* The Deepest B&B level of the last solution */
-        int        total_nodes;        /* total number of nodes processed in b&b */
-        public float[]  solution;           /* sum_alloc+1 :The Solution of the last LP, 
-                                         0 = The Optimal Value, 
-                                         1..rows The Slacks, 
-                                         rows+1..sum The Variables */
-        public float[]  best_solution;      /*  "       "  :The Best 'Integer' Solution */
-        float[]  duals;              /* rows_alloc+1 :The dual variables of the
-                                         last LP */
-  
-        short     maximise;           /* TRUE if the goal is to maximise the 
-                                         objective function */
-        short     floor_first;        /* TRUE if B&B does floor bound first */
-        short[]   ch_sign;            /* rows_alloc+1 :TRUE if the Row in the matrix
-                                         has changed sign 
-                                         (a`x > b, x>=0) is translated to 
-                                         s + -a`x = -b with x>=0, s>=0) */ 
-
-        int        nr_lagrange;        /* Nr. of Langrangian relaxation constraints */
-        float[][]lag_row;              /* NumLagrange, columns+1:Pointer to pointer of 
-                                           rows */
-        float[]  lag_rhs;              /* NumLagrange :Pointer to pointer of Rhs */
-        float[]  lambda;               /* NumLagrange :Lambda Values */
-        short[]   lag_con_type;       /* NumLagrange :TRUE if constraint type EQ */
-        float    lag_bound;            /* the lagrangian lower bound */
-
-        short     valid;               /* Has this lp pased the 'test' */
-        float    infinite;           /* ## numercal stuff */
-        float    epsilon;            /* ## */
-        float    epsb;               /* ## */
-        float    epsd;               /* ## */
-        float    epsel;              /* ## */
-
-        int     Rows;
-        int     columns;
-        int     Sum;
-        int     Non_zeros;
-        int     Level;
-        MatrixArray  Mat;
-        int[]     Col_no;
-        int[]     Col_end;
-        int[]     Row_end;
-        float[]    Orig_rh;
-        float[]    Rh;
-        float[]    Rhs;
-        float[]    Orig_upbo;
-        float[]    Orig_lowbo;
-        float[]    Upbo;
-        float[]    Lowbo;
-        int[]     Bas;
-        short[]   Basis;
-        short[]   Lower;
-        int     Eta_alloc; 
-        int     Eta_size;           
-        float[]    Eta_value;
-        int[]     Eta_row_nr;
-        int[]     Eta_col_end;
-        int     Num_inv;
-        float[]    Solution;
-        public float[]    Best_solution;
-        float    Infinite;
-        float    Epsilon;
-        float    Epsb;
-        float    Epsd;
-        float    Epsel;
-  
-        float  TREJ;
-        float  TINV;
-  
-        short   Maximise;
-        short   Floor_first;
-        float    Extrad;
-
-        int     Warn_count; /* used in CHECK version of rounding macro */
-
-        public Simplex (int nrows, int ncolumns, int matalloc) {
-            int nsum;  
-            nsum=nrows+ncolumns;
-            rows=nrows;
-            columns=ncolumns;
-            sum=nsum;
-            rows_alloc=rows;
-            columns_alloc=columns;
-            sum_alloc=sum;
-            mat_alloc=matalloc;
-            eta_alloc=10000;
-            max_num_inv=DEFNUMINV;
-            col_no = new int[mat_alloc];
-            col_end = new int[columns + 1];
-            row_end = new int[rows + 1];
-            orig_rh = new float[rows + 1];
-            rh = new float[rows + 1];
-            rhs = new float[rows + 1];
-            orig_upbo = new float[sum + 1];
-            upbo = new float[sum + 1];
-            orig_lowbo = new float[sum + 1];
-            lowbo = new float[sum + 1];
-            bas = new int[rows+1];
-            basis = new short[sum + 1];
-            lower = new short[sum + 1];
-            eta_value = new float[eta_alloc];
-            eta_row_nr = new int[eta_alloc];
-            eta_col_end = new int[rows_alloc + max_num_inv];
-            solution = new float[sum + 1];
-            best_solution = new float[sum + 1];
-            duals = new float[rows + 1];
-            ch_sign = new short[rows + 1];
-            mat = new MatrixArray(mat_alloc);
-            alternate_mat = new MatrixArray(mat_alloc);
-        }
-        
-        public void init(int ncolumns) {
-            int nsum;  
-            int nrows = 0;
-            nsum=nrows+ncolumns;
-            active=FALSE;
-            debug=FALSE;
-            trace=FALSE;
-            rows=nrows;
-            columns=ncolumns;
-            sum=nsum;
-            obj_bound=DEF_INFINITE;
-            infinite=DEF_INFINITE;
-            epsilon=DEF_EPSILON;
-            epsb=DEF_EPSB;
-            epsd=DEF_EPSD;
-            epsel=DEF_EPSEL;
-            non_zeros=0;
-
-            for(int i = 0; i < col_end.length; i++) col_end[i] = 0;
-            for(int i = 0; i < rows + 1; i++)    row_end[i] = 0;
-            for(int i = 0; i < rows + 1; i++)   orig_rh[i] = 0;
-            for(int i = 0; i < rows + 1; i++)   rh[i] = 0;
-            for(int i = 0; i < rows + 1; i++)   rhs[i] = 0;
-            for(int i = 0; i <= sum; i++)       orig_upbo[i]=infinite;
-            for(int i = 0; i < sum + 1; i++)    upbo[i] = 0;
-            for(int i = 0; i < sum + 1; i++)    orig_lowbo[i] = 0;
-            for(int i = 0; i < sum + 1; i++)    lowbo[i] = 0;
-            for(int i = 0; i <= rows; i++)      bas[i] = 0;
-            for(int i = 0; i <= sum; i++)       basis[i] = 0;
-            for(int i = 0; i <= rows; i++)     { bas[i]=i; basis[i]=TRUE; }
-            for(int i = rows + 1; i <= sum; i++) basis[i]=FALSE;
-            for(int i = 0 ; i <= sum; i++)       lower[i]=TRUE;
-            for(int i = 0; i <= sum; i++) solution[i] = 0;
-            for(int i = 0; i <= sum; i++) best_solution[i] = 0;
-            for(int i = 0; i <= rows; i++) duals[i] = 0;
-            for(int i = 0; i <= rows; i++) ch_sign[i] = FALSE;
-
-            row_end_valid=FALSE;
-            bb_rule=FIRST_NI;
-            break_at_int=FALSE;
-            break_value=0;
-            iter=0;
-            total_iter=0;
-            basis_valid=TRUE; 
-            eta_valid=TRUE;
-            eta_size=0;
-            nr_lagrange=0;
-            maximise = FALSE;
-            floor_first = TRUE;
-            valid = FALSE; 
-        }
-
-        public void setObjective(float[] row, boolean maximize) {
-            for(int i=row.length-1; i>0; i--) row[i] = row[i-1];
-            row[0] = (float)0.0;
-            for(int j = 1; j <= columns; j++) {
-                int Row = 0;
-                int column = j;
-                float Value = row[j];
-                int elmnr, lastelm;
-                
-                if(Row > rows || Row < 0) throw new Error("row out of range");
-                if(column > columns || column < 1) throw new Error("column out of range");
-                
-                if (basis[column] == TRUE && Row > 0) basis_valid = FALSE;
-                eta_valid = FALSE;
-                elmnr = col_end[column-1];
-                while((elmnr < col_end[column]) ? (get_row_nr(mat, elmnr) != Row) : false) elmnr++;
-                if((elmnr != col_end[column]) ? (get_row_nr(mat, elmnr) == Row) : false ) {
-                    if (ch_sign[Row] != FALSE) set_value(mat, elmnr, -Value);
-                    else set_value(mat, elmnr, Value);
-                } else {
-                    /* check if more space is needed for matrix */
-                    if (non_zeros + 1 > mat_alloc) throw new Error("not enough mat space; this should not happen");
-                    /* Shift the matrix */
-                    lastelm=non_zeros; 
-                    for(int i = lastelm; i > elmnr ; i--) {
-                        set_row_nr(mat,i,get_row_nr(mat,i-1));
-                        set_value(mat,i,get_value(mat,i-1));
-                    }
-                    for(int i = column; i <= columns; i++) col_end[i]++;
-                    /* Set new element */
-                    set_row_nr(mat,elmnr, Row);
-                    if (ch_sign[Row] != FALSE) set_value(mat, elmnr, -Value);
-                    else set_value(mat, elmnr, Value);
-                    row_end_valid=FALSE;
-                    non_zeros++;
-                    if (active != FALSE) Non_zeros=non_zeros;
-                }      
-            }
-            if (maximize) {
-                if (maximise == FALSE) {
-                    for(int i = 0; i < non_zeros; i++)
-                        if(get_row_nr(mat, i)==0)
-                            set_value(mat, i, get_value(mat,i)* (float)-1.0);
-                    eta_valid=FALSE;
-                }
-                maximise=TRUE;
-                ch_sign[0]=TRUE;
-                if (active != FALSE) Maximise=TRUE;
-            } else {
-                if (maximise==TRUE) {
-                    for(int i = 0; i < non_zeros; i++)
-                        if(get_row_nr(mat, i)==0)
-                            set_value(mat, i, get_value(mat,i) * (float)-1.0);
-                    eta_valid=FALSE;
-                } 
-                maximise=FALSE;
-                ch_sign[0]=FALSE;
-                if (active != FALSE) Maximise=FALSE;
-            }
-        }
-
-        public void add_constraint(float[] row, short constr_type, float rh) {
-            for(int i=row.length-1; i>0; i--) row[i] = row[i-1];
-            row[0] = (float)0.0;
-
-            MatrixArray newmat;
-            int  elmnr;
-            int  stcol;
-
-            newmat = alternate_mat;
-            for(int i = 0; i < non_zeros; i++) { set_row_nr(newmat,i, 0); set_value(newmat, i, 0); }
-            for(int i = 1; i <= columns; i++) if (row[i]!=0) non_zeros++;
-            if (non_zeros > mat_alloc) throw new Error("not enough mat space; this should not happen");
-            rows++;
-            sum++;
-            if(rows > rows_alloc) throw new Error("not enough rows; this should never happen");
-            if(constr_type==GE) ch_sign[rows] = TRUE;
-            else ch_sign[rows] = FALSE;
-
-            elmnr = 0;
-            stcol = 0;
-            for(int i = 1; i <= columns; i++) {
-                for(int j = stcol; j < col_end[i]; j++) {  
-                    set_row_nr(newmat,elmnr, get_row_nr(mat, j));
-                    set_value(newmat, elmnr, get_value(mat,j));
-                    elmnr++;
-                }
-                if(((i>=1 && i< columns && row[i]!=0)?TRUE:FALSE) != FALSE) {
-                    if(ch_sign[rows] != FALSE) set_value(newmat, elmnr, -row[i]);
-                    else set_value(newmat, elmnr, row[i]);
-                    set_row_nr(newmat,elmnr, rows);
-                    elmnr++;
-                }
-                stcol=col_end[i];
-                col_end[i]=elmnr;
-            }    
-            
-            alternate_mat = mat;
-            mat = newmat;
-
-            for(int i = sum ; i > rows; i--) {
-                orig_upbo[i]=orig_upbo[i-1];
-                orig_lowbo[i]=orig_lowbo[i-1];
-                basis[i]=basis[i-1];
-                lower[i]=lower[i-1];
-            }
-
-            for(int i =  1 ; i <= rows; i++) if(bas[i] >= rows) bas[i]++;
-
-            if(constr_type==LE || constr_type==GE) orig_upbo[rows]=infinite;
-            else if(constr_type==EQ) orig_upbo[rows]=0;
-            else throw new Error("Wrong constraint type\n");
-            orig_lowbo[rows]=0;
-
-            if(constr_type==GE && rh != 0) orig_rh[rows]=-rh;
-            else orig_rh[rows]=rh;  
-
-            row_end_valid=FALSE;
-            bas[rows]=rows;
-            basis[rows]=TRUE;
-            lower[rows]=TRUE;   
-            if (active != FALSE) set_globals();
-            eta_valid=FALSE;
-        }
-
-        public void bound_sum(int column1, int column2, float bound, short type, float[] scratch) {
-            for(int i=0; i<scratch.length; i++) scratch[i] = (float)0.0;
-            scratch[column1] = (float)1.0;
-            scratch[column2] = (float)1.0;
-            add_constraint(scratch, type, bound);
-            for(int i=0; i<scratch.length; i++) scratch[i] = (float)0.0;
-        }
-
-        public void bound_difference(int column1, int column2, float bound, short type, float[] scratch) {
-            for(int i=0; i<scratch.length; i++) scratch[i] = (float)0.0;
-            scratch[column1] = (float)1.0;
-            scratch[column2] = (float)-1.0;
-            add_constraint(scratch, type, bound);
-            for(int i=0; i<scratch.length; i++) scratch[i] = (float)0.0;
-        }
-
-        public void set_upbo(int column, float value) {
-            if(column > columns || column < 1) throw new Error("column out of range");
-            if(value < orig_lowbo[rows + column]) throw new Error("UpperBound must be >= lowerBound"); 
-            eta_valid = FALSE;
-            orig_upbo[rows+column] = value;
-        }
-
-        public void set_lowbo(int column, float value) {
-            if(column > columns || column < 1) throw new Error("column out of range");
-            if(value > orig_upbo[rows + column]) throw new Error("UpperBound must be >= lowerBound"); 
-            eta_valid = FALSE;
-            orig_lowbo[rows+column] = value;
-        }
-
-        public void set_rh(int row, float value) {
-            if(row > rows || row < 0) throw new Error("Row out of Range");
-            if(row == 0) throw new Error("Warning: attempt to set RHS of objective function, ignored");
-            if (ch_sign[row] != FALSE) orig_rh[row] = -value;
-            else orig_rh[row] = value;
-            eta_valid = FALSE;
-        } 
-
-        public void set_rh_vec(float[] rh) {
-            for(int i=1; i <= rows; i++)
-                if (ch_sign[i] != FALSE) orig_rh[i]=-rh[i];
-                else orig_rh[i]=rh[i];
-            eta_valid=FALSE;
-        }
-
-
-        public void set_constr_type(int row, short con_type) {
-            if (row > rows || row < 1) throw new Error("Row out of Range");
-            switch(con_type) {
-                case EQ:
-                    orig_upbo[row]=0;
-                    basis_valid=FALSE;
-                    if (ch_sign[row] != FALSE) {
-                        for(int i = 0; i < non_zeros; i++)
-                            if (get_row_nr(mat, i)==row) set_value(mat, i, get_value(mat,i) * (float)-1);
-                        eta_valid=FALSE;
-                        ch_sign[row]=FALSE;
-                        if (orig_rh[row]!=0) orig_rh[row]*=-1;
-                    }
-                    break;
-                case LE:
-                    orig_upbo[row]=infinite;
-                    basis_valid=FALSE;
-                    if (ch_sign[row] != FALSE) {
-                        for(int i = 0; i < non_zeros; i++)
-                            if (get_row_nr(mat, i)==row) set_value(mat, i, get_value(mat,i) * (float)-1);
-                        eta_valid=FALSE;
-                        ch_sign[row]=FALSE;
-                        if (orig_rh[row]!=0) orig_rh[row]*=-1;
-                    }
-                    break;
-                case GE:
-                    orig_upbo[row]=infinite;
-                    basis_valid=FALSE;
-                    if (ch_sign[row] == FALSE) {
-                        for(int i = 0; i < non_zeros; i++)
-                            if (get_row_nr(mat, i)==row) set_value(mat, i, get_value(mat,i) * (float)-1);
-                        eta_valid=FALSE;
-                        ch_sign[row]=TRUE;
-                        if (orig_rh[row]!=0) orig_rh[row]*=-1;
-                    }
-                    break;
-                default: throw new Error("Constraint type not (yet) implemented");
-            }
-        }
-
-        void set_globals() {
-            Rows = rows;
-            columns = columns;
-            Sum = Rows + columns;
-            Non_zeros = non_zeros;
-            Mat = mat;
-            Col_no = col_no;
-            Col_end = col_end;
-            Row_end = row_end;
-            Rh = rh;
-            Rhs = rhs;
-            Orig_rh = orig_rh;
-            Orig_upbo = orig_upbo;
-            Orig_lowbo = orig_lowbo;
-            Upbo = upbo;
-            Lowbo = lowbo;
-            Bas = bas;
-            Basis = basis;
-            Lower = lower;
-            Eta_alloc = eta_alloc;
-            Eta_size = eta_size;
-            Num_inv = num_inv;
-            Eta_value = eta_value;
-            Eta_row_nr = eta_row_nr;
-            Eta_col_end = eta_col_end;
-            Solution = solution;
-            Best_solution = best_solution;
-            Infinite = infinite;
-            Epsilon = epsilon;
-            Epsb = epsb;
-            Epsd = epsd;
-            Epsel = epsel;
-            TREJ = TREJ;
-            TINV = TINV;
-            Maximise = maximise;
-            Floor_first = floor_first;
-            active = TRUE;
-        }
-
-        private void ftran(int start, int end, float[] pcol) {
-            int k, r;
-            float theta;
-            for(int i = start; i <= end; i++) {
-                k = Eta_col_end[i] - 1;
-                r = Eta_row_nr[k];
-                theta = pcol[r];
-                if (theta != 0) for(int j = Eta_col_end[i - 1]; j < k; j++)
-                    pcol[Eta_row_nr[j]] += theta * Eta_value[j];
-                pcol[r] *= Eta_value[k];
-            }
-            for(int i = 0; i <= Rows; i++) round(pcol[i], Epsel);
-        }
-
-        private void btran(float[] row) {
-            int k;
-            float f;
-            for(int i = Eta_size; i >= 1; i--) {
-                f = 0;
-                k = Eta_col_end[i] - 1;
-                for(int j = Eta_col_end[i - 1]; j <= k; j++) f += row[Eta_row_nr[j]] * Eta_value[j];
-                f = round(f, Epsel);
-                row[Eta_row_nr[k]] = f;
-            }
-        }
-
-        static int[] num = new int[65535];
-        static int[] rownum = new int[65535];
-        static int[] colnum = new int[65535];
-
-        short Isvalid() {
-            int row_nr;
-            if (row_end_valid == FALSE) {
-                for(int i = 0; i <= rows; i++) { num[i] = 0; rownum[i] = 0; }
-                for(int i = 0; i < non_zeros; i++) rownum[get_row_nr(mat, i)]++;
-                row_end[0] = 0;
-                for(int i = 1; i <= rows; i++) row_end[i] = row_end[i - 1] + rownum[i];
-                for(int i = 1; i <= columns; i++)
-                    for(int j = col_end[i - 1]; j < col_end[i]; j++) {
-                        row_nr = get_row_nr(mat, j);
-                        if (row_nr != 0) {
-                            num[row_nr]++;
-                            col_no[row_end[row_nr - 1] + num[row_nr]] = i;
-                        }
-                    }
-                row_end_valid = TRUE;
-            }
-            if (valid != FALSE) return(TRUE);
-            for(int i = 0; i <= rows; i++) rownum[i] = 0;
-            for(int i = 0; i <= columns; i++) colnum[i] = 0;
-            for(int i = 1 ; i <= columns; i++)
-                for(int j = col_end[i - 1]; j < col_end[i]; j++) {
-                    colnum[i]++;
-                    rownum[get_row_nr(mat, j)]++;
-                }
-            for(int i = 1; i <= columns; i++)
-                if (colnum[i] == 0)
-                    throw new Error("Warning: Variable " + i + " not used in any constaints\n");
-            valid = TRUE;
-            return(TRUE);
-        } 
-
-        private void resize_eta() {
-            Eta_alloc *= 2;
-            throw new Error("eta undersized; this should never happen");
-            /*
-            float[] db_ptr = Eta_value;
-            Eta_value = new float[Eta_alloc];
-            System.arraycopy(db_ptr, 0, Eta_value, 0, db_ptr.length);
-            eta_value = Eta_value;
-
-            int[] int_ptr = Eta_row_nr;
-            Eta_row_nr = new int[Eta_alloc];
-            System.arraycopy(int_ptr, 0, Eta_row_nr, 0, int_ptr.length);
-            eta_row_nr = Eta_row_nr;
-            */
-        }
-
-        private void condensecol(int row_nr, float[] pcol) {
-            int elnr;
-            elnr = Eta_col_end[Eta_size];
-            if (elnr + Rows + 2 > Eta_alloc) resize_eta();
-            for(int i = 0; i <= Rows; i++)
-                if (i != row_nr && pcol[i] != 0) {
-                    Eta_row_nr[elnr] = i;
-                    Eta_value[elnr] = pcol[i];
-                    elnr++;
-                }
-            Eta_row_nr[elnr] = row_nr;
-            Eta_value[elnr] = pcol[row_nr];
-            elnr++;
-            Eta_col_end[Eta_size + 1] = elnr;
-        }
-
-        private void addetacol() {
-            int k;
-            float theta;
-            int j = Eta_col_end[Eta_size];
-            Eta_size++;
-            k = Eta_col_end[Eta_size];
-            theta = 1 / (float) Eta_value[k - 1];
-            Eta_value[k - 1] = theta;
-            for(int i = j; i < k - 1; i++) Eta_value[i] *= -theta;
-            JustInverted = FALSE;
-        }
-
-        private void setpivcol(short lower,  int varin, float[]   pcol) {
-            int colnr;
-            float f;
-            if (lower != FALSE) f = 1;
-            else f = -1;
-            for(int i = 0; i <= Rows; i++) pcol[i] = 0;
-            if (varin > Rows) {
-                colnr = varin - Rows;
-                for(int i = Col_end[colnr - 1]; i < Col_end[colnr]; i++) pcol[get_row_nr(Mat, i)] = get_value(Mat,i) * f;
-                pcol[0] -= Extrad * f;
-            } else {
-                if (lower != FALSE) pcol[varin] = 1;
-                else pcol[varin] = -1;
-            }
-            ftran(1, Eta_size, pcol);
-        }
-
-        private void minoriteration(int colnr, int row_nr) {
-            int k, wk, varin, varout, elnr;
-            float piv = 0, theta;
-            varin = colnr + Rows;
-            elnr = Eta_col_end[Eta_size];
-            wk = elnr;
-            Eta_size++;
-            if (Extrad != 0) {
-                Eta_row_nr[elnr] = 0;
-                Eta_value[elnr] = -Extrad;
-                elnr++;
-            }
-            for(int j = Col_end[colnr - 1] ; j < Col_end[colnr]; j++) {
-                k = get_row_nr(Mat, j);
-                if (k == 0 && Extrad != 0) Eta_value[Eta_col_end[Eta_size -1]] += get_value(Mat,j);
-                else if (k != row_nr) {
-                    Eta_row_nr[elnr] = k;
-                    Eta_value[elnr] = get_value(Mat,j);
-                    elnr++;
-                } else {
-                    piv = get_value(Mat,j);
-                }
-            }
-            Eta_row_nr[elnr] = row_nr;
-            Eta_value[elnr] = 1 / (float) piv;
-            elnr++;
-            theta = Rhs[row_nr] / (float) piv;
-            Rhs[row_nr] = theta;
-            for(int i = wk; i < elnr - 1; i++) Rhs[Eta_row_nr[i]] -= theta * Eta_value[i];
-            varout = Bas[row_nr];
-            Bas[row_nr] = varin;
-            Basis[varout] = FALSE;
-            Basis[varin] = TRUE;
-            for(int i = wk; i < elnr - 1; i++) Eta_value[i] /= - (float) piv;
-            Eta_col_end[Eta_size] = elnr;
-        }
-
-        private void rhsmincol(float theta, int row_nr, int varin) {
-            int varout;
-            float f;
-            if (row_nr > Rows + 1) {
-                System.err.println("Error: rhsmincol called with row_nr: " + row_nr + ", rows: " + Rows + "\n");
-                System.err.println("This indicates numerical instability\n");
-            }
-            int j = Eta_col_end[Eta_size];
-            int k = Eta_col_end[Eta_size + 1];
-            for(int i = j; i < k; i++) {
-                f = Rhs[Eta_row_nr[i]] - theta * Eta_value[i];
-                f = round(f, Epsb);
-                Rhs[Eta_row_nr[i]] = f;
-            }
-            Rhs[row_nr] = theta;
-            varout = Bas[row_nr];
-            Bas[row_nr] = varin;
-            Basis[varout] = FALSE;
-            Basis[varin] = TRUE;
-        }
-
-        private static int[] rownum_ = new int[65535];
-        private static int[] colnum_ = new int[65535];
-        private static int[] col = new int[65535];
-        private static int[] row = new int[65535];
-        private static float[] pcol = new float[65535];
-        private static short[] frow = new short[65535];
-        private static short[] fcol = new short[65535];
-
-        void invert() {
-            int    v, wk, numit, varnr, row_nr, colnr, varin;
-            float    theta;
-
-            for(int i = 0; i <= Rows; i++) rownum_[i] = 0;
-            for(int i = 0; i <= Rows; i++) col[i] = 0;
-            for(int i = 0; i <= Rows; i++) row[i] = 0;
-            for(int i = 0; i <= Rows; i++) pcol[i] = 0;
-            for(int i = 0; i <= Rows; i++) frow[i] = TRUE;
-            for(int i = 0; i < columns; i++) fcol[i] = FALSE;
-            for(int i = 0; i <= columns; i++) colnum_[i] = 0;
-
-            for(int i = 0; i <= Rows; i++)
-                if (Bas[i] > Rows) fcol[Bas[i] - Rows - 1] = TRUE;
-                else frow[Bas[i]] = FALSE;
-
-            for(int i = 1; i <= Rows; i++)
-                if (frow[i] != FALSE)
-                    for(int j = Row_end[i - 1] + 1; j <= Row_end[i]; j++) {
-                        wk = Col_no[j];
-                        if (fcol[wk - 1] != FALSE) {
-                            colnum_[wk]++;
-                            rownum_[i - 1]++;
-                        }
-                    }
-
-            for(int i = 1; i <= Rows; i++) Bas[i] = i;
-            for(int i = 1; i <= Rows; i++) Basis[i] = TRUE;
-            for(int i = 1; i <= columns; i++) Basis[i + Rows] = FALSE;
-            for(int i = 0; i <= Rows; i++) Rhs[i] = Rh[i];
-            for(int i = 1; i <= columns; i++) {
-                varnr = Rows + i;
-                if (Lower[varnr] == FALSE) {
-                    theta = Upbo[varnr];
-                    for(int j = Col_end[i - 1]; j < Col_end[i]; j++)
-                        Rhs[get_row_nr(Mat, j)] -= theta * get_value(Mat,j);
-                }
-            }
-            for(int i = 1; i <= Rows; i++) if (Lower[i] == FALSE) Rhs[i] -= Upbo[i];
-            Eta_size = 0;
-            v = 0;
-            row_nr = 0;
-            Num_inv = 0;
-            numit = 0;
-            while(v < Rows) {
-                int j;
-                row_nr++;
-                if (row_nr > Rows) row_nr = 1;
-                v++;
-                if (rownum_[row_nr - 1] == 1)
-                    if (frow[row_nr] != FALSE) {
-                        v = 0;
-                        j = Row_end[row_nr - 1] + 1;
-                        while(fcol[Col_no[j] - 1] == FALSE) j++;
-                        colnr = Col_no[j];
-                        fcol[colnr - 1] = FALSE;
-                        colnum_[colnr] = 0;
-                        for(j = Col_end[colnr - 1]; j < Col_end[colnr]; j++)
-                            if (frow[get_row_nr(Mat, j)] != FALSE)
-                                rownum_[get_row_nr(Mat, j) - 1]--;
-                        frow[row_nr] = FALSE;
-                        minoriteration(colnr, row_nr);
-                    }
-            }
-            v = 0;
-            colnr = 0;
-            while(v < columns) {
-                int j;
-                colnr++;
-                if (colnr > columns) colnr = 1;
-                v++;
-                if (colnum_[colnr] == 1)
-                    if (fcol[colnr - 1] != FALSE) {
-                        v = 0;
-                        j = Col_end[colnr - 1] + 1;
-                        while(frow[get_row_nr(Mat, j - 1)] == FALSE) j++;
-                        row_nr = get_row_nr(Mat, j - 1);
-                        frow[row_nr] = FALSE;
-                        rownum_[row_nr - 1] = 0;
-                        for(j = Row_end[row_nr - 1] + 1; j <= Row_end[row_nr]; j++)
-                            if (fcol[Col_no[j] - 1] != FALSE)
-                                colnum_[Col_no[j]]--;
-                        fcol[colnr - 1] = FALSE;
-                        numit++;
-                        col[numit - 1] = colnr;
-                        row[numit - 1] = row_nr;
-                    }
-            }
-            for(int j = 1; j <= columns; j++)
-                if (fcol[j - 1] != FALSE) {
-                    fcol[j - 1] = FALSE;
-                    setpivcol(Lower[Rows + j], j + Rows, pcol);
-                    row_nr = 1;
-                    while((frow[row_nr] == FALSE || pcol[row_nr] == FALSE) && row_nr <= Rows)
-                        row_nr++; /* this sometimes sets row_nr to Rows + 1 and makes
-                                     rhsmincol crash. Solved in 2.0? MB */
-                    if (row_nr == Rows + 1) throw new Error("Inverting failed");
-                    frow[row_nr] = FALSE;
-                    condensecol(row_nr, pcol);
-                    theta = Rhs[row_nr] / (float) pcol[row_nr];
-                    rhsmincol(theta, row_nr, Rows + j);
-                    addetacol();
-                }
-            for(int i = numit - 1; i >= 0; i--) {
-                colnr = col[i];
-                row_nr = row[i];
-                varin = colnr + Rows;
-                for(int j = 0; j <= Rows; j++) pcol[j] = 0;
-                for(int j = Col_end[colnr - 1]; j < Col_end[colnr]; j++) pcol[get_row_nr(Mat, j)] = get_value(Mat,j);
-                pcol[0] -= Extrad;
-                condensecol(row_nr, pcol);
-                theta = Rhs[row_nr] / (float) pcol[row_nr];
-                rhsmincol(theta, row_nr, varin);
-                addetacol();
-            }
-            for(int i = 1; i <= Rows; i++) Rhs[i] = round(Rhs[i], Epsb);
-            JustInverted = TRUE;
-            DoInvert = FALSE;
-        }
-
-        private short colprim(Ref colnr, short minit, float[]   drow) {
-            int  varnr;
-            float f, dpiv;
-              dpiv = -Epsd;
-            colnr.value = 0;
-            if (minit == FALSE) {
-                for(int i = 1; i <= Sum; i++) drow[i] = 0;
-                drow[0] = 1;
-                btran(drow);
-                for(int i = 1; i <= columns; i++) {
-                    varnr = Rows + i;
-                    if (Basis[varnr] == FALSE)
-                        if (Upbo[varnr] > 0) {
-                            f = 0;
-                            for(int j = Col_end[i - 1]; j < Col_end[i]; j++) f += drow[get_row_nr(Mat, j)] * get_value(Mat,j);
-                            drow[varnr] = f;
-                        }
-                }
-                for(int i = 1; i <= Sum; i++) drow[i] = round(drow[i], Epsd);
-            }
-            for(int i = 1; i <= Sum; i++)
-                if (Basis[i] == FALSE)
-                    if (Upbo[i] > 0) {
-                        if (Lower[i] != FALSE) f = drow[i];
-                        else f = -drow[i];
-                        if (f < dpiv) {
-                            dpiv = f;
-                            colnr.value = i;
-                        }
-                    }
-            if (colnr.value == 0) {
-                Doiter   = FALSE;
-                DoInvert = FALSE;
-                Status   = OPTIMAL;
-            }
-            return(colnr.value > 0 ? (short)1 : (short)0);
-        }
-
-        private short rowprim(int colnr, Ref row_nr, Ref theta, float[] pcol) {
-            float f = 0, quot; 
-            row_nr.value = 0;
-            theta.value = Infinite;
-            for(int i = 1; i <= Rows; i++) {
-                f = pcol[i];
-                if (Math.abs(f) < TREJ) f = 0;
-                if (f != 0) {
-                    quot = 2 * Infinite;
-                    if (f > 0) quot = Rhs[i] / (float) f;
-                    else if (Upbo[Bas[i]] < Infinite) quot = (Rhs[i] - Upbo[Bas[i]]) / (float) f;
-                    round(quot, Epsel);
-                    if (quot < theta.value) {
-                        theta.value = quot;
-                        row_nr.value = i;
-                    }
-                }
-            }
-            if (row_nr.value == 0)  
-                for(int i = 1; i <= Rows; i++) {
-                    f = pcol[i];
-                    if (f != 0) {
-                        quot = 2 * Infinite;
-                        if (f > 0) quot = Rhs[i] / (float) f;
-                        else if (Upbo[Bas[i]] < Infinite) quot = (Rhs[i] - Upbo[Bas[i]]) / (float) f;
-                        quot = round(quot, Epsel);
-                        if (quot < theta.value) {
-                            theta.value = quot;
-                            row_nr.value = i;
-                        }
-                    }
-                }
-
-            if (theta.value < 0) throw new Error("Warning: Numerical instability, qout = " + theta.value);
-            if (row_nr.value == 0) {
-                if (Upbo[colnr] == Infinite) {
-                    Doiter   = FALSE;
-                    DoInvert = FALSE;
-                    Status   = UNBOUNDED;
-                } else {
-                    int i = 1;
-                    while(pcol[i] >= 0 && i <= Rows) i++;
-                    if (i > Rows) {
-                        Lower[colnr] = FALSE;
-                        Rhs[0] += Upbo[colnr]*pcol[0];
-                        Doiter = FALSE;
-                        DoInvert = FALSE;
-                    } else if (pcol[i]<0) {
-                        row_nr.value = i;
-                    }
-                }
-            }
-            if (row_nr.value > 0) Doiter = TRUE;
-            return((row_nr.value > 0) ? (short)1 : (short)0);
-        }
-
-        private short rowdual(Ref row_nr) {
-            int   i;
-            float  f, g, minrhs;
-            short artifs;
-            row_nr.value = 0;
-            minrhs = -Epsb;
-            i = 0;
-            artifs = FALSE;
-            while(i < Rows && artifs == FALSE) {
-                i++;
-                f = Upbo[Bas[i]];
-                if (f == 0 && (Rhs[i] != 0)) {
-                    artifs = TRUE;
-                    row_nr.value = i;
-                } else {
-                    if (Rhs[i] < f - Rhs[i]) g = Rhs[i];
-                    else g = f - Rhs[i];
-                    if (g < minrhs) {
-                        minrhs = g;
-                        row_nr.value = i;
-                    }
-                }
-            }
-            return(row_nr.value > 0 ? (short)1 : (short)0);
-        }
-
-        private short coldual(int row_nr, Ref colnr, short minit, float[] prow, float[] drow) {
-            int r, varnr;
-            float theta, quot, pivot, d, f, g;
-            Doiter = FALSE;
-            if (minit == FALSE) {
-                for(int i = 0; i <= Rows; i++) {
-                    prow[i] = 0;
-                    drow[i] = 0;
-                }
-                drow[0] = 1;
-                prow[row_nr] = 1;
-                for(int i = Eta_size; i >= 1; i--) {
-                    d = 0;
-                    f = 0;
-                    r = Eta_row_nr[Eta_col_end[i] - 1];
-                    for(int j = Eta_col_end[i - 1]; j < Eta_col_end[i]; j++) {
-                        /* this is where the program consumes most cpu time */
-                        f += prow[Eta_row_nr[j]] * Eta_value[j];
-                        d += drow[Eta_row_nr[j]] * Eta_value[j];
-                    }
-                    f = round(f, Epsel);
-                    prow[r] = f;
-                    d = round(d, Epsel);
-                    drow[r] = d;
-                }
-                for(int i = 1; i <= columns; i++) {
-                    varnr = Rows + i;
-                    if (Basis[varnr] == FALSE) {
-                        d = - Extrad * drow[0];
-                        f = 0;
-                        for(int j = Col_end[i - 1]; j < Col_end[i]; j++) {
-                            d = d + drow[get_row_nr(Mat, j)] * get_value(Mat,j);
-                            f = f + prow[get_row_nr(Mat, j)] * get_value(Mat,j);
-                        }
-                        drow[varnr] = d;
-                        prow[varnr] = f;
-                    }
-                }
-                for(int i = 0; i <= Sum; i++) {
-                    prow[i] = round(prow[i], Epsel);
-                    drow[i] = round(drow[i], Epsd);
-                }
-            }
-            if (Rhs[row_nr] > Upbo[Bas[row_nr]]) g = -1;
-            else g = 1;
-            pivot = 0;
-            colnr.value = 0;
-            theta = Infinite;
-            for(int i = 1; i <= Sum; i++) {
-                if (Lower[i] != FALSE) d = prow[i] * g;
-                else d = -prow[i] * g;
-                if ((d < 0) && (Basis[i] == FALSE) && (Upbo[i] > 0)) {
-                    if (Lower[i] == FALSE) quot = -drow[i] / (float) d;
-                    else quot = drow[i] / (float) d;
-                    if (quot < theta) {
-                        theta = quot;
-                        pivot = d;
-                        colnr.value = i;
-                    } else if ((quot == theta) && (Math.abs(d) > Math.abs(pivot))) {
-                        pivot = d;
-                        colnr.value = i;
-                    }
-                }
-            }
-            if (colnr.value > 0) Doiter = TRUE;
-            return(colnr.value > 0 ? (short)1 : (short)0);
-        }
-
-        private void iteration(int row_nr, int varin, Ref theta, float up, Ref minit, Ref low, short primal,float[] pcol) {
-            int k, varout;
-            float f;
-            float pivot;
-            iter++;
-            minit.value = theta.value > (up + Epsb) ? 1 : 0;
-            if (minit.value != 0) {
-                theta.value = up;
-                low.value = low.value == 0 ? 1 : 0;
-            }
-            k = Eta_col_end[Eta_size + 1];
-            pivot = Eta_value[k - 1];
-            for(int i = Eta_col_end[Eta_size]; i < k; i++) {
-                f = Rhs[Eta_row_nr[i]] - theta.value * Eta_value[i];
-                f = round(f, Epsb);
-                Rhs[Eta_row_nr[i]] = f;
-            }
-            if (minit.value == 0) {
-                Rhs[row_nr] = theta.value;
-                varout = Bas[row_nr];
-                Bas[row_nr] = varin;
-                Basis[varout] = FALSE;
-                Basis[varin] = TRUE;
-                if (primal != FALSE && pivot < 0) Lower[varout] = FALSE;
-                if (low.value == 0 && up < Infinite) {
-                    low.value = TRUE;
-                    Rhs[row_nr] = up - Rhs[row_nr];
-                    for(int i = Eta_col_end[Eta_size]; i < k; i++) Eta_value[i] = -Eta_value[i];
-                }
-                addetacol();
-                Num_inv++;
-            }
-        }
-
-        static float[] drow = new float[65535];
-        static float[] prow = new float[65535];
-        static float[] Pcol = new float[65535];
-
-        private int solvelp() {
-            int    varnr;
-            float   f = 0, theta = 0;
-            short  primal;
-            short  minit;
-            int    colnr, row_nr;
-            colnr = 0;
-            row_nr = 0;
-            short flag; 
-            Ref ref1, ref2, ref3;
-            ref1 = new Ref(0);
-            ref2 = new Ref(0);
-            ref3 = new Ref(0);
-
-            for(int i = 0; i <= Sum; i++) { drow[i] = 0; prow[i] = 0; }
-            for(int i = 0; i <= Rows; i++) Pcol[i] = 0;
-            iter = 0;
-            minit = FALSE;
-            Status = RUNNING;
-            DoInvert = FALSE;
-            Doiter = FALSE;
-            primal = TRUE;
-            for(int i = 0; i != Rows && primal != FALSE;) {
-                i++;
-                primal = (Rhs[i] >= 0 && Rhs[i] <= Upbo[Bas[i]]) ? (short)1: (short)0;
-            }
-            if (primal == FALSE) {
-                drow[0] = 1;
-                for(int i = 1; i <= Rows; i++) drow[i] = 0;
-                Extrad = 0;
-                for(int i = 1; i <= columns; i++) {
-                    varnr = Rows + i;
-                    drow[varnr] = 0;
-                    for(int j = Col_end[i - 1]; j < Col_end[i]; j++)
-                        if (drow[get_row_nr(Mat, j)] != 0)
-                            drow[varnr] += drow[get_row_nr(Mat, j)] * get_value(Mat,j);
-                    if (drow[varnr] < Extrad) Extrad = drow[varnr];
-                }
-            } else {
-                Extrad = 0;
-            }
-            minit = FALSE;
-            while(Status == RUNNING) {
-                Doiter = FALSE;
-                DoInvert = FALSE;
-                construct_solution(Solution);
-                if (primal != FALSE) {
-                    ref1.value = colnr;
-                    flag = colprim(ref1, minit, drow);
-                    colnr = (int)ref1.value;
-                    if (flag != FALSE) {
-                        setpivcol(Lower[colnr], colnr, Pcol);
-                        ref1.value = row_nr;
-                        ref2.value = theta;
-                        flag = rowprim(colnr, ref1, ref2, Pcol);
-                        row_nr = (int)ref1.value;
-                        theta = ref2.value;
-                        if (flag != FALSE) condensecol(row_nr, Pcol);
-                    }
-                } else {
-                    if (minit == FALSE) {
-                        ref1.value = row_nr;
-                        flag = rowdual(ref1);
-                        row_nr = (int)ref1.value;
-                    }
-                    if (row_nr > 0) {
-                        ref1.value = colnr;
-                        flag = coldual(row_nr, ref1, minit, prow, drow);
-                        colnr = (int)ref1.value;
-                        if (flag != FALSE) {
-                            setpivcol(Lower[colnr], colnr, Pcol);
-                            /* getting div by zero here ... MB */
-                            if (Pcol[row_nr] == 0) {
-                                throw new Error("An attempt was made to divide by zero (Pcol[" + row_nr + "])");
-                            } else {
-                                condensecol(row_nr, Pcol);
-                                f = Rhs[row_nr] - Upbo[Bas[row_nr]];
-                                if (f > 0) {
-                                    theta = f / (float) Pcol[row_nr];
-                                    if (theta <= Upbo[colnr])
-                                        Lower[Bas[row_nr]] = (Lower[Bas[row_nr]] == FALSE)? (short)1:(short)0;
-                                } else theta = Rhs[row_nr] / (float) Pcol[row_nr];
-                            }
-                        } else Status = INFEASIBLE;
-                    } else {
-                        primal   = TRUE;
-                        Doiter   = FALSE;
-                        Extrad   = 0;
-                        DoInvert = TRUE;
-                    }    
-                }
-                if (Doiter != FALSE) {
-                    ref1.value = theta;
-                    ref2.value = minit;
-                    ref3.value = Lower[colnr];
-                    iteration(row_nr, colnr, ref1, Upbo[colnr], ref2, ref3, primal, Pcol);
-                    theta = ref1.value;
-                    minit = (short)ref2.value;
-                    Lower[colnr] = (short)ref3.value;
-                }
-                if (Num_inv >= max_num_inv) DoInvert = TRUE;
-                if (DoInvert != FALSE) invert();
-            } 
-            total_iter += iter;
-            return(Status);
-        }
-
-        private void construct_solution(float[]   sol) {
-            float   f;
-            int basi;
-            for(int i = 0; i <= Rows; i++) sol[i] = 0;
-            for(int i = Rows + 1; i <= Sum; i++) sol[i] = Lowbo[i];
-            for(int i = 1; i <= Rows; i++) {
-                basi = Bas[i];
-                if (basi > Rows) sol[basi] += Rhs[i];
-            }
-            for(int i = Rows + 1; i <= Sum; i++)
-                if (Basis[i] == FALSE && Lower[i] == FALSE)
-                    sol[i] += Upbo[i];
-            for(int j = 1; j <= columns; j++) {
-                f = sol[Rows + j];
-                if (f != 0)
-                    for(int i = Col_end[j - 1]; i < Col_end[j]; i++)
-                        sol[get_row_nr(Mat, i)] += f * get_value(Mat,i);
-            }
-            for(int i = 0; i <= Rows; i++) {
-                if (Math.abs(sol[i]) < Epsb) sol[i] = 0;
-                else if (ch_sign[i] != FALSE) sol[i] = -sol[i];
-            }
-        }
-
-        private void calculate_duals() {
-            for(int i = 1; i <= Rows; i++) duals[i] = 0;
-            duals[0] = 1;
-            btran(duals);
-            for(int i = 1; i <= Rows; i++) {
-                if (basis[i] != FALSE) duals[i] = 0;
-                else if ( ch_sign[0] == ch_sign[i]) duals[i] = -duals[i];
-            }
-        }
-
-        private static Random rdm = new Random();
-
-        private int milpsolve(float[]   upbo, float[]   lowbo, short[]  sbasis, short[]  slower, int[]    sbas) {
-            int failure, notint, is_worse;
-            float theta, tmpfloat;
-            notint = 0;
-
-            if (Break_bb != FALSE) return(BREAK_BB);
-            Level++;
-            total_nodes++;
-            if (Level > max_level) max_level = Level;
-            System.arraycopy(upbo, 0, Upbo, 0, Sum + 1);
-            System.arraycopy(lowbo, 0, Lowbo, 0, Sum + 1);
-            System.arraycopy(sbasis, 0, Basis, 0, Sum + 1);
-            System.arraycopy(slower, 0, Lower, 0, Sum + 1);
-            System.arraycopy(sbas, 0, Bas, 0, Rows + 1);
-            System.arraycopy(Orig_rh, 0, Rh, 0, Rows + 1);
-            if (eta_valid == FALSE) {
-                for(int i = 1; i <= columns; i++)
-                    if (Lowbo[Rows + i] != 0) {
-                        theta = Lowbo[ Rows + i];
-                        if (Upbo[Rows + i]<Infinite) Upbo[Rows + i] -= theta;
-                        for(int j = Col_end[i - 1]; j < Col_end[i]; j++) Rh[get_row_nr(Mat, j)] -= theta * get_value(Mat,j);
-                    }
-                invert();
-                eta_valid = TRUE;
-            }
-            failure = solvelp();
-            if (failure == OPTIMAL) {
-                construct_solution(Solution);
-                /* if this solution is worse than the best sofar, this branch must die */
-                if (Maximise != FALSE) is_worse = (Solution[0] <= Best_solution[0]) ? 1:0;
-                else is_worse = (Solution[0] >= Best_solution[0]) ? 1:0;
-                if (is_worse != FALSE) {
-                    Level--;
-                    return(MILP_FAIL);
-                }
-                /* check if solution contains enough ints */
-                if (bb_rule == FIRST_NI) {
-                    notint = 0;
-                    int i = Rows + 1;
-                    while(i <= Sum && notint == 0) i++;
-                }
-                if (bb_rule == RAND_NI) {
-                    int nr_not_int, select_not_int;
-                    nr_not_int = 0;
-                    for(int i = Rows + 1; i <= Sum; i++)
-                        if (nr_not_int == 0) notint = 0;
-                        else {
-                            select_not_int=(rdm.nextInt() % nr_not_int) + 1;
-                            i = Rows + 1;
-                            while(select_not_int > 0) i++;
-                            notint = i - 1;
-                        }
-                }
-                if (notint != FALSE) throw new Error("integer linear programming not supported");
-                if (Maximise != FALSE) is_worse = (Solution[0] < Best_solution[0]) ? 1:0;
-                else is_worse = (Solution[0] > Best_solution[0]) ? 1:0;
-                if (is_worse == FALSE) {
-                    System.arraycopy(Solution, 0, Best_solution, 0, Sum + 1);
-                    calculate_duals();
-                    if (break_at_int != FALSE) {
-                        if (Maximise != FALSE &&  (Best_solution[0] > break_value)) Break_bb = TRUE;
-                        if (Maximise == FALSE &&  (Best_solution[0] < break_value)) Break_bb = TRUE;
-                    }
-                }
-            }
-            Level--;
-            return(failure);
-        }
-
-        public int solve() {
-            int result = FAILURE;
-            if (active == FALSE) set_globals();
-            total_iter  = 0;
-            max_level   = 1;
-            total_nodes = 0;
-            if (Isvalid() != FALSE) {
-                if (Maximise != FALSE && obj_bound == Infinite) Best_solution[0]=-Infinite;
-                else if (Maximise == FALSE && obj_bound==-Infinite) Best_solution[0] = Infinite;
-                else Best_solution[0] = obj_bound;
-                Level = 0;
-                if (basis_valid == FALSE) {
-                    for(int i = 0; i <= rows; i++) {
-                        basis[i] = TRUE;
-                        bas[i] = i;
-                    }
-                    for(int i = rows+1; i <= sum; i++) basis[i] = FALSE;
-                    for(int i = 0; i <= sum; i++) lower[i] = TRUE;
-                    basis_valid = TRUE;
-                }
-                eta_valid = FALSE;
-                Break_bb      = FALSE;
-                result        = milpsolve(Orig_upbo, Orig_lowbo, Basis, Lower, Bas); 
-                eta_size  = Eta_size;
-                eta_alloc = Eta_alloc;
-                num_inv   = Num_inv;
-            }
-            for(int i = 0; i < maxmat; i++) { set_row_nr(mat,i, 0); set_value(mat, i, 0); }
-            for(int i = 0; i < maxmat; i++)   col_no[i] = 0;
-
-            // FIXME: not sure about this
-            for(int i = 0; i < Eta_size; i++) eta_value[i] = 0;
-            for(int i = 0; i < Eta_size; i++) eta_row_nr[i] = 0;
-            for(int i = 0; i < Eta_size; i++) eta_col_end[i] = 0;
-
-            maxmat = 0;
-            return(result);
-        }
-
-    private int maxmat = 0;
-    private final static float round( float val, float eps) { return (Math.abs(val) < eps) ? 0 : val; }
-    int get_row_nr(MatrixArray m, int i) { return m.row_nr[i]; }
-    void set_row_nr(MatrixArray m, int i, int val) { m.row_nr[i] = val; maxmat = Math.max(i, maxmat); }
-    float get_value(MatrixArray m, int i) { return m.value[i]; }
-    void set_value(MatrixArray m, int i, float val) { m.value[i] = val; maxmat = Math.max(i, maxmat); }
-    public static class MatrixArray {
-        public int[] row_nr;
-        public float[] value;
-        public final int length;
-        public MatrixArray(int length) { row_nr = new int[length]; value = new float[length]; this.length = length; }
-    }
-
-}
-
diff --git a/src/org/ibex/util/Task.java b/src/org/ibex/util/Task.java
deleted file mode 100644 (file)
index e710724..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.util;
-import java.io.IOException;
-import org.ibex.js.*;
-
-public interface Task {
-    public abstract void perform() throws IOException, JSExn;
-}
diff --git a/src/org/ibex/util/Vec.java b/src/org/ibex/util/Vec.java
deleted file mode 100644 (file)
index ffe7cfd..0000000
+++ /dev/null
@@ -1,454 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-import java.io.*;
-
-/** 
- *  An unsynchronized Vector implementation; same semantics as
- *  java.util.Vector. Useful for JDK1.1 platforms that don't have
- *  java.util.ArrayList.
- *
- *  May contain nulls.
- *
- *  @see java.util.Vector
- */
-public final class Vec implements Serializable {
-    
-    private Object[] store;
-    private int size = 0;
-    
-    public Vec() { this(10); }
-    public Vec(int i) { store = new Object[i]; }
-    public Vec(int i, Object[] store) { size = i; this.store = store; }
-    
-    private void grow() { grow(store.length * 2); }
-    private void grow(int newsize) {
-        Object[] newstore = new Object[newsize];
-        System.arraycopy(store, 0, newstore, 0, size);
-        store = newstore;
-    }
-
-    public void removeAllElements() {
-        for(int i=0; i<size; i++) store[i] = null;
-        size = 0;
-    }
-
-    public void toArray(Object[] o) {
-        for(int i=0; i<size; i++)
-            o[i] = store[i];
-    }
-    
-    public int indexOf(Object o) {
-        for(int i=0; i<size; i++)
-            if (o == null ? store[i] == null : store[i].equals(o)) return i;
-        
-        return -1;
-    }
-    
-    public void addElement(Object o) {
-        if (size >= store.length - 1) grow();
-        store[size++] = o;
-    }
-
-    public Object peek() {
-        return lastElement();
-    }
-
-    public Object elementAt(int i) {
-        return store[i];
-    }
-    
-    public Object lastElement() {
-        if (size == 0) return null;
-        return store[size - 1];
-    }
-
-    public void push(Object o) { addElement(o); }
-    public Object pop() {
-        Object ret = lastElement();
-        if (size > 0) store[size--] = null;
-        return ret;
-    }
-
-    public int size() { return size; }
-
-    public void setSize(int newSize) {
-        if (newSize < 0) throw new RuntimeException("tried to set size to negative value");
-        if (newSize > store.length) grow(newSize * 2);
-        if (newSize < size)
-            for(int i=newSize; i<size; i++)
-                store[i] = null;
-        size = newSize;
-    }
-
-    public void copyInto(Object[] out) {
-        for(int i=0; i<size; i++)
-            out[i] = store[i];
-    }
-
-    public void fromArray(Object[] in) {
-        setSize(in.length);
-        for(int i=0; i<size; i++)
-            store[i] = in[i];
-    }
-
-    public void removeElementAt(int i) {
-        if (i >= size || i < 0) throw new RuntimeException("tried to remove an element outside the vector's limits");
-        for(int j=i; j<size - 1; j++)
-            store[j] = store[j + 1];
-        setSize(size - 1);
-    }
-
-    public void setElementAt(Object o, int i) {
-        if (i >= size) setSize(i);
-        store[i] = o;
-    }
-
-    public void removeElement(Object o) {
-        int idx = indexOf(o);
-        if (idx != -1) removeElementAt(idx);
-    }
-
-    public void insertElementAt(Object o, int at) {
-        if (size == store.length) grow();
-        for(int i=size; i>at; i--)
-            store[i] = store[i-1];
-        store[at] = o;
-        size++;
-    }
-
-    public interface CompareFunc {
-        public int compare(Object a, Object b);
-    }
-
-    public void sort(CompareFunc c) {
-        sort(this, null, c, 0, size-1);
-    }
-
-    public static void sort(Vec a, Vec b, CompareFunc c) {
-        if (b != null && a.size != b.size) throw new IllegalArgumentException("Vec a and b must be of equal size");
-        sort(a, b, c, 0, a.size-1);
-    }
-
-    private static final void sort(Vec a, Vec b, CompareFunc c, int start, int end) {
-        Object tmpa, tmpb = null;
-        if(start >= end) return;
-        if(end-start <= 6) {
-            for(int i=start+1;i<=end;i++) {
-                tmpa = a.store[i];
-                if (b != null) tmpb = b.store[i];
-                int j;
-                for(j=i-1;j>=start;j--) {
-                    if(c.compare(a.store[j],tmpa) <= 0) break;
-                    a.store[j+1] = a.store[j];
-                    if (b != null) b.store[j+1] = b.store[j];
-                }
-                a.store[j+1] = tmpa;
-                if (b != null) b.store[j+1] = tmpb;
-            }
-            return;
-        }
-
-        Object pivot = a.store[end];
-        int lo = start - 1;
-        int hi = end;
-
-        do {
-            while(c.compare(a.store[++lo],pivot) < 0) { }
-            while((hi > lo) && c.compare(a.store[--hi],pivot) > 0) { }
-            swap(a, lo,hi);
-            if (b != null) swap(b, lo,hi);
-        } while(lo < hi);
-
-        swap(a, lo,end);
-        if (b != null) swap(b, lo,end);
-
-        sort(a, b, c, start, lo-1);
-        sort(a, b, c, lo+1, end);
-    }
-
-    private static final void swap(Vec vec, int a, int b) {
-        if(a != b) {
-            Object tmp = vec.store[a];
-            vec.store[a] = vec.store[b];
-            vec.store[b] = tmp;
-        }
-    }
-
-    public static final void sortInts(int[] a, int start, int end) {
-        int tmpa;
-        if(start >= end) return;
-        if(end-start <= 6) {
-            for(int i=start+1;i<=end;i++) {
-                tmpa = a[i];
-                int j;
-                for(j=i-1;j>=start;j--) {
-                    if(a[j] <= tmpa) break;
-                    a[j+1] = a[j];
-                }
-                a[j+1] = tmpa;
-            }
-            return;
-        }
-        int pivot = a[end];
-        int lo = start - 1;
-        int hi = end;
-        do {
-            while(a[++lo] < pivot) { }
-            while((hi > lo) && a[--hi] > pivot) { }
-            swapInts(a, lo, hi);
-        } while(lo < hi);
-        swapInts(a, lo, end);
-        sortInts(a, start, lo-1);
-        sortInts(a, lo+1, end);
-    }
-    private static final void swapInts(int[] vec, int a, int b) {
-        if(a != b) {
-            int tmp = vec[a];
-            vec[a] = vec[b];
-            vec[b] = tmp;
-        }
-    }
-
-
-
-    // just a cut-and-paste copy of Vec with int storage
-    public static class Int {
-        private int[] store;
-        private int size = 0;
-    
-        public Int() { this(10); }
-        public Int(int i) { store = new int[i]; }
-        public Int(int i, int[] store) { size = i; this.store = store; }
-    
-        private void grow() { grow(store.length * 2); }
-        private void grow(int newsize) {
-            int[] newstore = new int[newsize];
-            System.arraycopy(store, 0, newstore, 0, size);
-            store = newstore;
-        }
-
-        public void removeAllElements() {
-            for(int i=0; i<size; i++) store[i] = 0;
-            size = 0;
-        }
-
-        public void toArray(int[] o) {
-            for(int i=0; i<size; i++)
-                o[i] = store[i];
-        }
-    
-        public int[] dump() { int[] o = new int[size]; toArray(o); return o; }
-    
-        public int indexOf(int o) {
-            for(int i=0; i<size; i++)
-                if (o == store[i]) return i;
-        
-            return -1;
-        }
-    
-        public void addElement(int o) {
-            if (size >= store.length - 1) grow();
-            store[size++] = o;
-        }
-
-        public int peek() {
-            return lastElement();
-        }
-
-        public int elementAt(int i) {
-            return store[i];
-        }
-    
-        public int lastElement() {
-            if (size == 0) return 0;
-            return store[size - 1];
-        }
-
-        public void push(int o) { addElement(o); }
-        public int pop() {
-            int ret = lastElement();
-            if (size > 0) store[size--] = 0;
-            return ret;
-        }
-
-        public int size() { return size; }
-
-        public void setSize(int newSize) {
-            if (newSize < 0) throw new RuntimeException("tried to set size to negative value");
-            if (newSize > store.length) grow(newSize * 2);
-            if (newSize < size)
-                for(int i=newSize; i<size; i++)
-                    store[i] = 0;
-            size = newSize;
-        }
-
-        public void copyInto(int[] out) {
-            for(int i=0; i<size; i++)
-                out[i] = store[i];
-        }
-
-        public void fromArray(int[] in) {
-            setSize(in.length);
-            for(int i=0; i<size; i++)
-                store[i] = in[i];
-        }
-
-        public void removeElementAt(int i) {
-            if (i >= size || i < 0) throw new RuntimeException("tried to remove an element outside the vector's limits");
-            for(int j=i; j<size - 1; j++)
-                store[j] = store[j + 1];
-            setSize(size - 1);
-        }
-
-        public void setElementAt(int o, int i) {
-            if (i >= size) setSize(i);
-            store[i] = o;
-        }
-
-        public void removeElement(int o) {
-            int idx = indexOf(o);
-            if (idx != -1) removeElementAt(idx);
-        }
-
-        public void insertElementAt(int o, int at) {
-            if (size == store.length) grow();
-            for(int i=size; i>at; i--)
-                store[i] = store[i-1];
-            store[at] = o;
-            size++;
-        }
-
-        public void sort() { sort(this, null, 0, size-1); }
-
-        public static void sort(Vec.Int a, Vec.Int b) {
-            if (b != null && a.size != b.size) throw new IllegalArgumentException("Vec.Int a and b must be of equal size");
-            sort(a, b, 0, a.size-1);
-        }
-
-        private static final void sort(Vec.Int a, Vec.Int b, int start, int end) {
-            int tmpa, tmpb = 0;
-            if(start >= end) return;
-            if(end-start <= 6) {
-                for(int i=start+1;i<=end;i++) {
-                    tmpa = a.store[i];
-                    if (b != null) tmpb = b.store[i];
-                    int j;
-                    for(j=i-1;j>=start;j--) {
-                        if((a.store[j]-tmpa) <= 0) break;
-                        a.store[j+1] = a.store[j];
-                        if (b != null) b.store[j+1] = b.store[j];
-                    }
-                    a.store[j+1] = tmpa;
-                    if (b != null) b.store[j+1] = tmpb;
-                }
-                return;
-            }
-
-            int pivot = a.store[end];
-            int lo = start - 1;
-            int hi = end;
-
-            do {
-                while((a.store[++lo]-pivot) < 0) { }
-                while((hi > lo) && (a.store[--hi]-pivot) > 0) { }
-                swap(a, lo,hi);
-                if (b != null) swap(b, lo,hi);
-            } while(lo < hi);
-
-            swap(a, lo,end);
-            if (b != null) swap(b, lo,end);
-
-            sort(a, b, start, lo-1);
-            sort(a, b, lo+1, end);
-        }
-
-        private static final void swap(Vec.Int vec, int a, int b) {
-            if(a != b) {
-                int tmp = vec.store[a];
-                vec.store[a] = vec.store[b];
-                vec.store[b] = tmp;
-            }
-        }
-
-        public static final void sortInts(int[] a, int start, int end) {
-            int tmpa;
-            if(start >= end) return;
-            if(end-start <= 6) {
-                for(int i=start+1;i<=end;i++) {
-                    tmpa = a[i];
-                    int j;
-                    for(j=i-1;j>=start;j--) {
-                        if(a[j] <= tmpa) break;
-                        a[j+1] = a[j];
-                    }
-                    a[j+1] = tmpa;
-                }
-                return;
-            }
-
-            int pivot = a[end];
-            int lo = start - 1;
-            int hi = end;
-
-            do {
-                while(a[++lo] < pivot) { }
-                while((hi > lo) && a[--hi] > pivot) { }
-                swapInts(a, lo, hi);
-            } while(lo < hi);
-            swapInts(a, lo, end);
-            sortInts(a, start, lo-1);
-            sortInts(a, lo+1, end);
-        }
-
-        private static final void swapInts(int[] vec, int a, int b) {
-            if(a != b) {
-                int tmp = vec[a];
-                vec[a] = vec[b];
-                vec[b] = tmp;
-            }
-        }
-    }
-
-
-
-    public static final void sortFloats(float[] a, int start, int end) {
-        float tmpa;
-        if(start >= end) return;
-        if(end-start <= 6) {
-            for(int i=start+1;i<=end;i++) {
-                tmpa = a[i];
-                int j;
-                for(j=i-1;j>=start;j--) {
-                    if(a[j] <= tmpa) break;
-                    a[j+1] = a[j];
-                }
-                a[j+1] = tmpa;
-            }
-            return;
-        }
-        float pivot = a[end];
-        int lo = start - 1;
-        int hi = end;
-        do {
-            while(a[++lo] < pivot) { }
-            while((hi > lo) && a[--hi] > pivot) { }
-            swapFloats(a, lo, hi);
-        } while(lo < hi);
-        swapFloats(a, lo, end);
-        sortFloats(a, start, lo-1);
-        sortFloats(a, lo+1, end);
-    }
-    private static final void swapFloats(float[] vec, int a, int b) {
-        if(a != b) {
-            float tmp = vec[a];
-            vec[a] = vec[b];
-            vec[b] = tmp;
-        }
-    }
-}
diff --git a/src/org/ibex/util/XML.java b/src/org/ibex/util/XML.java
deleted file mode 100644 (file)
index d0775c7..0000000
+++ /dev/null
@@ -1,1174 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-import java.io.Reader;
-import java.io.IOException;
-import java.io.EOFException;
-
-/**
- * An Event-Driving, Non-Validating XML Parser with Namespace support.
- *
- * A subclass can implement the abstract functions for receiving details
- * about an xml file as it is parsed. To initate a parse, use the parse()
- * function. 
- *
- * <h3>Implementation Notes</h3>
- * <p>As the parser traverses into an element, it adds it to the linked list
- * called <tt>elements</tt>. However, <tt>elements</tt> has been pre-filled
- * with instances of the Element inner class. So in the vast majority of
- * cases, the pointer current is moved along one, and the values for the
- * new element are filled into the current object.</p>
- *
- * <p>This parser supports all the unicode ranges required by the XML
- * Specification. However, it is optimised for well-formed ASCII documents.
- * Documents containing unicode Names and Attributes will take much longer
- * to process, and invalid documents (badly formed Names or invalid attributes)
- * will be run through a test on every single unicode character range before 
- * being declared invalid.</p> 
- *
- * <ul>
- *  <li>Each time the buffer offset <tt>off</tt> is moved, the length
- *   <tt>len</tt> must be decreased.</li>
- *  <li>Each time the buffer length is decreased, it must be checked to make
- *   sure it is &gt;0.</li>
- *  <li><i>error</i> is defined as a Validity Constraint Violation and
- *   is recoverable</li>
- *  <li><i>fatal error</i> is defined as a Well-formedness Constraint
- *   Violation and is not recoverable</li>
- * </ul> 
- *
- * @author David Crawshaw 
- * @see <a href="http://w3.org/TR/REC-xml">XML Specification</a> 
- * @see <a href="http://w3.org/TR/REC-xml-names">XML Namespaces</a>
- */
-public abstract class XML
-{
-    /////////////////////////////////////////////////////////////////////////////////////////////
-    // XML Parser
-    /////////////////////////////////////////////////////////////////////////////////////////////
-
-    public static final int BUFFER_SIZE = 255;
-
-    /** static pool of XML.Element instances shared by all XML Parsers. */
-    private static final Queue elements = new Queue(30);
-
-    private static final char[] single_amp  = new char[] { '&'  };
-    private static final char[] single_apos = new char[] { '\'' };
-    private static final char[] single_gt   = new char[] { '>'  };
-    private static final char[] single_lt   = new char[] { '<'  };
-    private static final char[] single_quot = new char[] { '"'  };
-
-    private int line;
-    private int col;
-
-    private Reader in;
-    private char[] buf;
-    private int    off;
-    private int    base;  // base+off == distance into the stream
-    private int    len;
-
-    private Element current;
-
-    // used in readEntity() to process a single character without creating a new array
-    private char[] singlechar = new char[1];
-
-
-    public XML() { this(BUFFER_SIZE); }
-
-    public XML(int bSize) {
-        buf = new char[bSize];
-
-        current = (Element)elements.remove(false);
-        if (current == null) current = new Element();
-    }
-
-    /** Returns the line number at the beginning of the last process call. */
-    public int getLine() { return line; }
-
-    /** Returns the column number at the beginning of the last process call. */
-    public int getCol()  { return col; }
-
-    /** Returns the global file offset at the beginning of the last process call. */
-    public int getGlobalOffset() { return base + off; }
-
-    /**
-     * Parse given input and call the abstract event functions.
-     *
-     * Careful with threading, as this function is not synchronized.
-     */ 
-    public final void parse(Reader reader) throws IOException, Exn {
-        in  = reader;
-        off = len = 0;
-        line = col = 1;
-
-        clear(); // clean up possible mid-way linked-list element
-
-        try {
-            // process the stream
-            while (true) {
-                if (!buffer(1)) {
-                    if (current.qName == null) break;
-                    throw new Exn("reached eof without closing <"+current.qName+"> element", Exn.WFC, getLine(), getCol());
-                }
-
-                if (buf[off] == '<') readTag();
-                readChars(current.qName != null);
-            }
-        } finally { clear(); } // clean up elements
-    }
-
-    /** remove any leftover elements from the linked list and queue them */
-    private final void clear() {
-        for (Element last = current; current.parent != null; ) {
-            current = current.parent;
-            last.clear();
-            elements.append(last);
-        }
-        current.clear();
-    }
-
-    /** reads in a tag. expects <tt>buf[off] == '&#60;'</tt> */
-    private final void readTag() throws IOException, Exn {
-        // Start Tag    '<' Name (S Attribute)* S? '>'
-        boolean starttag  = true;
-
-        // End Tag     '</' Name S? '>'
-        boolean endtag    = false;
-
-        // if (starttag & endtag) then: EmptyElemTag '<' Name (S Attribute)* S? '/>'
-
-        // Position in the name of the ':' namespace prefix
-        int prefix = -1;
-
-        int namelen   = 0;
-
-        col++; off++; len--;
-        if (!buffer(1)) throw new EOFException("Unexpected EOF processing element tag");
-
-        // work out what we can from the beginning of the tag
-        char s = buf[off]; 
-        if (s == '!') {
-            // definitions here don't necessarily conform to xml spec (as DTDs not yet implemented)
-            col++; off++; len--; 
-            if (!buffer(4)) throw new EOFException("Unexpected EOF processing <! element");
-
-            boolean bad = false;
-            switch (buf[off]) {
-                case '-':
-                    if (buf[off+1] != '-') { bad = true; break; }
-                    col += 2; off += 2; len -= 2;
-
-                    // Comment        '<!--'      ((Char - '-') | ('-' (Char - '-')))* '-->'
-                    readChars(false, "-->", false); 
-                    col += 3; off += 3; len -= 3;
-                    break;
-
-                // we don't care about the following definitions
-
-                case 'A':
-                    if (!buffer(7)
-                            || buf[off+1] != 'T' || buf[off+2] != 'T' || buf[off+3] != 'L'
-                            || buf[off+4] != 'I' || buf[off+5] != 'S' || buf[off+6] != 'T') {
-                        bad = true; break;
-                    } 
-                    col += 7; off += 7; len -= 7; 
-
-                    // ATTLIST        '<!ATTLIST'   (Char* - '>') '>'
-                    readChars(false, ">", true); 
-                    col++; off++; len--;
-                    break;
-                case 'D':
-                    if (!buffer(7)
-                            || buf[off+1] != 'O' || buf[off+2] != 'C' || buf[off+3] != 'T'
-                            || buf[off+4] != 'Y' || buf[off+5] != 'P' || buf[off+6] != 'E') {
-                        bad = true; break;
-                    }
-                    col += 7; off += 7; len -= 7;
-
-                    // DTD            '<!DOCTYPE'   (Char* - '>') '>'
-                    readChars(false, ">", true); 
-                    col++; off++; len--;
-                    break; 
-                case 'E':
-                    if (!buffer(7)) {
-                        bad = true;
-                    } else if (buf[off+1] == 'L' && buf[off+2] == 'E' && buf[off+3] == 'M'
-                            && buf[off+4] == 'E' && buf[off+5] == 'N' && buf[off+6] == 'T') {
-                        // ELEMENT        '<!ELEMENT'   (Char* - '>') '>'
-                        readChars(false, ">", true); 
-                        col++; off++; len--;
-
-                    } else if (buf[off+1] == 'N' && buf[off+2] == 'T' && buf[off+3] == 'I'
-                            && buf[off+4] == 'T' && buf[off+5] == 'Y') {
-                        // ENTITY         '<!ENTITY'    (Char* - '>') '>'
-                        readChars(false, ">", true); 
-                        col++; off++; len--;
-
-                    } else {
-                        bad = true;
-                    }
-                    break;
-
-                case 'N':
-                    if (!buffer(8)
-                            || buf[off+1] != 'O' || buf[off+2] != 'T' || buf[off+3] != 'A' || buf[off+4] != 'T'
-                            || buf[off+5] != 'I' || buf[off+6] != 'O' || buf[off+7] != 'N') {
-                        bad = true; break;
-                    }
-                    col += 8; off += 8; len -= 8;
-                    // NOTATION       '<!NOTATION'  (Char* - '>') '>'
-                    readChars(false, ">", true); 
-                    col++; off++; len--;
-
-                    break;
-                default: bad = true;
-            }
-
-            if (bad) throw new Exn("element tag start character is invalid", Exn.MARKUP, getLine(), getCol());
-
-        } else if (s == '?') {
-            // PI (Ignored)   '<?'  (Char* - (Char* '?>' Char*))  '?>'
-            col++; off++; len--;
-            readChars(false, "?>", true);
-            if (!buffer(2)) throw new EOFException("Unexpected EOF at end of Processing Instruction");
-            col += 2; off += 2; len -= 2;
-
-        } else if (s == '[') {
-            if (!buffer(7)
-                    || buf[off+1] != 'C' || buf[off+2] != 'D' || buf[off+3] != 'A'
-                    || buf[off+4] != 'T' || buf[off+5] != 'A' || buf[off+6] != '[') {
-                col++; off--; len++; 
-                // Conditional    '<![' (Char* - (Char* ']]>' Char*)) ']]>'
-                readChars(false, "]]>", false); 
-            } else {
-                col += 7; off += 7; len -=7;
-                // CDATA          '<![CDATA[' (Char* - (Char* ']]>' Char*))        ']]>'
-                readChars(true, "]]>", false);
-            } 
-            col += 3; off += 3; len -= 3;
-        } else {
-            if (s == '/') {
-                // End Tag        '</' Name S? '>'
-                starttag = false; 
-                endtag = true;
-
-                col++; off++; len--;
-                if (!buffer(1)) throw new EOFException("Unexpected EOF processing end tag");
-                s = buf[off];
-            }
-
-            if (!Name(s)) throw new Exn("invalid starting character in element name", Exn.MARKUP, getLine(), getCol()); 
-
-            // find the element name (defined in XML Spec: section 2.3)
-            for (namelen = 0; ; namelen++) {
-                if (!buffer(namelen+1)) throw new EOFException("Unexpected EOF in element tag name");
-
-                s = buf[off+namelen];
-
-                if (S(s) || s == '>') {
-                    break;
-                } else if (s == '/') {
-                    endtag = true;
-                    break;
-                } else if (s == ':' && namelen > 0 && prefix < 1) {
-                    // we have a definition of the prefix range available
-                    prefix = namelen; 
-                } else if (!NameChar(s)) {
-                    throw new Exn("element name contains invalid character", Exn.MARKUP, getLine(), getCol());
-                }
-            }
-
-            // process name (based on calculated region)
-            if (namelen < 1) throw new Exn("element name is null", Exn.MARKUP, getLine(), getCol()); 
-
-            // we have marked out the name region, so turn it into a string and move on
-            String qName = new String(buf, off, namelen);
-
-            col += namelen; off += namelen; len -= namelen;
-
-            if (starttag) {
-                // create the in-memory element representation of this beast
-                // if current.qName == null then this is the root element we're dealing with
-                if (current.qName != null) {
-                    Element next = (Element)elements.remove(false);
-                    if (next == null) next = new Element();
-                    //next.clear(); // TODO: remove as elements now checked as they're added to the queue
-                    next.parent = current;
-                    current = next;
-                }
-
-                current.qName = qName;
-
-                if (prefix > 0) {
-                    current.prefix = current.qName.substring(0, prefix);
-                    current.localName = current.qName.substring(prefix+1);
-                } else {
-                    current.prefix = null;
-                    current.localName = current.qName;
-                }
-
-                // process attributes
-                readWhitespace(); 
-                if (!buffer(1)) throw new EOFException("Unexpected EOF - processing attributes part 1");
-                while (buf[off] != '/' && buf[off] != '>') {
-                    readAttribute();
-                    if (!buffer(1)) throw new EOFException("Unexpected EOF - processing attributes part 2");
-                    readWhitespace();
-                }
-
-                // work out the uri of this element
-                current.uri = current.getUri(current.getPrefix()); 
-                if (current.getUri().equals("") && current.getPrefix() != null)
-                    current.addError(new Exn("undefined prefix '"+current.getPrefix()+"'", Exn.NC, getLine(), getCol()));
-
-            } else {
-                // this is an end-of-element tag
-                if (!qName.equals(current.getQName())) throw new Exn(
-                    "end tag </"+qName+"> does not line up with start tag <"+current.getQName()+">", Exn.WFC, getLine(), getCol()
-                );
-            }
-
-            // deal with whitespace
-            readWhitespace(); 
-
-            // process tag close
-            if (!buffer(1)) throw new EOFException("Unexpected EOF before end of tag"); 
-            if (buf[off] == '/') {
-                endtag = true;
-                off++; len--; col++;
-            }
-            if (!buffer(1)) throw new EOFException("Unexpected EOF before end of endtag"); 
-            if (buf[off] == '>') {
-                off++; len--; col++;
-            } else {
-                throw new Exn("missing '>' character from element '"+qName+"'", Exn.MARKUP, getLine(), getCol());
-            }
-
-            // send element signals
-            if (starttag) startElement(current);
-            if (endtag) {
-                endElement(current);
-
-                // we just closed an element, so remove it from the element 'stack'
-                if (current.getParent() == null) {
-                    // we just finished the root element
-                    current.clear(); 
-                } else {
-                    Element last = current;
-                    current = current.parent;
-                    last.clear();
-                    elements.append(last);
-                }
-            }
-        }
-    }
-
-    /** reads in an attribute of an element. expects Name(buf[off]) */
-    private final void readAttribute() throws IOException, Exn {
-        int ref = 0;
-        int prefix = 0;
-        String n, v, p, u; // attribute name, value, prefix and uri respectively
-        n = v = p = u = null;
-        char s;
-
-        // find the element name (defined in XML Spec: section 2.3)
-        for (ref= 0; ; ref++) {
-            if (!buffer(ref+1)) throw new EOFException("Unexpected EOF in read attribute loop part 1");
-
-            s = buf[off+ref];
-
-            if (s == '=' || S(s)) {
-                break;
-            } else if (s == ':' && ref > 0 && prefix < 1) {
-                // we have a definition of the prefix range available
-                prefix = ref+1;
-            } else if (!NameChar(s)) {
-                throw new Exn("attribute name contains invalid characters", Exn.MARKUP, getLine(), getCol());
-            }
-        }
-
-        // determine prefix and key name
-        if (prefix > 0) {
-            p = new String(buf, off, prefix-1);
-            col += prefix; off += prefix; len -= prefix; ref -= prefix;
-        }
-        n = new String(buf, off, ref);
-        col += ref; off += ref; len -= ref;
-
-        // find name/value divider ('=')
-        readWhitespace();
-        if (!buffer(1)) throw new EOFException("Unexpected EOF before attribute '=' divider");
-        if (buf[off] != '=') throw new Exn("attribute name not followed by '=' sign", Exn.MARKUP, getLine(), getCol());
-
-        col++; off++; len--;
-        readWhitespace();
-
-        if (!buffer(1)) throw new EOFException("Unexpected EOF after attribute '=' divider");
-
-        char wrap;
-        if (buf[off] == '\'' || buf[off] == '"') {
-            wrap = buf[off];
-        } else {
-            throw new Exn("attribute '"+n+"' must have attribute wrapped in ' or \"", Exn.MARKUP, getLine(), getCol());
-        }
-        col++; off++; len--;
-
-        // find the attribute value
-        attval: for (ref = 0; ; ref++) {
-            if (!buffer(ref+1)) throw new EOFException("Unexpected EOF in attribute value");
-
-            if (buf[off+ref] == wrap) {
-                break attval;
-            } else if (buf[off+ref] == '<') {
-                throw new Exn("attribute value for '"+n+"' must not contain '<'", Exn.WFC, getLine(), getCol());
-            } 
-        }
-
-        v = new String(buf, off, ref);
-        col += ref; off += ref; len -= ref;
-
-        // remove end wrapper character
-        col++; off++; len--;
-
-        // process attribute
-        if (p != null && p.equals("xmlns")) {
-            current.addUri(n, v);
-        } else if (n.equals("xmlns")) {
-            if (current.getUri().equals("")) {
-                current.addUri("", v);
-            } else {
-                current.addError(new Exn("default namespace definition repeated", Exn.NC, getLine(), getCol()));
-            }
-        } else {
-            // find attribute uri
-            u = current.getUri(p); 
-            if (p != null && u.equals("")) current.addError(new Exn("undefined attribute prefix '"+p+"'", Exn.NC, getLine(), getCol()));
-
-            // check to see if attribute is a repeat
-            for (int i=0; current.len > i; i++) if (n.equals(current.getAttrKey(i)) && u.equals(current.getAttrUri(i))) throw new Exn(
-                "attribute name '"+n+"' may not appear more than once in the same element tag", Exn.WFC, getLine(), getCol()
-            );
-
-            current.addAttr(n, v, u); 
-        }
-    }
-
-    /** reads an entity and processes out its value. expects buf[off] == '&amp;' */
-    private final void readEntity() throws IOException, Exn {
-        off++; len--;
-        if (!buffer(2)) throw new EOFException("Unexpected EOF reading entity");
-
-        boolean unknown = false;
-        switch (buf[off]) {
-            case '#':
-                off++; len--;
-
-                int radix;
-                if (buf[off] == 'x') { off++; len--; radix = 16; } else { radix = 10; }
-                int c = 0;
-
-                // read in each char, then shift total value to the left and add the extra
-                // style of loop is slightly different from all the others, as this should run a limited number of times 
-                findchar: while (true) {
-                    if (!buffer(1)) throw new EOFException("Unexpected EOF reading entity");
-                    int d = Character.digit(buf[off], radix);
-                    if (d == -1) {
-                        if (buf[off] != ';') throw new Exn("illegal characters in entity reference", Exn.WFC, getLine(), getCol());
-                        off++; len--; col++;
-                        break findchar;
-                    }
-                    c = (c * radix) + d;
-
-                    off++; len--;
-                }
-
-                singlechar[0] = Character.forDigit(c, radix);
-                characters(singlechar, 0, 1);
-                break;
-
-            case 'a':
-                if (buffer(4) && buf[off+1] == 'm' && buf[off+2] == 'p' && buf[off+3] == ';') {
-                    characters(single_amp, 0, 1); // &amp;
-                    off += 4; len -= 4; col++;
-                } else if (buffer(5) && buf[off+1] == 'p' && buf[off+2] == 'o' && buf[off+3] == 's' && buf[off+4] == ';') {
-                    characters(single_apos, 0, 1); // &apos;
-                    off += 5; len -= 5; col++;
-                } else {
-                    unknown = true;
-                }
-                break;
-
-            case 'g':
-                if (buffer(3) && buf[off+1] == 't' && buf[off+2] == ';') {
-                    characters(single_gt, 0, 1); // &gt;
-                    off += 3; len -= 3; col++;
-                } else {
-                    unknown = true;
-                }
-                break;
-
-            case 'l':
-                if (buffer(3) && buf[off+1] == 't' && buf[off+2] == ';') {
-                    characters(single_lt, 0, 1); // &lt;
-                    off += 3; len -= 3; col++;
-                } else {
-                    unknown = true;
-                }
-                break;
-
-            case 'q':
-                if (buffer(5) && buf[off+1] == 'u' && buf[off+2] == 'o' && buf[off+3] == 't' && buf[off+4] == ';') {
-                    characters(single_quot, 0, 1); // &quot;
-                    off += 5; len -= 5; col++;
-                } else {
-                    unknown = true;
-                }
-                break;
-
-            // TODO: check a parser-level Hash of defined entities
-        }
-
-        if (unknown) throw new Exn("unknown entity (<!ENTITY> not supported)", Exn.WFC, getLine(), getCol());
-    }
-
-    /** reads until the passed string is encountered. */
-    private final void readChars(boolean p, String match, boolean entities) throws IOException, Exn {
-        int ref;
-        char[] end = match.toCharArray();
-
-        for (boolean more = true; more;) {
-            if (!buffer(1)) return;
-
-            buf: for (ref = 0; ref < len; ref++) {
-                switch (buf[off+ref]) {
-                    case '\r': // windows or macos9 newline
-                        // normalise and process
-                        buf[off+ref] = '\n'; ref++;
-                        if (p) characters(buf, off, ref);
-                        off += ref; len -= ref; ref = -1;
-                        line++; col = 1;
-
-                        // windows double-char newline; skip the next char
-                        if (!buffer(1)) return;
-                        if (buf[off] == '\n') { off++; len--; }
-                        break;
-
-                    case '\n': // unix newline
-                        ref++;
-                        if (p) characters(buf, off, ref);
-                        off += ref; len -= ref; ref = -1;
-                        line++; col = 1;
-                        break;
-
-                    case '&':  // entity
-                        if (entities) {
-                            if (p) {
-                                if (ref > 0) characters(buf, off, ref);
-                                off += ref; len -= ref; ref = -1;
-                                readEntity();
-                            }
-                            break;
-                        }
-
-                    default:
-                        if (!buffer(ref+end.length)) continue buf;
-                        for (int i=0; end.length > i; i++) if (end[i] != buf[off+ref+i]) continue buf;
-                        more = false;
-                        break buf;
-                }
-            }
-
-            if (p && ref > 0) characters(buf, off, ref);
-            off += ref; len -= ref; col += ref;
-        }
-    }
-
-    /**
-     * reads until a <tt>&#60;</tt> symbol is encountered
-     * @param p If true call the characters(char[],int,int) funciton for the processed characters 
-     */
-    private final void readChars(boolean p) throws IOException, Exn {
-        int ref;
-
-        for (boolean more = true; more;) {
-            if (!buffer(1)) return;
-
-            buf: for (ref = 0; ref < len; ref++) {
-                switch (buf[off+ref]) {
-                    case '\r': // windows or macos9 newline
-                        // normalise and process
-                        buf[off+ref] = '\n'; ref++;
-                        if (p) characters(buf, off, ref);
-                        off += ref; len -= ref; ref = -1;
-                        line++; col = 1;
-
-                        // windows double-char newline; skip the next char
-                        if (!buffer(1)) return;
-                        if (buf[off] == '\n') { off++; len--; }
-                        break;
-
-                    case '\n': // unix newline
-                        ref++;
-                        if (p) characters(buf, off, ref);
-                        off += ref; len -= ref; ref = -1;
-                        line++; col = 1;
-                        break;
-
-                    case '&':  // entity
-                        if (p) {
-                            if (ref > 0) characters(buf, off, ref);
-                            off += ref; len -= ref; ref = -1;
-                            readEntity();
-                        }
-                        break;
-
-                    case '<':  // end of chars section
-                        more = false;
-                        break buf;
-                }
-            }
-
-            if (p && ref > 0) characters(buf, off, ref);
-            off += ref; len -= ref; col += ref;
-        }
-    }
-
-    /** reads until a non-whitespace symbol is encountered */
-    private final void readWhitespace() throws IOException, Exn {
-        int ref;
-
-        for (boolean more = true; more;) {
-            if (!buffer(1)) return;
-
-            buf: for (ref = 0; ref < len; ref++) {
-                switch (buf[off+ref]) {
-                    case '\r': // windows or macos9 newline
-                        // normalise and process
-                        buf[off+ref] = '\n';
-                        whitespace(buf, off, ++ref);
-                        off += ref; len -= ref; ref = -1;
-                        line++; col = 1;
-
-                        // windows double-char newline; skip the next char
-                        if (!buffer(1)) return;
-                        if (buf[off] == '\n') { off++; len--; }
-                        break;
-
-                    case '\n': // unix newline
-                        whitespace(buf, off, ++ref);
-                        off += ref; len -= ref; ref = -1;
-                        line++; col = 1;
-                        break;
-
-                    case ' ':  // space
-                    case '\t': // tab
-                        break;
-
-                    default:   // end of whitespace
-                        more = false;
-                        break buf;
-                }
-            }
-
-            off += ref; len -= ref; col += ref;
-        }
-    }
-
-    /**
-     * attempt to fill the buffer.
-     *
-     * @param min Minimum number of characters to read (even if we have to block to do it).
-     * @return return false if min can't be reached.
-     */
-    private final boolean buffer(int min) throws IOException {
-        if (len > min) return true;
-
-        if (buf.length - (off+len) >= min) {
-            // plenty of space left on the end of the buffer
-        } else if (off >= min) {
-            // moving offset data to start will leave enough free space on the end
-            System.arraycopy(buf, off, buf, 0, len); 
-            base += off;
-            off = 0;
-        } else {
-            // buffer size will have to be increased
-            char[] newbuf = new char[buf.length * 2];
-            System.arraycopy(buf, off, newbuf, 0, len);
-            buf = newbuf;
-            base += off;
-            off = 0;
-        }
-
-        while (min > len) {
-            int newlen = in.read(buf, off+len, buf.length-(off+len));
-            if (newlen < 0) return false; 
-            len += newlen;
-        }
-
-        return true;
-    }
-
-
-    /////////////////////////////////////////////////////////////////////////////////////////////
-    // Abstract SAX-Like Interface
-    /////////////////////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * Called when the start of an element is processed.
-     *
-     * <p><b>DO NOT</b> store a reference to the Element object, as
-     * they are reused by XML Parser.</p>
-     */ 
-    public abstract void startElement(Element e) throws Exn;
-
-    /**
-     * Represents up to a line of character data. 
-     *
-     * <p>Newlines are all normalised to the Unix \n as per the XML Spec,
-     * and a newline will only appear as the last character in the passed
-     * array segment.</p>
-     *
-     * <p>XML.getLine() and XML.getCol() report the position at the
-     * beginning of this character segment, which can be processed in a
-     * line-by-line fashion due to the above newline restriction.</p>
-     */
-    public abstract void characters(char[] ch, int start, int length) throws Exn, IOException;
-
-    /** Represents up to a line of ignorable whitespace. */
-    public abstract void whitespace(char[] ch, int start, int length) throws Exn, IOException;
-
-    /** Represents the end of an Element. */
-    public abstract void endElement(Element e) throws Exn, IOException;
-
-
-    /////////////////////////////////////////////////////////////////////////////////////////////
-    // Inner Classes for Parser Support
-    /////////////////////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * Represents an element in an XML document. Stores a reference to its
-     * parent, forming a one-way linked list.
-     *
-     * Element objects are reused, so client code making use of them must
-     * drop their references after the specific element process function
-     * has returned.
-     */
-    public static final class Element {
-
-        private static final int DEFAULT_ATTR_SIZE = 10;
-
-        protected Element parent = null;
-
-        protected String uri = null;
-        protected String localName = null;
-        protected String qName = null;
-        protected String prefix = null;
-
-        protected Hash urimap = new Hash(3,3);
-
-        protected String[] keys = new String[DEFAULT_ATTR_SIZE];
-        protected String[] vals = new String[DEFAULT_ATTR_SIZE];
-        protected String[] uris = new String[DEFAULT_ATTR_SIZE];
-        protected int len = 0;
-
-        protected Exn[] errors = new Exn[] {};
-
-        /** Parent of current element. */
-        public Element getParent() { return parent; }
-
-        /** Qualified Name of current element.  XML Namespace Spec 14-Jan-1999 [6] */
-        public String getQName() { return qName; }
-
-        /** LocalPart of current element. XML Namespace Spec 14-Jan-1999 [8] */
-        public String getLocalName() { return localName; }
-
-        /** Prefix of current element. Substring of qName. XML Namespace Spec 14-Jan-1999 [7] */
-        public String getPrefix() { return prefix; }
-
-        // HACK
-        public Hash getUriMap() {
-            Hash map = new Hash();
-            for (Element e = this; e != null; e = e.getParent()) {
-                java.util.Enumeration en = e.urimap.keys();
-                while(en.hasMoreElements()) {
-                    String key = (String)en.nextElement();
-                    String val = getUri(key);
-                    map.put(key, val);
-                }
-            }
-            return map;
-        }
-
-        /** URI of current tag. XML Namespace Spec 14-Jan-1999 section 1 */
-        public String getUri() { return getUri(prefix); }
-
-        /** URI of a given prefix. Never returns null, instead gives "". */
-        public String getUri(String p) {
-            String ret = null;
-            for (Element e = this; e != null && ret == null; e = e.getParent()) {
-                ret = (String)e.urimap.get(p == null ? "" : p);
-            }
-            return ret == null ? "" : ret;
-        }
-
-        /** An array of attribute names. */
-        public String getAttrKey(int pos) { return len > pos ? keys[pos] : null; }
-
-        /** An array of attribute values. */
-        public String getAttrVal(int pos) { return len > pos ? vals[pos] : null; }
-
-        /** An array of attribute uris. */
-        public String getAttrUri(int pos) { return len > pos ? uris[pos] : null; }
-
-        /** Current number of attributes in the element. */
-        public int getAttrLen() { return len; }
-
-        /** Poor performance, but easier to use when speed is not a concern */
-        public Hash getAttrHash() {
-            Hash ret = new Hash(getAttrLen() * 2, 3);
-            for(int i=0; i<len; i++)
-                ret.put(getAttrKey(i), getAttrVal(i));
-            return ret;
-        }
-
-        /** Poor performance, but easier to use */
-        public String getAttrVal(String key) {
-            for(int i=0; i<len; i++) if (keys[i].equals(key)) return vals[i];
-            return null;
-        }
-
-        /** An array of non-fatal errors related to this element. */
-        public Exn[] getErrors() { return errors; }
-
-        protected Element() { }
-
-        /** Add (replace if exists in current element) a Namespace prefix/uri map. */
-        public void addUri(String name, String value) {
-            urimap.put(name, value);
-        }
-
-        /** Add an attribute. */
-        protected void addAttr(String key, String val, String uri) {
-            if (len == keys.length) {
-                // increase the size of the attributes arrays
-                String[] newkeys = new String[keys.length*2];
-                String[] newvals = new String[vals.length*2];
-                String[] newuris = new String[uris.length*2];
-                System.arraycopy(keys, 0, newkeys, 0, keys.length);
-                System.arraycopy(vals, 0, newvals, 0, vals.length);
-                System.arraycopy(uris, 0, newuris, 0, uris.length);
-                keys = newkeys; vals = newvals; uris = newuris;
-            }
-
-            keys[len] = key;
-            vals[len] = val;
-            uris[len] = uri;
-            len++;
-        }
-
-        /** Add an error. */
-        protected void addError(Exn e) {
-            // it doesn't really matter about continually expanding the array, as this case is quite rare
-            Exn[] newe = new Exn[errors.length+1];
-            System.arraycopy(errors, 0, newe, 0, errors.length);
-            newe[errors.length] = e;
-            errors = newe;
-        }
-
-        /** Empty out all the data from the Element. */
-        protected void clear() {
-            parent = null;
-            uri = localName = qName = prefix = null;
-            urimap.clear();
-
-            if (keys.length != vals.length || vals.length != uris.length) {
-                keys = new String[DEFAULT_ATTR_SIZE];
-                vals = new String[DEFAULT_ATTR_SIZE];
-                uris = new String[DEFAULT_ATTR_SIZE];
-            } else {
-                for (int i=0; keys.length > i; i++) { keys[i] = null; vals[i] = null; uris[i] = null; };
-            }
-            len = 0;
-
-            errors = new Exn[] {};
-        }
-    }
-
-    /** Parse or Structural Error */
-    public static class Exn extends Exception {
-        /** Violation of Markup restrictions in XML Specification - Fatal Error */
-        public static final int MARKUP = 1;
-
-        /** Well-Formedness Constraint Violation - Fatal Error */
-        public static final int WFC = 2;
-
-        /** Namespace Constraint Violation - Recoverable Error */
-        public static final int NC = 3;
-
-        /** Schema Violation - Fatal Error */
-        public static final int SCHEMA = 4;
-
-        private String error;
-        private int type;
-        private int line;
-        private int col;
-
-        public Exn(String e) { this(e, MARKUP, -1, -1); }
-
-        public Exn(String e, int type, int line, int col) {
-            this.error = e;
-            this.type  = type;
-            this.line  = line;
-            this.col   = col;
-        }
-
-        public int getType() { return this.type; }
-        public int getLine() { return this.line; }
-        public int getCol()  { return this.col;  }
-        public String getMessage() { return this.error + (line >= 0 && col >= 0 ? " at " + line + ":" + col: ""); }
-    }
-
-
-    /////////////////////////////////////////////////////////////////////////////////////////////
-    // Static Support Functions for the XML Specification 
-    /////////////////////////////////////////////////////////////////////////////////////////////
-    // attempt to avoid these functions unless you *expect* the input to fall in the given range.
-
-    /** First Character of Name - XML Specification 1.0 [5] */
-    private static final boolean Name(char c) {
-        return BaseCharAscii(c) || c == '_' || c == ':' || Letter(c);
-    } 
-
-    /** NameChar - XML Specification 1.0 [4] */
-    private static final boolean NameChar(char c) {
-        return BaseCharAscii(c) || c == '.' || c == '-' || c == '_' || c == ':'
-            || Digit(c) || Letter(c) || Extender(c); // TODO: || CombiningChar(c);
-    } 
-
-    /** BaseChar - XMl Specification 1.0 [84] */
-    private static final boolean Letter(char c) {
-        return BaseChar(c) || Ideographic(c);
-    }
-
-    /** Elements of BaseChar that exist in ASCII. */
-    private static final boolean BaseCharAscii(char c) {
-        return (c >= '\u0041' && c <= '\u005A') || (c >= '\u0061' && c <= '\u007A');
-    }
-
-    /** Char - XML Specification 1.0 [2] */
-    private static final boolean Char(char c) {
-        // u000A == r and u000D == n, but the javac compiler can't handle the \ u form
-        return c == '\u0009' || c == '\r' || c == '\n'
-            || (c >= '\u0020' && c <= '\uD7FF')
-            || (c >= '\uE000' && c <= '\uFFFD');
-    }
-
-    /** BaseChar - XML Specification 1.0 [85] */
-    private static final boolean BaseChar(char c) {
-        return  BaseCharAscii(c) || (c >= '\u00C0' && c <= '\u00D6')
-            || (c >= '\u00D8' && c <= '\u00F6') || (c >= '\u00F8' && c <= '\u00FF') || (c >= '\u0100' && c <= '\u0131')
-            || (c >= '\u0134' && c <= '\u013E') || (c >= '\u0141' && c <= '\u0148') || (c >= '\u014A' && c <= '\u017E')
-            || (c >= '\u0180' && c <= '\u01C3') || (c >= '\u01CD' && c <= '\u01F0') || (c >= '\u01F4' && c <= '\u01F5')
-            || (c >= '\u01FA' && c <= '\u0217') || (c >= '\u0250' && c <= '\u02A8') || (c >= '\u02BB' && c <= '\u02C1')
-            || (c == '\u0386')                  || (c >= '\u0388' && c <= '\u038A') || (c == '\u038C')
-            || (c >= '\u038E' && c <= '\u03A1') || (c >= '\u03A3' && c <= '\u03CE') || (c >= '\u03D0' && c <= '\u03D6')
-            || (c == '\u03DA')                  || (c == '\u03DC')                  || (c == '\u03DE')
-            || (c == '\u03E0')
-            || (c >= '\u03E2' && c <= '\u03F3') || (c >= '\u0401' && c <= '\u040C') || (c >= '\u040E' && c <= '\u044F')
-            || (c >= '\u0451' && c <= '\u045C') || (c >= '\u045E' && c <= '\u0481') || (c >= '\u0490' && c <= '\u04C4')
-            || (c >= '\u04C7' && c <= '\u04C8') || (c >= '\u04CB' && c <= '\u04CC') || (c >= '\u04D0' && c <= '\u04EB')
-            || (c >= '\u04EE' && c <= '\u04F5') || (c >= '\u04F8' && c <= '\u04F9') || (c >= '\u0531' && c <= '\u0556')
-            || (c == '\u0559')
-            || (c >= '\u0561' && c <= '\u0586') || (c >= '\u05D0' && c <= '\u05EA') || (c >= '\u05F0' && c <= '\u05F2')
-            || (c >= '\u0621' && c <= '\u063A') || (c >= '\u0641' && c <= '\u064A') || (c >= '\u0671' && c <= '\u06B7')
-            || (c >= '\u06BA' && c <= '\u06BE') || (c >= '\u06C0' && c <= '\u06CE') || (c >= '\u06D0' && c <= '\u06D3')
-            || (c == '\u06D5')
-            || (c >= '\u06E5' && c <= '\u06E6') || (c >= '\u0905' && c <= '\u0939')
-            || (c == '\u093D')
-            || (c >= '\u0958' && c <= '\u0961') || (c >= '\u0985' && c <= '\u098C') || (c >= '\u098F' && c <= '\u0990')
-            || (c >= '\u0993' && c <= '\u09A8') || (c >= '\u09AA' && c <= '\u09B0')
-            || (c == '\u09B2')
-            || (c >= '\u09B6' && c <= '\u09B9') || (c >= '\u09DF' && c <= '\u09E1') || (c >= '\u09F0' && c <= '\u09F1')
-            || (c >= '\u0A05' && c <= '\u0A0A') || (c >= '\u0A0F' && c <= '\u0A10') || (c >= '\u0A13' && c <= '\u0A28')
-            || (c >= '\u0A2A' && c <= '\u0A30') || (c >= '\u0A32' && c <= '\u0A33') || (c >= '\u0A35' && c <= '\u0A36')
-            || (c >= '\u0A38' && c <= '\u0A39') || (c >= '\u0A59' && c <= '\u0A5C')
-            || (c == '\u0A5E')
-            || (c >= '\u0A72' && c <= '\u0A74') || (c >= '\u0A85' && c <= '\u0A8B')
-            || (c == '\u0A8D')
-            || (c >= '\u0A8F' && c <= '\u0A91') || (c >= '\u0A93' && c <= '\u0AA8') || (c >= '\u0AAA' && c <= '\u0AB0') 
-            || (c >= '\u0AB2' && c <= '\u0AB3') || (c >= '\u0AB5' && c <= '\u0AB9') 
-            || (c == '\u0ABD') 
-            || (c == '\u0AE0') 
-            || (c >= '\u0B05' && c <= '\u0B0C') || (c >= '\u0B0F' && c <= '\u0B10') || (c >= '\u0B13' && c <= '\u0B28') 
-            || (c >= '\u0B2A' && c <= '\u0B30') || (c >= '\u0B32' && c <= '\u0B33') || (c >= '\u0B36' && c <= '\u0B39') 
-            || (c == '\u0B3D') 
-            || (c >= '\u0B5C' && c <= '\u0B5D') || (c >= '\u0B5F' && c <= '\u0B61') || (c >= '\u0B85' && c <= '\u0B8A') 
-            || (c >= '\u0B8E' && c <= '\u0B90') || (c >= '\u0B92' && c <= '\u0B95') || (c >= '\u0B99' && c <= '\u0B9A') 
-            || (c == '\u0B9C') 
-            || (c >= '\u0B9E' && c <= '\u0B9F') || (c >= '\u0BA3' && c <= '\u0BA4') || (c >= '\u0BA8' && c <= '\u0BAA') 
-            || (c >= '\u0BAE' && c <= '\u0BB5') || (c >= '\u0BB7' && c <= '\u0BB9') || (c >= '\u0C05' && c <= '\u0C0C') 
-            || (c >= '\u0C0E' && c <= '\u0C10') || (c >= '\u0C12' && c <= '\u0C28') || (c >= '\u0C2A' && c <= '\u0C33') 
-            || (c >= '\u0C35' && c <= '\u0C39') || (c >= '\u0C60' && c <= '\u0C61') || (c >= '\u0C85' && c <= '\u0C8C') 
-            || (c >= '\u0C8E' && c <= '\u0C90') || (c >= '\u0C92' && c <= '\u0CA8') || (c >= '\u0CAA' && c <= '\u0CB3') 
-            || (c >= '\u0CB5' && c <= '\u0CB9') 
-            || (c == '\u0CDE') 
-            || (c >= '\u0CE0' && c <= '\u0CE1') || (c >= '\u0D05' && c <= '\u0D0C') || (c >= '\u0D0E' && c <= '\u0D10') 
-            || (c >= '\u0D12' && c <= '\u0D28') || (c >= '\u0D2A' && c <= '\u0D39') || (c >= '\u0D60' && c <= '\u0D61') 
-            || (c >= '\u0E01' && c <= '\u0E2E') 
-            || (c == '\u0E30') 
-            || (c >= '\u0E32' && c <= '\u0E33') || (c >= '\u0E40' && c <= '\u0E45') || (c >= '\u0E81' && c <= '\u0E82') 
-            || (c == '\u0E84') 
-            || (c >= '\u0E87' && c <= '\u0E88') 
-            || (c == '\u0E8A') 
-            || (c == '\u0E8D') 
-            || (c >= '\u0E94' && c <= '\u0E97') || (c >= '\u0E99' && c <= '\u0E9F') || (c >= '\u0EA1' && c <= '\u0EA3') 
-            || (c == '\u0EA5') 
-            || (c == '\u0EA7') 
-            || (c >= '\u0EAA' && c <= '\u0EAB') || (c >= '\u0EAD' && c <= '\u0EAE') 
-            || (c == '\u0EB0') 
-            || (c >= '\u0EB2' && c <= '\u0EB3') 
-            || (c == '\u0EBD') 
-            || (c >= '\u0EC0' && c <= '\u0EC4') || (c >= '\u0F40' && c <= '\u0F47') || (c >= '\u0F49' && c <= '\u0F69') 
-            || (c >= '\u10A0' && c <= '\u10C5') || (c >= '\u10D0' && c <= '\u10F6') 
-            || (c == '\u1100') 
-            || (c >= '\u1102' && c <= '\u1103') || (c >= '\u1105' && c <= '\u1107') 
-            || (c == '\u1109') 
-            || (c >= '\u110B' && c <= '\u110C') || (c >= '\u110E' && c <= '\u1112') 
-            || (c == '\u113C') 
-            || (c == '\u113E') 
-            || (c == '\u1140') 
-            || (c == '\u114C') 
-            || (c == '\u114E') 
-            || (c == '\u1150') 
-            || (c >= '\u1154' && c <= '\u1155') 
-            || (c == '\u1159') 
-            || (c >= '\u115F' && c <= '\u1161') 
-            || (c == '\u1163') 
-            || (c == '\u1165') 
-            || (c == '\u1167') 
-            || (c == '\u1169') 
-            || (c >= '\u116D' && c <= '\u116E') || (c >= '\u1172' && c <= '\u1173') 
-            || (c == '\u1175') 
-            || (c == '\u119E') 
-            || (c == '\u11A8') 
-            || (c == '\u11AB') 
-            || (c >= '\u11AE' && c <= '\u11AF') || (c >= '\u11B7' && c <= '\u11B8') 
-            || (c == '\u11BA') 
-            || (c >= '\u11BC' && c <= '\u11C2') 
-            || (c == '\u11EB') 
-            || (c == '\u11F0') 
-            || (c == '\u11F9') 
-            || (c >= '\u1E00' && c <= '\u1E9B') || (c >= '\u1EA0' && c <= '\u1EF9') || (c >= '\u1F00' && c <= '\u1F15') 
-            || (c >= '\u1F18' && c <= '\u1F1D') || (c >= '\u1F20' && c <= '\u1F45') || (c >= '\u1F48' && c <= '\u1F4D') 
-            || (c >= '\u1F50' && c <= '\u1F57') 
-            || (c == '\u1F59') 
-            || (c == '\u1F5B') 
-            || (c == '\u1F5D') 
-            || (c >= '\u1F5F' && c <= '\u1F7D') || (c >= '\u1F80' && c <= '\u1FB4') || (c >= '\u1FB6' && c <= '\u1FBC') 
-            || (c == '\u1FBE') 
-            || (c >= '\u1FC2' && c <= '\u1FC4') || (c >= '\u1FC6' && c <= '\u1FCC') || (c >= '\u1FD0' && c <= '\u1FD3') 
-            || (c >= '\u1FD6' && c <= '\u1FDB') || (c >= '\u1FE0' && c <= '\u1FEC') || (c >= '\u1FF2' && c <= '\u1FF4') 
-            || (c >= '\u1FF6' && c <= '\u1FFC') 
-            || (c == '\u2126') 
-            || (c >= '\u212A' && c <= '\u212B') 
-            || (c == '\u212E') 
-            || (c >= '\u2180' && c <= '\u2182') || (c >= '\u3041' && c <= '\u3094') || (c >= '\u30A1' && c <= '\u30FA') 
-            || (c >= '\u3105' && c <= '\u312C') || (c >= '\uAC00' && c <= '\uD7A3');
-    }
-
-    /** BaseChar - XMl Specification 1.0 [86] */
-    private static final boolean Ideographic(char c) {
-        return (c >= '\u4E00' && c <= '\u9FA5') || c == '\u3007' || (c >= '\u3021' && c <= '\u3029');
-    }
-    /** CombiningChar - XMl Specification 1.0 [87] */
-    /*private static final boolean CombiningChar(char c) {
-        return (c >= '\u0300' && c <= '\u0345')
-            || (c >= '\u0360' && c <= '\u0361') || (c >= '\u0483' && c <= '\u0486') || (c >= '\u0591' && c <= '\u05A1') 
-            || (c >= '\u05A3' && c <= '\u05B9') || (c >= '\u05BB' && c <= '\u05BD') 
-            || (c == '\u05BF') 
-            || (c >= '\u05C1' && c <= '\u05C2') 
-            || (c == '\u05C4') 
-            || (c >= '\u064B' && c <= '\u0652') 
-            || (c == '\u0670') 
-            || (c >= '\u06D6' && c <= '\u06DC') || (c >= '\u06DD' && c <= '\u06DF') || (c >= '\u06E0' && c <= '\u06E4') 
-            || (c >= '\u06E7' && c <= '\u06E8') || (c >= '\u06EA' && c <= '\u06ED') || (c >= '\u0901' && c <= '\u0903') 
-            || (c == '\u093C') 
-            || (c >= '\u093E' && c <= '\u094C') 
-            || (c == '\u094D') 
-            || (c >= '\u0951' && c <= '\u0954') || (c >= '\u0962' && c <= '\u0963') || (c >= '\u0981' && c <= '\u0983') 
-            || (c == '\u09BC') 
-            || (c == '\u09BE') 
-            || (c == '\u09BF') 
-            || (c >= '\u09C0' && c <= '\u09C4') || (c >= '\u09C7' && c <= '\u09C8') || (c >= '\u09CB' && c <= '\u09CD') 
-            || (c == '\u09D7') 
-            || (c >= '\u09E2' && c <= '\u09E3') 
-            || (c == '\u0A02') 
-            || (c == '\u0A3C') 
-            || (c == '\u0A3E') 
-            || (c == '\u0A3F') 
-            || (c >= '\u0A40' && c <= '\u0A42') || (c >= '\u0A47' && c <= '\u0A48') || (c >= '\u0A4B' && c <= '\u0A4D') 
-            || (c >= '\u0A70' && c <= '\u0A71') || (c >= '\u0A81' && c <= '\u0A83') 
-            || (c == '\u0ABC') 
-            || (c >= '\u0ABE' && c <= '\u0AC5') || (c >= '\u0AC7' && c <= '\u0AC9') || (c >= '\u0ACB' && c <= '\u0ACD') 
-            || (c >= '\u0B01' && c <= '\u0B03') 
-            || (c == '\u0B3C') 
-            || (c >= '\u0B3E' && c <= '\u0B43') || (c >= '\u0B47' && c <= '\u0B48') || (c >= '\u0B4B' && c <= '\u0B4D') 
-            || (c >= '\u0B56' && c <= '\u0B57') || (c >= '\u0B82' && c <= '\u0B83') || (c >= '\u0BBE' && c <= '\u0BC2') 
-            || (c >= '\u0BC6' && c <= '\u0BC8') || (c >= '\u0BCA' && c <= '\u0BCD') 
-            || (c == '\u0BD7') 
-            || (c >= '\u0C01' && c <= '\u0C03') || (c >= '\u0C3E' && c <= '\u0C44') || (c >= '\u0C46' && c <= '\u0C48') 
-            || (c >= '\u0C4A' && c <= '\u0C4D') || (c >= '\u0C55' && c <= '\u0C56') || (c >= '\u0C82' && c <= '\u0C83') 
-            || (c >= '\u0CBE' && c <= '\u0CC4') || (c >= '\u0CC6' && c <= '\u0CC8') || (c >= '\u0CCA' && c <= '\u0CCD') 
-            || (c >= '\u0CD5' && c <= '\u0CD6') || (c >= '\u0D02' && c <= '\u0D03') || (c >= '\u0D3E' && c <= '\u0D43') 
-            || (c >= '\u0D46' && c <= '\u0D48') || (c >= '\u0D4A' && c <= '\u0D4D') 
-            || (c == '\u0D57') 
-            || (c == '\u0E31') 
-            || (c >= '\u0E34' && c <= '\u0E3A') || (c >= '\u0E47' && c <= '\u0E4E') 
-            || (c == '\u0EB1') 
-            || (c >= '\u0EB4' && c <= '\u0EB9') || (c >= '\u0EBB' && c <= '\u0EBC') || (c >= '\u0EC8' && c <= '\u0ECD') 
-            || (c >= '\u0F18' && c <= '\u0F19') 
-            || (c == '\u0F35') 
-            || (c == '\u0F37') 
-            || (c == '\u0F39') 
-            || (c == '\u0F3E') 
-            || (c == '\u0F3F') 
-            || (c >= '\u0F71' && c <= '\u0F84') || (c >= '\u0F86' && c <= '\u0F8B') || (c >= '\u0F90' && c <= '\u0F95') 
-            || (c == '\u0F97') 
-            || (c >= '\u0F99' && c <= '\u0FAD') || (c >= '\u0FB1' && c <= '\u0FB7') 
-            || (c == '\u0FB9') 
-            || (c >= '\u20D0' && c <= '\u20DC') 
-            || (c == '\u20E1') 
-            || (c >= '\u302A' && c <= '\u302F') 
-            || (c == '\u3099') 
-            || (c == '\u309A');
-    }*/
-
-    /** Digit - XMl Specification 1.0 [88] */
-    private static final boolean Digit(char c) {
-        return (c >= '\u0030' && c <= '\u0039') || (c >= '\u0660' && c <= '\u0669') || (c >= '\u06F0' && c <= '\u06F9')
-            || (c >= '\u0966' && c <= '\u096F') || (c >= '\u09E6' && c <= '\u09EF') || (c >= '\u0A66' && c <= '\u0A6F')
-            || (c >= '\u0AE6' && c <= '\u0AEF') || (c >= '\u0B66' && c <= '\u0B6F') || (c >= '\u0BE7' && c <= '\u0BEF')
-            || (c >= '\u0C66' && c <= '\u0C6F') || (c >= '\u0CE6' && c <= '\u0CEF') || (c >= '\u0D66' && c <= '\u0D6F')
-            || (c >= '\u0E50' && c <= '\u0E59') || (c >= '\u0ED0' && c <= '\u0ED9') || (c >= '\u0F20' && c <= '\u0F29');
-    }
-
-    /** Extender - XMl Specification 1.0 [89] */
-    private static final boolean Extender(char c) {
-        return c == '\u00B7' || c == '\u02D0' || c == '\u02D1' || c == '\u0387'
-            || c == '\u0640' || c == '\u0E46' || c == '\u0EC6' || c == '\u3005'
-            || (c >= '\u3031' && c <= '\u3035') || (c >= '\u309D' && c <= '\u309E') || (c >= '\u30FC' && c <= '\u30FE');
-    }
-
-    /** Whitespace - XML Specification 1.0 [3] */
-    private static final boolean S(char c) {
-        return c == '\u0020' || c == '\u0009' || c == '\r' || c == '\n';
-    }
-}