diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index 552143bb828f91a3910d159cbbc903a59c4daf91..6d6a78006af8e0ccf810b925574b67d3e5e687b1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@ import com.oracle.truffle.r.library.fastrGrid.grDevices.DevHoldFlush;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevOff;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevSize;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.InitWindowedDevice;
+import com.oracle.truffle.r.library.fastrGrid.grDevices.PDF;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.SavePlot;
 import com.oracle.truffle.r.library.fastrGrid.graphics.CPar;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
@@ -64,7 +65,7 @@ public final class FastRGridExternalLookup {
             case "devoff":
                 return DevOff.create();
             case "PDF":
-                return new IgnoredGridExternal(RNull.instance);
+                return new PDF();
             case "devCairo":
                 return new DevCairo();
             default:
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/NullDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/NullDevice.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ce65bcc9666103b342352ab4e6fea0ef5d4365e
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/NullDevice.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device;
+
+public class NullDevice implements GridDevice {
+
+    @Override
+    public void openNewPage() {
+    }
+
+    @Override
+    public void drawRect(DrawingContext ctx, double leftX, double bottomY, double width, double height, double rotationAnticlockWise) {
+    }
+
+    @Override
+    public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
+    }
+
+    @Override
+    public void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
+    }
+
+    @Override
+    public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) {
+    }
+
+    @Override
+    public void drawRaster(double leftX, double bottomY, double width, double height, int[] pixels, int pixelsColumnsCount, ImageInterpolation interpolation) {
+    }
+
+    @Override
+    public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) {
+    }
+
+    @Override
+    public double getWidth() {
+        return 0;
+    }
+
+    @Override
+    public double getHeight() {
+        return 0;
+    }
+
+    @Override
+    public int getNativeWidth() {
+        return 0;
+    }
+
+    @Override
+    public int getNativeHeight() {
+        return 0;
+    }
+
+    @Override
+    public double getStringWidth(DrawingContext ctx, String text) {
+        return 0;
+    }
+
+    @Override
+    public double getStringHeight(DrawingContext ctx, String text) {
+        return 0;
+    }
+
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java
index 371fe577b934023e585821fb963aaff0067f9172..872a98d181113df7a3837d2d39915b9ef23e7c60 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.library.fastrGrid.grDevices;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.device.NullDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.SVGDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -44,6 +45,11 @@ public class DevCairo extends RExternalBuiltinNode {
         }
 
         String filename = RRuntime.asString(args.getArgument(0));
+        if (filename == null) {
+            GridContext.getContext().setCurrentDevice("null", new NullDevice());
+            return RNull.instance;
+        }
+
         int witdh = RRuntime.asInteger(args.getArgument(2));
         int height = RRuntime.asInteger(args.getArgument(3));
         if (RRuntime.isNA(witdh) || RRuntime.isNA(height) || RRuntime.isNA(filename) || filename.isEmpty()) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/PDF.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/PDF.java
new file mode 100644
index 0000000000000000000000000000000000000000..78926da43b23d03a62785c91c0d5851589f32ba2
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/PDF.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.grDevices;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.device.NullDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public class PDF extends RExternalBuiltinNode {
+    static {
+        Casts.noCasts(PDF.class);
+    }
+
+    @Override
+    @TruffleBoundary
+    protected Object call(RArgsValuesAndNames args) {
+        if (args.getLength() < 1) {
+            throw error(Message.ARGUMENTS_REQUIRED_COUNT, args.getLength(), "PDF", 1);
+        }
+
+        GridContext.getContext().setCurrentDevice("null", new NullDevice());
+        RError.warning(this, RError.Message.GENERIC, "PDF device not supported. Using a dummy device.");
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
index f674261f52a3bb6ce12a93b23534fd86c567d2f5..f32979e54aedc0fd2a7082a71ffda161e7bea1e9 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
@@ -1,4 +1,4 @@
-# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,12 @@ eval(expression({
     recordPlot <- function() {
 		dl <- grid:::grid.Call(grid:::C_getDisplayList)
 		dl.idx <- grid:::grid.Call(grid:::C_getDLindex)
-		list(dl = dl, dl.idx = dl.idx)
+		# The dummy elements and the class 'recordedplot' make the display list look 
+		# like the GNUR one, which enables its use in the 'evaluate' package
+		# (used in knitr, for instance).
+		pl <- list(list(list("dummyCallX",list(list("dummyCallY")))), dl = dl, dl.idx = dl.idx)
+		class(pl) <- "recordedplot"
+		pl
 	}
 
     # When replaying, the argument DL must be one produced by the overridden function recordPlot.
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
index f076d1a5e64fc162513b8369fe2d4d50108ec9d0..dad8d6b0fd1451bb70cca74236935405efa243d9 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -114,6 +114,9 @@ public final class CPar extends RExternalBuiltinNode {
             case "ylog":
                 // TODO:
                 return RDataFactory.createLogicalVectorFromScalar(false);
+            case "page":
+                // TODO:
+                return RDataFactory.createLogicalVectorFromScalar(false);
             default:
                 if (!FastROptions.IgnoreGraphicsCalls.getBooleanValue()) {
                     throw RError.nyi(RError.NO_CALLER, "C_Par parameter '" + name + "'");
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
index 7cd01653107b217d3acc4cef2fdd5d7d27685406..aaf82384b184450d1e136097cbfa4b44f8dd95e1 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
@@ -1378,6 +1378,9 @@ SEXP Rf_asS4(SEXP x, Rboolean b, int i) {
 
 static SEXP R_tryEvalInternal(SEXP x, SEXP y, int *ErrorOccurred, int silent) {
     TRACE0();
+    if (ErrorOccurred) {
+       *ErrorOccurred = 0;
+    }
     return ((call_R_tryEval) callbacks[R_tryEval_x])(x, y, ErrorOccurred, silent);
 }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
index 2132fb8c92c6c75705e584d404c7253e9709ceac..dd35239badd6926d5752e2991c11e175a68fd6f6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
@@ -170,6 +170,15 @@ public abstract class Bind extends RBaseNode {
                 fromNotNullArgVector = vector;
             }
             if (emptyVectorProfile.profile(vector.getLength() == 0)) {
+                int[] dims = getVectorDimensions(vector);
+                int srcDim1Ind = type == BindType.cbind ? 0 : 1;
+                if (dims != null && dims[srcDim1Ind] > 0) {
+                    // an empty matrix with a positive column, resp. row, dimension cannot be
+                    // ignored
+                    vectors[ind] = vector;
+                    complete &= vector.isComplete();
+                    ind++;
+                }
                 // nothing to do
             } else {
                 vectors[ind] = vector;
@@ -704,6 +713,9 @@ public abstract class Bind extends RBaseNode {
         boolean allRowDimNamesNull = true;
         int dstRowInd = 0;
         for (int i = 0; i < vectors.length; i++) {
+            if (firstDims[i] == 0) {
+                continue;
+            }
             RAbstractVector vec = vectorProfile.profile(vectors[i]);
             if (colDimResultNames == RNull.instance) {
                 // get the first valid names value
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index eb61710d5e4fa123dbfb62a8b509f1215917d241..74c1128cc92dac05607e393db1f8ffcd5ede5c3c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -345,7 +345,7 @@ public abstract class ConnectionFunctions {
             Casts casts = new Casts(TextConnection.class);
             CastsHelper.description(casts);
             casts.arg("text").allowNull().mustBe(stringValue());
-            CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a")))), RError.Message.UNSUPPORTED_MODE);
+            CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a").or(equalTo("wr"))))), RError.Message.UNSUPPORTED_MODE);
             casts.arg("env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
             casts.arg("encoding").asIntegerVector().findFirst().mustNotBeNA();
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
index 2799b9c753295d5c511ebfbe90c87763da88e9bb..0925aa27d1f64b30e5e755d0ab023c34bd2508c1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2015, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -468,9 +468,10 @@ public class GrepFunctions {
                     String value;
                     if (fixed) {
                         if (gsub) {
-                            value = input.replace(pattern, replacement);
+                            value = Pattern.compile(pattern, Pattern.LITERAL).matcher(input).replaceAll(replacement);
                         } else {
                             int ix = input.indexOf(pattern);
+                            replacement = replacement.replace("\\\\", "\\");
                             value = ix < 0 ? input : input.substring(0, ix) + replacement + input.substring(ix + pattern.length());
                         }
                     } else if (perl) {
@@ -535,10 +536,11 @@ public class GrepFunctions {
                     } else {
                         replacement = convertGroups(replacement);
 
+                        Matcher matcher = Pattern.compile(pattern, Pattern.DOTALL).matcher(input);
                         if (gsub) {
-                            value = input.replaceAll(pattern, replacement);
+                            value = matcher.replaceAll(replacement);
                         } else {
-                            value = input.replaceFirst(pattern, replacement);
+                            value = matcher.replaceFirst(replacement);
                         }
                     }
                     result[i] = value;
@@ -958,7 +960,7 @@ public class GrepFunctions {
             if (pattern.length() > 0 && pattern.charAt(0) == '*') {
                 actualPattern = pattern.substring(1);
             }
-            return Pattern.compile(actualPattern, ignoreCase ? Pattern.CASE_INSENSITIVE : 0).matcher(text);
+            return Pattern.compile(actualPattern, Pattern.DOTALL | (ignoreCase ? Pattern.CASE_INSENSITIVE : 0)).matcher(text);
         }
     }
 
@@ -1069,7 +1071,7 @@ public class GrepFunctions {
 
         @TruffleBoundary
         private static Matcher getPatternMatcher(String pattern, String text, boolean ignoreCase) {
-            return Pattern.compile(pattern, ignoreCase ? Pattern.CASE_INSENSITIVE : 0).matcher(text);
+            return Pattern.compile(pattern, Pattern.DOTALL | (ignoreCase ? Pattern.CASE_INSENSITIVE : 0)).matcher(text);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
index bf81f8a617cbe6c47303c4e6c100ffcd7d80de18..953d92bd68749e0dfa19d9e1cfac95283dac0dd9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
@@ -31,8 +31,13 @@ import java.io.File;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.EnumSet;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -59,9 +64,11 @@ import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -286,13 +293,53 @@ public abstract class Parse extends RBuiltinNode.Arg6 {
 
     /**
      * This class aspires to reconstruct the original parse tree through visiting a parsed
-     * expression(s).
-     *
-     * The current implementation does not reconstruct the parse tree completely. Instead, it deals
-     * with symbols only (i.e. a flat tree is produced), which should suffice for templating
-     * packages, such as knitr.
+     * expression(s). The reconstruction cannot be done completely as some information is lost, but
+     * the result should suffice for templating packages, such as knitr.
      */
-    static class ParseDataVisitor extends RSyntaxVisitor<Object> {
+    static class ParseDataVisitor extends RSyntaxVisitor<ParseDataVisitor.OctetNode> {
+
+        static class OctetNode {
+            static final List<OctetNode> NO_CHILDREN = java.util.Collections.emptyList();
+
+            final int id;
+            final int startLine;
+            final int startColumn;
+            final int endLine;
+            final int endColumn;
+            final TokenType tokenType;
+            final String txt;
+            final List<OctetNode> children;
+
+            OctetNode(int id, int startLine, int startColumn, int endLine, int endColumn, TokenType tokenType, String txt, List<OctetNode> children) {
+                this.id = id;
+                this.startLine = startLine;
+                this.startColumn = startColumn;
+                this.endLine = endLine;
+                this.endColumn = endColumn;
+                this.tokenType = tokenType;
+                this.txt = txt;
+                this.children = children;
+            }
+
+            void store(ParseDataVisitor vis, int parentId) {
+                for (OctetNode child : children) {
+                    child.store(vis, id);
+                }
+
+                vis.data.add(startLine);
+                vis.data.add(startColumn);
+                vis.data.add(endLine);
+                vis.data.add(endColumn);
+                vis.data.add(tokenType.terminal ? 1 : 0);
+                vis.data.add(tokenType.code);
+                vis.data.add(id);
+                vis.data.add(parentId);
+
+                vis.tokens.add(tokenType.tokenName);
+                vis.text.add(txt);
+            }
+
+        }
 
         private final RExpression exprs;
 
@@ -322,64 +369,115 @@ public abstract class Parse extends RBuiltinNode.Arg6 {
          * This enum mimics the <code>yytokentype</code> enum from <code>src/main/gram.c</code>.
          */
         enum TokenType {
+            expr(77, false),
+            IF(272, true, "if"),
+            WHILE(274, true, "while"),
+            FOR(270, true, "for"),
+            IN(271, true, "in"),
+            BREAK(276, true, "break"),
+            REPEAT(277, true, "repeat"),
+            NEXT(275, true, "next"),
+            LEFT_ASSIGN(266, true, "<-"),
+            EQ_ASSIGN(267, true, "="),
+            RIGHT_ASSIGN(268, true, "->"),
+            PLUS(43, true, "+", true, true),
+            MINUS(45, true, "-", true, true),
+            MULT(42, true, "*", true, true),
+            DIV(47, true, "/", true, true),
+            POW(94, true, "^", true, true),
+            DOLLAR(36, true, "$", true, true),
+            AT(64, true, "@", true, true),
+            COLON(58, true, ":", true, true),
+            QUESTION(63, true, "?", true, false),
+            TILDE(126, true, "~", true, false),
+            EXCLAMATION(33, true, "!", true, false),
+            GT(278, true, ">"),
+            GE(279, true, ">="),
+            LT(280, true, "<"),
+            LE(281, true, "<="),
+            EQ(282, true, "=="),
+            NE(283, true, "!="),
+            AND(284, true, "&"),
+            AND2(286, true, "&&"),
+            OR(285, true, "|"),
+            OR2(287, true, "||"),
             SYMBOL(263, true),
             SYMBOL_FUNCTION_CALL(296, true),
-            SPECIAL(304, true);
+            SPECIAL(304, true),
+            NULL_CONST(262, true),
+            NUM_CONST(261, true),
+            STR_CONST(260, true),
+            FUNCTION(264, true),
+            LPAREN(40, true, "(", true, false),
+            RPAREN(41, true, ")", true, false);
 
             final int code;
             final boolean terminal;
+            final String symbol;
+            final String tokenName;
+            final boolean infix;
 
-            TokenType(int c, boolean term) {
+            TokenType(int c, boolean term, String symbol, boolean useSymbolAsTokenName, boolean infix) {
                 this.code = c;
                 this.terminal = term;
+                this.symbol = symbol;
+                this.tokenName = useSymbolAsTokenName ? "'" + symbol + "'" : name();
+                this.infix = infix;
             }
-        }
 
-        private void addOctet(RSyntaxElement element, TokenType tokenType, String txt) {
-            addOctet(element.getSourceSection().getStartLine(), element.getSourceSection().getStartColumn(), element.getSourceSection().getEndLine(), element.getSourceSection().getEndColumn(),
-                            tokenType, txt);
-        }
+            TokenType(int c, boolean term, String symbol) {
+                this(c, term, symbol, false, false);
+            }
 
-        private void addOctet(RSymbol symbol) {
-            addOctet(RRuntime.INT_NA, RRuntime.INT_NA, RRuntime.INT_NA, RRuntime.INT_NA, TokenType.SYMBOL, symbol.getName());
-            containsNA = true;
+            TokenType(int c, boolean term) {
+                this(c, term, null, false, false);
+            }
+
+            String getSymbol() {
+                return symbol;
+            }
         }
 
-        private void addOctet(int startLine, int startColumn, int endLine, int endColumn, TokenType tokenType, String txt) {
-            // TODO: adjust the parentId correctly
-            int parentId = 0;
+        private static final Map<String, TokenType> FUNCTION_TOKENS = Arrays.stream(TokenType.values()).filter(tt -> tt.symbol != null).collect(
+                        Collectors.toMap(TokenType::getSymbol, Function.identity()));
 
-            data.add(startLine);
-            data.add(startColumn);
-            data.add(endLine);
-            data.add(endColumn);
-            data.add(tokenType.terminal ? 1 : 0);
-            data.add(tokenType.code);
-            data.add(idCounter);
-            data.add(parentId);
+        private OctetNode newOctet(RSyntaxElement element, TokenType tokenType, String txt, List<OctetNode> children) {
+            return newOctet(element.getSourceSection().getStartLine(), element.getSourceSection().getStartColumn(), element.getSourceSection().getEndLine(), element.getSourceSection().getEndColumn(),
+                            tokenType, txt, children);
+        }
 
-            tokens.add(tokenType.name());
-            text.add(txt);
+        private OctetNode newOctet(RSymbol symbol, List<OctetNode> children) {
+            OctetNode octet = newOctet(RRuntime.INT_NA, RRuntime.INT_NA, RRuntime.INT_NA, RRuntime.INT_NA, TokenType.SYMBOL, symbol.getName(), children);
+            containsNA = true;
+            return octet;
+        }
 
-            idCounter++;
+        private OctetNode newOctet(int startLine, int startColumn, int endLine, int endColumn, TokenType tokenType, String txt, List<OctetNode> children) {
+            return new OctetNode(++idCounter, startLine, startColumn, endLine, endColumn, tokenType, txt, children);
         }
 
         @TruffleBoundary
         RIntVector getParseData() {
             int exprLen = exprs.getLength();
+            List<OctetNode> rootOctets = new ArrayList<>();
             for (int i = 0; i < exprLen; i++) {
                 Object x = exprs.getDataAt(i);
                 if (x instanceof RLanguage) {
                     RBaseNode rep = ((RLanguage) x).getRep();
                     assert rep instanceof RSyntaxElement;
-                    accept((RSyntaxElement) rep);
+                    rootOctets.add(accept((RSyntaxElement) rep));
                 } else if (x instanceof RSymbol) {
-                    addOctet((RSymbol) x);
+                    rootOctets.add(newOctet((RSymbol) x, OctetNode.NO_CHILDREN));
                 } else {
                     // TODO: primitives
                 }
             }
 
+            // Store the octet tree to the corresponding vectors
+            for (OctetNode rootOctet : rootOctets) {
+                rootOctet.store(this, 0);
+            }
+
             int[] dataArray = new int[data.size()];
             for (int i = 0; i < dataArray.length; i++) {
                 dataArray[i] = data.get(i);
@@ -396,56 +494,98 @@ public abstract class Parse extends RBuiltinNode.Arg6 {
                 tokensArray[i] = tokens.get(i);
             }
 
-            parseData.setAttr("text", RDataFactory.createStringVector(textArray, true));
             parseData.setAttr("tokens", RDataFactory.createStringVector(tokensArray, true));
+            parseData.setAttr("text", RDataFactory.createStringVector(textArray, true));
             parseData.setClassAttr(RDataFactory.createStringVector("parseData"));
             parseData.setDimensions(new int[]{8, idCounter});
+
             return parseData;
         }
 
         @Override
-        protected Object visit(RSyntaxCall element) {
+        protected OctetNode visit(RSyntaxCall element) {
+            LinkedList<OctetNode> children = new LinkedList<>();
+
             RSyntaxElement lhs = element.getSyntaxLHS();
-            if (lhs instanceof RSyntaxLookup) {
+            if (lhs instanceof RSyntaxCall) {
+                children.add(accept(lhs));
+                children.addAll(visitArguments(element, 0, Integer.MAX_VALUE));
+            } else if (lhs instanceof RSyntaxLookup) {
                 String symbol = ((RSyntaxLookup) lhs).getIdentifier();
                 RDeparse.Func func = RDeparse.getFunc(symbol);
-                if (func == null) {
-                    addOctet(element, TokenType.SYMBOL_FUNCTION_CALL, symbol);
+                TokenType tt = null;
+                if (func != null) {
+                    tt = FUNCTION_TOKENS.get(symbol);
+                }
+                if (tt == null) {
+                    tt = TokenType.SYMBOL_FUNCTION_CALL;
+                }
+                if (tt.infix) {
+                    children.addAll(visitArguments(element, 0, 1));
+                    children.add(newOctet(lhs, tt, symbol, OctetNode.NO_CHILDREN));
+                    children.addAll(visitArguments(element, 1, 2));
+                } else {
+                    children.add(newOctet(lhs, tt, symbol, OctetNode.NO_CHILDREN));
+                    children.addAll(visitArguments(element, 0, Integer.MAX_VALUE));
+                }
+                if (tt == TokenType.LPAREN) {
+                    OctetNode lastChild = children.getLast();
+                    children.add(new OctetNode(++idCounter, lastChild.endLine, lastChild.endColumn + 1, lastChild.endLine, lastChild.endColumn + 1, TokenType.RPAREN, ")", OctetNode.NO_CHILDREN));
                 }
             }
 
+            return newOctet(element, TokenType.expr, "", children);
+        }
+
+        private List<OctetNode> visitArguments(RSyntaxCall element, int from, int to) {
+            List<OctetNode> children = new ArrayList<>();
             RSyntaxElement[] args = element.getSyntaxArguments();
-            for (int i = 0; i < args.length; i++) {
-                accept(args[i]);
+            for (int i = from; i < Math.min(args.length, to); i++) {
+                OctetNode argOctet = accept(args[i]);
+                if (argOctet != null) {
+                    children.add(argOctet);
+                }
             }
-
-            return null;
+            return children;
         }
 
         @Override
-        protected Object visit(RSyntaxConstant element) {
-            // TODO: recognize constants
-            return null;
+        protected OctetNode visit(RSyntaxConstant element) {
+            TokenType tt;
+            Object value = element.getValue();
+            if (value == RNull.instance) {
+                tt = TokenType.NULL_CONST;
+            } else if (value instanceof Number) {
+                tt = TokenType.NUM_CONST;
+            } else if (value instanceof String) {
+                tt = TokenType.STR_CONST;
+            } else if (value == REmpty.instance || value == RMissing.instance) {
+                return null;    // ignored
+            } else {
+                throw RInternalError.shouldNotReachHere("Unknown RSyntaxConstant in ParseDataVisitor " + (value == null ? "null" : value.getClass().getSimpleName()));
+            }
+
+            OctetNode constChild = newOctet(element, tt, element.getSourceSection().getCharacters().toString(), OctetNode.NO_CHILDREN);
+            return newOctet(element, TokenType.expr, "", java.util.Collections.singletonList(constChild));
         }
 
         @Override
-        protected Object visit(RSyntaxLookup element) {
+        protected OctetNode visit(RSyntaxLookup element) {
             String symbol = element.getIdentifier();
-            addOctet(element, TokenType.SYMBOL, symbol);
-            return null;
+            return newOctet(element, TokenType.SYMBOL, symbol, OctetNode.NO_CHILDREN);
         }
 
         @Override
-        protected Object visit(RSyntaxFunction element) {
+        protected OctetNode visit(RSyntaxFunction element) {
+            List<OctetNode> children = new ArrayList<>();
             for (RSyntaxElement arg : element.getSyntaxArgumentDefaults()) {
                 if (arg != null) {
-                    accept(arg);
+                    children.add(accept(arg));
                 }
             }
 
-            accept(element.getSyntaxBody());
-
-            return null;
+            children.add(accept(element.getSyntaxBody()));
+            return newOctet(element, TokenType.FUNCTION, "function", children);
         }
 
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
index ebd98fae25d107759455ac237a1670fb0236b499..52c05fa2eda814358fd124fc27d01cb885fcb343 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
@@ -47,6 +47,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -175,6 +176,22 @@ public abstract class Sprintf extends RBuiltinNode.Arg2 {
         return RDataFactory.createStringVector(r, RDataFactory.COMPLETE_VECTOR);
     }
 
+    @Specialization(guards = "fmtLengthOne(fmt)")
+    @TruffleBoundary
+    protected RStringVector sprintf(RAbstractStringVector fmt, RAbstractLogicalVector x) {
+        return sprintf(fmt.getDataAt(0), x);
+    }
+
+    @Specialization
+    @TruffleBoundary
+    protected RStringVector sprintf(String fmt, RAbstractLogicalVector x) {
+        String[] r = new String[x.getLength()];
+        for (int k = 0; k < r.length; k++) {
+            r[k] = format(fmt, x.getDataAt(k));
+        }
+        return RDataFactory.createStringVector(r, RDataFactory.COMPLETE_VECTOR);
+    }
+
     @Specialization(guards = "fmtLengthOne(fmt)")
     @TruffleBoundary
     protected RStringVector sprintf(RAbstractStringVector fmt, RAbstractStringVector x) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index d60b9779df596070a35d174b733b3aeecdf37d55..5bbff2e39bac2b7d38b8bdcbdbac458a4326b703 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -222,7 +222,7 @@ public class ConnectionSupport {
     enum AbstractOpenMode {
         Lazy(new String[]{""}, true, true, true),
         Read(new String[]{"r", "rt"}, true, true, false),
-        Write(new String[]{"w", "wt"}, true, false, true),
+        Write(new String[]{"w", "wt", "wr"}, true, false, true),
         Append(new String[]{"a", "at"}, true, false, true),
         ReadBinary(new String[]{"rb"}, false, true, false),
         WriteBinary(new String[]{"wb"}, false, false, true),
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index d606d1ca45d80460b2e8e0e214d2926d37694371..8ad6b28bbead4b239ae670cd2e29eabd6202b81f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -13755,6 +13755,15 @@ c    2
 b    1
 c    2
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testCbind#
+#{ cbind(integer(0), NULL, matrix(integer(0),0,1)) }
+     [,1] [,2] [,3]
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testCbind#
+#{ cbind(integer(0), NULL, matrix(integer(0),1,0)) }
+
+[1,]
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testCbind#
 #{ cbind(list(1,2), TRUE, "a") }
      [,1] [,2] [,3]
@@ -29082,6 +29091,14 @@ integer(0)
 #{ .Internal(grepl("7", 7, F, F, F, F, F, F)) }
 Error: invalid 'text' argument
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grepl.testGrepl#
+#{ .Internal(grepl('.+X', 'a<<<NEWLINE>>>Xb', F, F, F, F, F, F)) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grepl.testGrepl#
+#{ .Internal(grepl('.+X', 'a<<<NEWLINE>>>Xb', F, F, T, F, F, F)) }
+[1] FALSE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_grepl.testGrepl#
 #{ .Internal(grepl(7, "7", F, F, F, F, F, F)) }
 Error: invalid 'pattern' argument
@@ -29216,6 +29233,18 @@ In gsub("a", "aa", "prAgue alley", fixed = TRUE, ignore.case = TRUE) :
 #{ gsub("h","", c("hello", "hi", "bye"), fixed=TRUE) }
 [1] "ello" "i"    "bye"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub#
+#{ gsub('.*X', '', 'a<<<NEWLINE>>>Xb', perl = FALSE) }
+[1] "b"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub#
+#{ gsub('.*X', '', 'a<<<NEWLINE>>>Xb', perl = TRUE) }
+[1] "a\nb"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub#
+#{ gsub('~', '\\\\X', '~') }
+[1] "\\X"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub#
 #{ gsub(pattern = 'a*', replacement = 'x', x = 'ÄaaaaÄ', perl = TRUE) }
 [1] "xÄxÄx"
@@ -48241,39 +48270,56 @@ expression(NULL)
 expression(expr1)
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testParseData#
-#if (!any(R.version$engine == "FastR")) { structure(c(1L, 1L, 1L, 1L, 1L, 263L, 0L, 0L), text = "x", tokens = "SYMBOL", class = "parseData", .Dim = c(8L, 1L)) } else { p <- parse(text = 'x = 1', keep.source = TRUE); attr(p, 'srcfile')$parseData }
-     [,1]
-[1,]    1
-[2,]    1
-[3,]    1
-[4,]    1
-[5,]    1
-[6,]  263
-[7,]    0
-[8,]    0
-attr(,"text")
-[1] "x"
+#if (!any(R.version$engine == "FastR")) { structure(c(1L, 3L, 1L, 3L, 1L, 267L, 1L, 5L, 1L, 1L, 1L, 1L, 1L, 263L, 2L, 5L, 1L, 5L, 1L, 5L, 1L, 261L, 3L, 4L, 1L, 5L, 1L, 5L, 0L, 77L, 4L, 5L, 1L, 1L, 1L, 5L, 0L, 77L, 5L, 0L), tokens = c("EQ_ASSIGN", "SYMBOL", "NUM_CONST", "expr", "expr"), text = c("=", "x", "1", "", ""), class = "parseData", .Dim = c(8L, 5L)) } else { p <- parse(text = 'x = 1', keep.source = TRUE); attr(p, 'srcfile')$parseData }
+     [,1] [,2] [,3] [,4] [,5]
+[1,]    1    1    1    1    1
+[2,]    3    1    5    5    1
+[3,]    1    1    1    1    1
+[4,]    3    1    5    5    5
+[5,]    1    1    1    0    0
+[6,]  267  263  261   77   77
+[7,]    1    2    3    4    5
+[8,]    5    5    4    5    0
 attr(,"tokens")
-[1] "SYMBOL"
+[1] "EQ_ASSIGN" "SYMBOL"    "NUM_CONST" "expr"      "expr"
+attr(,"text")
+[1] "=" "x" "1" ""  ""
 attr(,"class")
 [1] "parseData"
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testParseData#
-#if (!any(R.version$engine == "FastR")) { structure(c(1L, 1L, 1L, 1L, 1L, 263L, 0L, 0L, 1L, 5L, 1L, 5L, 1L, 263L, 1L, 0L, 1L, 12L, 1L, 28L, 1L, 296L, 2L, 0L, 1L, 27L, 1L, 27L, 1L, 263L, 3L, 0L, 1L, 31L, 1L, 32L, 1L, 263L, 4L, 0L, 1L, 51L, 1L, 51L, 1L, 263L, 5L, 0L), text = c("x", "x", "rnorm", "z", "f2", "a"), tokens = c("SYMBOL", "SYMBOL", "SYMBOL_FUNCTION_CALL", "SYMBOL", "SYMBOL", "SYMBOL"), class = "parseData", .Dim = c(8L, 6L)) } else { p <- parse(text = 'x = x + 1; rnorm(1, std = z); f2 <- function(a=1) a', keep.source = TRUE); attr(p, 'srcfile')$parseData }
-     [,1] [,2] [,3] [,4] [,5] [,6]
-[1,]    1    1    1    1    1    1
-[2,]    1    5   12   27   31   51
-[3,]    1    1    1    1    1    1
-[4,]    1    5   28   27   32   51
-[5,]    1    1    1    1    1    1
-[6,]  263  263  296  263  263  263
-[7,]    0    1    2    3    4    5
-[8,]    0    0    0    0    0    0
-attr(,"text")
-[1] "x"     "x"     "rnorm" "z"     "f2"    "a"
+#if (!any(R.version$engine == "FastR")) { structure(c(1L, 3L, 1L, 3L, 1L, 267L, 1L, 8L, 1L, 1L, 1L, 1L, 1L, 263L, 2L, 8L, 1L, 5L, 1L, 5L, 1L, 263L, 3L, 7L, 1L, 7L, 1L, 7L, 1L, 43L, 4L, 7L, 1L, 9L, 1L, 9L, 1L, 261L, 5L, 6L, 1L, 9L, 1L, 9L, 0L, 77L, 6L, 7L, 1L, 5L, 1L, 9L, 0L, 77L, 7L, 8L, 1L, 1L, 1L, 9L, 0L, 77L, 8L, 0L, 1L, 12L, 1L, 16L, 1L, 296L, 9L, 13L, 1L, 18L, 1L, 18L, 1L, 261L, 10L, 11L, 1L, 18L, 1L, 18L, 0L, 77L, 11L, 13L, 1L, 27L, 1L, 27L, 1L, 263L, 12L, 13L, 1L, 12L, 1L, 28L, 0L, 77L, 13L, 0L, 1L, 34L, 1L, 35L, 1L, 266L, 14L, 20L, 1L, 31L, 1L, 32L, 1L, 263L, 15L, 20L, 1L, 48L, 1L, 48L, 1L, 261L, 16L, 17L, 1L, 48L, 1L, 48L, 0L, 77L, 17L, 19L, 1L, 51L, 1L, 51L, 1L, 263L, 18L, 19L, 1L, 37L, 1L, 51L, 1L, 264L, 19L, 20L, 1L, 31L, 1L, 51L, 0L, 77L, 20L, 0L), tokens = c("EQ_ASSIGN", "SYMBOL", "SYMBOL", "'+'", "NUM_CONST", "expr", "expr", "expr", "SYMBOL_FUNCTION_CALL", "NUM_CONST", "expr", "SYMBOL", "expr", "LEFT_ASSIGN", "SYMBOL", "NUM_CONST", "expr", "SYMBOL", "FUNCTION", "expr"), text = c("=", "x", "x", "+", "1", "", "", "", "rnorm", "1", "", "z", "", "<-", "f2", "1", "", "a", "function", ""), class = "parseData", .Dim = c(8L, 20L)) } else { p <- parse(text = 'x = x + 1; rnorm(1, std = z); f2 <- function(a=1) a', keep.source = TRUE); attr(p, 'srcfile')$parseData }
+     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
+[1,]    1    1    1    1    1    1    1    1    1     1     1     1     1     1
+[2,]    3    1    5    7    9    9    5    1   12    18    18    27    12    34
+[3,]    1    1    1    1    1    1    1    1    1     1     1     1     1     1
+[4,]    3    1    5    7    9    9    9    9   16    18    18    27    28    35
+[5,]    1    1    1    1    1    0    0    0    1     1     0     1     0     1
+[6,]  267  263  263   43  261   77   77   77  296   261    77   263    77   266
+[7,]    1    2    3    4    5    6    7    8    9    10    11    12    13    14
+[8,]    8    8    7    7    6    7    8    0   13    11    13    13     0    20
+     [,15] [,16] [,17] [,18] [,19] [,20]
+[1,]     1     1     1     1     1     1
+[2,]    31    48    48    51    37    31
+[3,]     1     1     1     1     1     1
+[4,]    32    48    48    51    51    51
+[5,]     1     1     0     1     1     0
+[6,]   263   261    77   263   264    77
+[7,]    15    16    17    18    19    20
+[8,]    20    17    19    19    20     0
 attr(,"tokens")
-[1] "SYMBOL"               "SYMBOL"               "SYMBOL_FUNCTION_CALL"
-[4] "SYMBOL"               "SYMBOL"               "SYMBOL"
+ [1] "EQ_ASSIGN"            "SYMBOL"               "SYMBOL"
+ [4] "'+'"                  "NUM_CONST"            "expr"
+ [7] "expr"                 "expr"                 "SYMBOL_FUNCTION_CALL"
+[10] "NUM_CONST"            "expr"                 "SYMBOL"
+[13] "expr"                 "LEFT_ASSIGN"          "SYMBOL"
+[16] "NUM_CONST"            "expr"                 "SYMBOL"
+[19] "FUNCTION"             "expr"
+attr(,"text")
+ [1] "="        "x"        "x"        "+"        "1"        ""
+ [7] ""         ""         "rnorm"    "1"        ""         "z"
+[13] ""         "<-"       "f2"       "1"        ""         "a"
+[19] "function" ""
 attr(,"class")
 [1] "parseData"
 
@@ -51770,6 +51816,22 @@ b 3 4
      b c
 [1,] 1 2
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testRbind#
+#{ rbind(integer(0), NULL, matrix(integer(0),0,1)) }
+     [,1]
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testRbind#
+#{ rbind(integer(0), NULL, matrix(integer(0),1,0)) }
+
+[1,]
+[2,]
+[3,]
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testRbind#
+#{ rbind(logical(0),matrix(character(0),0,0)) }
+
+[1,]
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testRbind#
 #{ rbind(matrix(1:4, nrow=2), z=c(m=8,n=9)) }
   m n
@@ -72120,6 +72182,10 @@ Error: invalid 'pattern' argument
 #{ sub('^[[:space:]]*(.*)', '\\1', 'R (>= 3.0.3)') }
 [1] "R (>= 3.0.3)"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sub.testSub#
+#{ sub('~', '\\\\X', '~') }
+[1] "\\X"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sub.testSub#
 #{ sub(pattern = 'a*', replacement = 'x', x = 'ÄaaaaÄ', perl = TRUE) }
 [1] "xÄaaaaÄ"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
index 81f4608d39ae4e2164a607bf9846dc2c753c772c..3f40e8a74cc168c016e666380a75bcd749cdfb79 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
@@ -91,6 +91,9 @@ public class TestBuiltin_cbind extends TestBase {
         assertEval("{ cbind(2,3, c(1,1,1)) }");
         assertEval("{ cbind(2.1:10,32.2) }");
 
+        assertEval("{ cbind(integer(0), NULL, matrix(integer(0),0,1)) }");
+        assertEval("{ cbind(integer(0), NULL, matrix(integer(0),1,0)) }");
+
         assertEval("{ x<-list(a=7, b=NULL, c=42); y<-as.data.frame(do.call(cbind,x)); y }");
 
         // Note: CachedExtractVectorNode replaces vector 'a', 'b', with a scalar 'b', which caused
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java
index 1e2e74500566da9a3ca4116c2d461072c978c3dc..c2875465a19c225ab16d28dd1e4df50f45b37b33 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grepl.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -79,5 +79,9 @@ public class TestBuiltin_grepl extends TestBase {
         assertEval("{ .Internal(grepl(7, \"7\", F, F, F, F, F, F)) }");
         assertEval("{ .Internal(grepl(character(), \"7\", F, F, F, F, F, F)) }");
         assertEval("{ .Internal(grepl(\"7\", 7, F, F, F, F, F, F)) }");
+        // the dot does not match the new line in a non-Perl regexp
+        assertEval("{ .Internal(grepl('.+X', 'a\nXb', F, F, F, F, F, F)) }");
+        // the dot matches the new line in a Perl regexp
+        assertEval("{ .Internal(grepl('.+X', 'a\nXb', F, F, T, F, F, F)) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java
index 05e8cbecd2e5d7d4cf71e6785fb3ed0811b8eb77..69f01ee11f09832b4337134c45d2ba7970fa3cb5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -200,6 +200,13 @@ public class TestBuiltin_gsub extends TestBase {
         assertEval("{ gsub(pattern = 'a*', replacement = 'x', x = 'ÄaÄ', perl = TRUE) }");
         assertEval("{ gsub(pattern = 'a*', replacement = 'x', x = 'ÄaaaaÄ', perl = TRUE) }");
 
+        // the dot does not match the new line in a non-Perl regexp
+        assertEval("{ gsub('.*X', '', 'a\nXb', perl = FALSE) }");
+        // the dot matches the new line in a Perl regexp
+        assertEval("{ gsub('.*X', '', 'a\nXb', perl = TRUE) }");
+
+        assertEval("{ gsub('~', '\\\\\\\\X', '~') }");
+
         // Expected output: [1] "xaxbx"
         // FastR output: [1] "axxxxxb"
         assertEval(Ignored.ImplementationError, "{ gsub(pattern = 'Ä*', replacement = 'x', x = 'aÄÄÄÄÄb', perl = TRUE) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java
index 4d9589c26e31486799cbcec15d79ccc81d008062..9dbac73a69d7c5abae093953f1b1373f81068ec7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java
@@ -70,9 +70,9 @@ public class TestBuiltin_parse extends TestBase {
     @Test
     public void testParseData() {
         assertEvalFastR("p <- parse(text = 'x = 1', keep.source = TRUE); attr(p, 'srcfile')$parseData",
-                        "structure(c(1L, 1L, 1L, 1L, 1L, 263L, 0L, 0L), text = \"x\", tokens = \"SYMBOL\", class = \"parseData\", .Dim = c(8L, 1L))");
+                        "structure(c(1L, 3L, 1L, 3L, 1L, 267L, 1L, 5L, 1L, 1L, 1L, 1L, 1L, 263L, 2L, 5L, 1L, 5L, 1L, 5L, 1L, 261L, 3L, 4L, 1L, 5L, 1L, 5L, 0L, 77L, 4L, 5L, 1L, 1L, 1L, 5L, 0L, 77L, 5L, 0L), tokens = c(\"EQ_ASSIGN\", \"SYMBOL\", \"NUM_CONST\", \"expr\", \"expr\"), text = c(\"=\", \"x\", \"1\", \"\", \"\"), class = \"parseData\", .Dim = c(8L, 5L))");
         assertEvalFastR("p <- parse(text = 'x = x + 1; rnorm(1, std = z); f2 <- function(a=1) a', keep.source = TRUE); attr(p, 'srcfile')$parseData",
-                        "structure(c(1L, 1L, 1L, 1L, 1L, 263L, 0L, 0L, 1L, 5L, 1L, 5L, 1L, 263L, 1L, 0L, 1L, 12L, 1L, 28L, 1L, 296L, 2L, 0L, 1L, 27L, 1L, 27L, 1L, 263L, 3L, 0L, 1L, 31L, 1L, 32L, 1L, 263L, 4L, 0L, 1L, 51L, 1L, 51L, 1L, 263L, 5L, 0L), text = c(\"x\", \"x\", \"rnorm\", \"z\", \"f2\", \"a\"), tokens = c(\"SYMBOL\", \"SYMBOL\", \"SYMBOL_FUNCTION_CALL\", \"SYMBOL\", \"SYMBOL\", \"SYMBOL\"), class = \"parseData\", .Dim = c(8L, 6L))");
+                        "structure(c(1L, 3L, 1L, 3L, 1L, 267L, 1L, 8L, 1L, 1L, 1L, 1L, 1L, 263L, 2L, 8L, 1L, 5L, 1L, 5L, 1L, 263L, 3L, 7L, 1L, 7L, 1L, 7L, 1L, 43L, 4L, 7L, 1L, 9L, 1L, 9L, 1L, 261L, 5L, 6L, 1L, 9L, 1L, 9L, 0L, 77L, 6L, 7L, 1L, 5L, 1L, 9L, 0L, 77L, 7L, 8L, 1L, 1L, 1L, 9L, 0L, 77L, 8L, 0L, 1L, 12L, 1L, 16L, 1L, 296L, 9L, 13L, 1L, 18L, 1L, 18L, 1L, 261L, 10L, 11L, 1L, 18L, 1L, 18L, 0L, 77L, 11L, 13L, 1L, 27L, 1L, 27L, 1L, 263L, 12L, 13L, 1L, 12L, 1L, 28L, 0L, 77L, 13L, 0L, 1L, 34L, 1L, 35L, 1L, 266L, 14L, 20L, 1L, 31L, 1L, 32L, 1L, 263L, 15L, 20L, 1L, 48L, 1L, 48L, 1L, 261L, 16L, 17L, 1L, 48L, 1L, 48L, 0L, 77L, 17L, 19L, 1L, 51L, 1L, 51L, 1L, 263L, 18L, 19L, 1L, 37L, 1L, 51L, 1L, 264L, 19L, 20L, 1L, 31L, 1L, 51L, 0L, 77L, 20L, 0L), tokens = c(\"EQ_ASSIGN\", \"SYMBOL\", \"SYMBOL\", \"'+'\", \"NUM_CONST\", \"expr\", \"expr\", \"expr\", \"SYMBOL_FUNCTION_CALL\", \"NUM_CONST\", \"expr\", \"SYMBOL\", \"expr\", \"LEFT_ASSIGN\", \"SYMBOL\", \"NUM_CONST\", \"expr\", \"SYMBOL\", \"FUNCTION\", \"expr\"), text = c(\"=\", \"x\", \"x\", \"+\", \"1\", \"\", \"\", \"\", \"rnorm\", \"1\", \"\", \"z\", \"\", \"<-\", \"f2\", \"1\", \"\", \"a\", \"function\", \"\"), class = \"parseData\", .Dim = c(8L, 20L))");
     }
 
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java
index ccf9cc0a6af505c946cd22616e20791a9619997e..eb80b28132dd018ce1f2d1248d2db16e95352ccc 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -66,6 +66,10 @@ public class TestBuiltin_rbind extends TestBase {
         assertEval("{ rbind(matrix(1:4, nrow=2, dimnames=list(NULL, c('x', 'y'))), c(m=8,n=9)) }");
         assertEval("{ rbind(matrix(1:4, nrow=2), z=c(m=8,n=9)) }");
 
+        assertEval("{ rbind(logical(0),matrix(character(0),0,0)) }");
+        assertEval("{ rbind(integer(0), NULL, matrix(integer(0),0,1)) }");
+        assertEval("{ rbind(integer(0), NULL, matrix(integer(0),1,0)) }");
+
         assertEval("{ info <- c(\"print\", \"AES\", \"print.AES\") ; ns <- integer(0) ; rbind(info, ns) }");
 
         assertEval("{ x<-list(a=7, b=NULL, c=42); y<-as.data.frame(do.call(rbind,x)); y }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java
index 79ac5f153443783fb40127cbed696bd8c954de66..8832836c9b691b4e131b3428295846c9e52b8c71 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -150,6 +150,8 @@ public class TestBuiltin_sub extends TestBase {
         assertEval("{ .Internal(sub(\"7\", character(), \"7\", F, F, F, F)) }");
         assertEval("{ .Internal(sub(\"7\", \"42\", 7, F, F, F, F)) }");
 
+        assertEval("{ sub('~', '\\\\\\\\X', '~') }");
+
         assertEval("{ sub('\\\\s*$', '', 'Ä', perl=TRUE) }");
 
         assertEval("{ sub(pattern = 'a*', replacement = 'x', x = 'ÄaÄ', perl = TRUE) }");