From e1a848d464d62deef4cb96e6505160a3bb43e528 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Mon, 1 Jun 2015 12:06:39 -0700
Subject: [PATCH] refactor JNI-based OS calls from rfficall into osextras

---
 com.oracle.truffle.r.native/Makefile          |  2 +
 com.oracle.truffle.r.native/osextras/Makefile | 63 +++++++++++++++++++
 .../{fficall/jni => osextras}/src/doglob.c    |  0
 .../jni => osextras}/src/getutsname.c         |  0
 .../truffle/r/runtime/ffi/BuiltinLibPath.java | 43 +++++++++++++
 .../r/runtime/ffi/jnr/CallRFFIWithJNI.java    |  9 +--
 .../r/runtime/ffi/jnr/JNR_RFFIFactory.java    | 47 +++++++++++++-
 7 files changed, 156 insertions(+), 8 deletions(-)
 create mode 100644 com.oracle.truffle.r.native/osextras/Makefile
 rename com.oracle.truffle.r.native/{fficall/jni => osextras}/src/doglob.c (100%)
 rename com.oracle.truffle.r.native/{fficall/jni => osextras}/src/getutsname.c (100%)
 create mode 100644 com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/BuiltinLibPath.java

diff --git a/com.oracle.truffle.r.native/Makefile b/com.oracle.truffle.r.native/Makefile
index 79cb3ed05a..9c24dba8b6 100644
--- a/com.oracle.truffle.r.native/Makefile
+++ b/com.oracle.truffle.r.native/Makefile
@@ -39,6 +39,7 @@ all:
 	$(MAKE) -C gnur
 	$(MAKE) -C include
 	$(MAKE) -C builtinlibs
+	$(MAKE) -C osextras
 	$(MAKE) -C fficall
 	$(MAKE) -C library
 	$(MAKE) -C run
@@ -46,6 +47,7 @@ all:
 clean: 
 	$(MAKE) -C include clean
 	$(MAKE) -C builtinlibs clean
+	$(MAKE) -C osextras clean
 	$(MAKE) -C fficall clean
 	$(MAKE) -C library clean
 	$(MAKE) -C run clean
diff --git a/com.oracle.truffle.r.native/osextras/Makefile b/com.oracle.truffle.r.native/osextras/Makefile
new file mode 100644
index 0000000000..8196a23684
--- /dev/null
+++ b/com.oracle.truffle.r.native/osextras/Makefile
@@ -0,0 +1,63 @@
+#
+# Copyright (c) 2014, 2015, 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.
+#
+
+ifeq ($(TOPDIR),)
+    TOPDIR = $(abspath ../..)
+endif
+
+ifneq ($(MAKECMDGOALS),clean)
+include $(TOPDIR)/platform.mk
+endif
+
+.PHONY: all clean
+
+OBJ = lib
+SRC = src
+C_SOURCES := $(wildcard $(SRC)/*.c)
+C_LIBNAME := libosextras$(DYLIB_EXT)
+C_OBJECTS := $(subst $(SRC),$(OBJ),$(C_SOURCES:.c=.o))
+C_LIB := $(TOPDIR)/builtinlibs/$(OBJ)/$(C_LIBNAME)
+CFLAGS := $(CFLAGS) -DFASTR
+ifeq ($(OS_DIR),sunos)
+OS_INCLUDE := solaris
+else
+OS_INCLUDE := $(OS_DIR)
+endif
+
+JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(OS_INCLUDE)
+
+INCLUDES := $(JNI_INCLUDES)
+
+all: $(C_LIB)
+
+$(C_LIB): $(OBJ) $(C_OBJECTS)
+	$(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(C_LIB) $(C_OBJECTS)
+
+$(OBJ):
+	mkdir -p $(OBJ)
+
+$(OBJ)/%.o: $(SRC)/%.c 
+	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
+
+clean:
+	rm -rf $(OBJ) $(C_LIB)
diff --git a/com.oracle.truffle.r.native/fficall/jni/src/doglob.c b/com.oracle.truffle.r.native/osextras/src/doglob.c
similarity index 100%
rename from com.oracle.truffle.r.native/fficall/jni/src/doglob.c
rename to com.oracle.truffle.r.native/osextras/src/doglob.c
diff --git a/com.oracle.truffle.r.native/fficall/jni/src/getutsname.c b/com.oracle.truffle.r.native/osextras/src/getutsname.c
similarity index 100%
rename from com.oracle.truffle.r.native/fficall/jni/src/getutsname.c
rename to com.oracle.truffle.r.native/osextras/src/getutsname.c
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/BuiltinLibPath.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/BuiltinLibPath.java
new file mode 100644
index 0000000000..96d156d48e
--- /dev/null
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/BuiltinLibPath.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, 2015, 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.runtime.ffi;
+
+import java.nio.file.*;
+
+import com.oracle.truffle.r.runtime.*;
+import com.oracle.truffle.r.runtime.RPlatform.*;
+
+public class BuiltinLibPath {
+
+    /**
+     * Returns the absolute path to the builtin library {@code libName} for use with
+     * {@link System#load}.
+     */
+    public static String getLibPath(String libName) {
+        String rHome = REnvVars.rHome();
+        String packageName = "com.oracle.truffle.r.native";
+        OSInfo osInfo = RPlatform.getOSInfo();
+        Path path = FileSystems.getDefault().getPath(rHome, packageName, "builtinlibs", "lib", "lib" + libName + "." + osInfo.libExt);
+        return path.toString();
+    }
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIWithJNI.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIWithJNI.java
index a2c8758110..8a2df7223a 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIWithJNI.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIWithJNI.java
@@ -56,16 +56,13 @@ public class CallRFFIWithJNI implements CallRFFI {
      */
     @TruffleBoundary
     private static void loadLibrary() {
-        String rHome = REnvVars.rHome();
-        String packageName = "com.oracle.truffle.r.native";
-        OSInfo osInfo = RPlatform.getOSInfo();
-        Path path = FileSystems.getDefault().getPath(rHome, packageName, "builtinlibs", "lib", "librfficall." + osInfo.libExt);
+        String librffiPath = BuiltinLibPath.getLibPath("rfficall");
         try {
-            DLL.load(path.toString(), ForceRTLDGlobal, false);
+            DLL.load(librffiPath, ForceRTLDGlobal, false);
         } catch (DLLException ex) {
             throw RError.error((SourceSection) null, ex);
         }
-        System.load(path.toString());
+        System.load(librffiPath);
         initialize(RNull.instance);
     }
 
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java
index 0732ce125f..db5d1e3ff3 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java
@@ -204,12 +204,55 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI, BaseRFFI, Stat
         return com.kenai.jffi.Library.getLastError();
     }
 
+    /*
+     * Missing from JNR and require non-trivial support. We use JNI.
+     */
+
+    private interface OSExtras {
+        UtsName uname();
+
+        ArrayList<String> glob(String pattern);
+    }
+
+    private static class OSExtraProvider implements OSExtras {
+        private static OSExtras osExtras;
+
+        @TruffleBoundary
+        private static OSExtras createAndLoadLib() {
+            try {
+                System.load(BuiltinLibPath.getLibPath("osextras"));
+                return new OSExtraProvider();
+            } catch (UnsatisfiedLinkError ex) {
+                throw RInternalError.shouldNotReachHere("osextras");
+            }
+        }
+
+        static OSExtras osExtras() {
+            if (osExtras == null) {
+                osExtras = createAndLoadLib();
+            }
+            return osExtras;
+        }
+
+        public UtsName uname() {
+            return JNIUtsName.get();
+        }
+
+        public ArrayList<String> glob(String pattern) {
+            return JNIGlob.glob(pattern);
+        }
+    }
+
+    private static OSExtras osExtras() {
+        return OSExtraProvider.osExtras();
+    }
+
     public UtsName uname() {
-        return JNIUtsName.get();
+        return osExtras().uname();
     }
 
     public ArrayList<String> glob(String pattern) {
-        return JNIGlob.glob(pattern);
+        return osExtras().glob(pattern);
     }
 
     /*
-- 
GitLab