[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 {
-        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); }
     }
 
@@ -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: {
-                //#jswitch(method)
+                //#switch(JS.toString(method))
                 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);
 
-        //#jswitch(name)
+        //#switch(JS.toString(name))
         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 {
-            //#jswitch(key)
+            //#switch(JS.toString(key))
             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; }
-        //#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();
@@ -684,7 +684,7 @@ public final class Box extends JS.O implements Task {
 
     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);
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)
-        //#jswitch(name)
+        //#switch(JS.toString(name))
         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 {
-        //#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;
@@ -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 {
-            //#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
@@ -156,21 +156,21 @@ public final class Ibex extends JS implements JS.Cloneable {
  
             switch (nargs) {
                 case 0:
-                    //#jswitch(name)
+                    //#switch(JS.toString(name))
                     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 "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":
-                        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);
@@ -200,12 +200,12 @@ public final class Ibex extends JS implements JS.Cloneable {
                     //#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:
-                    //#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)));
@@ -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 {
-                //#jswitch(key)
+                //#switch(JS.toString(key))
                 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 {
-                //#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);
@@ -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 {
-                //#jswitch(key)
+                //#switch(JS.toString(key))
                 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 {
-                //#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);
index e4c85fa..f6c0774 100644 (file)
@@ -1,5 +1,5 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.util;
+package org.ibex.core;
 
 import java.io.IOException;
 
index 40fc71f..24f96c4 100644 (file)
@@ -1,10 +1,11 @@
 // 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 org.ibex.js.*;
 import org.ibex.util.*;
-//import org.ibex.plat.*;
+import org.ibex.plat.*;
 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.
  */
-public abstract class Stream extends JS.Cloneable {
+public abstract class Stream extends JS.O implements JS.Cloneable {
 
     // 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;
-        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 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 */
@@ -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 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); }
@@ -88,6 +89,7 @@ public abstract class Stream extends JS.Cloneable {
     }
 
     /** "unwrap" a Cab archive */
+    /*
     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); }
     }
+    */
 
     /** 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 org.ibex.core.*;
 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.*;
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);
-                        }
-    &n