diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ESoftVersionResult.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ESoftVersionResult.java new file mode 100644 index 0000000000000000000000000000000000000000..a3e8e86c2f81530097ea840db51d5df9eb2b62fe --- /dev/null +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ESoftVersionResult.java @@ -0,0 +1,46 @@ +/* + * 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.ffi.impl.interop.base; + +import java.util.HashMap; +import java.util.Map; + +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.r.runtime.data.RTruffleObject; + +public final class ESoftVersionResult implements RTruffleObject { + private final Map<String, String> paths = new HashMap<>(); + + public void putVersion(String libName, String version) { + paths.put(libName, version); + } + + public Map<String, String> getVersions() { + return paths; + } + + @Override + public ForeignAccess getForeignAccess() { + return ESoftVersionResultMRForeign.ACCESS; + } +} diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ESoftVersionResultMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ESoftVersionResultMR.java new file mode 100644 index 0000000000000000000000000000000000000000..fc958b7b30ff2f235e3ff12999bb024c86b95d03 --- /dev/null +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ESoftVersionResultMR.java @@ -0,0 +1,58 @@ +/* + * 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.ffi.impl.interop.base; + +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.MessageResolution; +import com.oracle.truffle.api.interop.Resolve; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; + +@MessageResolution(receiverType = ESoftVersionResult.class) +public class ESoftVersionResultMR { + @CanResolve + public abstract static class ESoftVersionResultCallbackCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof ESoftVersionResult; + } + } + + @Resolve(message = "IS_EXECUTABLE") + public abstract static class ESoftVersionResultIsExecutable extends Node { + protected Object access(@SuppressWarnings("unused") ESoftVersionResult receiver) { + return true; + } + } + + @Resolve(message = "EXECUTE") + public abstract static class ESoftVersionResultCallbackExecute extends Node { + protected Object access(ESoftVersionResult receiver, Object[] arguments) { + if (arguments.length == 2) { + receiver.putVersion("zlib", arguments[0].toString()); + receiver.putVersion("PCRE", arguments[1].toString()); + } + return receiver; + } + } +} diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Base.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Base.java index bfe843a1f8b43ddc6a4aa65973d4976189fe8bfd..0f61b48a678c82be4291124847ffa9a88b9879e0 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Base.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Base.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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,8 +24,10 @@ package com.oracle.truffle.r.ffi.impl.llvm; import java.io.IOException; import java.util.ArrayList; +import java.util.Map; import com.oracle.truffle.r.ffi.impl.interop.NativeCharArray; +import com.oracle.truffle.r.ffi.impl.interop.base.ESoftVersionResult; import com.oracle.truffle.r.ffi.impl.interop.base.GlobResult; import com.oracle.truffle.r.ffi.impl.interop.base.ReadlinkResult; import com.oracle.truffle.r.ffi.impl.interop.base.StrtolResult; @@ -224,6 +226,22 @@ public class TruffleLLVM_Base implements BaseRFFI { } } + private static class TruffleLLVM_ESoftVersionNode extends TruffleLLVM_DownCallNode implements ESoftVersionNode { + + @Override + protected NativeFunction getFunction() { + return NativeFunction.eSoftVersion; + } + + @Override + public Map<String, String> eSoftVersion() { + ESoftVersionResult result = new ESoftVersionResult(); + call(result); + return result.getVersions(); + } + + } + @Override public GetpidNode createGetpidNode() { return new TruffleLLVM_GetpidNode(); @@ -273,4 +291,9 @@ public class TruffleLLVM_Base implements BaseRFFI { public GlobNode createGlobNode() { return new TruffleLLVM_GlobNode(); } + + @Override + public ESoftVersionNode createESoftVersionNode() { + return new TruffleLLVM_ESoftVersionNode(); + } } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_Base.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_Base.java index 185cf45f55a9247a410794dc1681ff6132ccc3a0..a1280ebd9b70b973f6ccb6d4c1d772b1de1350d6 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_Base.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_Base.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 @@ -200,4 +200,9 @@ public class Managed_Base implements BaseRFFI { public GlobNode createGlobNode() { return null; } + + @Override + public ESoftVersionNode createESoftVersionNode() { + return null; + } } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Base.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Base.java index 7628b86c76a65db335336d11c6a3e2e1022c5506..7d8f8a9a8a5300fe18ec2e0fd0fbff81a0c044bc 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Base.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Base.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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,9 +24,11 @@ package com.oracle.truffle.r.ffi.impl.nfi; import java.io.IOException; import java.util.ArrayList; +import java.util.Map; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.r.ffi.impl.interop.base.ESoftVersionResult; import com.oracle.truffle.r.ffi.impl.interop.base.GlobResult; import com.oracle.truffle.r.ffi.impl.interop.base.ReadlinkResult; import com.oracle.truffle.r.ffi.impl.interop.base.StrtolResult; @@ -214,6 +216,22 @@ public class TruffleNFI_Base implements BaseRFFI { } } + private static class TruffleNFI_ESoftVersionNode extends TruffleNFI_DownCallNode implements ESoftVersionNode { + + @Override + protected NativeFunction getFunction() { + return NativeFunction.eSoftVersion; + } + + @Override + public Map<String, String> eSoftVersion() { + ESoftVersionResult result = new ESoftVersionResult(); + call(result); + return result.getVersions(); + } + + } + @Override public GetpidNode createGetpidNode() { return new TruffleNFI_GetpidNode(); @@ -263,4 +281,10 @@ public class TruffleNFI_Base implements BaseRFFI { public GlobNode createGlobNode() { return new TruffleNFI_GlobNode(); } + + @Override + public ESoftVersionNode createESoftVersionNode() { + return new TruffleNFI_ESoftVersionNode(); + } + } diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/base_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_common/base_rffi.c index 25215c77f151d7cdeefe188bee891b245ff1d96a..17c0363e6cc98c9bee698420babe26fc6d70f154 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_common/base_rffi.c +++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/base_rffi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -107,3 +107,18 @@ void call_base_strtol(void (*call_setresult)(long result, int cerrno), char *s, long rc = strtol(s, NULL, base); call_setresult(rc, errno); } + +#include <zlib.h> +#include <bzlib.h> +#ifdef HAVE_PCRE_PCRE_H +# include <pcre/pcre.h> +#else +# include <pcre.h> +#endif +void call_base_eSoftVersion(void (*call_eSoftVersion_setfields)(char *zlibVersion, char *pcreVersion)) { + + char sZlibVersion[256], sPcreVersion[256]; + snprintf(sZlibVersion, 256, "%s", zlibVersion()); + snprintf(sPcreVersion, 256, "%s", pcre_version()); + call_eSoftVersion_setfields(sZlibVersion, sPcreVersion); +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java index 0a3cf0343b971211a7bca1d18d0ce6dcb06e4715..a2bd261a010db0f0de92690e60863f29b8e8df5a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java @@ -40,6 +40,7 @@ import com.oracle.truffle.r.nodes.builtin.base.ConnectionFunctions.SockSelect; import com.oracle.truffle.r.nodes.builtin.base.ConnectionFunctionsFactory.SockSelectNodeGen; import com.oracle.truffle.r.nodes.builtin.base.DebugFunctions.FastRSetBreakpoint; import com.oracle.truffle.r.nodes.builtin.base.DebugFunctionsFactory.FastRSetBreakpointNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.VersionFunctions.RVersion; import com.oracle.truffle.r.nodes.builtin.base.fastpaths.AssignFastPathNodeGen; import com.oracle.truffle.r.nodes.builtin.base.fastpaths.ExistsFastPathNodeGen; import com.oracle.truffle.r.nodes.builtin.base.fastpaths.GetFastPathNodeGen; @@ -395,6 +396,7 @@ public class BasePackage extends RBuiltinPackage { add(DynLoadFunctions.GetLoadedDLLs.class, DynLoadFunctionsFactory.GetLoadedDLLsNodeGen::create); add(DynLoadFunctions.GetSymbolInfo.class, DynLoadFunctionsFactory.GetSymbolInfoNodeGen::create); add(DynLoadFunctions.IsLoaded.class, DynLoadFunctionsFactory.IsLoadedNodeGen::create); + add(VersionFunctions.ExtSoftVersion.class, VersionFunctionsFactory.ExtSoftVersionNodeGen::create); add(EncodeString.class, EncodeStringNodeGen::create); add(EncodingFunctions.Encoding.class, EncodingFunctionsFactory.EncodingNodeGen::create); add(EncodingFunctions.SetEncoding.class, EncodingFunctionsFactory.SetEncodingNodeGen::create); @@ -599,6 +601,7 @@ public class BasePackage extends RBuiltinPackage { add(LaFunctions.Version.class, LaFunctionsFactory.VersionNodeGen::create); add(LaFunctions.LaSolve.class, LaFunctionsFactory.LaSolveNodeGen::create); add(LaFunctions.Svd.class, LaFunctionsFactory.SvdNodeGen::create); + add(LaFunctions.LaLibrary.class, LaFunctionsFactory.LaLibraryNodeGen::create); add(Lapply.class, LapplyNodeGen::create); add(Length.class, LengthNodeGen::create); add(Lengths.class, LengthsNodeGen::create); @@ -667,7 +670,7 @@ public class BasePackage extends RBuiltinPackage { add(RNGFunctions.RNGkind.class, RNGFunctionsFactory.RNGkindNodeGen::create); add(RNGFunctions.SetSeed.class, RNGFunctionsFactory.SetSeedNodeGen::create); add(RNGFunctions.FastRSetSeed.class, RNGFunctionsFactory.FastRSetSeedNodeGen::create); - add(RVersion.class, RVersionNodeGen::create); + add(RVersion.class, VersionFunctionsFactory.RVersionNodeGen::create); add(RawFunctions.CharToRaw.class, RawFunctionsFactory.CharToRawNodeGen::create); add(RawFunctions.RawToChar.class, RawFunctionsFactory.RawToCharNodeGen::create); add(RawFunctions.RawShift.class, RawFunctionsFactory.RawShiftNodeGen::create); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java index b872653b289458c180eeea4bf635342526498a23..05c9f4f3e4473716fbc0ddd35fec26b398cf8dda 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java index a75d886e0ad27c539f783b7f8d61249b6298e49c..49f5c90d3a70bf8a9266ea29ab7554649a6b447c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java @@ -41,6 +41,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.ffi.impl.common.LibPaths; import com.oracle.truffle.r.nodes.access.vector.ExtractListElement; import com.oracle.truffle.r.nodes.attributes.CopyAttributesNode; import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; @@ -63,7 +64,6 @@ import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDataFactory.VectorFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; @@ -866,4 +866,17 @@ public class LaFunctions { return RDataFactory.createList(val, nm); } } + + @RBuiltin(name = "La_library", kind = INTERNAL, parameterNames = {}, behavior = PURE) + public abstract static class LaLibrary extends RBuiltinNode.Arg0 { + + static { + Casts.noCasts(LaLibrary.class); + } + + @Specialization + protected Object doLibrary() { + return RDataFactory.createStringVector(LibPaths.getBuiltinLibPath("Rlapack")); + } + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VersionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VersionFunctions.java new file mode 100644 index 0000000000000000000000000000000000000000..a012fdfa939be6db14f894b61d71d91d4cf3643d --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VersionFunctions.java @@ -0,0 +1,96 @@ +/* + * 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.nodes.builtin.base; + +import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; +import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.ffi.impl.common.LibPaths; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RCompression; +import com.oracle.truffle.r.runtime.RVersionInfo; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.ffi.BaseRFFI; +import com.oracle.truffle.r.runtime.ffi.BaseRFFI.ESoftVersionNode; + +public abstract class VersionFunctions { + + @RBuiltin(name = "Version", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) + public abstract static class RVersion extends RBuiltinNode.Arg0 { + + @Specialization + @TruffleBoundary + protected Object doRVersion() { + return RDataFactory.createList(RVersionInfo.listValues(), RDataFactory.createStringVector(RVersionInfo.listNames(), RDataFactory.COMPLETE_VECTOR)); + } + } + + @RBuiltin(name = "eSoftVersion", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) + public abstract static class ExtSoftVersion extends RBuiltinNode.Arg0 { + @Child private ESoftVersionNode eSoftVersionNode = BaseRFFI.ESoftVersionNode.create(); + + static { + Casts.noCasts(ExtSoftVersion.class); + } + + @Specialization + @TruffleBoundary + protected RStringVector getSymbolInfo() { + + Map<String, String> eSoftVersion = eSoftVersionNode.eSoftVersion(); + + List<String> libNames = new ArrayList<>(); + List<String> versions = new ArrayList<>(); + + for (Map.Entry<String, String> versionEntry : eSoftVersion.entrySet()) { + libNames.add(versionEntry.getKey()); + versions.add(versionEntry.getValue()); + } + + // BZIP2 + try { + versions.add(RCompression.getBz2Version()); + libNames.add("bzip2"); + } catch (IOException e) { + // ignore + } + + // BLAS + libNames.add("BLAS"); + versions.add(LibPaths.getBuiltinLibPath("Rblas")); + + RStringVector names = RDataFactory.createStringVector(libNames.toArray(new String[0]), true); + return RDataFactory.createStringVector(versions.toArray(new String[0]), true, names); + + } + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java index d95a86df371ee0199a5f05c546dd74ad20c2b43b..92868ceba0918ea765bb21c11bfb4412b5f1c061 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java @@ -250,4 +250,39 @@ public class RCompression { } throw new IOException(); } + + public static String getBz2Version() throws IOException { + // assumes: "bzip2, a block-sorting file compressor. Version 1.0.6, 6-Sept-2010." + String[] command = {"bzip2", "-V"}; + int rc; + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + // version is written to the error output stream + InputStream is = p.getErrorStream(); + OutputStream os = p.getOutputStream(); + ProcessOutputManager.OutputThreadVariable readThread = new ProcessOutputManager.OutputThreadVariable(command[0], is); + readThread.start(); + os.close(); + try { + rc = p.waitFor(); + if (rc == 0) { + readThread.join(); + String output = new String(readThread.getData(), 0, readThread.getTotalRead()); + String version = "Version "; + String firstLine = output.split("\\n")[0]; + int versionIdx = firstLine.indexOf(version); + if (versionIdx >= 0) { + int commaIdx = firstLine.lastIndexOf('.'); + if (commaIdx > versionIdx) { + return firstLine.substring(versionIdx + version.length(), commaIdx); + } + } + } else { + throw new IOException("bzip2 error code: " + rc); + } + } catch (InterruptedException ex) { + // fall through + } + throw new IOException(); + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java index ed2fdc7b53a9229f96a2e584e76ca7274a009de7..4dd512a84a0a8283b8ecb4afed0dfb7e8d053656 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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.runtime.ffi; import java.io.IOException; import java.util.ArrayList; +import java.util.Map; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.NodeInterface; @@ -163,6 +164,14 @@ public interface BaseRFFI { } } + interface ESoftVersionNode extends NodeInterface { + Map<String, String> eSoftVersion(); + + static ESoftVersionNode create() { + return RFFIFactory.getBaseRFFI().createESoftVersionNode(); + } + } + /* * The RFFI implementation influences exactly what subclass of the above nodes is created. Each * implementation must therefore, implement these methods that are called by the associated @@ -189,6 +198,8 @@ public interface BaseRFFI { GlobNode createGlobNode(); + ESoftVersionNode createESoftVersionNode(); + /* * Some functions are called from non-Truffle contexts, which requires a RootNode */ diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java index 77e64b651b6fc773256b0342f1bd56ea5ada3f35..7ea60974f127f4e77b12c0d1c6148cb07b8404ff 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java @@ -43,6 +43,7 @@ public enum NativeFunction { strtol("((sint64, sint32): void, string, sint32): void", "call_base_"), uname("((string, string, string, string, string): void): void", "call_base_"), glob("((string): void, string): void", "call_base_"), + eSoftVersion("((string, string): void): void", "call_base_"), // PCRE maketables("(): sint64", "call_pcre_"), compile("((uint64, string, sint32): void, string, sint32, uint64): void", "call_pcre_"), 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 cd370d6523e88dfacbdd0f04daf20995a2ed5a4b..56a64a29f0b4ef9de71ecb392cfc6496c22cb9a9 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 @@ -23592,6 +23592,10 @@ logical(0) #argv <- list(structure('lattice', .Names = ''), FALSE, FALSE, NA); .Internal(duplicated(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) [1] FALSE +##com.oracle.truffle.r.test.builtins.TestBuiltin_eSoftVersion.testESoftVersion# +#{ v <- .Internal(eSoftVersion()); !is.null(v) && length(v) > 0 } +[1] TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_enc2native.testInvalidArguments#Output.IgnoreErrorMessage# #enc2native(42); Error in enc2native(42) : argument is not a character vector diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eSoftVersion.java similarity index 50% rename from com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java rename to com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eSoftVersion.java index 5deeb4662eddf0329a88478afd547eee3a3fcdbf..36108046e543c72d7303be8478bc336cd4f8e118 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eSoftVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 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 @@ -20,24 +20,16 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes.builtin.base; +package com.oracle.truffle.r.test.builtins; -import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; -import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +import org.junit.Test; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.runtime.RVersionInfo; -import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.test.TestBase; -@RBuiltin(name = "Version", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) -public abstract class RVersion extends RBuiltinNode.Arg0 { +public class TestBuiltin_eSoftVersion extends TestBase { - @Specialization - @TruffleBoundary - protected Object doRVersion() { - return RDataFactory.createList(RVersionInfo.listValues(), RDataFactory.createStringVector(RVersionInfo.listNames(), RDataFactory.COMPLETE_VECTOR)); + @Test + public void testESoftVersion() { + assertEval("{ v <- .Internal(eSoftVersion()); !is.null(v) && length(v) > 0 }"); } } diff --git a/mx.fastr/mx_fastr_pkgs.py b/mx.fastr/mx_fastr_pkgs.py index 01c06cdd18d173999e700a5a4b2560a662021911..0a4c5df475c90b454ea09fabc17f230aef3eac10 100644 --- a/mx.fastr/mx_fastr_pkgs.py +++ b/mx.fastr/mx_fastr_pkgs.py @@ -617,6 +617,10 @@ def _replace_engine_references(output): output[idx] = val.replace('fastr', '<engine>').replace('gnur', '<engine>') +def _is_ignored_function(fun_name, gnur_content, gnur_stmt, fastr_content, fastr_stmt): + return gnur_stmt != -1 and fun_name in gnur_content[gnur_stmt] and fastr_stmt != -1 and fun_name in fastr_content[fastr_stmt] + + def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename, verbose=False): """ Compares the test output of GnuR and FastR by ignoring implementation-specific differences like header, error, @@ -647,12 +651,12 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename, v gnur_prompt = _capture_prompt(gnur_content, gnur_i) fastr_prompt = _capture_prompt(fastr_content, fastr_i) - gnur_cur_statement_start = -1 - fastr_cur_statement_start = -1 - while True: - gnur_line, gnur_i = _get_next_line(gnur_prompt, gnur_content, gnur_end, gnur_i) - fastr_line, fastr_i = _get_next_line(fastr_prompt, fastr_content, fastr_len, fastr_i) + gnur_line, gnur_i = _get_next_line(gnur_prompt, gnur_content, gnur_end, gnur_i) + fastr_line, fastr_i = _get_next_line(fastr_prompt, fastr_content, fastr_len, fastr_i) + gnur_cur_statement_start = gnur_i + fastr_cur_statement_start = fastr_i + while True: if gnur_line is None or fastr_line is None: # fail if FastR's output is shorter than GnuR's if gnur_line is not None and fastr_line is None: @@ -661,14 +665,6 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename, v overall_result = 1 break - # check if the current line starts a statement - if _is_statement_begin(gnur_prompt, gnur_line) and gnur_cur_statement_start != gnur_i: - gnur_cur_statement_start = gnur_i - - # if we find a new statement begin - if _is_statement_begin(fastr_prompt, fastr_line) and fastr_cur_statement_start != fastr_i: - fastr_cur_statement_start = fastr_i - # flag indicating that we want to synchronize sync = False if gnur_line != fastr_line: @@ -678,30 +674,41 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename, v if fastr_content[fastr_i].startswith('NULL') and not gnur_line.startswith('NULL'): # ignore additional visible NULL fastr_i = fastr_i + 1 - continue - if gnur_line.startswith('Warning') and gnur_i + 1 < gnur_end and 'closing unused connection' in gnur_content[gnur_i + 1]: + sync = True + elif gnur_line.startswith('Warning') and gnur_i + 1 < gnur_end and 'closing unused connection' in gnur_content[gnur_i + 1]: # ignore message about closed connection gnur_i = gnur_i + 2 - continue - if gnur_i > 0 and gnur_content[gnur_i - 1].startswith(' user system elapsed'): + sync = True + elif gnur_i > 0 and gnur_content[gnur_i - 1].startswith(' user system elapsed'): # ignore differences in timing gnur_i = gnur_i + 1 fastr_i = fastr_i + 1 - continue + sync = True # we are fuzzy on Error/Warning as FastR often differs # in the context/format of the error/warning message AND GnuR is sometimes # inconsistent over which error message it uses. Unlike the unit test environment, # we cannot tag tests in any way, so we simply check that FastR does report # an error. We then scan forward to try to get the files back in sync, as the # the number of error/warning lines may differ. - if 'Error' in gnur_line or 'Warning' in gnur_line: + elif 'Error' in gnur_line or 'Warning' in gnur_line: to_match = 'Error' if 'Error' in gnur_line else 'Warning' if to_match not in fastr_line: result = 1 else: # accept differences in the error/warning messages but we need to synchronize + gnur_i = gnur_i + 1 + fastr_i = fastr_i + 1 sync = True - + elif _is_ignored_function("sessionInfo", gnur_content, gnur_cur_statement_start, fastr_content, fastr_cur_statement_start): + # ignore differences in 'sessionInfo' output + gnur_i = gnur_i + 1 + fastr_i = fastr_i + 1 + sync = True + elif _is_ignored_function("extSoftVersion", gnur_content, gnur_cur_statement_start, fastr_content, fastr_cur_statement_start): + # ignore differences in 'extSoftVersion' output + gnur_i = gnur_i + 1 + fastr_i = fastr_i + 1 + sync = True else: # genuine difference (modulo whitespace) if not _ignore_whitespace(gnur_line, fastr_line): @@ -716,6 +723,8 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename, v print fastr_line.strip() # we need to synchronize the indices such that we can continue + gnur_i = gnur_i + 1 + fastr_i = fastr_i + 1 sync = True # report the last statement to produce different output assert fastr_cur_statement_start != -1 @@ -733,8 +742,6 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename, v # synchronize: skip until lines match (or file end reached) if sync: - gnur_i = gnur_i + 1 - fastr_i = fastr_i + 1 if gnur_i == gnur_end - 1: # at end (there is always a blank line) break @@ -754,6 +761,17 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename, v gnur_i = gnur_i + 1 fastr_i = fastr_i + 1 + gnur_line, gnur_i = _get_next_line(gnur_prompt, gnur_content, gnur_end, gnur_i) + fastr_line, fastr_i = _get_next_line(fastr_prompt, fastr_content, fastr_len, fastr_i) + + # check if the current line starts a statement + if _is_statement_begin(gnur_prompt, gnur_line) and gnur_cur_statement_start != gnur_i: + gnur_cur_statement_start = gnur_i + + # if we find a new statement begin + if _is_statement_begin(fastr_prompt, fastr_line) and fastr_cur_statement_start != fastr_i: + fastr_cur_statement_start = fastr_i + return overall_result, len(statements_passed), len(statements_failed) @@ -781,8 +799,10 @@ def _capture_prompt(lines, idx): def _is_statement_begin(captured_prompt, line): - line_wo_prompt = line.replace(captured_prompt, "").strip() - return line.startswith(captured_prompt) and line_wo_prompt is not "" and not line_wo_prompt.startswith("#") + if not line is None: + line_wo_prompt = line.replace(captured_prompt, "").strip() + return line.startswith(captured_prompt) and line_wo_prompt is not "" and not line_wo_prompt.startswith("#") + return False def pkgtest_cmp(args):