From: megacz Date: Fri, 30 Jan 2004 07:00:28 +0000 (+0000) Subject: 2003/05/12 05:31:49 X-Git-Tag: RC3~969 X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=commitdiff_plain;h=4784113be7528a05f832456ad0e2db156d8f204b 2003/05/12 05:31:49 darcs-hash:20040130070028-2ba56-f4e73bb4a8614ff8b8a2102785ed315fd3a69689.gz --- diff --git a/src/org/mozilla/javascript/debug/DebugFrame.java b/src/org/mozilla/javascript/debug/DebugFrame.java deleted file mode 100644 index 5f7687c..0000000 --- a/src/org/mozilla/javascript/debug/DebugFrame.java +++ /dev/null @@ -1,51 +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-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * 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. - */ - -// API class - -package org.mozilla.javascript.debug; - -import org.mozilla.javascript.*; - -public interface DebugFrame { - - public Scriptable getVariableObject(); - - public String getSourceName(); - - public int getLineNumber(); - - public DebuggableScript getScript(); -} diff --git a/src/org/mozilla/javascript/debug/DebugReader.java b/src/org/mozilla/javascript/debug/DebugReader.java deleted file mode 100644 index e88e46a..0000000 --- a/src/org/mozilla/javascript/debug/DebugReader.java +++ /dev/null @@ -1,101 +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, 1998. - * - * 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): - * - * 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.mozilla.javascript.debug; - -import java.io.*; - -public class DebugReader extends Reader { - - public DebugReader(Reader reader) { - this.reader = new BufferedReader(reader); - this.saved = new StringBuffer(); - } - - public StringBuffer getSaved() { - return saved; - } - - public int read() throws IOException { - int c = reader.read(); - if (c != -1) - saved.append((char)c); - return c; - } - - public int read(char cbuf[]) throws IOException { - int i = reader.read(cbuf); - if (i != -1) - saved.append(cbuf, 0, i); - return i; - } - - public int read(char cbuf[], int off, int len) throws IOException { - int i = reader.read(cbuf, off, len); - if (i > 0) - saved.append(cbuf, off, i); - return i; - } - - public long skip(long n) throws IOException { - return reader.skip(n); - } - - public boolean ready() throws IOException { - return reader.ready(); - } - - public boolean markSupported() { - return reader.markSupported(); - } - - public void mark(int readAheadLimit) throws IOException { - reader.mark(readAheadLimit); - } - - public void reset() throws IOException { - reader.reset(); - } - - public void close() throws IOException { - reader.close(); - } - - protected void finalize() throws Throwable { - reader = null; - } - - private BufferedReader reader; - private StringBuffer saved; -} diff --git a/src/org/mozilla/javascript/debug/DebuggableEngine.java b/src/org/mozilla/javascript/debug/DebuggableEngine.java deleted file mode 100644 index 351cd8a..0000000 --- a/src/org/mozilla/javascript/debug/DebuggableEngine.java +++ /dev/null @@ -1,92 +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-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * 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. - */ - -// API class - -package org.mozilla.javascript.debug; - - -public interface DebuggableEngine { - - /** - * Set whether the engine should break when it encounters - * the next line. - *

- * The engine will call the attached debugger's handleBreakpointHit - * method on the next line it executes if isLineStep is true. - * May be used from another thread to interrupt execution. - * - * @param isLineStep if true, break next line - */ - public void setBreakNextLine(boolean isLineStep); - - /** - * Return the value of the breakNextLine flag. - * @return true if the engine will break on execution of the - * next line. - */ - public boolean getBreakNextLine(); - - /** - * Set the associated debugger. - * @param debugger the debugger to be used on callbacks from - * the engine. - */ - public void setDebugger(Debugger debugger); - - /** - * Return the current debugger. - * @return the debugger, or null if none is attached. - */ - public Debugger getDebugger(); - - /** - * Return the number of frames in current execution. - * @return the count of current frames - */ - public int getFrameCount(); - - /** - * Return a frame from the current execution. - * Frames are numbered starting from 0 for the innermost - * frame. - * @param frameNumber the number of the frame in the range - * [0,frameCount-1] - * @return the relevant Frame, or null if frameNumber is out - * of range or the engine isn't currently saving - * frames - */ - public DebugFrame getFrame(int frameNumber); -} diff --git a/src/org/mozilla/javascript/debug/DebuggableScript.java b/src/org/mozilla/javascript/debug/DebuggableScript.java deleted file mode 100644 index ff26115..0000000 --- a/src/org/mozilla/javascript/debug/DebuggableScript.java +++ /dev/null @@ -1,84 +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-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * 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. - */ - -// API class - -package org.mozilla.javascript.debug; - -import org.mozilla.javascript.*; - -import java.util.Enumeration; - -/** - * This interface exposes debugging information from executable - * code (either functions or top-level scripts). - */ -public interface DebuggableScript { - - /** - * Returns true if this is a function, false if it is a script. - */ - public boolean isFunction(); - - /** - * Get the Scriptable object (Function or Script) that is - * described by this DebuggableScript object. - */ - public Scriptable getScriptable(); - - /** - * Get the name of the source (usually filename or URL) - * of the script. - */ - public String getSourceName(); - - /** - * Get array containing the line numbers that - * can have breakpoints placed on them. - */ - public int[] getLineNumbers(); - - /** - * Place a breakpoint at the given line. - * @return true if the breakpoint was successfully set. - */ - public boolean placeBreakpoint(int line); - - /** - * Remove a breakpoint from the given line. - * @return true if there was a breakpoint at the given line. - */ - public boolean removeBreakpoint(int line); -} diff --git a/src/org/mozilla/javascript/debug/Debugger.java b/src/org/mozilla/javascript/debug/Debugger.java deleted file mode 100644 index bb0febb..0000000 --- a/src/org/mozilla/javascript/debug/Debugger.java +++ /dev/null @@ -1,51 +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-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * Norris Boyd - * - * 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. - */ - -// API class - -package org.mozilla.javascript.debug; - -import org.mozilla.javascript.Context; - -public interface Debugger { - - void handleCompilationDone(Context cx, DebuggableScript fnOrScript, - StringBuffer source); - - void handleBreakpointHit(Context cx); - - void handleExceptionThrown(Context cx, Object exception); - -} diff --git a/src/org/mozilla/javascript/regexp/NativeRegExp.java b/src/org/mozilla/javascript/regexp/NativeRegExp.java deleted file mode 100644 index d8b6337..0000000 --- a/src/org/mozilla/javascript/regexp/NativeRegExp.java +++ /dev/null @@ -1,2502 +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, 1998. - * - * 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 - * Brendan Eich - * Matthias Radestock - * - * 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.mozilla.javascript.regexp; - -import org.mozilla.javascript.*; -import java.lang.reflect.Method; - -/** - * This class implements the RegExp native object. - * - * Revision History: - * Implementation in C by Brendan Eich - * Initial port to Java by Norris Boyd from jsregexp.c version 1.36 - * Merged up to version 1.38, which included Unicode support. - * Merged bug fixes in version 1.39. - * Merged JSFUN13_BRANCH changes up to 1.32.2.13 - * - * @author Brendan Eich - * @author Norris Boyd - */ -public class NativeRegExp extends IdScriptable implements Function { - - public static final int GLOB = 0x1; // 'g' flag: global - public static final int FOLD = 0x2; // 'i' flag: fold - public static final int MULTILINE = 0x4; // 'm' flag: multiline - - //type of match to perform - public static final int TEST = 0; - public static final int MATCH = 1; - public static final int PREFIX = 2; - - private static final boolean debug = false; - - public static void init(Context cx, Scriptable scope, boolean sealed) { - - NativeRegExp proto = new NativeRegExp(); - proto.prototypeFlag = true; - proto.activateIdMap(MAX_PROTOTYPE_ID); - proto.setSealFunctionsFlag(sealed); - proto.setFunctionParametrs(cx); - proto.setParentScope(scope); - proto.setPrototype(getObjectPrototype(scope)); - - - NativeRegExpCtor ctor = new NativeRegExpCtor(); - - ctor.setPrototype(getClassPrototype(scope, "Function")); - ctor.setParentScope(scope); - - ctor.setImmunePrototypeProperty(proto); - - if (sealed) { - proto.sealObject(); - ctor.sealObject(); - } - - defineProperty(scope, "RegExp", ctor, ScriptableObject.DONTENUM); - } - - public NativeRegExp(Context cx, Scriptable scope, String source, - String global, boolean flat) { - init(cx, scope, source, global, flat); - } - - public void init(Context cx, Scriptable scope, String source, - String global, boolean flat) { - this.source = source; - flags = 0; - if (global != null) { - for (int i=0; i < global.length(); i++) { - char c = global.charAt(i); - if (c == 'g') { - flags |= GLOB; - } else if (c == 'i') { - flags |= FOLD; - } else if (c == 'm') { - flags |= MULTILINE; - } else { - Object[] errArgs = { new Character(c) }; - throw NativeGlobal.constructError(cx, "SyntaxError", - ScriptRuntime.getMessage( - "msg.invalid.re.flag", errArgs), - scope); - } - } - } - - CompilerState state = new CompilerState(source, flags, cx, scope); - if (flat) { - ren = null; - int sourceLen = source.length(); - int index = 0; - while (sourceLen > 0) { - int len = sourceLen; - if (len > REOP_FLATLEN_MAX) { - len = REOP_FLATLEN_MAX; - } - RENode ren2 = new RENode(state, len == 1 ? REOP_FLAT1 : REOP_FLAT, - new Integer(index)); - ren2.flags = RENode.NONEMPTY; - if (len > 1) { - ren2.kid2 = index + len; - } else { - ren2.flags |= RENode.SINGLE; - ren2.chr = state.source[index]; - } - index += len; - sourceLen -= len; - if (ren == null) - ren = ren2; - else - setNext(state, ren, ren2); - } - } - else - this.ren = parseRegExp(state); - if (ren == null) return; - RENode end = new RENode(state, REOP_END, null); - setNext(state, ren, end); - if (debug) - dumpRegExp(state, ren); - this.lastIndex = 0; - this.parenCount = state.parenCount; - this.flags = flags; - - scope = org.xwt.util.JSObject.defaultObjects; - setPrototype(getClassPrototype(scope, "RegExp")); - setParentScope(scope); - } - - public String getClassName() { - return "RegExp"; - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) { - return execSub(cx, scope, args, MATCH); - } - - public Scriptable construct(Context cx, Scriptable scope, Object[] args) { - return (Scriptable) call(cx, scope, null, args); - } - - Scriptable compile(Context cx, Scriptable scope, Object[] args) { - if (args.length > 0 && args[0] instanceof NativeRegExp) { - if (args.length > 1 && args[1] != Undefined.instance) { - // report error - throw NativeGlobal.constructError( - cx, "TypeError", - "only one argument may be specified " + - "if the first argument is a RegExp object", - scope); - } - NativeRegExp thatObj = (NativeRegExp) args[0]; - source = thatObj.source; - lastIndex = thatObj.lastIndex; - parenCount = thatObj.parenCount; - flags = thatObj.flags; - program = thatObj.program; - ren = thatObj.ren; - return this; - } - String s = args.length == 0 ? "" : ScriptRuntime.toString(args[0]); - String global = args.length > 1 && args[1] != Undefined.instance - ? ScriptRuntime.toString(args[1]) - : null; - init(cx, scope, s, global, false); - return this; - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append('/'); - buf.append(source); - buf.append('/'); - if ((flags & GLOB) != 0) - buf.append('g'); - if ((flags & FOLD) != 0) - buf.append('i'); - if ((flags & MULTILINE) != 0) - buf.append('m'); - return buf.toString(); - } - - public NativeRegExp() { - } - - private static RegExpImpl getImpl(Context cx) { - return (RegExpImpl) ScriptRuntime.getRegExpProxy(cx); - } - - private Object execSub(Context cx, Scriptable scopeObj, - Object[] args, int matchType) - { - RegExpImpl reImpl = getImpl(cx); - String str; - if (args.length == 0) { - str = reImpl.input; - if (str == null) { - Object[] errArgs = { toString() }; - throw NativeGlobal.constructError( - cx, "SyntaxError", - ScriptRuntime.getMessage - ("msg.no.re.input.for", errArgs), - scopeObj); - } - } else { - str = ScriptRuntime.toString(args[0]); - } - int i = ((flags & GLOB) != 0) ? lastIndex : 0; - int indexp[] = { i }; - Object rval = executeRegExp(cx, scopeObj, - reImpl, str, indexp, matchType); - if ((flags & GLOB) != 0) { - lastIndex = (rval == null || rval == Undefined.instance) - ? 0 : indexp[0]; - } - return rval; - } - - private Object exec(Context cx, Scriptable scopeObj, Object[] args) { - return execSub(cx, scopeObj, args, MATCH); - } - - private Object test(Context cx, Scriptable scopeObj, Object[] args) { - Object rval = execSub(cx, scopeObj, args, TEST); - if (rval == null || !rval.equals(Boolean.TRUE)) - rval = Boolean.FALSE; - return rval; - } - - private Object prefix(Context cx, Scriptable scopeObj, Object[] args) { - return execSub(cx, scopeObj, args, PREFIX); - } - - static final int JS_BITS_PER_BYTE = 8; - - private static final byte REOP_EMPTY = 0; /* match rest of input against rest of r.e. */ - private static final byte REOP_ALT = 1; /* alternative subexpressions in kid and next */ - private static final byte REOP_BOL = 2; /* beginning of input (or line if multiline) */ - private static final byte REOP_EOL = 3; /* end of input (or line if multiline) */ - private static final byte REOP_WBDRY = 4; /* match "" at word boundary */ - private static final byte REOP_WNONBDRY = 5; /* match "" at word non-boundary */ - private static final byte REOP_QUANT = 6; /* quantified atom: atom{1,2} */ - private static final byte REOP_STAR = 7; /* zero or more occurrences of kid */ - private static final byte REOP_PLUS = 8; /* one or more occurrences of kid */ - private static final byte REOP_OPT = 9; /* optional subexpression in kid */ - private static final byte REOP_LPAREN = 10; /* left paren bytecode: kid is u.num'th sub-regexp */ - private static final byte REOP_RPAREN = 11; /* right paren bytecode */ - private static final byte REOP_DOT = 12; /* stands for any character */ - private static final byte REOP_CCLASS = 13; /* character class: [a-f] */ - private static final byte REOP_DIGIT = 14; /* match a digit char: [0-9] */ - private static final byte REOP_NONDIGIT = 15; /* match a non-digit char: [^0-9] */ - private static final byte REOP_ALNUM = 16; /* match an alphanumeric char: [0-9a-z_A-Z] */ - private static final byte REOP_NONALNUM = 17; /* match a non-alphanumeric char: [^0-9a-z_A-Z] */ - private static final byte REOP_SPACE = 18; /* match a whitespace char */ - private static final byte REOP_NONSPACE = 19; /* match a non-whitespace char */ - private static final byte REOP_BACKREF = 20; /* back-reference (e.g., \1) to a parenthetical */ - private static final byte REOP_FLAT = 21; /* match a flat string */ - private static final byte REOP_FLAT1 = 22; /* match a single char */ - private static final byte REOP_JUMP = 23; /* for deoptimized closure loops */ - private static final byte REOP_DOTSTAR = 24; /* optimize .* to use a single opcode */ - private static final byte REOP_ANCHOR = 25; /* like .* but skips left context to unanchored r.e. */ - private static final byte REOP_EOLONLY = 26; /* $ not preceded by any pattern */ - private static final byte REOP_UCFLAT = 27; /* flat Unicode string; len immediate counts chars */ - private static final byte REOP_UCFLAT1 = 28; /* single Unicode char */ - private static final byte REOP_UCCLASS = 29; /* Unicode character class, vector of chars to match */ - private static final byte REOP_NUCCLASS = 30; /* negated Unicode character class */ - private static final byte REOP_BACKREFi = 31; /* case-independent REOP_BACKREF */ - private static final byte REOP_FLATi = 32; /* case-independent REOP_FLAT */ - private static final byte REOP_FLAT1i = 33; /* case-independent REOP_FLAT1 */ - private static final byte REOP_UCFLATi = 34; /* case-independent REOP_UCFLAT */ - private static final byte REOP_UCFLAT1i = 35; /* case-independent REOP_UCFLAT1 */ - private static final byte REOP_ANCHOR1 = 36; /* first-char discriminating REOP_ANCHOR */ - private static final byte REOP_NCCLASS = 37; /* negated 8-bit character class */ - private static final byte REOP_DOTSTARMIN = 38; /* ungreedy version of REOP_DOTSTAR */ - private static final byte REOP_LPARENNON = 39; /* non-capturing version of REOP_LPAREN */ - private static final byte REOP_RPARENNON = 40; /* non-capturing version of REOP_RPAREN */ - private static final byte REOP_ASSERT = 41; /* zero width positive lookahead assertion */ - private static final byte REOP_ASSERT_NOT = 42; /* zero width negative lookahead assertion */ - private static final byte REOP_END = 43; - - /* maximum length of FLAT string */ - private static final int REOP_FLATLEN_MAX = 255; - - /* not thread safe, used only for debugging */ - private static int level; - - private static String[] reopname = null; - static { - if (debug) { - String a[] = { - "empty", - "alt", - "bol", - "eol", - "wbdry", - "wnonbdry", - "quant", - "star", - "plus", - "opt", - "lparen", - "rparen", - "dot", - "cclass", - "digit", - "nondigit", - "alnum", - "nonalnum", - "space", - "nonspace", - "backref", - "flat", - "flat1", - "jump", - "dotstar", - "anchor", - "eolonly", - "ucflat", - "ucflat1", - "ucclass", - "nucclass", - "backrefi", - "flati", - "flat1i", - "ucflati", - "ucflat1i", - "anchor1", - "ncclass", - "dotstar_min", - "lparen_non", - "rparen_non", - "end" - }; - reopname = a; - } - } - - private String getPrintableString(String str) { - if (debug) { - StringBuffer buf = new StringBuffer(str.length()); - for (int i = 0; i < str.length(); i++) { - int c = str.charAt(i); - if ((c < 0x20) || (c > 0x7F)) { - if (c == '\n') - buf.append("\\n"); - else - buf.append("\\u" + Integer.toHexString(c)); - } - else - buf.append((char)c); - } - return buf.toString(); - } else { - return ""; - } - } - - private void dumpRegExp(CompilerState state, RENode ren) { - if (debug) { - if (level == 0) - System.out.print("level offset flags description\n"); - level++; - do { - char[] source = ren.s != null ? ren.s : state.source; - System.out.print(level); - System.out.print(" "); - System.out.print(ren.offset); - System.out.print(" " + - ((ren.flags & RENode.ANCHORED) != 0 ? "A" : "-") + - ((ren.flags & RENode.SINGLE) != 0 ? "S" : "-") + - ((ren.flags & RENode.NONEMPTY) != 0 ? "F" : "-") + // F for full - ((ren.flags & RENode.ISNEXT) != 0 ? "N" : "-") + // N for next - ((ren.flags & RENode.GOODNEXT) != 0 ? "G" : "-") + - ((ren.flags & RENode.ISJOIN) != 0 ? "J" : "-") + - ((ren.flags & RENode.MINIMAL) != 0 ? "M" : "-") + - " " + - reopname[ren.op]); - - switch (ren.op) { - case REOP_ALT: - System.out.print(" "); - System.out.println(ren.next.offset); - dumpRegExp(state, (RENode) ren.kid); - break; - - case REOP_STAR: - case REOP_PLUS: - case REOP_OPT: - case REOP_ANCHOR1: - case REOP_ASSERT: - case REOP_ASSERT_NOT: - System.out.println(); - dumpRegExp(state, (RENode) ren.kid); - break; - - case REOP_QUANT: - System.out.print(" next "); - System.out.print(ren.next.offset); - System.out.print(" min "); - System.out.print(ren.min); - System.out.print(" max "); - System.out.println(ren.max); - dumpRegExp(state, (RENode) ren.kid); - break; - - case REOP_LPAREN: - System.out.print(" num "); - System.out.println(ren.num); - dumpRegExp(state, (RENode) ren.kid); - break; - - case REOP_LPARENNON: - System.out.println(); - dumpRegExp(state, (RENode) ren.kid); - break; - - case REOP_BACKREF: - case REOP_RPAREN: - System.out.print(" num "); - System.out.println(ren.num); - break; - - case REOP_CCLASS: { - int index = ((Integer) ren.kid).intValue(); - int index2 = ren.kid2; - int len = index2 - index; - System.out.print(" ["); - System.out.print(getPrintableString(new String(source, index, len))); - System.out.println("]"); - break; - } - - case REOP_FLAT: { - int index = ((Integer) ren.kid).intValue(); - int index2 = ren.kid2; - int len = index2 - index; - System.out.print(" "); - System.out.print(getPrintableString(new String(source, index, len))); - System.out.print(" ("); - System.out.print(len); - System.out.println(")"); - break; - } - - case REOP_FLAT1: - System.out.print(" "); - System.out.print(ren.chr); - System.out.print(" ('\\"); - System.out.print(Integer.toString(ren.chr, 8)); - System.out.println("')"); - break; - - case REOP_JUMP: - System.out.print(" "); - System.out.println(ren.next.offset); - break; - - case REOP_UCFLAT: { - int index = ((Integer) ren.kid).intValue(); - int len = ren.kid2 - index; - for (int i = 0; i < len; i++) - System.out.print("\\u" + - Integer.toHexString(source[index+i])); - System.out.println(); - break; - } - - case REOP_UCFLAT1: - System.out.print("\\u" + - Integer.toHexString(ren.chr)); - System.out.println(); - break; - - case REOP_UCCLASS: { - int index = ((Integer) ren.kid).intValue(); - int len = ren.kid2 - index; - System.out.print(" ["); - for (int i = 0; i < len; i++) - System.out.print("\\u" + - Integer.toHexString(source[index+i])); - System.out.println("]"); - break; - } - - default: - System.out.println(); - break; - } - - if ((ren.flags & RENode.GOODNEXT) == 0) - break; - } while ((ren = ren.next) != null); - level--; - } - } - - private void fixNext(CompilerState state, RENode ren1, RENode ren2, - RENode oldnext) { - boolean goodnext; - RENode next, kid, ren; - - goodnext = ren2 != null && (ren2.flags & RENode.ISNEXT) == 0; - - /* - * Find the final node in a list of alternatives, or concatenations, or - * even a concatenation of alternatives followed by non-alternatives (e.g. - * ((x|y)z)w where ((x|y)z) is ren1 and w is ren2). - */ - for (; (next = ren1.next) != null && next != oldnext; ren1 = next) { - if (ren1.op == REOP_ALT) { - /* Find the end of this alternative's operand list. */ - kid = (RENode) ren1.kid; - if (kid.op == REOP_JUMP) - continue; - for (ren = kid; ren.next != null; ren = ren.next) { - if (ren.op == REOP_ALT) - throw new RuntimeException("REOP_ALT not expected"); - } - - /* Append a jump node to all but the last alternative. */ - ren.next = new RENode(state, REOP_JUMP, null); - ren.next.flags |= RENode.ISNEXT; - ren.flags |= RENode.GOODNEXT; - - /* Recur to fix all descendent nested alternatives. */ - fixNext(state, kid, ren2, oldnext); - } - } - - /* - * Now ren1 points to the last alternative, or to the final node on a - * concatenation list. Set its next link to ren2, flagging a join point - * if appropriate. - */ - if (ren2 != null) { - if ((ren2.flags & RENode.ISNEXT) == 0) - ren2.flags |= RENode.ISNEXT; - else - ren2.flags |= RENode.ISJOIN; - } - ren1.next = ren2; - if (goodnext) - ren1.flags |= RENode.GOODNEXT; - - /* - * The following ops have a kid subtree through which to recur. Here is - * where we fix the next links under the final ALT node's kid. - */ - switch (ren1.op) { - case REOP_ALT: - case REOP_QUANT: - case REOP_STAR: - case REOP_PLUS: - case REOP_OPT: - case REOP_LPAREN: - case REOP_LPARENNON: - case REOP_ASSERT: - case REOP_ASSERT_NOT: - fixNext(state, (RENode) ren1.kid, ren2, oldnext); - break; - default:; - } - } - - private void setNext(CompilerState state, RENode ren1, RENode ren2) { - fixNext(state, ren1, ren2, null); - } - - /* - * Top-down regular expression grammar, based closely on Perl 4. - * - * regexp: altern A regular expression is one or more - * altern '|' regexp alternatives separated by vertical bar. - */ - private RENode parseRegExp(CompilerState state) { - RENode ren = parseAltern(state); - if (ren == null) - return null; - char[] source = state.source; - int index = state.index; - if (index < source.length && source[index] == '|') { - RENode kid = ren; - ren = new RENode(state, REOP_ALT, kid); - if (ren == null) - return null; - ren.flags = (byte) (kid.flags & (RENode.ANCHORED | RENode.NONEMPTY)); - RENode ren1 = ren; - do { - /* (balance: */ - state.index = ++index; - if (index < source.length && (source[index] == '|' || - source[index] == ')')) - { - kid = new RENode(state, REOP_EMPTY, null); - } else { - kid = parseAltern(state); - index = state.index; - } - if (kid == null) - return null; - RENode ren2 = new RENode(state, REOP_ALT, kid); - if (ren2 == null) - return null; - ren1.next = ren2; - ren1.flags |= RENode.GOODNEXT; - ren2.flags = (byte) ((kid.flags & (RENode.ANCHORED | - RENode.NONEMPTY)) - | RENode.ISNEXT); - ren1 = ren2; - } while (index < source.length && source[index] == '|'); - } - return ren; - } - - /* - * altern: item An alternative is one or more items, - * item altern concatenated together. - */ - private RENode parseAltern(CompilerState state) { - RENode ren = parseItem(state); - if (ren == null) - return null; - RENode ren1 = ren; - int flags = 0; - char[] source = state.source; - int index = state.index; - char c; - /* (balance: */ - while (index != source.length && (c = source[index]) != '|' && - c != ')') - { - RENode ren2 = parseItem(state); - if (ren2 == null) - return null; - setNext(state, ren1, ren2); - flags |= ren2.flags; - ren1 = ren2; - index = state.index; - } - - /* - * Propagate NONEMPTY to the front of a concatenation list, so that the - * first alternative in (^a|b) is considered non-empty. The first node - * in a list may match the empty string (as ^ does), but if the list is - * non-empty, then the first node's NONEMPTY flag must be set. - */ - ren.flags |= flags & RENode.NONEMPTY; - return ren; - } - - /* - * item: assertion An item is either an assertion or - * quantatom a quantified atom. - * - * assertion: '^' Assertions match beginning of string - * (or line if the class static property - * RegExp.multiline is true). - * '$' End of string (or line if the class - * static property RegExp.multiline is - * true). - * '\b' Word boundary (between \w and \W). - * '\B' Word non-boundary. - */ - RENode parseItem(CompilerState state) { - RENode ren; - byte op; - - char[] source = state.source; - int index = state.index; - switch (index < source.length ? source[index] : '\0') { - case '^': - state.index = index + 1; - ren = new RENode(state, REOP_BOL, null); - ren.flags |= RENode.ANCHORED; - return ren; - - case '$': - state.index = index + 1; - return new RENode(state, - (index == state.indexBegin || - ((source[index-1] == '(' || - source[index-1] == '|') && /*balance)*/ - (index - 1 == state.indexBegin || - source[index-2] != '\\'))) - ? REOP_EOLONLY - : REOP_EOL, - null); - - case '\\': - switch (++index < source.length ? source[index] : '\0') { - case 'b': - op = REOP_WBDRY; - break; - case 'B': - op = REOP_WNONBDRY; - break; - default: - return parseQuantAtom(state); - } - - /* - * Word boundaries and non-boundaries are flagged as non-empty - * so they will be prefixed by an anchoring node. - */ - state.index = index + 1; - ren = new RENode(state, op, null); - ren.flags |= RENode.NONEMPTY; - return ren; - - default:; - } - return parseQuantAtom(state); - } - - /* - * quantatom: atom An unquantified atom. - * quantatom '{' n ',' m '}' - * Atom must occur between n and m times. - * quantatom '{' n ',' '}' Atom must occur at least n times. - * quantatom '{' n '}' Atom must occur exactly n times. - * quantatom '*' Zero or more times (same as {0,}). - * quantatom '+' One or more times (same as {1,}). - * quantatom '?' Zero or one time (same as {0,1}). - * - * any of which can be optionally followed by '?' for ungreedy - */ - RENode parseQuantAtom(CompilerState state) { - RENode ren = parseAtom(state); - if (ren == null) - return null; - - int up; - char c; - RENode ren2; - int min, max; - char[] source = state.source; - int index = state.index; - loop: - while (index < source.length) { - switch (source[index]) { - case '{': - if (++index == source.length || !isDigit(c = source[index])) { - reportError("msg.bad.quant", - String.valueOf(source[state.index]), state); - return null; - } - min = unDigit(c); - while (++index < source.length && isDigit(c = source[index])) { - min = 10 * min + unDigit(c); - if ((min >> 16) != 0) { - reportError("msg.overlarge.max", tail(source, index), - state); - return null; - } - } - if (source[index] == ',') { - up = ++index; - if (isDigit(source[index])) { - max = unDigit(source[index]); - while (isDigit(c = source[++index])) { - max = 10 * max + unDigit(c); - if ((max >> 16) != 0) { - reportError("msg.overlarge.max", - String.valueOf(source[up]), state); - return null; - } - } - if (max == 0) { - reportError("msg.zero.quant", - tail(source, state.index), state); - return null; - } - if (min > max) { - reportError("msg.max.lt.min", tail(source, up), state); - return null; - } - } else { - /* 0 means no upper bound. */ - max = 0; - } - } else { - /* Exactly n times. */ - if (min == 0) { - reportError("msg.zero.quant", - tail(source, state.index), state); - return null; - } - max = min; - } - if (source[index] != '}') { - reportError("msg.unterm.quant", - String.valueOf(source[state.index]), state); - return null; - } - index++; - - ren2 = new RENode(state, REOP_QUANT, ren); - if (min > 0 && (ren.flags & RENode.NONEMPTY) != 0) - ren2.flags |= RENode.NONEMPTY; - ren2.min = (short) min; - ren2.max = (short) max; - ren = ren2; - break; - - case '*': - index++; - ren = new RENode(state, REOP_STAR, ren); - break; - - case '+': - index++; - ren2 = new RENode(state, REOP_PLUS, ren); - if ((ren.flags & RENode.NONEMPTY) != 0) - ren2.flags |= RENode.NONEMPTY; - ren = ren2; - break; - - case '?': - index++; - ren = new RENode(state, REOP_OPT, ren); - break; - - default: - break loop; - } - if ((index < source.length) && (source[index] == '?')) { - ren.flags |= RENode.MINIMAL; - index++; - } - } - - state.index = index; - return ren; - } - - /* - * atom: '(' regexp ')' A parenthesized regexp (what matched - * can be addressed using a backreference, - * see '\' n below). - * '.' Matches any char except '\n'. - * '[' classlist ']' A character class. - * '[' '^' classlist ']' A negated character class. - * '\f' Form Feed. - * '\n' Newline (Line Feed). - * '\r' Carriage Return. - * '\t' Horizontal Tab. - * '\v' Vertical Tab. - * '\d' A digit (same as [0-9]). - * '\D' A non-digit. - * '\w' A word character, [0-9a-z_A-Z]. - * '\W' A non-word character. - * '\s' A whitespace character, [ \b\f\n\r\t\v]. - * '\S' A non-whitespace character. - * '\' n A backreference to the nth (n decimal - * and positive) parenthesized expression. - * '\' octal An octal escape sequence (octal must be - * two or three digits long, unless it is - * 0 for the null character). - * '\x' hex A hex escape (hex must be two digits). - * '\c' ctrl A control character, ctrl is a letter. - * '\' literalatomchar Any character except one of the above - * that follow '\' in an atom. - * otheratomchar Any character not first among the other - * atom right-hand sides. - */ - static final String metachars = "|^${*+?().[\\"; - static final String closurechars = "{*+?"; - - RENode parseAtom(CompilerState state) { - int num = 0, len; - RENode ren = null; - RENode ren2; - char c; - byte op; - - boolean skipCommon = false; - boolean doFlat = false; - - char[] source = state.source; - int index = state.index; - int ocp = index; - if (index == source.length) { - state.index = index; - return new RENode(state, REOP_EMPTY, null); - } - switch (source[index]) { - /* handle /|a/ by returning an empty node for the leftside */ - case '|': - return new RENode(state, REOP_EMPTY, null); - - case '(': - op = REOP_END; - if (source[index + 1] == '?') { - switch (source[index + 2]) { - case ':' : - op = REOP_LPARENNON; - break; - case '=' : - op = REOP_ASSERT; - break; - case '!' : - op = REOP_ASSERT_NOT; - break; - } - } - if (op == REOP_END) { - op = REOP_LPAREN; - num = state.parenCount++; /* \1 is numbered 0, etc. */ - index++; - } - else - index += 3; - state.index = index; - /* Handle empty paren */ - if (source[index] == ')') { - ren2 = new RENode(state, REOP_EMPTY, null); - } - else { - ren2 = parseRegExp(state); - if (ren2 == null) - return null; - index = state.index; - if (index >= source.length || source[index] != ')') { - reportError("msg.unterm.paren", tail(source, ocp), state); - return null; - } - } - index++; - ren = new RENode(state, op, ren2); - ren.flags = (byte) (ren2.flags & (RENode.ANCHORED | - RENode.NONEMPTY)); - ren.num = num; - if ((op == REOP_LPAREN) || (op == REOP_LPARENNON)) { - /* Assume RPAREN ops immediately succeed LPAREN ops */ - ren2 = new RENode(state, (byte)(op + 1), null); - setNext(state, ren, ren2); - ren2.num = num; - } - break; - - case '.': - ++index; - op = REOP_DOT; - if ((index < source.length) && (source[index] == '*')) { - index++; - op = REOP_DOTSTAR; - if ((index < source.length) && (source[index] == '?')) { - index++; - op = REOP_DOTSTARMIN; - } - } - ren = new RENode(state, op, null); - if (ren.op == REOP_DOT) - ren.flags = RENode.SINGLE | RENode.NONEMPTY; - break; - - case '[': - /* A char class must have at least one char in it. */ - if (++index == source.length) { - reportError("msg.unterm.class", tail(source, ocp), state); - return null; - } - c = source[index]; - ren = new RENode(state, REOP_CCLASS, new Integer(index)); - - /* A negated class must have at least one char in it after the ^. */ - if (c == '^' && ++index == source.length) { - reportError("msg.unterm.class", tail(source, ocp), state); - return null; - } - - for (;;) { - if (++index == source.length) { - reportError("msg.unterm.paren", tail(source, ocp), state); - return null; - } - c = source[index]; - if (c == ']') - break; - if (c == '\\' && index+1 != source.length) - index++; - } - ren.kid2 = index++; - - /* Since we rule out [] and [^], we can set the non-empty flag. */ - ren.flags = RENode.SINGLE | RENode.NONEMPTY; - break; - - case '\\': - if (++index == source.length) { - Context.reportError(ScriptRuntime.getMessage("msg.trail.backslash", - null)); - return null; - } - c = source[index]; - switch (c) { - case 'f': - case 'n': - case 'r': - case 't': - case 'v': - c = getEscape(c); - ren = new RENode(state, REOP_FLAT1, null); - break; - case 'd': - ren = new RENode(state, REOP_DIGIT, null); - break; - case 'D': - ren = new RENode(state, REOP_NONDIGIT, null); - break; - case 'w': - ren = new RENode(state, REOP_ALNUM, null); - break; - case 'W': - ren = new RENode(state, REOP_NONALNUM, null); - break; - case 's': - ren = new RENode(state, REOP_SPACE, null); - break; - case 'S': - ren = new RENode(state, REOP_NONSPACE, null); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - /* - Yuk. Keeping the old style \n interpretation for 1.2 - compatibility. - */ - if ((state.cx.getLanguageVersion() != Context.VERSION_DEFAULT) - && (state.cx.getLanguageVersion() <= Context.VERSION_1_4)) { - switch (c) { - case '0': - state.index = index; - num = doOctal(state); - index = state.index; - ren = new RENode(state, REOP_FLAT1, null); - c = (char) num; - break; - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - num = unDigit(c); - len = 1; - while (++index < source.length - && isDigit(c = source[index])) { - num = 10 * num + unDigit(c); - len++; - } - /* n in [8-9] and > count of parenetheses, then revert to - '8' or '9', ignoring the '\' */ - if (((num == 8) || (num == 9)) && (num > state.parenCount)) { - ocp = --index; /* skip beyond the '\' */ - doFlat = true; - skipCommon = true; - break; - } - /* more than 1 digit, or a number greater than - the count of parentheses => it's an octal */ - if ((len > 1) || (num > state.parenCount)) { - state.index = ocp; - num = doOctal(state); - index = state.index; - ren = new RENode(state, REOP_FLAT1, null); - c = (char) num; - break; - } - index--; - ren = new RENode(state, REOP_BACKREF, null); - ren.num = num - 1; /* \1 is numbered 0, etc. */ - - /* Avoid common chr- and flags-setting - code after switch. */ - ren.flags = RENode.NONEMPTY; - skipCommon = true; - break; - } - } - else { - if (c == '0') { - ren = new RENode(state, REOP_FLAT1, null); - c = 0; - } - else { - num = unDigit(c); - len = 1; - while (++index < source.length - && isDigit(c = source[index])) { - num = 10 * num + unDigit(c); - len++; - } - index--; - ren = new RENode(state, REOP_BACKREF, null); - ren.num = num - 1; /* \1 is numbered 0, etc. */ - /* Avoid common chr- and flags-setting - code after switch. */ - ren.flags = RENode.NONEMPTY; - skipCommon = true; - } - } - break; - - case 'x': - ocp = index; - if (++index < source.length && isHex(c = source[index])) { - num = unHex(c); - if (++index < source.length && isHex(c = source[index])) { - num <<= 4; - num += unHex(c); - } else { - if ((state.cx.getLanguageVersion() - != Context.VERSION_DEFAULT) - && (state.cx.getLanguageVersion() - <= Context.VERSION_1_4)) - index--; /* back up so index points to last hex char */ - else { /* ecma 2 requires pairs of hex digits. */ - index = ocp; - num = 'x'; - } - } - } else { - index = ocp; /* \xZZ is xZZ (Perl does \0ZZ!) */ - num = 'x'; - } - ren = new RENode(state, REOP_FLAT1, null); - c = (char)num; - break; - - case 'c': - c = source[++index]; - if (!('A' <= c && c <= 'Z') && !('a' <= c && c <= 'z')) { - index -= 2; - ocp = index; - doFlat = true; - skipCommon = true; - break; - } - c = Character.toUpperCase(c); - c = (char) (c ^ 64); // JS_TOCTRL - ren = new RENode(state, REOP_FLAT1, null); - break; - - case 'u': - if (index+4 < source.length && - isHex(source[index+1]) && isHex(source[index+2]) && - isHex(source[index+3]) && isHex(source[index+4])) - { - num = (((((unHex(source[index+1]) << 4) + - unHex(source[index+2])) << 4) + - unHex(source[index+3])) << 4) + - unHex(source[index+4]); - c = (char) num; - index += 4; - ren = new RENode(state, REOP_FLAT1, null); - break; - } - - /* Unlike Perl \\xZZ, we take \\uZZZ to be literal-u then ZZZ. */ - ocp = index; - doFlat = true; - skipCommon = true; - break; - - default: - ocp = index; - doFlat = true; - skipCommon = true; - break; - } - - /* Common chr- and flags-setting code for escape opcodes. */ - if (ren != null && !skipCommon) { - ren.chr = c; - ren.flags = RENode.SINGLE | RENode.NONEMPTY; - } - skipCommon = false; - - if (!doFlat) { - /* Skip to next unparsed char. */ - index++; - break; - } - - /* fall through since doFlat was true */ - doFlat = false; - - default: - while (++index != source.length && - metachars.indexOf(source[index]) == -1) - ; - len = (int)(index - ocp); - if (index != source.length && len > 1 && - closurechars.indexOf(source[index]) != -1) - { - index--; - len--; - } - if (len > REOP_FLATLEN_MAX) { - len = REOP_FLATLEN_MAX; - index = ocp + len; - } - ren = new RENode(state, len == 1 ? REOP_FLAT1 : REOP_FLAT, - new Integer(ocp)); - ren.flags = RENode.NONEMPTY; - if (len > 1) { - ren.kid2 = index; - } else { - ren.flags |= RENode.SINGLE; - ren.chr = source[ocp]; - } - break; - } - - state.index = index; - return ren; - } - - private int doOctal(CompilerState state) { - char[] source = state.source; - int index = state.index; - int tmp, num = 0; - char c; - while (++index < source.length && '0' <= (c = source[index]) && - c <= '7') - { - tmp = 8 * num + (int)(c - '0'); - if (tmp > 0377) { - break; - } - num = tmp; - } - index--; - state.index = index; - return num; - } - - static char getEscape(char c) { - switch (c) { - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - case 'v': - return (char) 11; // '\v' is not vtab in Java - } - throw new RuntimeException(); - } - - static public boolean isDigit(char c) { - return '0' <= c && c <= '9'; - } - - static int unDigit(char c) { - return c - '0'; - } - - static boolean isHex(char c) { - return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || - ('A' <= c && c <= 'F'); - } - - static int unHex(char c) { - if ('0' <= c && c <= '9') - return c - '0'; - return 10 + Character.toLowerCase(c) - 'a'; - } - - static boolean isWord(char c) { - return Character.isLetter(c) || isDigit(c) || c == '_'; - } - - private String tail(char[] a, int i) { - return new String(a, i, a.length - i); - } - - private static boolean matchChar(int flags, char c, char c2) { - if (c == c2) - return true; - else - if ((flags & FOLD) != 0) { - c = Character.toUpperCase(c); - c2 = Character.toUpperCase(c2); - return c == c2 || - Character.toLowerCase(c) == Character.toLowerCase(c2); - } - else - return false; - } - - - int greedyRecurse(GreedyState grState, int index, int previousKid) { - int kidMatch; - int match; - int num; - - /* - * when the kid match fails, we reset the parencount and run any - * previously succesful kid in order to restablish it's paren - * contents. - */ - - num = grState.state.parenCount; - kidMatch = matchRENodes(grState.state, grState.kid, grState.next, index); - if (kidMatch == -1) { - match = matchRENodes(grState.state, grState.next, grState.stop, index); - if (match != -1) { - grState.state.parenCount = num; - if (previousKid != -1) - matchRENodes(grState.state, grState.kid, grState.next, previousKid); - return index; - } - else - return -1; - } - else { - if (kidMatch == index) { - if (previousKid != -1) - matchRENodes(grState.state, grState.kid, grState.next, previousKid); - return kidMatch; /* no point pursuing an empty match forever */ - } - if ((grState.maxKid == 0) || (++grState.kidCount < grState.maxKid)) { - match = greedyRecurse(grState, kidMatch, index); - if (match != -1) return match; - if (grState.maxKid != 0) --grState.kidCount; - } - grState.state.parenCount = num; - match = matchRENodes(grState.state, grState.next, grState.stop, kidMatch); - if (match != -1) { - matchRENodes(grState.state, grState.kid, grState.next, index); - return kidMatch; - } - else - return -1; - } - } - - int matchGreedyKid(MatchState state, RENode ren, RENode stop, - int kidCount, int index, int previousKid) { - GreedyState grState = new GreedyState(); - grState.state = state; - grState.kid = (RENode)ren.kid; - grState.next = ren.next; - grState.maxKid = (ren.op == REOP_QUANT) ? ren.max : 0; - /* - * We try to match the sub-tree to completion first, and if that - * doesn't work, match only up to the given end of the sub-tree. - */ - grState.stop = null; - grState.kidCount = kidCount; - int match = greedyRecurse(grState, index, previousKid); - if (match != -1 || stop == null) return match; - grState.kidCount = kidCount; - grState.stop = stop; - return greedyRecurse(grState, index, previousKid); - } - - int matchNonGreedyKid(MatchState state, RENode ren, - int kidCount, int maxKid, - int index) { - int kidMatch; - int match; - - match = matchRENodes(state, ren.next, null, index); - if (match != -1) return index; - kidMatch = matchRENodes(state, (RENode)ren.kid, ren.next, index); - if (kidMatch == -1) return -1; - if (kidMatch == index) return kidMatch; /* no point pursuing an empty match forever */ - return matchNonGreedyKid(state, ren, kidCount, maxKid, kidMatch); - } - - int matchRENodes(MatchState state, RENode ren, RENode stop, int index) { - int num; - char[] input = state.input; - while ((ren != stop) && (ren != null)) { - switch (ren.op) { - case REOP_EMPTY: - break; - case REOP_ALT: { - if (ren.next.op != REOP_ALT) { - ren = (RENode)ren.kid; - continue; - } - else { - num = state.parenCount; - int kidMatch = matchRENodes(state, (RENode)ren.kid, - stop, index); - if (kidMatch != -1) return kidMatch; - for (int i = num; i < state.parenCount; i++) - state.parens[i] = null; - state.parenCount = num; - } - } - break; - case REOP_QUANT: { - int lastKid = -1; - for (num = 0; num < ren.min; num++) { - int kidMatch = matchRENodes(state, (RENode)ren.kid, - ren.next, index); - if (kidMatch == -1) - return -1; - else { - lastKid = index; - index = kidMatch; - } - } - if (num == ren.max) - // Have matched the exact count required, - // need to match the rest of the regexp. - break; - if ((ren.flags & RENode.MINIMAL) == 0) { - int kidMatch = matchGreedyKid(state, ren, stop, num, - index, lastKid); - if (kidMatch == -1) - index = matchRENodes(state, (RENode)ren.kid, - ren.next, index); - else - index = kidMatch; - } - else { - index = matchNonGreedyKid(state, ren, num, - ren.max, index); - } - if (index == -1) return -1; - } - break; - case REOP_PLUS: { - int kidMatch = matchRENodes(state, (RENode)ren.kid, - ren.next, index); - if (kidMatch == -1) - return -1; - if ((ren.flags & RENode.MINIMAL) == 0) { - kidMatch = matchGreedyKid(state, ren, stop, 1, - kidMatch, index); - if (kidMatch == -1) - index = matchRENodes(state,(RENode)ren.kid, - ren.next, index); - else - index = kidMatch; - } - else - index = matchNonGreedyKid(state, ren, 1, 0, kidMatch); - if (index == -1) return -1; - } - break; - case REOP_STAR: - if ((ren.flags & RENode.MINIMAL) == 0) { - int kidMatch = matchGreedyKid(state, ren, stop, 0, index, -1); - if (kidMatch != -1) - index = kidMatch; - } - else { - index = matchNonGreedyKid(state, ren, 0, 0, index); - if (index == -1) return -1; - } - break; - case REOP_OPT: { - int saveNum = state.parenCount; - if (((ren.flags & RENode.MINIMAL) != 0)) { - int restMatch = matchRENodes(state, ren.next, - stop, index); - if (restMatch != -1) return restMatch; - } - int kidMatch = matchRENodes(state, (RENode)ren.kid, - ren.next, index); - if (kidMatch == -1) { - state.parenCount = saveNum; - break; - } - else { - int restMatch = matchRENodes(state, ren.next, - stop, kidMatch); - if (restMatch == -1) { - // need to undo the result of running the kid - state.parenCount = saveNum; - break; - } - else - return restMatch; - } - } - case REOP_LPARENNON: - ren = (RENode)ren.kid; - continue; - case REOP_RPARENNON: - break; - case REOP_LPAREN: { - num = ren.num; - ren = (RENode)ren.kid; - SubString parsub = state.parens[num]; - if (parsub == null) { - parsub = state.parens[num] = new SubString(); - parsub.charArray = input; - } - parsub.index = index; - parsub.length = 0; - if (num >= state.parenCount) - state.parenCount = num + 1; - continue; - } - case REOP_RPAREN: { - num = ren.num; - SubString parsub = state.parens[num]; - if (parsub == null) - throw new RuntimeException("Paren problem"); - parsub.length = index - parsub.index; - break; - } - case REOP_ASSERT: { - int kidMatch = matchRENodes(state, (RENode)ren.kid, - ren.next, index); - if (kidMatch == -1) return -1; - break; - } - case REOP_ASSERT_NOT: { - int kidMatch = matchRENodes(state, (RENode)ren.kid, - ren.next, index); - if (kidMatch != -1) return -1; - break; - } - case REOP_BACKREF: { - num = ren.num; - if (num >= state.parens.length) { - Context.reportError( - ScriptRuntime.getMessage( - "msg.bad.backref", null)); - return -1; - } - SubString parsub = state.parens[num]; - if (parsub == null) - parsub = state.parens[num] = new SubString(); - int length = parsub.length; - for (int i = 0; i < length; i++, index++) { - if (index >= input.length) { - return state.noMoreInput(); - } - if (!matchChar(state.flags, input[index], - parsub.charArray[parsub.index + i])) - return -1; - } - } - break; - case REOP_CCLASS: - if (index >= input.length) { - return state.noMoreInput(); - } - if (ren.bitmap == null) { - char[] source = (ren.s != null) - ? ren.s - : this.source.toCharArray(); - ren.buildBitmap(state, source, ((state.flags & FOLD) != 0)); - } - char c = input[index]; - int b = (c >>> 3); - if (b >= ren.bmsize) { - if (ren.kid2 == -1) // a ^ class - index++; - else - return -1; - } else { - int bit = c & 7; - bit = 1 << bit; - if ((ren.bitmap[b] & bit) != 0) - index++; - else - return -1; - } - break; - case REOP_DOT: - if (index >= input.length) { - return state.noMoreInput(); - } - if (input[index] != '\n') - index++; - else - return -1; - break; - case REOP_DOTSTARMIN: { - int cp2; - for (cp2 = index; cp2 < input.length; cp2++) { - int cp3 = matchRENodes(state, ren.next, stop, cp2); - if (cp3 != -1) return cp3; - if (input[cp2] == '\n') - return -1; - } - return state.noMoreInput(); - } - case REOP_DOTSTAR: { - int cp2; - for (cp2 = index; cp2 < input.length; cp2++) - if (input[cp2] == '\n') - break; - while (cp2 >= index) { - int cp3 = matchRENodes(state, ren.next, stop, cp2); - if (cp3 != -1) { - index = cp2; - break; - } - cp2--; - } - break; - } - case REOP_WBDRY: - if (index == 0 || !isWord(input[index-1])) { - if (index >= input.length) - return state.noMoreInput(); - if (!isWord(input[index])) - return -1; - } - else { - if (index < input.length && isWord(input[index])) - return -1; - } - break; - case REOP_WNONBDRY: - if (index == 0 || !isWord(input[index-1])) { - if (index < input.length && isWord(input[index])) - return -1; - } - else { - if (index >= input.length) - return state.noMoreInput(); - if (!isWord(input[index])) - return -1; - } - break; - case REOP_EOLONLY: - case REOP_EOL: { - if (index == input.length) - ; // leave index; - else { - Context cx = Context.getCurrentContext(); - RegExpImpl reImpl = getImpl(cx); - if ((reImpl.multiline) - || ((state.flags & MULTILINE) != 0)) - if (input[index] == '\n') - ;// leave index - else - return -1; - else - return -1; - } - } - break; - case REOP_BOL: { - Context cx = Context.getCurrentContext(); - RegExpImpl reImpl = getImpl(cx); - if (index != 0) { - if (reImpl.multiline || - ((state.flags & MULTILINE) != 0)) { - if (index >= input.length) { - return state.noMoreInput(); - } - if (input[index - 1] == '\n') { - break; - } - } - return -1; - } - // leave index - } - break; - case REOP_DIGIT: - if (index >= input.length) { - return state.noMoreInput(); - } - if (!isDigit(input[index])) return -1; - index++; - break; - case REOP_NONDIGIT: - if (index >= input.length) { - return state.noMoreInput(); - } - if (isDigit(input[index])) return -1; - index++; - break; - case REOP_ALNUM: - if (index >= input.length) { - return state.noMoreInput(); - } - if (!isWord(input[index])) return -1; - index++; - break; - case REOP_NONALNUM: - if (index >= input.length) { - return state.noMoreInput(); - } - if (isWord(input[index])) return -1; - index++; - break; - case REOP_SPACE: - if (index >= input.length) { - return state.noMoreInput(); - } - if (!(TokenStream.isJSSpace(input[index]) || - TokenStream.isJSLineTerminator(input[index]))) - return -1; - index++; - break; - case REOP_NONSPACE: - if (index >= input.length) { - return state.noMoreInput(); - } - if (TokenStream.isJSSpace(input[index]) || - TokenStream.isJSLineTerminator(input[index])) - return -1; - index++; - break; - case REOP_FLAT1: - if (index >= input.length) { - return state.noMoreInput(); - } - if (!matchChar(state.flags, ren.chr, input[index])) - return -1; - index++; - break; - case REOP_FLAT: { - char[] source = (ren.s != null) - ? ren.s - : this.source.toCharArray(); - int start = ((Integer)ren.kid).intValue(); - int length = ren.kid2 - start; - for (int i = 0; i < length; i++, index++) { - if (index >= input.length) { - return state.noMoreInput(); - } - if (!matchChar(state.flags, input[index], - source[start + i])) - return -1; - } - } - break; - case REOP_JUMP: - break; - case REOP_END: - break; - default : - throw new RuntimeException("Unsupported by node matcher"); - } - ren = ren.next; - } - return index; - } - - int matchRegExp(MatchState state, RENode ren, int index) { - // have to include the position beyond the last character - // in order to detect end-of-input/line condition - for (int i = index; i <= state.input.length; i++) { - state.skipped = i - index; - state.parenCount = 0; - int result = matchRENodes(state, ren, null, i); - if (result != -1) - return result; - } - return -1; - } - - /* - * indexp is assumed to be an array of length 1 - */ - Object executeRegExp(Context cx, Scriptable scopeObj, RegExpImpl res, - String str, int indexp[], int matchType) - { - NativeRegExp re = this; - /* - * Initialize a CompilerState to minimize recursive argument traffic. - */ - MatchState state = new MatchState(); - state.inputExhausted = false; - state.anchoring = false; - state.flags = re.flags; - state.scope = scopeObj; - - char[] charArray = str.toCharArray(); - int start = indexp[0]; - if (start > charArray.length) - start = charArray.length; - int index = start; - state.cpbegin = 0; - state.cpend = charArray.length; - state.start = start; - state.skipped = 0; - state.input = charArray; - - state.parenCount = 0; - state.maybeParens = new SubString[re.parenCount]; - state.parens = new SubString[re.parenCount]; - // We allocate the elements of "parens" and "maybeParens" lazily in - // the Java port since we don't have arenas. - - /* - * Call the recursive matcher to do the real work. Return null on mismatch - * whether testing or not. On match, return an extended Array object. - */ - index = matchRegExp(state, ren, index); - if (index == -1) { - if (matchType != PREFIX || !state.inputExhausted) return null; - return Undefined.instance; - } - int i = index - state.cpbegin; - indexp[0] = i; - int matchlen = i - (start + state.skipped); - int ep = index; - index -= matchlen; - Object result; - Scriptable obj; - - if (matchType == TEST) { - /* - * Testing for a match and updating cx.regExpImpl: don't allocate - * an array object, do return true. - */ - result = Boolean.TRUE; - obj = null; - } - else { - /* - * The array returned on match has element 0 bound to the matched - * string, elements 1 through state.parenCount bound to the paren - * matches, an index property telling the length of the left context, - * and an input property referring to the input string. - */ - Scriptable scope = getTopLevelScope(scopeObj); - result = ScriptRuntime.newObject(cx, scope, "Array", null); - obj = (Scriptable) result; - - String matchstr = new String(charArray, index, matchlen); - obj.put(0, obj, matchstr); - } - - if (state.parenCount > re.parenCount) - throw new RuntimeException(); - if (state.parenCount == 0) { - res.parens.setSize(0); - res.lastParen = SubString.emptySubString; - } else { - SubString parsub = null; - int num; - res.parens.setSize(state.parenCount); - for (num = 0; num < state.parenCount; num++) { - parsub = state.parens[num]; - res.parens.setElementAt(parsub, num); - if (matchType == TEST) continue; - String parstr = parsub == null ? "": parsub.toString(); - obj.put(num+1, obj, parstr); - } - res.lastParen = parsub; - } - - if (! (matchType == TEST)) { - /* - * Define the index and input properties last for better for/in loop - * order (so they come after the elements). - */ - obj.put("index", obj, new Integer(start + state.skipped)); - obj.put("input", obj, str); - } - - if (res.lastMatch == null) { - res.lastMatch = new SubString(); - res.leftContext = new SubString(); - res.rightContext = new SubString(); - } - res.lastMatch.charArray = charArray; - res.lastMatch.index = index; - res.lastMatch.length = matchlen; - - res.leftContext.charArray = charArray; - if (cx.getLanguageVersion() == Context.VERSION_1_2) { - /* - * JS1.2 emulated Perl4.0.1.8 (patch level 36) for global regexps used - * in scalar contexts, and unintentionally for the string.match "list" - * psuedo-context. On "hi there bye", the following would result: - * - * Language while(/ /g){print("$`");} s/ /$`/g - * perl4.036 "hi", "there" "hihitherehi therebye" - * perl5 "hi", "hi there" "hihitherehi therebye" - * js1.2 "hi", "there" "hihitheretherebye" - * - * Insofar as JS1.2 always defined $` as "left context from the last - * match" for global regexps, it was more consistent than perl4. - */ - res.leftContext.index = start; - res.leftContext.length = state.skipped; - } else { - /* - * For JS1.3 and ECMAv2, emulate Perl5 exactly: - * - * js1.3 "hi", "hi there" "hihitherehi therebye" - */ - res.leftContext.index = 0; - res.leftContext.length = start + state.skipped; - } - - res.rightContext.charArray = charArray; - res.rightContext.index = ep; - res.rightContext.length = state.cpend - ep; - - return result; - } - - public byte getFlags() { - return flags; - } - - private void reportError(String msg, String arg, CompilerState state) { - Object[] args = { arg }; - throw NativeGlobal.constructError( - state.cx, "SyntaxError", - ScriptRuntime.getMessage(msg, args), - state.scope); - } - - protected int getIdDefaultAttributes(int id) { - switch (id) { - case Id_lastIndex: - return ScriptableObject.PERMANENT; - case Id_source: - case Id_global: - case Id_ignoreCase: - case Id_multiline: - return ScriptableObject.PERMANENT | ScriptableObject.READONLY; - } - return super.getIdDefaultAttributes(id); - } - - protected Object getIdValue(int id) { - switch (id) { - case Id_lastIndex: return wrap_long(0xffffffffL & lastIndex); - case Id_source: return source; - case Id_global: return wrap_boolean((flags & GLOB) != 0); - case Id_ignoreCase: return wrap_boolean((flags & FOLD) != 0); - case Id_multiline: return wrap_boolean((flags & MULTILINE) != 0); - } - return super.getIdValue(id); - } - - protected void setIdValue(int id, Object value) { - if (id == Id_lastIndex) { - setLastIndex(ScriptRuntime.toInt32(value)); - return; - } - super.setIdValue(id, value); - } - - void setLastIndex(int value) { - lastIndex = value; - } - - public int methodArity(int methodId) { - if (prototypeFlag) { - switch (methodId) { - case Id_compile: return 1; - case Id_toString: return 0; - case Id_exec: return 1; - case Id_test: return 1; - case Id_prefix: return 1; - } - } - return super.methodArity(methodId); - } - - public Object execMethod(int methodId, IdFunction f, Context cx, - Scriptable scope, Scriptable thisObj, - Object[] args) - throws JavaScriptException - { - if (prototypeFlag) { - switch (methodId) { - case Id_compile: - return realThis(thisObj, f, false).compile(cx, scope, args); - - case Id_toString: - return realThis(thisObj, f, true).toString(); - - case Id_exec: - return realThis(thisObj, f, false).exec(cx, scope, args); - - case Id_test: - return realThis(thisObj, f, false).test(cx, scope, args); - - case Id_prefix: - return realThis(thisObj, f, false).prefix(cx, scope, args); - } - } - return super.execMethod(methodId, f, cx, scope, thisObj, args); - } - - private NativeRegExp realThis(Scriptable thisObj, IdFunction f, - boolean readOnly) - { - while (!(thisObj instanceof NativeRegExp)) { - thisObj = nextInstanceCheck(thisObj, f, readOnly); - } - return (NativeRegExp)thisObj; - } - - protected String getIdName(int id) { - switch (id) { - case Id_lastIndex: return "lastIndex"; - case Id_source: return "source"; - case Id_global: return "global"; - case Id_ignoreCase: return "ignoreCase"; - case Id_multiline: return "multiline"; - } - - if (prototypeFlag) { - switch (id) { - case Id_compile: return "compile"; - case Id_toString: return "toString"; - case Id_exec: return "exec"; - case Id_test: return "test"; - case Id_prefix: return "prefix"; - } - } - return null; - } - - protected int maxInstanceId() { return MAX_INSTANCE_ID; } - -// #string_id_map# - - private static final int - Id_lastIndex = 1, - Id_source = 2, - Id_global = 3, - Id_ignoreCase = 4, - Id_multiline = 5, - - MAX_INSTANCE_ID = 5; - - protected int mapNameToId(String s) { - int id; -// #generated# Last update: 2001-05-24 12:01:22 GMT+02:00 - L0: { id = 0; String X = null; int c; - int s_length = s.length(); - if (s_length==6) { - c=s.charAt(0); - if (c=='g') { X="global";id=Id_global; } - else if (c=='s') { X="source";id=Id_source; } - } - else if (s_length==9) { - c=s.charAt(0); - if (c=='l') { X="lastIndex";id=Id_lastIndex; } - else if (c=='m') { X="multiline";id=Id_multiline; } - } - else if (s_length==10) { X="ignoreCase";id=Id_ignoreCase; } - if (X!=null && X!=s && !X.equals(s)) id = 0; - } -// #/generated# -// #/string_id_map# - - if (id != 0 || !prototypeFlag) { return id; } - -// #string_id_map# -// #generated# Last update: 2001-05-24 12:01:22 GMT+02:00 - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 4: c=s.charAt(0); - if (c=='e') { X="exec";id=Id_exec; } - else if (c=='t') { X="test";id=Id_test; } - break L; - case 6: X="prefix";id=Id_prefix; break L; - case 7: X="compile";id=Id_compile; break L; - case 8: X="toString";id=Id_toString; break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - } -// #/generated# - return id; - } - - private static final int - Id_compile = MAX_INSTANCE_ID + 1, - Id_toString = MAX_INSTANCE_ID + 2, - Id_exec = MAX_INSTANCE_ID + 3, - Id_test = MAX_INSTANCE_ID + 4, - Id_prefix = MAX_INSTANCE_ID + 5, - - MAX_PROTOTYPE_ID = MAX_INSTANCE_ID + 5; - -// #/string_id_map# - private boolean prototypeFlag; - - private String source; /* locked source string, sans // */ - private int lastIndex; /* index after last match, for //g iterator */ - private int parenCount; /* number of parenthesized submatches */ - private byte flags; /* flags */ - private byte[] program; /* regular expression bytecode */ - - RENode ren; -} - -class CompilerState { - CompilerState(String source, int flags, Context cx, Scriptable scope) { - this.source = source.toCharArray(); - this.scope = scope; - this.flags = flags; - this.cx = cx; - } - Context cx; - Scriptable scope; - char[] source; - int indexBegin; - int index; - int flags; - int parenCount; - int progLength; - byte[] prog; -} - - -class RENode { - public static final int ANCHORED = 0x01; /* anchored at the front */ - public static final int SINGLE = 0x02; /* matches a single char */ - public static final int NONEMPTY = 0x04; /* does not match empty string */ - public static final int ISNEXT = 0x08; /* ren is next after at least one node */ - public static final int GOODNEXT = 0x10; /* ren.next is a tree-like edge in the graph */ - public static final int ISJOIN = 0x20; /* ren is a join point in the graph */ - public static final int REALLOK = 0x40; /* REOP_FLAT owns tempPool space to realloc */ - public static final int MINIMAL = 0x80; /* un-greedy matching for ? * + {} */ - - RENode(CompilerState state, byte op, Object kid) { - this.op = op; - this.kid = kid; - } - - private void calcBMSize(char[] s, int index, int cp2, boolean fold) { - char maxc = 0; - while (index < cp2) { - char c = s[index++]; - if (c == '\\') { - if (index + 5 <= cp2 && s[index] == 'u' - && NativeRegExp.isHex(s[index+1]) - && NativeRegExp.isHex(s[index+2]) - && NativeRegExp.isHex(s[index+3]) - && NativeRegExp.isHex(s[index+4])) - { - int x = (((((NativeRegExp.unHex(s[index+0]) << 4) + - NativeRegExp.unHex(s[index+1])) << 4) + - NativeRegExp.unHex(s[index+2])) << 4) + - NativeRegExp.unHex(s[index+3]); - c = (char) x; - index += 5; - } else { - /* - * Octal and hex escapes can't be > 255. Skip this - * backslash and let the loop pass over the remaining - * escape sequence as if it were text to match. - */ - if (maxc < 255) maxc = 255; - continue; - } - } - if (fold) { - /* - * Don't assume that lowercase are above uppercase, or - * that c is either even when c has upper and lowercase - * versions. - */ - char c2; - if ((c2 = Character.toUpperCase(c)) > maxc) - maxc = c2; - if ((c2 = Character.toLowerCase(c2)) > maxc) - maxc = c2; - } - if (c > maxc) - maxc = c; - } - bmsize = (short)((maxc + NativeRegExp.JS_BITS_PER_BYTE) - / NativeRegExp.JS_BITS_PER_BYTE); - } - - private void matchBit(char c, int fill) { - int i = (c) >> 3; - byte b = (byte) (c & 7); - b = (byte) (1 << b); - if (fill != 0) - bitmap[i] &= ~b; - else - bitmap[i] |= b; - } - - private void checkRange(char lastc, int fill) { - matchBit(lastc, fill); - matchBit('-', fill); - } - - void buildBitmap(MatchState state, char[] s, boolean fold) { - int index = ((Integer) kid).intValue(); - int end = kid2; - byte fill = 0; - int i,n,ocp; - - boolean not = false; - kid2 = 0; - if (s[index] == '^') { - not = true; - kid2 = -1; - index++; - } - - calcBMSize(s, index, end, fold); - bitmap = new byte[bmsize]; - if (not) { - fill = (byte)0xff; - for (i = 0; i < bmsize; i++) - bitmap[i] = (byte)0xff; - bitmap[0] = (byte)0xfe; - } - int nchars = bmsize * NativeRegExp.JS_BITS_PER_BYTE; - char lastc = (char)nchars; - boolean inrange = false; - - while (index < end) { - char c = s[index++]; - if (c == '\\') { - c = s[index++]; - switch (c) { - case 'b': - case 'f': - case 'n': - case 'r': - case 't': - case 'v': - c = NativeRegExp.getEscape(c); - break; - - case 'd': - if (inrange) - checkRange(lastc, fill); - lastc = (char) nchars; - for (c = '0'; c <= '9'; c++) - matchBit(c, fill); - continue; - - case 'D': - if (inrange) - checkRange(lastc, fill); - lastc = (char) nchars; - for (c = 0; c < '0'; c++) - matchBit(c, fill); - for (c = '9' + 1; c < nchars; c++) - matchBit(c, fill); - continue; - - case 'w': - if (inrange) - checkRange(lastc, fill); - lastc = (char) nchars; - for (c = 0; c < nchars; c++) - if (NativeRegExp.isWord(c)) - matchBit(c, fill); - continue; - - case 'W': - if (inrange) - checkRange(lastc, fill); - lastc = (char) nchars; - for (c = 0; c < nchars; c++) - if (!NativeRegExp.isWord(c)) - matchBit(c, fill); - continue; - - case 's': - if (inrange) - checkRange(lastc, fill); - lastc = (char) nchars; - for (c = 0; c < nchars; c++) - if (Character.isWhitespace(c)) - matchBit(c, fill); - continue; - - case 'S': - if (inrange) - checkRange(lastc, fill); - lastc = (char) nchars; - for (c = 0; c < nchars; c++) - if (!Character.isWhitespace(c)) - matchBit(c, fill); - continue; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - n = NativeRegExp.unDigit(c); - ocp = index - 2; - c = s[index]; - if ('0' <= c && c <= '7') { - index++; - n = 8 * n + NativeRegExp.unDigit(c); - - c = s[index]; - if ('0' <= c && c <= '7') { - index++; - i = 8 * n + NativeRegExp.unDigit(c); - if (i <= 0377) - n = i; - else - index--; - } - } - c = (char) n; - break; - - case 'x': - ocp = index; - if (index < s.length && - NativeRegExp.isHex(c = s[index++])) - { - n = NativeRegExp.unHex(c); - if (index < s.length && - NativeRegExp.isHex(c = s[index++])) - { - n <<= 4; - n += NativeRegExp.unHex(c); - } - } else { - index = ocp; /* \xZZ is xZZ (Perl does \0ZZ!) */ - n = 'x'; - } - c = (char) n; - break; - - case 'u': - if (s.length > index+3 - && NativeRegExp.isHex(s[index+0]) - && NativeRegExp.isHex(s[index+1]) - && NativeRegExp.isHex(s[index+2]) - && NativeRegExp.isHex(s[index+3])) { - n = (((((NativeRegExp.unHex(s[index+0]) << 4) + - NativeRegExp.unHex(s[index+1])) << 4) + - NativeRegExp.unHex(s[index+2])) << 4) + - NativeRegExp.unHex(s[index+3]); - c = (char) n; - index += 4; - } - break; - - case 'c': - c = s[index++]; - c = Character.toUpperCase(c); - c = (char) (c ^ 64); // JS_TOCTRL - break; - } - } - - if (inrange) { - if (lastc > c) { - throw NativeGlobal.constructError( - Context.getCurrentContext(), "RangeError", - ScriptRuntime.getMessage( - "msg.bad.range", null), - state.scope); - } - inrange = false; - } else { - // Set lastc so we match just c's bit in the for loop. - lastc = c; - - // [balance: - if (index + 1 < end && s[index] == '-' && - s[index+1] != ']') - { - index++; - inrange = true; - continue; - } - } - - // Match characters in the range [lastc, c]. - for (; lastc <= c; lastc++) { - matchBit(lastc, fill); - if (fold) { - /* - * Must do both upper and lower for Turkish dotless i, - * Georgian, etc. - */ - char foldc = Character.toUpperCase(lastc); - matchBit(foldc, fill); - foldc = Character.toLowerCase(foldc); - matchBit(foldc, fill); - } - } - lastc = c; - } - } - byte op; /* packed r.e. op bytecode */ - byte flags; /* flags, see below */ - short offset; /* bytecode offset */ - RENode next; /* next in concatenation order */ - Object kid; /* first operand */ - int kid2; /* second operand */ - int num; /* could be a number */ - char chr; /* or a char */ - short min,max; /* or a range */ - short kidlen; /* length of string at kid, in chars */ - short bmsize; /* bitmap size, based on max char code */ - char[] s; /* if null, use state.source */ - byte[] bitmap; /* cclass bitmap */ -} - - -class MatchState { - boolean inputExhausted; /* did we run out of input chars ? */ - boolean anchoring; /* true if multiline anchoring ^/$ */ - int pcend; /* pc limit (fencepost) */ - int cpbegin, cpend; /* cp base address and limit */ - int start; /* offset from cpbegin to start at */ - int skipped; /* chars skipped anchoring this r.e. */ - byte flags; /* pennants */ - int parenCount; /* number of paren substring matches */ - SubString[] maybeParens; /* possible paren substring pointers */ - SubString[] parens; /* certain paren substring matches */ - Scriptable scope; - char[] input; - - public int noMoreInput() { - inputExhausted = true; - /* - try { - throw new Exception(); - } - catch (Exception e) { - e.printStackTrace(); - } - */ - return -1; - } -} - -class GreedyState { - MatchState state; - RENode kid; - RENode next; - RENode stop; - int kidCount; - int maxKid; -} - diff --git a/src/org/mozilla/javascript/regexp/NativeRegExpCtor.java b/src/org/mozilla/javascript/regexp/NativeRegExpCtor.java deleted file mode 100644 index 3b8e7c0..0000000 --- a/src/org/mozilla/javascript/regexp/NativeRegExpCtor.java +++ /dev/null @@ -1,271 +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, 1998. - * - * 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): - * - * 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.mozilla.javascript.regexp; - -import org.mozilla.javascript.*; -import java.lang.reflect.Method; - -/** - * This class implements the RegExp constructor native object. - * - * Revision History: - * Implementation in C by Brendan Eich - * Initial port to Java by Norris Boyd from jsregexp.c version 1.36 - * Merged up to version 1.38, which included Unicode support. - * Merged bug fixes in version 1.39. - * Merged JSFUN13_BRANCH changes up to 1.32.2.11 - * - * @author Brendan Eich - * @author Norris Boyd - */ -public class NativeRegExpCtor extends NativeFunction { - - public NativeRegExpCtor() { - functionName = "RegExp"; - } - - public String getClassName() { - return "Function"; - } - - public Object call(Context cx, Scriptable scope, Scriptable thisObj, - Object[] args) - { - if (args.length > 0 && args[0] instanceof NativeRegExp && - (args.length == 1 || args[1] == Undefined.instance)) - { - return args[0]; - } - return construct(cx, parent, args); - } - - public Scriptable construct(Context cx, Scriptable scope, Object[] args) { - NativeRegExp re = new NativeRegExp(); - re.compile(cx, scope, args); - re.setPrototype(getClassPrototype(scope, "RegExp")); - re.setParentScope(getParentScope()); - return re; - } - - static RegExpImpl getImpl() { - Context cx = Context.getCurrentContext(); - return (RegExpImpl) ScriptRuntime.getRegExpProxy(cx); - } - - protected int getIdDefaultAttributes(int id) { - int shifted = id - idBase; - if (1 <= shifted && shifted <= MAX_INSTANCE_ID) { - switch (shifted) { - case Id_multiline: - case Id_STAR: - case Id_input: - case Id_UNDERSCORE: - return PERMANENT; - } - return PERMANENT | READONLY; - } - return super.getIdDefaultAttributes(id); - } - - private static String stringResult(Object obj) { - return (obj == null) ? "" : obj.toString(); - } - - protected Object getIdValue(int id) { - int shifted = id - idBase; - if (1 <= shifted && shifted <= MAX_INSTANCE_ID) { - RegExpImpl impl = getImpl(); - switch (shifted) { - case Id_multiline: - case Id_STAR: - return wrap_boolean(impl.multiline); - - case Id_input: - case Id_UNDERSCORE: - return stringResult(impl.input); - - case Id_lastMatch: - case Id_AMPERSAND: - return stringResult(impl.lastMatch); - - case Id_lastParen: - case Id_PLUS: - return stringResult(impl.lastParen); - - case Id_leftContext: - case Id_BACK_QUOTE: - return stringResult(impl.leftContext); - - case Id_rightContext: - case Id_QUOTE: - return stringResult(impl.rightContext); - } - // Must be one of $1..$9, convert to 0..8 - int substring_number = shifted - DOLLAR_ID_BASE - 1; - return impl.getParenSubString(substring_number).toString(); - } - return super.getIdValue(id); - } - - protected void setIdValue(int id, Object value) { - switch (id - idBase) { - case Id_multiline: - case Id_STAR: - getImpl().multiline = ScriptRuntime.toBoolean(value); - return; - - case Id_input: - case Id_UNDERSCORE: - getImpl().input = ScriptRuntime.toString(value); - return; - } - super.setIdValue(id, value); - } - - protected String getIdName(int id) { - int shifted = id - idBase; - if (1 <= shifted && shifted <= MAX_INSTANCE_ID) { - switch (shifted) { - case Id_multiline: return "multiline"; - case Id_STAR: return "$*"; - - case Id_input: return "input"; - case Id_UNDERSCORE: return "$_"; - - case Id_lastMatch: return "lastMatch"; - case Id_AMPERSAND: return "$&"; - - case Id_lastParen: return "lastParen"; - case Id_PLUS: return "$+"; - - case Id_leftContext: return "leftContext"; - case Id_BACK_QUOTE: return "$`"; - - case Id_rightContext: return "rightContext"; - case Id_QUOTE: return "$'"; - } - // Must be one of $1..$9, convert to 0..8 - int substring_number = shifted - DOLLAR_ID_BASE - 1; - char[] buf = { '$', (char)('1' + substring_number) }; - return new String(buf); - } - return super.getIdName(id); - } - - protected int maxInstanceId() { - // Note: check for idBase == 0 can not be done in constructor, - // because IdScriptable calls maxInstanceId in its constructor - // before NativeRegExpCtor constructor gets chance to run any code - if (idBase == 0) { idBase = super.maxInstanceId(); } - return idBase + MAX_INSTANCE_ID; - } - -// #string_id_map# - - private static final int - Id_multiline = 1, - Id_STAR = 2, // #string=$*# - - Id_input = 3, - Id_UNDERSCORE = 4, // #string=$_# - - Id_lastMatch = 5, - Id_AMPERSAND = 6, // #string=$&# - - Id_lastParen = 7, - Id_PLUS = 8, // #string=$+# - - Id_leftContext = 9, - Id_BACK_QUOTE = 10, // #string=$`# - - Id_rightContext = 11, - Id_QUOTE = 12, // #string=$'# - - DOLLAR_ID_BASE = 12; - - private static final int - Id_DOLLAR_1 = DOLLAR_ID_BASE + 1, // #string=$1# - Id_DOLLAR_2 = DOLLAR_ID_BASE + 2, // #string=$2# - Id_DOLLAR_3 = DOLLAR_ID_BASE + 3, // #string=$3# - Id_DOLLAR_4 = DOLLAR_ID_BASE + 4, // #string=$4# - Id_DOLLAR_5 = DOLLAR_ID_BASE + 5, // #string=$5# - Id_DOLLAR_6 = DOLLAR_ID_BASE + 6, // #string=$6# - Id_DOLLAR_7 = DOLLAR_ID_BASE + 7, // #string=$7# - Id_DOLLAR_8 = DOLLAR_ID_BASE + 8, // #string=$8# - Id_DOLLAR_9 = DOLLAR_ID_BASE + 9, // #string=$9# - - MAX_INSTANCE_ID = DOLLAR_ID_BASE + 9; - - protected int mapNameToId(String s) { - int id; -// #generated# Last update: 2001-05-24 16:09:31 GMT+02:00 - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 2: switch (s.charAt(1)) { - case '&': if (s.charAt(0)=='$') {id=Id_AMPERSAND; break L0;} break L; - case '\'': if (s.charAt(0)=='$') {id=Id_QUOTE; break L0;} break L; - case '*': if (s.charAt(0)=='$') {id=Id_STAR; break L0;} break L; - case '+': if (s.charAt(0)=='$') {id=Id_PLUS; break L0;} break L; - case '1': if (s.charAt(0)=='$') {id=Id_DOLLAR_1; break L0;} break L; - case '2': if (s.charAt(0)=='$') {id=Id_DOLLAR_2; break L0;} break L; - case '3': if (s.charAt(0)=='$') {id=Id_DOLLAR_3; break L0;} break L; - case '4': if (s.charAt(0)=='$') {id=Id_DOLLAR_4; break L0;} break L; - case '5': if (s.charAt(0)=='$') {id=Id_DOLLAR_5; break L0;} break L; - case '6': if (s.charAt(0)=='$') {id=Id_DOLLAR_6; break L0;} break L; - case '7': if (s.charAt(0)=='$') {id=Id_DOLLAR_7; break L0;} break L; - case '8': if (s.charAt(0)=='$') {id=Id_DOLLAR_8; break L0;} break L; - case '9': if (s.charAt(0)=='$') {id=Id_DOLLAR_9; break L0;} break L; - case '_': if (s.charAt(0)=='$') {id=Id_UNDERSCORE; break L0;} break L; - case '`': if (s.charAt(0)=='$') {id=Id_BACK_QUOTE; break L0;} break L; - } break L; - case 5: X="input";id=Id_input; break L; - case 9: c=s.charAt(4); - if (c=='M') { X="lastMatch";id=Id_lastMatch; } - else if (c=='P') { X="lastParen";id=Id_lastParen; } - else if (c=='i') { X="multiline";id=Id_multiline; } - break L; - case 11: X="leftContext";id=Id_leftContext; break L; - case 12: X="rightContext";id=Id_rightContext; break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - } -// #/generated# -// #/string_id_map# - - return (id != 0) ? idBase + id : super.mapNameToId(s); - } - - private static int idBase; -} diff --git a/src/org/mozilla/javascript/regexp/RegExpImpl.java b/src/org/mozilla/javascript/regexp/RegExpImpl.java deleted file mode 100644 index dcba755..0000000 --- a/src/org/mozilla/javascript/regexp/RegExpImpl.java +++ /dev/null @@ -1,567 +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, 1998. - * - * 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): - * - * 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.mozilla.javascript.regexp; - -import org.mozilla.javascript.*; -import java.util.Vector; - -/** - * - */ -public class RegExpImpl implements RegExpProxy { - - public RegExpImpl() { - parens = new Vector(9); - } - - public boolean isRegExp(Object obj) { - return obj instanceof NativeRegExp; - } - - public Object newRegExp(Context cx, Scriptable scope, String source, - String global, boolean flat) - { - return new NativeRegExp(cx, scope, source, global, flat); - } - - public Object match(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - throws JavaScriptException - { - MatchData mdata = new MatchData(); - mdata.optarg = 1; - mdata.mode = GlobData.GLOB_MATCH; - mdata.parent = ScriptableObject.getTopLevelScope(scope); - Object rval = matchOrReplace(cx, scope, thisObj, args, - this, mdata, false); - return mdata.arrayobj == null ? rval : mdata.arrayobj; - } - - public Object search(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - throws JavaScriptException - { - MatchData mdata = new MatchData(); - mdata.optarg = 1; - mdata.mode = GlobData.GLOB_SEARCH; - mdata.parent = ScriptableObject.getTopLevelScope(scope); - return matchOrReplace(cx, scope, thisObj, args, this, mdata, false); - } - - public Object replace(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args) - throws JavaScriptException - { - Object arg1 = args.length < 2 ? Undefined.instance : args[1]; - String repstr = null; - Function lambda = null; - if (arg1 instanceof Function) { - lambda = (Function) arg1; - } else { - repstr = ScriptRuntime.toString(arg1); - } - - ReplaceData rdata = new ReplaceData(); - rdata.optarg = 2; - rdata.mode = GlobData.GLOB_REPLACE; - rdata.lambda = lambda; - rdata.repstr = repstr == null ? null : repstr.toCharArray(); - rdata.dollar = repstr == null ? -1 : repstr.indexOf('$'); - rdata.charArray = null; - rdata.length = 0; - rdata.index = 0; - rdata.leftIndex = 0; - Object val = matchOrReplace(cx, scope, thisObj, args, - this, rdata, true); - char[] charArray; - - if (rdata.charArray == null) { - if (rdata.global || val == null || !val.equals(Boolean.TRUE)) { - /* Didn't match even once. */ - return rdata.str; - } - int leftlen = this.leftContext.length; - int length = leftlen + rdata.findReplen(cx, this); - charArray = new char[length]; - SubString leftContext = this.leftContext; - System.arraycopy(leftContext.charArray, leftContext.index, - charArray, 0, leftlen); - rdata.doReplace(cx, this, charArray, leftlen); - rdata.charArray = charArray; - rdata.length = length; - } - - SubString rc = this.rightContext; - int rightlen = rc.length; - int length = rdata.length + rightlen; - charArray = new char[length]; - System.arraycopy(rdata.charArray, 0, - charArray, 0, rdata.charArray.length); - System.arraycopy(rc.charArray, rc.index, charArray, - rdata.length, rightlen); - return new String(charArray, 0, length); - } - - /** - * Analog of C match_or_replace. - */ - private static Object matchOrReplace(Context cx, Scriptable scope, - Scriptable thisObj, Object[] args, - RegExpImpl reImpl, - GlobData data, boolean forceFlat) - throws JavaScriptException - { - NativeRegExp re; - - String str = ScriptRuntime.toString(thisObj); - data.str = str; - Scriptable topScope = ScriptableObject.getTopLevelScope(scope); - - if (args.length == 0) - re = new NativeRegExp(cx, topScope, "", "", false); - else - if (args[0] instanceof NativeRegExp) { - re = (NativeRegExp) args[0]; - } else { - String src = ScriptRuntime.toString(args[0]); - String opt; - if (data.optarg < args.length) { - args[0] = src; - opt = ScriptRuntime.toString(args[data.optarg]); - } else { - opt = null; - } - re = new NativeRegExp(cx, topScope, src, opt, forceFlat); - } - data.regexp = re; - - data.global = (re.getFlags() & NativeRegExp.GLOB) != 0; - int[] indexp = { 0 }; - Object result = null; - if (data.mode == GlobData.GLOB_SEARCH) { - result = re.executeRegExp(cx, scope, reImpl, - str, indexp, NativeRegExp.TEST); - if (result != null && result.equals(Boolean.TRUE)) - result = new Integer(reImpl.leftContext.length); - else - result = new Integer(-1); - } else if (data.global) { - re.setLastIndex(0); - for (int count = 0; indexp[0] <= str.length(); count++) { - result = re.executeRegExp(cx, scope, reImpl, - str, indexp, NativeRegExp.TEST); - if (result == null || !result.equals(Boolean.TRUE)) - break; - data.doGlobal(cx, scope, count, reImpl); - if (reImpl.lastMatch.length == 0) { - if (indexp[0] == str.length()) - break; - indexp[0]++; - } - } - } else { - result = re.executeRegExp(cx, scope, reImpl, str, indexp, - ((data.mode == GlobData.GLOB_REPLACE) - ? NativeRegExp.TEST - : NativeRegExp.MATCH)); - } - - return result; - } - - - - public int find_split(Scriptable scope, String target, String separator, - Object reObj, int[] ip, int[] matchlen, - boolean[] matched, String[][] parensp) - { - int i = ip[0]; - int length = target.length(); - int result; - Context cx = Context.getCurrentContext(); - - int version = cx.getLanguageVersion(); - NativeRegExp re = (NativeRegExp) reObj; - again: - while (true) { // imitating C label - /* JS1.2 deviated from Perl by never matching at end of string. */ - int ipsave = ip[0]; // reuse ip to save object creation - ip[0] = i; - Object ret = re.executeRegExp(cx, scope, this, target, ip, - NativeRegExp.TEST); - if (ret != Boolean.TRUE) { - // Mismatch: ensure our caller advances i past end of string. - ip[0] = ipsave; - matchlen[0] = 1; - matched[0] = false; - return length; - } - i = ip[0]; - ip[0] = ipsave; - matched[0] = true; - - SubString sep = this.lastMatch; - matchlen[0] = sep.length; - if (matchlen[0] == 0) { - /* - * Empty string match: never split on an empty - * match at the start of a find_split cycle. Same - * rule as for an empty global match in - * match_or_replace. - */ - if (i == ip[0]) { - /* - * "Bump-along" to avoid sticking at an empty - * match, but don't bump past end of string -- - * our caller must do that by adding - * sep->length to our return value. - */ - if (i == length) { - if (version == Context.VERSION_1_2) { - matchlen[0] = 1; - result = i; - } - else - result = -1; - break; - } - i++; - continue again; // imitating C goto - } - } - // PR_ASSERT((size_t)i >= sep->length); - result = i - matchlen[0]; - break; - } - int size = parens.size(); - parensp[0] = new String[size]; - for (int num = 0; num < size; num++) { - SubString parsub = getParenSubString(num); - parensp[0][num] = parsub.toString(); - } - return result; - } - - /** - * Analog of REGEXP_PAREN_SUBSTRING in C jsregexp.h. - * Assumes zero-based; i.e., for $3, i==2 - */ - SubString getParenSubString(int i) { - if (i >= parens.size()) - return SubString.emptySubString; - return (SubString) parens.elementAt(i); - } - - String input; /* input string to match (perl $_, GC root) */ - boolean multiline; /* whether input contains newlines (perl $*) */ - Vector parens; /* Vector of SubString; last set of parens - matched (perl $1, $2) */ - SubString lastMatch; /* last string matched (perl $&) */ - SubString lastParen; /* last paren matched (perl $+) */ - SubString leftContext; /* input to left of last match (perl $`) */ - SubString rightContext; /* input to right of last match (perl $') */ -} - - -abstract class GlobData { - static final int GLOB_MATCH = 1; - static final int GLOB_REPLACE = 2; - static final int GLOB_SEARCH = 3; - - abstract void doGlobal(Context cx, Scriptable scope, int count, - RegExpImpl reImpl) - throws JavaScriptException; - - byte mode; /* input: return index, match object, or void */ - int optarg; /* input: index of optional flags argument */ - boolean global; /* output: whether regexp was global */ - String str; /* output: 'this' parameter object as string */ - NativeRegExp regexp;/* output: regexp parameter object private data */ - Scriptable parent; -} - - -class MatchData extends GlobData { - - /* - * Analog of match_glob() in jsstr.c - */ - void doGlobal(Context cx, Scriptable scope, int count, RegExpImpl reImpl) - throws JavaScriptException - { - MatchData mdata; - Object v; - - mdata = this; - if (arrayobj == null) { - Scriptable s = ScriptableObject.getTopLevelScope(scope); - arrayobj = ScriptRuntime.newObject(cx, s, "Array", null); - } - SubString matchsub = reImpl.lastMatch; - String matchstr = matchsub.toString(); - arrayobj.put(count, arrayobj, matchstr); - } - - Scriptable arrayobj; -} - - -class ReplaceData extends GlobData { - - ReplaceData() { - dollar = -1; - } - - /* - * Analog of replace_glob() in jsstr.c - */ - void doGlobal(Context cx, Scriptable scope, int count, RegExpImpl reImpl) - throws JavaScriptException - { - ReplaceData rdata = this; - - SubString lc = reImpl.leftContext; - - char[] leftArray = lc.charArray; - int leftIndex = rdata.leftIndex; - - int leftlen = reImpl.lastMatch.index - leftIndex; - rdata.leftIndex = reImpl.lastMatch.index + reImpl.lastMatch.length; - int replen = findReplen(cx, reImpl); - int growth = leftlen + replen; - char[] charArray; - if (rdata.charArray != null) { - charArray = new char[rdata.length + growth]; - System.arraycopy(rdata.charArray, 0, charArray, 0, rdata.length); - } else { - charArray = new char[growth]; - } - - rdata.charArray = charArray; - rdata.length += growth; - int index = rdata.index; - rdata.index += growth; - System.arraycopy(leftArray, leftIndex, charArray, index, leftlen); - index += leftlen; - doReplace(cx, reImpl, charArray, index); - } - - static SubString dollarStr = new SubString("$"); - - static SubString interpretDollar(Context cx, RegExpImpl res, - char[] da, int dp, int bp, int[] skip) - { - char[] ca; - int cp; - char dc; - int num, tmp; - - /* Allow a real backslash (literal "\\") to escape "$1" etc. */ - if (da[dp] != '$') - throw new RuntimeException(); - if ((cx.getLanguageVersion() != Context.VERSION_DEFAULT) - && (cx.getLanguageVersion() <= Context.VERSION_1_4)) - if (dp > bp && da[dp-1] == '\\') - return null; - - /* Interpret all Perl match-induced dollar variables. */ - dc = da[dp+1]; - if (NativeRegExp.isDigit(dc)) { - if ((cx.getLanguageVersion() != Context.VERSION_DEFAULT) - && (cx.getLanguageVersion() <= Context.VERSION_1_4)) { - if (dc == '0') - return null; - /* Check for overflow to avoid gobbling arbitrary decimal digits. */ - num = 0; - ca = da; - cp = dp; - while (++cp < ca.length && NativeRegExp.isDigit(dc = ca[cp])) { - tmp = 10 * num + NativeRegExp.unDigit(dc); - if (tmp < num) - break; - num = tmp; - } - } - else { /* ECMA 3, 1-9 or 01-99 */ - num = NativeRegExp.unDigit(dc); - cp = dp + 2; - if ((dp + 2) < da.length) { - dc = da[dp + 2]; - if (NativeRegExp.isDigit(dc)) { - num = 10 * num + NativeRegExp.unDigit(dc); - cp++; - } - } - if (num == 0) return null; /* $0 or $00 is not valid */ - } - /* Adjust num from 1 $n-origin to 0 array-index-origin. */ - num--; - skip[0] = cp - dp; - return res.getParenSubString(num); - } - - skip[0] = 2; - switch (dc) { - case '$': - return dollarStr; - case '&': - return res.lastMatch; - case '+': - return res.lastParen; - case '`': - if (cx.getLanguageVersion() == Context.VERSION_1_2) { - /* - * JS1.2 imitated the Perl4 bug where left context at each step - * in an iterative use of a global regexp started from last match, - * not from the start of the target string. But Perl4 does start - * $` at the beginning of the target string when it is used in a - * substitution, so we emulate that special case here. - */ - res.leftContext.index = 0; - res.leftContext.length = res.lastMatch.index; - } - return res.leftContext; - case '\'': - return res.rightContext; - } - return null; - } - - /** - * Corresponds to find_replen in jsstr.c. rdata is 'this', and - * the result parameter sizep is the return value (errors are - * propagated with exceptions). - */ - int findReplen(Context cx, RegExpImpl reImpl) - throws JavaScriptException - { - if (lambda != null) { - // invoke lambda function with args lastMatch, $1, $2, ... $n, - // leftContext.length, whole string. - Vector parens = reImpl.parens; - int parenCount = parens.size(); - Object[] args = new Object[parenCount + 3]; - args[0] = reImpl.lastMatch.toString(); - for (int i=0; i < parenCount; i++) { - SubString sub = (SubString) parens.elementAt(i); - args[i+1] = sub.toString(); - } - args[parenCount+1] = new Integer(reImpl.leftContext.length); - args[parenCount+2] = str; - Scriptable parent = lambda.getParentScope(); - Object result = lambda.call(cx, parent, parent, args); - - this.repstr = ScriptRuntime.toString(result).toCharArray(); - return this.repstr.length; - } - - int replen = this.repstr.length; - if (dollar == -1) - return replen; - - int bp = 0; - for (int dp = dollar; dp < this.repstr.length ; ) { - char c = this.repstr[dp]; - if (c != '$') { - dp++; - continue; - } - int[] skip = { 0 }; - SubString sub = interpretDollar(cx, reImpl, this.repstr, dp, - bp, skip); - if (sub != null) { - replen += sub.length - skip[0]; - dp += skip[0]; - } - else - dp++; - } - return replen; - } - - /** - * Analog of do_replace in jsstr.c - */ - void doReplace(Context cx, RegExpImpl regExpImpl, char[] charArray, - int arrayIndex) - { - int cp = 0; - char[] da = repstr; - int dp = this.dollar; - int bp = cp; - if (dp != -1) { - outer: - for (;;) { - int len = dp - cp; - System.arraycopy(repstr, cp, charArray, arrayIndex, - len); - arrayIndex += len; - cp = dp; - int[] skip = { 0 }; - SubString sub = interpretDollar(cx, regExpImpl, da, - dp, bp, skip); - if (sub != null) { - len = sub.length; - if (len > 0) { - System.arraycopy(sub.charArray, sub.index, charArray, - arrayIndex, len); - } - arrayIndex += len; - cp += skip[0]; - dp += skip[0]; - } - else - dp++; - if (dp >= repstr.length) break; - while (repstr[dp] != '$') { - dp++; - if (dp >= repstr.length) break outer; - } - } - } - if (repstr.length > cp) { - System.arraycopy(repstr, cp, charArray, arrayIndex, - repstr.length - cp); - } - } - - Function lambda; /* replacement function object or null */ - char[] repstr; /* replacement string */ - int dollar; /* -1 or index of first $ in repstr */ - char[] charArray; /* result characters, null initially */ - int length; /* result length, 0 initially */ - int index; /* index in result of next replacement */ - int leftIndex; /* leftContext index, always 0 for JS1.2 */ -} diff --git a/src/org/mozilla/javascript/regexp/SubString.java b/src/org/mozilla/javascript/regexp/SubString.java deleted file mode 100644 index 90e0979..0000000 --- a/src/org/mozilla/javascript/regexp/SubString.java +++ /dev/null @@ -1,62 +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, 1998. - * - * 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): - * - * 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.mozilla.javascript.regexp; - -class SubString { - - public SubString() - { - } - - public SubString(String str) - { - index = 0; - charArray = str.toCharArray(); - length = str.length(); - } - - public String toString() { - return charArray == null - ? "" - : new String(charArray, index, length); - } - - static final SubString emptySubString = new SubString(); - - char[] charArray; - int index; - int length; -} - diff --git a/src/org/xwt/Box.java b/src/org/xwt/Box.java index 1e55cb8..2ab32b9 100644 --- a/src/org/xwt/Box.java +++ b/src/org/xwt/Box.java @@ -4,8 +4,8 @@ package org.xwt; import java.io.*; import java.net.*; import java.util.*; +import org.xwt.js.*; import org.xwt.util.*; -import org.mozilla.javascript.*; /** *

@@ -82,7 +82,7 @@ import org.mozilla.javascript.*; * uses x1,y1,x2,y2 tuples. *

*/ -public final class Box extends JSObject { +public final class Box extends JS.Scope { // Static Data ////////////////////////////////////////////////////////////// @@ -100,7 +100,7 @@ public final class Box extends JSObject { static Hash imageToNameMap = new Hash(); /** the empty object, used for get-traps */ - private static Object[] emptyobj = new Object[] { }; + private static JS.Array emptyobj = new JS.Array(); // Instance Data: Templates //////////////////////////////////////////////////////// @@ -263,22 +263,18 @@ public final class Box extends JSObject { // Instance Data: IndexOf //////////////////////////////////////////////////////////// /** The indexof() Function; created lazily */ - public Function indexof = null; - public Function indexof() { - if (indexof == null) indexof = new IndexOf(); - return indexof; - } + public JS.Function indexof = null; + public JS.Function indexof() { if (indexof == null) indexof = new IndexOf(); return indexof; } /** a trivial private class to serve as the box.indexof function object */ - private class IndexOf extends JSObject implements Function { + private class IndexOf extends JS.Function { public IndexOf() { this.setSeal(true); } - public Scriptable construct(Context cx, Scriptable scope, java.lang.Object[] args) { return null; } - public Object call(Context cx, Scriptable scope, Scriptable thisObj, java.lang.Object[] args) throws JavaScriptException { - if (args == null || args.length != 1 || args[0] == null || !(args[0] instanceof Box)) return new Integer(-1); - Box b = (Box)args[0]; + public Object _call(JS.Array args) throws JS.Exn { + if (args.length() != 1 || args.elementAt(0) == null || !(args.elementAt(0) instanceof Box)) return new Integer(-1); + Box b = (Box)args.elementAt(0); if (b.getParent() != Box.this) { if (redirect == null || redirect == Box.this) return new Integer(-1); - return Box.this.redirect.indexof().call(cx, scope, thisObj, args); + return Box.this.redirect.indexof().call(args); } return new Integer(b.getIndexInParent()); } @@ -464,11 +460,13 @@ public final class Box extends JSObject { if (ret != -1) bytesDownloaded += ret; if (clear && callback != null) { clear = false; - ThreadMessage.newthread(new JSObject.JSFunction() { - public Object call(Context cx, Scriptable thisObj, Scriptable ctorObj, Object[] args) throws JavaScriptException { + ThreadMessage.newthread(new JS.Function() { + public Object _call(JS.Array args_) throws JS.Exn { try { - callback.call(cx, null, null, new Object[] { - new Double(bytesDownloaded), new Double(contentLength) }); + JS.Array args = new JS.Array(); + args.addElement(new Double(bytesDownloaded)); + args.addElement(new Double(contentLength)); + callback.call(args); } finally { clear = true; } @@ -520,8 +518,7 @@ public final class Box extends JSObject { } else { image = getPicture(s); if (image == null) { - if (Log.on) Log.log(Box.class, "unable to load image " + s + " at " + - Context.enter().interpreterSourceFile + ":" + Context.enter().interpreterLine); + if (Log.on) Log.log(Box.class, "unable to load image " + s + " at " + JS.getCurrentFunctionSourceName()); return; } if (sizetoimage) syncSizeToImage(); @@ -542,8 +539,7 @@ public final class Box extends JSObject { if (border == null) { ImageDecoder id = getImage(s, null); if (id == null) { - if (Log.on) Log.log(this, "unable to load border image " + s + " at " + - Context.enter().interpreterSourceFile + ":" + Context.enter().interpreterLine); + if (Log.on) Log.log(this, "unable to load border image " + s + " at " + JS.getCurrentFunctionSourceName()); return; } int[] data = id.getData(); @@ -588,21 +584,10 @@ public final class Box extends JSObject { } /** returns true if the property has a trap on it */ - boolean is_trapped(String property) { - if (traps == null) { - return false; - } else { - Object gc = traps.get(property); - return (gc != null && - !(gc instanceof org.mozilla.javascript.Undefined) && - gc != org.mozilla.javascript.Scriptable.NOT_FOUND); - } - } + boolean is_trapped(String property) { return traps != null && traps.get(property) != null; } /** Adds the node's current actual geometry to the Surface's dirty list */ - void dirty() { - dirty(pos(0), pos(1), size(0), size(1)); - } + void dirty() { dirty(pos(0), pos(1), size(0), size(1)); } /** Adds the intersection of (x,y,w,h) and the node's current actual geometry to the Surface's dirty list */ public final void dirty(int x, int y, int w, int h) { @@ -632,9 +617,9 @@ public final class Box extends JSObject { if (!wasinside && !isinside) return; - if (!wasinside && isinside && is_trapped("Enter")) put("Enter", null, this); - else if (wasinside && !isinside && is_trapped("Leave")) put("Leave", null, this); - else if (wasinside && isinside && (mousex != oldmousex || mousey != oldmousey) && is_trapped("Move")) put("Move", null, this); + if (!wasinside && isinside && is_trapped("Enter")) put("Enter", this); + else if (wasinside && !isinside && is_trapped("Leave")) put("Leave", this); + else if (wasinside && isinside && (mousex != oldmousex || mousey != oldmousey) && is_trapped("Move")) put("Move", this); if (isinside && cursor != null && surface != null) surface.cursor = cursor; @@ -650,7 +635,7 @@ public final class Box extends JSObject { /** creates a new box from an anonymous template; ids is passed through to Template.apply() */ Box(Template anonymous, Vec pboxes, Vec ptemplates, Function callback, int numerator, int denominator) { - super(true); + super(null); set(dmax, 0, Integer.MAX_VALUE); set(dmax, 1, Integer.MAX_VALUE); template = anonymous; @@ -662,7 +647,7 @@ public final class Box extends JSObject { /** creates a new box from an unresolved templatename and an importlist; use "box" for an untemplatized box */ public Box(String templatename, String[] importlist) { this(templatename, importlist, null); } public Box(String templatename, String[] importlist, Function callback) { - super(true); + super(null); set(dmax, 0, Integer.MAX_VALUE); set(dmax, 1, Integer.MAX_VALUE); this.importlist = importlist; @@ -756,16 +741,18 @@ public final class Box extends JSObject { if (++surface.sizePosChangesSinceLastRender >= 500) { if (surface.sizePosChangesSinceLastRender == 500) { if (Log.on) Log.log(this, "Warning, more than 500 SizeChange/PosChange traps triggered since last complete render"); - if (Log.on) Log.log(this, " interpreter is at " + Context.enter().interpreterSourceFile + ":" + Context.enter().interpreterLine); + if (Log.on) Log.log(this, " interpreter is at " + JS.getCurrentFunctionSourceName()); + /* try { Trap t = sizechange ? Trap.getTrap(this, "SizeChange") : Trap.getTrap(this, "PosChange"); InterpretedFunction f = (InterpretedFunction)t.f; if (Log.on) Log.log(this, "Current trap is at " + f.getSourceName() + ":" + f.getLineNumbers()[0]); } catch (Throwable t) { } + */ } } else { - if (sizechange) put("SizeChange", null, Boolean.TRUE); - if (poschange) put("PosChange", null, Boolean.TRUE); + if (sizechange) put("SizeChange", Boolean.TRUE); + if (poschange) put("PosChange", Boolean.TRUE); if (sizechange || poschange) { surface.abort = true; return; @@ -1072,9 +1059,9 @@ public final class Box extends JSObject { // Methods to implement org.mozilla.javascript.Scriptable ////////////////////////////////////// /** Returns the i_th child */ - public Object get(int i, Scriptable start) { + public Object get(int i) { if (redirect == null) return null; - if (redirect != this) return redirect.get(i, start); + if (redirect != this) return redirect.get(i); return i >= numChildren() ? null : getChild(i); } @@ -1084,31 +1071,27 @@ public final class Box extends JSObject { * INVARIANT: after completion, getChild(min(i, numChildren())) == newnode * WARNING: O(n) runtime, unless i == numChildren() */ - public void put(int i, Scriptable start, Object value) { + public void put(int i, Object value) { if (value != null && !(value instanceof Box)) { - if (Log.on) Log.log(this, "attempt to set a numerical property on a box to anything other than a box at " + - Context.enter().interpreterSourceFile + ":" + Context.enter().interpreterLine); + if (Log.on) Log.log(this, "attempt to set a numerical property on a box to anything other than a box at " + JS.getCurrentFunctionSourceName()); } else if (redirect == null) { - if (Log.on) Log.log(this, "attempt to add/remove children to/from a node with a null redirect at " + - Context.enter().interpreterSourceFile + ":" + Context.enter().interpreterLine); - + if (Log.on) Log.log(this, "attempt to add/remove children to/from a node with a null redirect at " + JS.getCurrentFunctionSourceName()); } else if (redirect != this) { - Box b = value == null ? (Box)redirect.get(i, null) : (Box)value; - redirect.put(i, null, value); - put("0", null, b); + Box b = value == null ? (Box)redirect.get(i) : (Box)value; + redirect.put(i, value); + put("0", b); } else if (value == null) { if (i >= 0 && i < numChildren()) { Box b = getChild(i); b.remove(); - put("0", null, b); + put("0", b); } } else if (value instanceof RootProxy) { - if (Log.on) Log.log(this, "attempt to reparent a box via its proxy object at " + - Context.enter().interpreterSourceFile + ":" + Context.enter().interpreterLine); + if (Log.on) Log.log(this, "attempt to reparent a box via its proxy object at " + JS.getCurrentFunctionSourceName()); } else { Box newnode = (Box)value; @@ -1116,16 +1099,14 @@ public final class Box extends JSObject { // check if box being moved is currently target of a redirect for(Box cur = newnode.getParent(); cur != null; cur = cur.getParent()) if (cur.redirect == newnode) { - if (Log.on) Log.log(this, "attempt to move a box that is the target of a redirect at "+ - Context.enter().interpreterSourceFile + ":" + Context.enter().interpreterLine); + if (Log.on) Log.log(this, "attempt to move a box that is the target of a redirect at "+ JS.getCurrentFunctionSourceName()); return; } // check for recursive ancestor violation for(Box cur = this; cur != null; cur = cur.getParent()) if (cur == newnode) { - if (Log.on) Log.log(this, "attempt to make a node a parent of its own ancestor at " + - Context.enter().interpreterSourceFile + ":" + Context.enter().interpreterLine); + if (Log.on) Log.log(this, "attempt to make a node a parent of its own ancestor at " + JS.getCurrentFunctionSourceName()); return; } @@ -1174,21 +1155,16 @@ public final class Box extends JSObject { sync_cmin_to_children(); // note that JavaScript box[0] will invoke put(int i), not put(String s) - put("0", null, newnode); + put("0", newnode); } } - public Object get(String name, Scriptable start) { return get(name, start, false); } - public Object get(String name, Scriptable start, boolean ignoretraps) { - - if (name == null || name.equals("")) return null; + public Object get(Object name) { return get(name, false); } + public Object get(Object name_, boolean ignoretraps) { + if (name_ instanceof Number) return get(((Number)name_).intValue()); - // hack since Rhino needs to be able to grab these functions to create new objects - if (name.equals("Object")) return JSObject.defaultObjects.get("Object", null); - if (name.equals("Array")) return JSObject.defaultObjects.get("Array", null); - if (name.equals("Function")) return JSObject.defaultObjects.get("Function", null); - if (name.equals("TypeError")) return JSObject.defaultObjects.get("TypeError", null); - if (name.equals("ConversionError")) return JSObject.defaultObjects.get("ConversionError", null); + String name = (String)name_; + if (name.equals("")) return null; // See if we're reading back the function value of a trap if (name.charAt(0) == '_') { @@ -1206,55 +1182,41 @@ public final class Box extends JSObject { SpecialBoxProperty gph = (SpecialBoxProperty)SpecialBoxProperty.specialBoxProperties.get(name); if (gph != null) return gph.get(this); - Object ret = super.get(name, start); + Object ret = super.get(name); if (name.startsWith("$") && ret == null) if (Log.on) Log.log(this, "WARNING: attempt to access " + name + ", but no child with id=\"" + name.substring(1) + "\" found; " + - Context.enter().interpreterSourceFile + ":" + Context.enter().interpreterLine); + JS.getFileAndLine()); return ret; } - /** indicate that we don't want JSObject trying to handle these */ - public boolean has(String name, Scriptable start) { - if (name.equals("")) return false; - if (traps != null && traps.get(name) != null) return true; - if (name.charAt(0) == '_') return true; - if (SpecialBoxProperty.specialBoxProperties.get(name) != null) return true; - if (name.equals("Function") || name.equals("Array") || name.equals("Object") || - name.equals("TypeError") || name.equals("ConversionError")) return true; - return super.has(name, start); - } - - public Object[] getIds() { + public Object[] keys() { Object[] ret = new Object[numChildren()]; - for(int i=0; idelete keyword is not valid in XWT scripts */ - public void delete(int i) { } - // Tree Manipulation ///////////////////////////////////////////////////////////////////// @@ -1370,7 +1323,7 @@ public final class Box extends JSObject { setSurface(null); // note that JavaScript box[0] will invoke put(int i), not put(String s) - if (oldparent != null) oldparent.put("0", null, this); + if (oldparent != null) oldparent.put("0", this); } /** returns our next sibling (parent[ourindex + 1]) */ @@ -1450,35 +1403,17 @@ public final class Box extends JSObject { // Root Proxy /////////////////////////////////////////////////////////////////////////////// RootProxy myproxy = null; - public Scriptable getRootProxy() { + public JS getRootProxy() { if (myproxy == null) myproxy = new RootProxy(this); return myproxy; } - private static class RootProxy implements Scriptable { - + private static class RootProxy extends JS { Box box; RootProxy(Box b) { this.box = b; } - - public void delete(String name) { box.delete(name); } - public Scriptable getParentScope() { return box.getParentScope(); } - public void setParentScope(Scriptable p) { box.setParentScope(p); } - public boolean hasInstance(Scriptable value) { return box.hasInstance(value); } - public Scriptable getPrototype() { return box.getPrototype(); } - public void setPrototype(Scriptable p) { box.setPrototype(p); } - public void delete(int i) { box.delete(i); } - public String getClassName() { return box.getClassName(); } - public Object getDefaultValue(Class hint) { return box.getDefaultValue(hint); } - - public void put(int i, Scriptable start, Object value) { if (value != null) box.put(i, start, value); } - public Object get(String name, Scriptable start) { return box.get(name, start); } - public Object get(int i, Scriptable start) { return null; } - - public void put(String name, Scriptable start, Object value) { box.put(name, start, value, false, this); } - public boolean has(String name, Scriptable start) { return box.has(name, start); } - public boolean has(int i, Scriptable start) { return box.has(i, start); } - public Object[] getIds() { return box.getIds(); } - + public Object get(Object name) { return box.get(name); } + public void put(Object name, Object value) { box.put(name, value, false, this); } + public Object[] keys() { return box.keys(); } }