[jruby-joni] 02/09: fix for jruby/jruby#4077

Hideki Yamane henrich at moszumanska.debian.org
Sun Aug 21 06:26:13 UTC 2016


This is an automated email from the git hooks/post-receive script.

henrich pushed a commit to branch debian/sid
in repository jruby-joni.

commit e0323eea7ae6c403d5d384520081731f9af283f4
Author: Marcin Mielzynski <lopx at gazeta.pl>
Date:   Wed Aug 17 02:54:15 2016 +0200

    fix for jruby/jruby#4077
---
 src/org/joni/Analyser.java        |  21 +++--
 src/org/joni/Config.java          |   2 +
 src/org/joni/Lexer.java           | 168 ++++++++++++++++++++++----------------
 src/org/joni/Parser.java          |  18 +++-
 src/org/joni/ScanEnvironment.java |   7 +-
 src/org/joni/StackMachine.java    |  25 +++---
 src/org/joni/Token.java           |   7 ++
 7 files changed, 151 insertions(+), 97 deletions(-)

diff --git a/src/org/joni/Analyser.java b/src/org/joni/Analyser.java
index 6a4e418..ddb0f5c 100644
--- a/src/org/joni/Analyser.java
+++ b/src/org/joni/Analyser.java
@@ -1277,7 +1277,6 @@ final class Analyser extends Parser {
 
         case NodeType.CALL:
             CallNode cn = (CallNode)node;
-
             if (cn.groupNum != 0) {
                 int gNum = cn.groupNum;
 
@@ -1290,15 +1289,19 @@ final class Analyser extends Parser {
                 setCallAttr(cn);
             } else {
                 if (Config.USE_NAMED_GROUP) {
-                    NameEntry ne = regex.nameToGroupNumbers(cn.name, cn.nameP, cn.nameEnd);
-
-                    if (ne == null) {
-                        newValueException(ERR_UNDEFINED_NAME_REFERENCE, cn.nameP, cn.nameEnd);
-                    } else if (ne.backNum > 1) {
-                        newValueException(ERR_MULTIPLEX_DEFINITION_NAME_CALL, cn.nameP, cn.nameEnd);
-                    } else {
-                        cn.groupNum = ne.backRef1; // ne.backNum == 1 ? ne.backRef1 : ne.backRefs[0]; // ??? need to check ?
+                    if (Config.USE_PERL_SUBEXP_CALL && cn.nameP == cn.nameEnd) {
                         setCallAttr(cn);
+                    } else {
+                        NameEntry ne = regex.nameToGroupNumbers(cn.name, cn.nameP, cn.nameEnd);
+
+                        if (ne == null) {
+                            newValueException(ERR_UNDEFINED_NAME_REFERENCE, cn.nameP, cn.nameEnd);
+                        } else if (ne.backNum > 1) {
+                            newValueException(ERR_MULTIPLEX_DEFINITION_NAME_CALL, cn.nameP, cn.nameEnd);
+                        } else {
+                            cn.groupNum = ne.backRef1; // ne.backNum == 1 ? ne.backRef1 : ne.backRefs[0]; // ??? need to check ?
+                            setCallAttr(cn);
+                        }
                     }
                 }
             }
diff --git a/src/org/joni/Config.java b/src/org/joni/Config.java
index 3467966..30f3871 100644
--- a/src/org/joni/Config.java
+++ b/src/org/joni/Config.java
@@ -23,9 +23,11 @@ import java.io.PrintStream;
 
 public interface Config extends org.jcodings.Config {
     final int CHAR_TABLE_SIZE = 256;
+    final int SCANENV_MEMNODES_SIZE = 8;
 
     final boolean USE_NAMED_GROUP = true;
     final boolean USE_SUBEXP_CALL = true;
+    final boolean USE_PERL_SUBEXP_CALL = true;
     final boolean USE_BACKREF_WITH_LEVEL = true;                            /* \k<name+n>, \k<name-n> */
 
     final boolean USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT = true; /* /(?:()|())*\2/ */
diff --git a/src/org/joni/Lexer.java b/src/org/joni/Lexer.java
index c1feb68..812369f 100644
--- a/src/org/joni/Lexer.java
+++ b/src/org/joni/Lexer.java
@@ -851,94 +851,122 @@ class Lexer extends ScannerSupport {
         }
     }
 
-    private void fetchTokenFor_namedBackref() {
-        if (syntax.op2EscKNamedBackref()) {
-            if (left()) {
+    private void fetchTokenFor_NamedBackref() {
+        if (Config.USE_NAMED_GROUP) {
+            if (syntax.op2EscKNamedBackref() && left()) {
                 fetch();
                 if (c =='<' || c == '\'') {
-                    int last = p;
-                    int backNum;
-                    if (Config.USE_BACKREF_WITH_LEVEL) {
-                        Ptr rbackNum = new Ptr();
-                        Ptr rlevel = new Ptr();
-                        token.setBackrefExistLevel(fetchNameWithLevel(c, rbackNum, rlevel));
-                        token.setBackrefLevel(rlevel.p);
-                        backNum = rbackNum.p;
-                    } else {
-                        backNum = fetchName(c, true);
-                    } // USE_BACKREF_AT_LEVEL
-                    int nameEnd = value; // set by fetchNameWithLevel/fetchName
-
-                    if (backNum != 0) {
-                        if (backNum < 0) {
-                            backNum = backrefRelToAbs(backNum);
-                            if (backNum <= 0) newValueException(ERR_INVALID_BACKREF);
-                        }
-
-                        if (syntax.strictCheckBackref() && (backNum > env.numMem || env.memNodes == null)) {
-                            newValueException(ERR_INVALID_BACKREF);
-                        }
-                        token.type = TokenType.BACKREF;
-                        token.setBackrefByName(false);
-                        token.setBackrefNum(1);
-                        token.setBackrefRef1(backNum);
-                    } else {
-                        NameEntry e = env.reg.nameToGroupNumbers(bytes, last, nameEnd);
-                        if (e == null) newValueException(ERR_UNDEFINED_NAME_REFERENCE, last, nameEnd);
-
-                        if (syntax.strictCheckBackref()) {
-                            if (e.backNum == 1) {
-                                if (e.backRef1 > env.numMem ||
-                                    env.memNodes == null ||
-                                    env.memNodes[e.backRef1] == null) newValueException(ERR_INVALID_BACKREF);
-                            } else {
-                                for (int i=0; i<e.backNum; i++) {
-                                    if (e.backRefs[i] > env.numMem ||
-                                        env.memNodes == null ||
-                                        env.memNodes[e.backRefs[i]] == null) newValueException(ERR_INVALID_BACKREF);
-                                }
-                            }
-                        }
-
-                        token.type = TokenType.BACKREF;
-                        token.setBackrefByName(true);
-
-                        if (e.backNum == 1) {
-                            token.setBackrefNum(1);
-                            token.setBackrefRef1(e.backRef1);
-                        } else {
-                            token.setBackrefNum(e.backNum);
-                            token.setBackrefRefs(e.backRefs);
-                        }
-                    }
+                    fetchNamedBackrefToken();
                 } else {
                     unfetch();
                     syntaxWarn(Warnings.INVALID_BACKREFERENCE);
                 }
-            } else {
-                syntaxWarn(Warnings.INVALID_BACKREFERENCE);
             }
         }
     }
 
     private void fetchTokenFor_subexpCall() {
-        if (syntax.op2EscGSubexpCall()) {
-            if (left()) {
+        if (Config.USE_NAMED_GROUP) {
+            if (syntax.op2EscGBraceBackref() && left()) {
+                fetch();
+                if (c == '{') {
+                    fetchNamedBackrefToken();
+                } else {
+                    unfetch();
+                }
+            }
+        }
+        if (Config.USE_SUBEXP_CALL) {
+            if (syntax.op2EscGSubexpCall() && left()) {
                 fetch();
                 if (c == '<' || c == '\'') {
-                    int last = p;
-                    int gNum = fetchName(c, true);
-                    int nameEnd = value;
+                    int gNum = -1;
+                    boolean rel = false;
+                    int cnext = peek();
+                    int nameEnd = 0;
+                    if (cnext == '0') {
+                        inc();
+                        if (peekIs(nameEndCodePoint(c))) { /* \g<0>, \g'0' */
+                            inc();
+                            nameEnd = p;
+                            gNum = 0;
+                        }
+                    } else if (cnext == '+') {
+                        inc();
+                        rel = true;
+                    }
+                    int prev = p;
+                    if (gNum < 0) {
+                        gNum = fetchName(c, true);
+                        nameEnd = value;
+                    }
                     token.type = TokenType.CALL;
-                    token.setCallNameP(last);
+                    token.setCallNameP(prev);
                     token.setCallNameEnd(nameEnd);
                     token.setCallGNum(gNum);
+                    token.setCallRel(rel);
                 } else {
-                    unfetch();
                     syntaxWarn(Warnings.INVALID_SUBEXP_CALL);
+                    unfetch();
                 }
+            }
+        }
+    }
+
+    private void fetchNamedBackrefToken() {
+        int last = p;
+        int backNum;
+        if (Config.USE_BACKREF_WITH_LEVEL) {
+            Ptr rbackNum = new Ptr();
+            Ptr rlevel = new Ptr();
+            token.setBackrefExistLevel(fetchNameWithLevel(c, rbackNum, rlevel));
+            token.setBackrefLevel(rlevel.p);
+            backNum = rbackNum.p;
+        } else {
+            backNum = fetchName(c, true);
+        } // USE_BACKREF_AT_LEVEL
+        int nameEnd = value; // set by fetchNameWithLevel/fetchName
+
+        if (backNum != 0) {
+            if (backNum < 0) {
+                backNum = backrefRelToAbs(backNum);
+                if (backNum <= 0) newValueException(ERR_INVALID_BACKREF);
+            }
+
+            if (syntax.strictCheckBackref() && (backNum > env.numMem || env.memNodes == null)) {
+                newValueException(ERR_INVALID_BACKREF);
+            }
+            token.type = TokenType.BACKREF;
+            token.setBackrefByName(false);
+            token.setBackrefNum(1);
+            token.setBackrefRef1(backNum);
+        } else {
+            NameEntry e = env.reg.nameToGroupNumbers(bytes, last, nameEnd);
+            if (e == null) newValueException(ERR_UNDEFINED_NAME_REFERENCE, last, nameEnd);
+
+            if (syntax.strictCheckBackref()) {
+                if (e.backNum == 1) {
+                    if (e.backRef1 > env.numMem ||
+                        env.memNodes == null ||
+                        env.memNodes[e.backRef1] == null) newValueException(ERR_INVALID_BACKREF);
+                } else {
+                    for (int i=0; i<e.backNum; i++) {
+                        if (e.backRefs[i] > env.numMem ||
+                            env.memNodes == null ||
+                            env.memNodes[e.backRefs[i]] == null) newValueException(ERR_INVALID_BACKREF);
+                    }
+                }
+            }
+
+            token.type = TokenType.BACKREF;
+            token.setBackrefByName(true);
+
+            if (e.backNum == 1) {
+                token.setBackrefNum(1);
+                token.setBackrefRef1(e.backRef1);
             } else {
-                syntaxWarn(Warnings.INVALID_SUBEXP_CALL);
+                token.setBackrefNum(e.backNum);
+                token.setBackrefRefs(e.backRefs);
             }
         }
     }
@@ -1110,10 +1138,10 @@ class Lexer extends ScannerSupport {
                     fetchTokenFor_zero();
                     break;
                 case 'k':
-                    if (Config.USE_NAMED_GROUP) fetchTokenFor_namedBackref();
+                    fetchTokenFor_NamedBackref();
                     break;
                 case 'g':
-                    if (Config.USE_SUBEXP_CALL) fetchTokenFor_subexpCall();
+                    fetchTokenFor_subexpCall();
                     break;
                 case 'Q':
                     if (syntax.op2EscCapitalQQuote()) token.type = TokenType.QUOTE_OPEN;
diff --git a/src/org/joni/Parser.java b/src/org/joni/Parser.java
index e480afd..81f635c 100644
--- a/src/org/joni/Parser.java
+++ b/src/org/joni/Parser.java
@@ -950,8 +950,8 @@ class Parser extends Lexer {
         case CALL:
             if (Config.USE_SUBEXP_CALL) {
                 int gNum = token.getCallGNum();
-
-                if (gNum < 0) {
+                if (gNum < 0 || token.getCallRel()) {
+                    if (gNum > 0) gNum--;
                     gNum = backrefRelToAbs(gNum);
                     if (gNum <= 0) newValueException(ERR_INVALID_BACKREF);
                 }
@@ -1163,6 +1163,18 @@ class Parser extends Lexer {
 
     private Node parseRegexp() {
         fetchToken();
-        return parseSubExp(TokenType.EOT);
+        Node top = parseSubExp(TokenType.EOT);
+        if (Config.USE_SUBEXP_CALL) {
+            if (env.numCall > 0) {
+                /* Capture the pattern itself. It is used for (?R), (?0) and \g<0>. */
+                EncloseNode np = new EncloseNode(env.option, false);
+                np.regNum = 0;
+                np.setTarget(top);
+                if (env.memNodes ==  null) env.memNodes = new Node[Config.SCANENV_MEMNODES_SIZE];
+                env.memNodes[0] = np;
+                top = np;
+            }
+        }
+        return top;
     }
 }
diff --git a/src/org/joni/ScanEnvironment.java b/src/org/joni/ScanEnvironment.java
index 0dbce24..4c68a04 100644
--- a/src/org/joni/ScanEnvironment.java
+++ b/src/org/joni/ScanEnvironment.java
@@ -27,9 +27,6 @@ import org.joni.exception.ErrorMessages;
 import org.joni.exception.InternalException;
 
 public final class ScanEnvironment {
-
-    private static final int SCANENV_MEMNODES_SIZE = 8;
-
     int option;
     final int caseFoldFlag;
     final public Encoding enc;
@@ -90,7 +87,7 @@ public final class ScanEnvironment {
 
     public int addMemEntry() {
         if (numMem++ == 0) {
-            memNodes = new Node[SCANENV_MEMNODES_SIZE];
+            memNodes = new Node[Config.SCANENV_MEMNODES_SIZE];
         } else if (numMem >= memNodes.length) {
             Node[]tmp = new Node[memNodes.length << 1];
             System.arraycopy(memNodes, 0, tmp, 0, memNodes.length);
@@ -111,7 +108,7 @@ public final class ScanEnvironment {
     public void pushPrecReadNotNode(Node node) {
         numPrecReadNotNodes++;
         if (precReadNotNodes == null) {
-            precReadNotNodes = new Node[SCANENV_MEMNODES_SIZE];
+            precReadNotNodes = new Node[Config.SCANENV_MEMNODES_SIZE];
         } else if (numPrecReadNotNodes >= precReadNotNodes.length) {
             Node[]tmp = new Node[precReadNotNodes.length << 1];
             System.arraycopy(precReadNotNodes, 0, tmp, 0, precReadNotNodes.length);
diff --git a/src/org/joni/StackMachine.java b/src/org/joni/StackMachine.java
index 07e5e04..d5210ca 100644
--- a/src/org/joni/StackMachine.java
+++ b/src/org/joni/StackMachine.java
@@ -42,15 +42,20 @@ abstract class StackMachine extends Matcher implements StackType {
 
     protected StackMachine(Regex regex, byte[]bytes, int p , int end) {
         super(regex, bytes, p, end);
-
-        this.stack = regex.requireStack ? fetchStack() : null;
-        int n = regex.numRepeat + (regex.numMem << 1);
-        this.repeatStk = n > 0 ? new int[n] : null;
-
-        memStartStk = regex.numRepeat - 1;
-        memEndStk   = memStartStk + regex.numMem;
-        /* for index start from 1, mem_start_stk[1]..mem_start_stk[num_mem] */
-        /* for index start from 1, mem_end_stk[1]..mem_end_stk[num_mem] */
+        stack = regex.requireStack ? fetchStack() : null;
+        final int n;
+        if (Config.USE_SUBEXP_CALL) {
+            n = regex.numRepeat + ((regex.numMem + 1) << 1);
+            memStartStk = regex.numRepeat;
+            memEndStk   = memStartStk + regex.numMem + 1;
+        } else {
+            n = regex.numRepeat + (regex.numMem << 1);
+            memStartStk = regex.numRepeat - 1;
+            memEndStk   = memStartStk + regex.numMem;
+            /* for index start from 1, mem_start_stk[1]..mem_start_stk[num_mem] */
+            /* for index start from 1, mem_end_stk[1]..mem_end_stk[num_mem] */
+        }
+        repeatStk = n > 0 ? new int[n] : null;
     }
 
     private static StackEntry[] allocateStack() {
@@ -86,7 +91,7 @@ abstract class StackMachine extends Matcher implements StackType {
     protected final void init() {
         if (stack != null) pushEnsured(ALT, regex.codeLength - 1); /* bottom stack */
         if (repeatStk != null) {
-            for (int i=1; i<=regex.numMem; i++) {
+            for (int i = (Config.USE_SUBEXP_CALL ? 0 : 1); i <= regex.numMem; i++) {
                 repeatStk[i + memStartStk] = repeatStk[i + memEndStk] = INVALID_INDEX;
             }
         }
diff --git a/src/org/joni/Token.java b/src/org/joni/Token.java
index 321ad91..c57662e 100644
--- a/src/org/joni/Token.java
+++ b/src/org/joni/Token.java
@@ -156,6 +156,13 @@ final class Token {
         INT3 = gnum;
     }
 
+    boolean getCallRel() {
+        return INT4 != 0;
+    }
+    void setCallRel(boolean rel) {
+        INT4 = rel ? 1 : 0;
+    }
+
     // prop union member
     int getPropCType() {
         return INT1;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jruby-joni.git



More information about the pkg-java-commits mailing list