/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.javascript.regexp; import org.mozilla.javascript.*; /** * 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 */ class NativeRegExpCtor extends BaseFunction { static final long serialVersionUID = -5733330028285400526L; NativeRegExpCtor() { } @Override public String getFunctionName() { return "RegExp"; } @Override public int getLength() { return 2; } @Override public int getArity() { return 2; } @Override 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, scope, args); } @Override public Scriptable construct(Context cx, Scriptable scope, Object[] args) { NativeRegExp re = new NativeRegExp(); re.compile(cx, scope, args); ScriptRuntime.setBuiltinProtoAndParent(re, scope, TopLevel.Builtins.RegExp); return re; } private static RegExpImpl getImpl() { Context cx = Context.getCurrentContext(); return (RegExpImpl) ScriptRuntime.getRegExpProxy(cx); } // #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; @Override protected int getMaxInstanceId() { return super.getMaxInstanceId() + MAX_INSTANCE_ID; } @Override protected int findInstanceIdInfo(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# if (id == 0) return super.findInstanceIdInfo(s); int attr; switch (id) { case Id_multiline: attr = multilineAttr; break; case Id_STAR: attr = starAttr; break; case Id_input: attr = inputAttr; break; case Id_UNDERSCORE: attr = underscoreAttr; break; default: attr = PERMANENT | READONLY; break; } return instanceIdInfo(attr, super.getMaxInstanceId() + id); } // #/string_id_map# @Override protected String getInstanceIdName(int id) { int shifted = id - super.getMaxInstanceId(); 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.getInstanceIdName(id); } @Override protected Object getInstanceIdValue(int id) { int shifted = id - super.getMaxInstanceId(); if (1 <= shifted && shifted <= MAX_INSTANCE_ID) { RegExpImpl impl = getImpl(); Object stringResult; switch (shifted) { case Id_multiline: case Id_STAR: return ScriptRuntime.wrapBoolean(impl.multiline); case Id_input: case Id_UNDERSCORE: stringResult = impl.input; break; case Id_lastMatch: case Id_AMPERSAND: stringResult = impl.lastMatch; break; case Id_lastParen: case Id_PLUS: stringResult = impl.lastParen; break; case Id_leftContext: case Id_BACK_QUOTE: stringResult = impl.leftContext; break; case Id_rightContext: case Id_QUOTE: stringResult = impl.rightContext; break; default: { // Must be one of $1..$9, convert to 0..8 int substring_number = shifted - DOLLAR_ID_BASE - 1; stringResult = impl.getParenSubString(substring_number); break; } } return (stringResult == null) ? "" : stringResult.toString(); } return super.getInstanceIdValue(id); } @Override protected void setInstanceIdValue(int id, Object value) { int shifted = id - super.getMaxInstanceId(); switch (shifted) { case Id_multiline: case Id_STAR: getImpl().multiline = ScriptRuntime.toBoolean(value); return; case Id_input: case Id_UNDERSCORE: getImpl().input = ScriptRuntime.toString(value); return; case Id_lastMatch: case Id_AMPERSAND: case Id_lastParen: case Id_PLUS: case Id_leftContext: case Id_BACK_QUOTE: case Id_rightContext: case Id_QUOTE: return; default: int substring_number = shifted - DOLLAR_ID_BASE - 1; if (0 <= substring_number && substring_number <= 8) { return; } } super.setInstanceIdValue(id, value); } @Override protected void setInstanceIdAttributes(int id, int attr) { int shifted = id - super.getMaxInstanceId(); switch (shifted) { case Id_multiline: multilineAttr = attr; return; case Id_STAR: starAttr = attr; return; case Id_input: inputAttr = attr; return; case Id_UNDERSCORE: underscoreAttr = attr; return; case Id_lastMatch: case Id_AMPERSAND: case Id_lastParen: case Id_PLUS: case Id_leftContext: case Id_BACK_QUOTE: case Id_rightContext: case Id_QUOTE: // non-configurable + non-writable return; default: int substring_number = shifted - DOLLAR_ID_BASE - 1; if (0 <= substring_number && substring_number <= 8) { // non-configurable + non-writable return; } } super.setInstanceIdAttributes(id, attr); } private int multilineAttr = PERMANENT; private int starAttr = PERMANENT; private int inputAttr = PERMANENT; private int underscoreAttr = PERMANENT; }