/* $Id$
*
* Project: Swicli.Library - Two Way Interface for .NET and MONO to SWI-Prolog
* Author: Douglas R. Miles
* E-mail: logicmoo@gmail.com
* WWW: http://www.logicmoo.com
* Copyright (C): 2010-2012 LogicMOO Developement
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*********************************************************/
using org.jpl7;
#if USE_IKVM
using IKVM.Internal;
using ikvm.runtime;
using java.net;
//using org.jpl7;
#endif
#if USE_IKVM
using Hashtable = java.util.Hashtable;
using ClassLoader = java.lang.ClassLoader;
using Class = java.lang.Class;
using sun.reflect.misc;
#endif
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using SbsSW.SwiPlCs;
using SbsSW.SwiPlCs.Callback;
using PlTerm = SbsSW.SwiPlCs.PlTerm;
namespace Swicli.Library
{
public partial class PrologCLR
{
static public void load_swiplcs()
{
}
private static readonly object PrologIsSetupLock = new object();
private static bool PrologIsSetupBegan;
public static bool PrologIsSetupComplete = false;
public static void SetupProlog()
{
lock (PrologIsSetupLock)
{
if (PrologIsSetupBegan) return;
Embedded.ConsoleWriteLine(typeof(PrologCLR).Name + ".AssemblyResolve starting");
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
PrologIsSetupBegan = true;
SafelyRun(SetupProlog0);
SafelyRun(SetupProlog2);
RegisterPLCSForeigns();
PrologIsSetupComplete = true;
}
}
public static void SetupProlog0()
{
Embedded.Debug("SetupProlog");
// SafelyRun(SetupIKVM);
if (!IsUseableSwiProlog(SwiHomeDir))
{
try
{
//SwiHomeDir = System.Windows.Forms.Application.StartupPath;
SwiHomeDir = Path.GetDirectoryName(Environment.CurrentDirectory);
// CommandLine.Trim(' ', '"', '\''));
if (!IsUseableSwiProlog(SwiHomeDir))
{
SwiHomeDir = null;
}
}
catch (Exception)
{
}
}
if (!IsUseableSwiProlog(SwiHomeDir))
{
SwiHomeDir = Environment.GetEnvironmentVariable("SWI_HOME_DIR");
if (!IsUseableSwiProlog(SwiHomeDir))
{
SwiHomeDir = null;
}
}
string pf = GetProgramFilesDir();
if (!IsUseableSwiProlog(SwiHomeDir))
{
SwiHomeDir = pf + "/pl";
if (!IsUseableSwiProlog(SwiHomeDir))
{
SwiHomeDir = pf + "/swipl";
}
}
AltSwiHomeDir = AltSwiHomeDir ?? ".";
bool copyPlatFormVersions = false;
if (!IsUseableSwiProlog(SwiHomeDir))
{
SwiHomeDir = AltSwiHomeDir;
copyPlatFormVersions = true;
if (true)
{
//for now never copy!
copyPlatFormVersions = false;
}
}
SwiHomeDir = SwiHomeDir ?? AltSwiHomeDir;
if (IsUseableSwiProlog(SwiHomeDir))
{
Environment.SetEnvironmentVariable("SWI_HOME_DIR", SwiHomeDir);
}
if (!ConfirmRCFile(SwiHomeDir)) ConsoleTrace("RC file missing from " + SwiHomeDir);
string platformSuffix = Embedded.Is64BitRuntime() ? "-x64" : "-x86";
if (copyPlatFormVersions)
{
string destination = Path.Combine(SwiHomeDir, "bin");
CopyFiles(destination + platformSuffix, destination, true, "*.*", true);
destination = Path.Combine(SwiHomeDir, "lib");
CopyFiles(destination + platformSuffix, destination, true, "*.*", true);
}
if (IsUseableSwiProlog(SwiHomeDir))
{
Environment.SetEnvironmentVariable("SWI_HOME_DIR", SwiHomeDir);
}
SafelyRun(SetupProlog1);
}
private static string GetProgramFilesDir()
{
if (Embedded.Is64BitComputer())
{
if (!Embedded.Is64BitRuntime())
{
return Environment.GetEnvironmentVariable("ProgramFiles(x86)");
}
}
return Environment.GetEnvironmentVariable("ProgramFiles");
}
private static string GetMyPathExtras()
{
if (libpath != null) return libpath;
string swiHomeBin = Path.Combine(SwiHomeDir, "bin");
libpath += swiHomeBin;
if (swiHomeBin != IKVMHome && !String.IsNullOrEmpty(IKVMHome))
{
libpath += Path.PathSeparator;
libpath += IKVMHome;
}
libpath += Path.PathSeparator;
libpath += ".";
return libpath;
}
///
/// This after the SwiPrologDir and IKVMHome is set up will update the environment
///
public static void SetupProlog1()
{
string myPathExt = GetMyPathExtras();
String path = Environment.GetEnvironmentVariable("PATH");
if (path != null)
{
if (!path.ToLower().StartsWith(myPathExt.ToLower()))
{
path = myPathExt + path;
Environment.SetEnvironmentVariable("PATH", path);
}
}
string LD_LIBRARY_PATH = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH");
if (String.IsNullOrEmpty(LD_LIBRARY_PATH))
{
LD_LIBRARY_PATH = libpath;
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", LD_LIBRARY_PATH);
}
else if (!LD_LIBRARY_PATH.ToLower().Contains(myPathExt.ToLower()))
{
LD_LIBRARY_PATH = myPathExt + LD_LIBRARY_PATH;
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", LD_LIBRARY_PATH);
}
// SafelyRun(SetupProlog1);
// SafelyRun(SetupProlog2);
}
/*
#if USE_IKVM
public static void SetupProlog1()
{
PrologCLR.ConsoleTrace("geting lib path");
CLASSPATH = java.lang.System.getProperty("java.class.path");
ConsoleTrace("GOT lib path");
string CLASSPATH0 = Environment.GetEnvironmentVariable("CLASSPATH");
if (String.IsNullOrEmpty(CLASSPATH))
{
CLASSPATH = CLASSPATH0;
}
string jplcp = clasPathOf(new org.jpl7.JPL());
if (!JplDisabled)
CLASSPATH = IKVMHome + "/SWIJPL.dll" + ";" + IKVMHome + "/SWIJPL.jar;" + CLASSPATH0;
ConsoleWriteLine("CLASSPATH=" + CLASSPATH);
if (CLASSPATH != null)
{
Environment.SetEnvironmentVariable("CLASSPATH", CLASSPATH);
java.lang.System.setProperty("java.class.path", CLASSPATH);
}
java.lang.System.setProperty("java.library.path", libpath);
}
#endif*/
static string libpath = null;
public static void SetupProlog2()
{
try
{
#if USE_IKVM
/*
if (!JplDisabled)
{
JPL.setNativeLibraryDir(SwiHomeDir + "/bin");
try
{
JPL.loadNativeLibrary();
}
catch (Exception e)
{
WriteException(e);
JplDisabled = true;
}
if (!JplDisabled)
{
SafelyRun(() => org.jpl7.fli.Prolog.initialise());
}
}
SafelyRun(TestClassLoader);
*/
#endif
//if (Embedded.IsPLWin) return;
try
{
if (!PlEngine.IsInitialized)
{
String[] param = { "-q" }; // suppressing informational and banner messages
PlEngine.Initialize(param);
}
if (Embedded.IsPLWin) return;
if (!PlEngine.IsStreamFunctionReadModified) PlEngine.SetStreamReader(Sread);
if (PlEngine.IsStreamFunctionWriteModified)
{
PlQuery.PlCall("nl.");
}
}
catch (Exception e)
{
Embedded.WriteException(e);
Embedded.PlCsDisabled = true;
}
// PlAssert("org.jpl7:jvm_ready");
// PlAssert("module_transparent(jvm_ready)");
}
catch (Exception exception)
{
Embedded.WriteException(exception);
return;
}
}
private static bool IsUseableSwiProlog(string swiHomeDir)
{
if (String.IsNullOrEmpty(swiHomeDir)) return false;
if (!Directory.Exists(swiHomeDir)) return false;
string swibin = Path.Combine(swiHomeDir, "bin");
String oldFile = Path.Combine(swibin, "libpl.dll");
if (File.Exists(oldFile))
{
ConsoleTrace("SWI too old: " + oldFile);
return false;
}
if (!ConfirmRCFile(swiHomeDir)) return false;
if (File.Exists(Path.Combine(swibin, "libswipl.dll"))) return true;
if (File.Exists(Path.Combine(swibin, "swipl.dll"))) return true;
return true;
}
private static bool ConfirmRCFile(string swiHomeDir)
{
if (!Embedded.Is64BitRuntime())
{
return File.Exists(Path.Combine(swiHomeDir, "boot32.prc")) ||
File.Exists(Path.Combine(swiHomeDir, "boot.prc"));
}
return File.Exists(Path.Combine(swiHomeDir, "boot64.prc"));
}
//FileInfo & DirectoryInfo are in System.IO
//This is something you should be able to tweak to your specific needs.
static void CopyFiles(string source,
string destination,
bool overwrite,
string searchPattern, bool recurse)
{
if (Directory.Exists(source))
CopyFiles(new DirectoryInfo(source), new DirectoryInfo(destination), overwrite, searchPattern, recurse);
}
static void CopyFiles(DirectoryInfo source,
DirectoryInfo destination,
bool overwrite,
string searchPattern, bool recurse)
{
FileInfo[] files = source.GetFiles(searchPattern);
if (!destination.Exists)
{
destination.Create();
}
foreach (FileInfo file in files)
{
string destName = Path.Combine(destination.FullName, file.Name);
try
{
file.CopyTo(destName, overwrite);
}
catch (Exception e0)
{
if (!overwrite)
{
Embedded.ConsoleWriteLine("file: " + file + " copy to " + destName + " " + e0);
}
else
{
try
{
if (File.Exists(destName))
{
if (File.Exists(destName + ".dead")) File.Delete(destName + ".dead");
File.Move(destName, destName + ".dead");
file.CopyTo(destName, false);
}
}
catch (Exception e)
{
Embedded.ConsoleWriteLine("file: " + file + " copy to " + destName + " " + e);
}
}
}
}
if (recurse)
{
foreach (var info in source.GetDirectories())
{
string destName = Path.Combine(destination.FullName, info.Name);
try
{
if (!Directory.Exists(destName)) Directory.CreateDirectory(destName);
CopyFiles(info, new DirectoryInfo(destName), overwrite, searchPattern, recurse);
}
catch (Exception e)
{
Embedded.ConsoleWriteLine("file: " + info + " copy to " + destName + " " + e);
}
}
}
}
//[MTAThread]
public static void Main(string[] args0)
{
while (false)
{
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = false;
startInfo.WindowStyle = ProcessWindowStyle.Maximized;
startInfo.FileName = @"c:\pf\swipl\bin\swipl-win.exe";
startInfo.Arguments = "winapi_dll.pl";
startInfo.WorkingDirectory = @"C:\Users\Administrator\AppData\Roaming\SWI-Prolog\pack\swicli\cffi-tests";
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
}
PingThreadFactories();
//bool demo = false;
SetupProlog();
libpl.PL_initialise(args0.Length, args0);
//Main12(args0);
libpl.PL_toplevel();
}
//[MTAThread]
public static void Main_Was(string[] args0)
{
PingThreadFactories();
bool demo = true;
SetupProlog();
if (demo)
{
DoQuery("asserta(fff(1))");
DoQuery("asserta(fff(9))");
DoQuery("nl");
DoQuery("flush");
PlAssert("father(martin, inka)");
if (!Embedded.PlCsDisabled)
{
PlQuery.PlCall("assert(father(uwe, gloria))");
PlQuery.PlCall("assert(father(uwe, melanie))");
PlQuery.PlCall("assert(father(uwe, ayala))");
using (PlQuery q = new PlQuery("father(P, C), atomic_list_concat([P,' is_father_of ',C], L)"))
{
foreach (PlTermV v in q.Solutions)
ConsoleTrace(ToCSString(v));
foreach (PlQueryVariables v in q.SolutionVariables)
ConsoleTrace(v["L"].ToString());
ConsoleTrace("all child's from uwe:");
q.Variables["P"].Unify("uwe");
foreach (PlQueryVariables v in q.SolutionVariables)
ConsoleTrace(v["C"].ToString());
}
//PlQuery.PlCall("ensure_loaded(library(thread_util))");
//Warning: [Thread 2] Thread running "thread_run_interactor" died on exception: thread_util:attach_console/0: Undefined procedure: thread_util:win_open_console/5
//PlQuery.PlCall("interactor");
//Delegate Foo0 = foo0;
RegisterPLCSForeigns();
}
PlAssert("tc2:-foo2(X,Y),writeq(f(X,Y)),nl,X=5");
PlAssert("tc3:-foo3(X,Y,Z),Z,writeln(f(X,Y,Z)),X=5");
}
#if USE_IKVM
// ClassFile.ThrowFormatErrors = false;
libpl.NoToString = true;
//SafelyRun((() => PlCall("jpl0")));
//SafelyRun((() => DoQuery(new Query(new org.jpl7.Atom("jpl0")))));
libpl.NoToString = false;
// ClassFile.ThrowFormatErrors = true;
#endif
if (args0.Length > 0)
{
int i = 0;
foreach (var s in args0)
{
if (s == "-f")
{
string s1 = args0[i + 1];
args0[i + 1] = "['" + s1 + "']";
continue;
}
PlCall(s);
i++;
}
}
if (!Embedded.JplDisabled)
{
#if USE_IKVM
var run = new org.jpl7.Atom("prolog");
while (!Embedded.IsHalted) SafelyRun(() => DoQuery(new org.jpl7.Query(run)));
#endif
}
else
{
if (!Embedded.PlCsDisabled)
// loops on exception
while (!SafelyRun(() => libpl.PL_toplevel())) ;
}
ConsoleTrace("press enter to exit");
Console.ReadLine();
SafelyRun(() => PlEngine.PlCleanup());
ConsoleTrace("finshed!");
}
private static bool SafelyRun(Action invoker)
{
try
{
invoker();
return true;
}
catch (Exception e)
{
Embedded.WriteException(e);
return false;
}
}
public static void RegisterPLCSForeigns()
{
CreatorThread = Thread.CurrentThread;
RegisterMainThread();
ShortNameType = new Dictionary();
ShortNameType["string"] = typeof(String);
ShortNameType["object"] = typeof(Object);
ShortNameType["sbyte"] = typeof(sbyte);
// libpl.PL_agc_hook(new AtomGCHook(Tracker_FreeAtom));
//ShortNameType = new PrologBackedDictionary(null, "shortTypeName");
//PlEngine.RegisterForeign(null, "cliFindClass", 2, new DelegateParameter2(PrologCli.cliFindClass), PlForeignSwitches.None);
PlEngine.RegisterForeign(Embedded.ExportModule, "cli_load_assembly", 1, new DelegateParameter1(cliLoadAssembly), PlForeignSwitches.None);
if (Embedded.VerboseStartup) Embedded.ConsoleWriteLine("RegisterPLCSForeigns");
InternMethod(null, "cwl", typeof(Console).GetMethod("WriteLine", ONE_STRING));
Type t = typeof(PrologCLR);
InternMethod(Embedded.ExportModule, "cli_load_assembly_methods", t.GetMethod("cliLoadAssemblyMethods"));
InternMethod(t.GetMethod("cliAddAssemblySearchPath"), "cli_");
InternMethod(t.GetMethod("cliRemoveAssemblySearchPath"), "cli_");
AddForeignMethods(t, false, "cli_");
RegisterJPLForeigns();
if (Embedded.VerboseStartup) Embedded.ConsoleWriteLine("done RegisterPLCSForeigns");
}
private static void RegisterJPLForeigns()
{
// backup old org.jpl7.pl and copy over it
if (!Embedded.JplDisabled)
SafelyRun(() =>
{
if (File.Exists(IKVMHome + "/jpl_for_ikvm.phps"))
{
if (!File.Exists(SwiHomeDir + "/library/org.jpl7.pl.old"))
{
File.Copy(SwiHomeDir + "/library/org.jpl7.pl",
SwiHomeDir + "/library/org.jpl7.pl.old",
true);
}
File.Copy(IKVMHome + "/jpl_for_ikvm.phps", SwiHomeDir + "/library/org.jpl7.pl", true);
}
});
PlEngine.RegisterForeign("swicli", "link_swiplcs", 1, new DelegateParameter1(link_swiplcs),
PlForeignSwitches.None);
//JplSafeNativeMethods.install();
Embedded.JplSafeNativeMethodsCalled = true;
//DoQuery(new Query("ensure_loaded(library(org.jpl7))."));
/*
jpl_jlist_demo :-
jpl_new( 'javax.swing.JFrame', ['modules'], F),
jpl_new( 'javax.swing.DefaultListModel', [], DLM),
jpl_new( 'javax.swing.JList', [DLM], L),
jpl_call( F, getContentPane, [], CP),
jpl_call( CP, add, [L], _),
( current_module( M),
jpl_call( DLM, addElement, [M], _),
fail
; true
),
jpl_call( F, pack, [], _),
jpl_call( F, getHeight, [], H),
jpl_call( F, setSize, [150,H], _),
jpl_call( F, setVisible, [@(true)], _).
% this directive runs the above demo
:- jpl_jlist_demo.
*/
return; //we dont need to really do this
PlCall("use_module(library(org.jpl7)).");
PlAssert("jpl0 :- jpl_new( 'java.lang.String', ['hi'], DLM),writeln(DLM)");
PlAssert("jpl1 :- jpl_new( 'javax.swing.DefaultListModel', [], DLM),writeln(DLM)");
}
private static bool link_swiplcs(PlTerm pathName)
{
try
{
return true;
if (Embedded.JplSafeNativeMethodsCalled)
{
bool enabled = !Embedded.JplSafeNativeMethodsDisabled;
SafelyRun(
() => ConsoleTrace("JplSafeNativeMethods called again from " + pathName + " result=" + enabled));
return enabled;
}
Embedded.JplSafeNativeMethodsCalled = true;
SafelyRun(() => ConsoleTrace("JplSafeNativeMethods call first time from " + pathName));
JplSafeNativeMethods.install();
//var v = new PlTerm("_1");
//JplSafeNativeMethods.jpl_c_lib_version_1_plc(v.TermRef);
return true;
}
catch (Exception e)
{
Embedded.JplSafeNativeMethodsDisabled = true;
Embedded.WriteException(e);
return false;
}
}
private static void FooMethod(String print)
{
//DoQuery(new Query("asserta(org.jpl7:jvm_ready)."));
//DoQuery(new Query("asserta(org.jpl7:jpl_c_lib_version(3-3-3-3))."));
//DoQuery(new Query("module(org.jpl7)."));
//JplSafeNativeMethods.install();
//DoQuery("ensure_loaded(library(org.jpl7)).");
//DoQuery("module(user).");
//DoQuery(new Query("load_foreign_library(foreign(org.jpl7))."));
// DoQuery(new Query(new org.jpl7.Compound("member", new Term[] { new org.jpl7.Integer(1), new org.jpl7.Variable("H") })));
//DoQuery(new Query(new org.jpl7.Atom("interactor")));
//DoQuery(new Query(new org.jpl7.Compound("writeq", new Term[] { new org.jpl7.Integer(1) })));
ConsoleTrace(print);
}
static internal long Sread(IntPtr handle, IntPtr buffer, long buffersize)
{
int i = Console.Read();
if (i == -1) return 0;
string s = "" + (char)i;
byte[] array = Encoding.Unicode.GetBytes(s);
Marshal.Copy(array, 0, buffer, array.Length);
return array.Length;
}
private static string _ikvmHome = ".";
public static string IKVMHome
{
get { return _ikvmHome; }
set { _ikvmHome = RemoveTrailingPathSeps(value); }
}
private static string _swiHomeDir;// = Path.Combine(".", "swiprolog");
public static string SwiHomeDir
{
get
{
if (_swiHomeDir == null)
{
_swiHomeDir = Environment.GetEnvironmentVariable("SWI_HOME_DIR");
}
return _swiHomeDir;
}
set
{
_swiHomeDir = RemoveTrailingPathSeps(value); ;
}
}
private static string RemoveTrailingPathSeps(string value)
{
if (value != null)
{
value = value.TrimEnd("\\/".ToCharArray()).Replace("\\", "/");
}
return value;
}
public static string AltSwiHomeDir = ".";//C:/development/opensim4opencog";// Path.Combine(".", "swiprolog");
private static Int64 TopOHandle = 6660000;
private static readonly Dictionary SavedDelegates = new Dictionary();
public static Thread CreatorThread;
public void InitFromUser()
{
ConsultIfExists("prolog/cogbot.pl");
}
}
}