public static SObject findCode(string module, string ns, int id, int number) { // First look in programAssembly CodeVector cv = findCodeInAssembly(Reg.programAssembly, ns, number); if (cv != null) { return(cv); } // Then look in external Assembly via module in name Assembly moduleAssembly; try { moduleAssembly = Assembly.LoadFrom(module + ".exe"); } catch { try { moduleAssembly = Assembly.LoadFrom(module + ".dll"); } catch { Exn.error("code not found (no EXE or DLL file): " + module); return(Factory.Impossible); } } cv = findCodeInAssembly(moduleAssembly, ns, number); if (cv != null) { return(cv); } Exn.error("code not found: " + module + " " + ns + " " + number); return(Factory.False); }
public static void ffi_syscall() { try { SObject scode = Reg.Register2; ffi_syscall_main(((SFixnum)scode).value); } catch (Exception e) { Exn.error("exception in ffi: " + e.ToString()); } }
private static object unwrapF(SObject s) { if (s is SFixnum) { return(((SFixnum)s).value); } else if (s is ForeignBox) { return(((ForeignBox)s).value); } else { Exn.error("cannot unwrap foreign argument"); return(Factory.Impossible); } }
private static SObject foreign2datum(int conversion, SObject obj) { // foreign->datum : conversion F -> value object value; if (obj is ForeignBox) { value = ((ForeignBox)obj).value; } else if (obj is SFixnum) { value = ((SFixnum)obj).value; } else { Exn.error ("foreign->datum: argument is not foreign-box or fixnum"); return(Factory.Impossible); } switch (conversion) { case 0: { // object return(obj); } case 1: { // schemeobject if (value is SObject) { return((SObject)value); } else { Exn.error("foreign->datum (schemeobject): not a scheme value"); return(Factory.Impossible); } } case 2: { // string if (value is string) { return(Factory.makeUString((string)value)); } else { Exn.error("foreign->datum (string): not a string"); return(Factory.Impossible); } } case 3: { // symbol Exn.error ("foreign->datum (symbol): not handled by runtime"); return(Factory.Impossible); } case 4: { // bytes if (value is byte[]) { return(Factory.makeByteVector ((byte[])((byte[])value).Clone())); } else { Exn.error("foreign->datum (bytes): not byte[]"); return(Factory.Impossible); } } case 5: { // int if (value is Enum) { Type enum_type = value.GetType(); Type underlying_type = Enum.GetUnderlyingType(enum_type); if (underlying_type == typeof(Byte)) { return(Factory.makeFixnum((byte)value)); } if (underlying_type == typeof(SByte)) { return(Factory.makeFixnum((sbyte)value)); } if (underlying_type == typeof(char)) { return(Factory.makeFixnum((char)value)); } if (underlying_type == typeof(short)) { return(Factory.makeFixnum((short)value)); } if (underlying_type == typeof(int)) { return(Factory.makeNumber((int)value)); } if (underlying_type == typeof(long)) { return(Factory.makeNumber((long)value)); } if (underlying_type == typeof(ushort)) { return(Factory.makeFixnum((ushort)value)); } if (underlying_type == typeof(uint)) { return(Factory.makeNumber((uint)value)); } if (underlying_type == typeof(ulong)) { return(Factory.makeNumber((ulong)value)); } Exn.error("foreign->datum (enum): not an integer"); return(Factory.Impossible); } if (value is Byte) { return(Factory.makeFixnum((byte)value)); } if (value is SByte) { return(Factory.makeFixnum((sbyte)value)); } if (value is char) { return(Factory.makeFixnum((char)value)); } if (value is short) { return(Factory.makeFixnum((short)value)); } if (value is int) { return(Factory.makeNumber((int)value)); } if (value is long) { return(Factory.makeNumber((long)value)); } if (value is ushort) { return(Factory.makeFixnum((ushort)value)); } if (value is uint) { return(Factory.makeNumber((uint)value)); } if (value is ulong) { return(Factory.makeNumber((ulong)value)); } Exn.error("foreign->datum (int): not an integer"); return(Factory.Impossible); } case 6: { // float if (value is float) { return(Factory.makeFlonum((float)value)); } else { Exn.error("foreign->datum (float): not a float"); return(Factory.Impossible); } } case 7: { // double if (value is double) { return(Factory.makeFlonum((double)value)); } else { Exn.error("foreign->datum (double): not a double"); return(Factory.Impossible); } } case 8: { // void return(Factory.Unspecified); } } Exn.error("foreign->datum: unknown conversion"); return(Factory.Impossible); }
private static SObject datum2foreign(int conversion, SObject obj) { // datum->foreign : conversion value -> F // Always returns a foreign box. Contents of the box is controlled // by the conversion switch. switch (conversion) { // No conversion. Scheme object is placed in the box. case 0: { return(Factory.makeForeignBox(obj)); } // String. case 1: { return(Factory.makeForeignBox (((SByteVL)obj).asString())); } // various integer forms case 2: { return(Factory.makeForeignBox ((Byte)((SFixnum)obj).value)); } case 3: { return(Factory.makeForeignBox ((UInt16)((SFixnum)obj).value)); } case 4: { return(Factory.makeForeignBox ((UInt32)((SFixnum)obj).value)); } case 5: { return(Factory.makeForeignBox ((SByte)((SFixnum)obj).value)); } case 6: { return(Factory.makeForeignBox ((Int16)((SFixnum)obj).value)); } case 7: { return(Factory.makeForeignBox ((Int32)((SFixnum)obj).value)); } case 8: // message filter { #if HAS_WINDOWS_FORMS return(Factory.makeForeignBox (new FFI_message_filter((Procedure)obj))); #else Exn.error("datum->foreign (message_filter) not supported in this version"); return(Factory.Impossible); #endif } case 10: // single precision float { return(Factory.makeForeignBox ((float)((SByteVL)obj).unsafeAsDouble(0))); } case 11: //double precision float { return(Factory.makeForeignBox ((double)((SByteVL)obj).unsafeAsDouble(0))); } case 12: // character { return(Factory.makeForeignBox((Char)((SChar)obj).val)); } case 13: // bytevector-like { object copy = ((SByteVL)obj).elements.Clone(); return(Factory.makeForeignBox((byte[])copy)); } #if NEVER case 0: // object { if (obj is SFixnum || obj is ForeignBox) { return(obj); } else { Exn.error("datum->foreign (object) expected F"); return(Factory.Impossible); } } case 1: // schemeobject { return(Factory.makeForeignBox(obj)); } case 2: // string { if (obj is SByteVL) { string value = ((SByteVL)obj).asString(); return(Factory.makeForeignBox(value)); } else { Exn.error("datum->foreign (string) expected string"); return(Factory.Impossible); } } case 3: // symbol { Exn.error ("datum->foreign (symbol) not implemented in runtime"); return(Factory.Impossible); } case 4: // bytes { if (obj is SByteVL) { return(Factory.makeForeignBox (((SByteVL)obj).elements)); } else { Exn.error ("datum->foreign (bytes) expected bytevector"); return(Factory.Impossible); } } case 5: // int { if (obj is SFixnum) { return(obj); } else if (obj.isBignum()) { SByteVL n = (SByteVL)obj; if (Number.getBignumLength(n) == 1) { uint magn = (uint)(Number.bignumRef(n, 1) << 16) + (uint)Number.bignumRef(n, 0); int val = magn; if (!(Number.getBignumSign(n))) { magn = -magn; } return(Factory.makeForeignBox(val)); } } Exn.error("datum->foreign (int) expected small integer"); return(Factory.Impossible); } case 6: // float { if (obj.isFlonum()) { double value = ((SByteVL)obj).unsafeAsDouble(0); return(Factory.makeForeignBox((float)value)); } else { Exn.error("datum->foreign (float) expected flonum"); return(Factory.Impossible); } } case 7: // double { if (obj.isFlonum()) { double value = ((SByteVL)obj).unsafeAsDouble(0); return(Factory.makeForeignBox(value)); } else { Exn.error("datum->foreign (float) expected flonum"); return(Factory.Impossible); } } case 8: // void { Exn.error("datum->foreign (void) not allowed"); return(Factory.Impossible); } case 9: // message filter { if (obj is Procedure) { return(Factory.makeForeignBox (new FFI_message_filter((Procedure)obj))); } else { Exn.error ("datum->foreign (message filter) expected procedure"); return(Factory.Impossible); } } #endif } Exn.error("datum->foreign: unknown conversion"); return(Factory.Impossible); }
private static void ffi_syscall_main(int code) { // SObject arg1 = Reg.Register3; // SObject arg2 = Reg.Register4; // SObject arg3 = Reg.Register5; // SObject arg4 = Reg.Register6; switch (code) { case 0: // clr-version // Return a list of integers indicating the version // of the CLR runtime. { Version v = Environment.Version; // return a list of 2, 3, or 4 elements Reg.Result = Factory.makePair (Factory.makeNumber(v.Major), Factory.makePair (Factory.makeNumber(v.Minor), (v.Build == -1) ? (SObject)Factory.Null : (SObject) Factory.makePair (Factory.makeNumber(v.Build), (v.Revision == -1) ? (SObject)Factory.Null : (SObject) Factory.makePair (Factory.makeNumber(v.Revision), Factory.Null)))); return; } case 1: // ffi version // Return a list of integers indicating the version of // this FFI. { // Should actually do real versioning here. Reg.Result = Factory.makePair (Factory.makeNumber(0), Factory.makePair(Factory.makeNumber(0), Factory.Null)); return; } case 2: // foreign? // Return True iff argument is a ForeignBox wrapper. { // SObject arg1 = Reg.Register3; // SObject arg2 = Reg.Register4; // SObject arg3 = Reg.Register5; // SObject arg4 = Reg.Register6; Reg.Result = (Reg.Register3 is ForeignBox) ? Factory.True : Factory.False; return; } case 3: // to-string { SObject arg1 = Reg.Register3; object val = ((ForeignBox)arg1).value; Reg.Result = Factory.makeUString((val == null) ? "null" : val.ToString()); return; } case 4: // object-type { SObject arg1 = Reg.Register3; Reg.Result = Factory.makeForeignBox (((ForeignBox)arg1).value.GetType()); return; } case 5: // isa? { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; object obj = ((ForeignBox)arg1).value; Type type = (Type)((ForeignBox)arg2).value; Reg.Result = type.IsInstanceOfType(obj) ? Factory.True : Factory.False; return; } case 6: // foreign-eq? { // this is a mess and should be rewritten! ~jrm SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; // SObject arg3 = Reg.Register5; // SObject arg4 = Reg.Register6; if (arg1 == arg2) { Reg.Result = Factory.True; } else if (arg1 is ForeignBox) { if (arg2 is ForeignBox) { // We can't use the Equals method on null // objects, so we have to test for those // first. if (((ForeignBox)arg1).value == null) { Reg.Result = (((ForeignBox)arg2).value == null) ? Factory.True : Factory.False; } else if (((ForeignBox)arg2).value == null) { Reg.Result = Factory.False; } else { Reg.Result = ((((ForeignBox)arg1).value) .Equals(((ForeignBox)arg2).value)) ? Factory.True : Factory.False; } } else if (arg2 is SFixnum) { Reg.Result = Factory.False; } else if (arg2 is SImmediate) { Reg.Result = Factory.False; } else { Exn.error("cannot unwrap foreign argument"); } } else if (arg1 is SFixnum) { if (arg2 is SFixnum) { Reg.Result = ((((ForeignBox)arg1).value) == (((ForeignBox)arg2).value)) ? Factory.True : Factory.False; } else if (arg2 is ForeignBox) { Reg.Result = Factory.False; } else if (arg2 is SImmediate) { Reg.Result = Factory.False; } else { Exn.error("cannot unwrap foreign argument"); } } else if (arg1 is SImmediate) { if (arg2 is SImmediate) { Reg.Result = Factory.False; } else if (arg2 is ForeignBox) { Reg.Result = Factory.False; } else if (arg2 is SFixnum) { Reg.Result = Factory.False; } else { Exn.error("cannot unwrap foreign argument"); } } else { Exn.error("cannot unwrap foreign argument"); } return; } case 7: // get type { // SObject arg1 = Reg.Register3; // string name = ((SByteVL)arg1).asString(); // case insensitive lookup Type ft = Type.GetType(((SByteVL)(Reg.Register3)) .asString(), false, true); // Return #F if not found. Reg.Result = (ft == null) ? Factory.False : Factory.makeForeignBox(ft); return; } // return the reflected field-info object associated with // a named field, or #F if not found case 8: // get field { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; FieldInfo fi = ((Type)((ForeignBox)arg1).value) .GetField(((SByteVL)arg2).asString()); Reg.Result = (fi == null) ? Factory.False : Factory.makeForeignBox(fi); return; } // return the reflected constructor // #F if not found case 9: // get-constructor { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject[] typev = ((SVL)arg2).elements; Type[] types = new Type[typev.Length]; for (int i = 0; i < types.Length; ++i) { types[i] = (Type)((ForeignBox)typev[i]).value; } ConstructorInfo ci = ((Type)((ForeignBox)arg1).value) .GetConstructor(types); Reg.Result = (ci == null) ? Factory.False : Factory.makeForeignBox(ci); return; } case 10: // get method { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject arg3 = Reg.Register5; SObject[] typev = ((SVL)arg3).elements; Type[] types = new Type[typev.Length]; for (int i = 0; i < types.Length; ++i) { types[i] = (Type)((ForeignBox)typev[i]).value; } MethodInfo mi = ((Type)((ForeignBox)arg1).value) .GetMethod(((SByteVL)arg2).asString(), types); Reg.Result = (mi == null) ? Factory.False : Factory.makeForeignBox(mi); return; } case 11: // get property { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject arg3 = Reg.Register5; SObject[] typev = ((SVL)arg3).elements; Type[] types = new Type[typev.Length]; for (int i = 0; i < types.Length; ++i) { types[i] = (Type)((ForeignBox)typev[i]).value; } PropertyInfo pi = ((Type)((ForeignBox)arg1).value) .GetProperty(((SByteVL)arg2).asString(), types); Reg.Result = (pi == null) ? Factory.False : Factory.makeForeignBox(pi); return; } case 12: // field-ref { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; FieldInfo fi = (FieldInfo)((ForeignBox)arg1).value; try { Reg.Result = Factory.makeForeignBox (fi.GetValue(fi.IsStatic ? null : ((ForeignBox)arg2).value)); return; } catch (Exception e) { Exn.error("ffi:field-get: " + e); return; } } case 13: // field-set! { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject arg3 = Reg.Register5; FieldInfo fi = (FieldInfo)((ForeignBox)arg1).value; try { fi.SetValue(fi.IsStatic ? null : ((ForeignBox)arg2).value, ((ForeignBox)arg3).value); Reg.Result = Factory.Unspecified; return; } catch (Exception e) { Exn.error("ffi:field-set: " + e); return; } } case 14: // invoke constructor { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; ConstructorInfo ci = (ConstructorInfo)((ForeignBox)arg1).value; SObject[] sargv = ((SVL)arg2).elements; object[] args = new object[sargv.Length]; for (int i = 0; i < args.Length; ++i) { args[i] = ((ForeignBox)(sargv[i])).value; } try { Reg.Result = Factory.makeForeignBox(ci.Invoke(args)); return; } catch (Exception e) { Exn.error("ffi:invoke-constructor: " + e); return; } } case 15: // invoke method { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject arg3 = Reg.Register5; MethodInfo mi = (MethodInfo)((ForeignBox)arg1).value; SObject[] sargv = ((SVL)arg3).elements; object[] args = new object[sargv.Length]; for (int i = 0; i < args.Length; i++) { args[i] = ((ForeignBox)(sargv[i])).value; } // I wonder if this version is better? // int i = 0; // foreach (SObject sarg in sargv) // args [i++] = ((ForeignBox) sarg).value; object result; try { result = mi.Invoke(mi.IsStatic ? null : ((ForeignBox)arg2).value, args); } catch (Exception e) { Exn.error ("ffi:invoke: error in foreign function: " + e); return; } Reg.Result = Factory.makeForeignBox(result); return; } case 16: // property-ref { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject arg3 = Reg.Register5; SObject[] sargv = ((SVL)arg3).elements; object[] args = new object[sargv.Length]; for (int i = 0; i < args.Length; ++i) { args[i] = ((ForeignBox)(sargv[i])).value; } object result; try { result = ((PropertyInfo)((ForeignBox)arg1).value) .GetValue(((ForeignBox)arg2).value, args); } catch (Exception e) { Exn.error ("ffi:invoke: error in foreign function: " + e); return; } Reg.Result = Factory.makeForeignBox(result); return; } case 17: // property-set { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject arg3 = Reg.Register5; SObject arg4 = Reg.Register6; SObject[] sargv = ((SVL)arg4).elements; object[] args = new object[sargv.Length]; for (int i = 0; i < args.Length; ++i) { args[i] = ((ForeignBox)(sargv[i])).value; } try { ((PropertyInfo) ((ForeignBox)arg1).value) .SetValue(((ForeignBox)arg2).value, ((ForeignBox)arg3).value, args); } catch (Exception e) { Exn.error ("ffi:invoke: error in foreign function: " + e); return; } Reg.Result = Factory.Unspecified; return; } case 18: // array ref { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; Reg.Result = Factory.makeForeignBox (((Array) ((ForeignBox)arg1).value) .GetValue(((SFixnum)arg2).value)); return; } case 19: // datum2foreign { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; Reg.Result = datum2foreign(((SFixnum)arg1).value, arg2); return; } case 20: // foreign2datum { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; Reg.Result = foreign2datum(((SFixnum)arg1).value, arg2); return; } case 21: // get-property-value-boolean { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject arg3 = Reg.Register5; SObject[] sargv = ((SVL)arg3).elements; object[] args = new object[sargv.Length]; for (int i = 0; i < args.Length; ++i) { args[i] = ((ForeignBox)(sargv[i])).value; } object result; try { result = ((PropertyInfo) ((ForeignBox)arg1).value) .GetValue(((ForeignBox)arg2).value, args); } catch (Exception e) { Exn.error ("ffi:invoke: error in foreign function: " + e); return; } Reg.Result = Factory.makeBoolean((bool)result != false); return; } case 22: // get-property-value-int { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject arg3 = Reg.Register5; SObject[] sargv = ((SVL)arg3).elements; object[] args = new object[sargv.Length]; for (int i = 0; i < args.Length; ++i) { args[i] = ((ForeignBox)(sargv[i])).value; } object result; try { result = ((PropertyInfo) ((ForeignBox)arg1).value) .GetValue(((ForeignBox)arg2).value, args); } catch (Exception e) { Exn.error ("ffi:invoke: error in foreign function: " + e); return; } Reg.Result = Factory.makeNumber((int)result); return; } #if HAS_WINDOWS_FORMS case 23: // get-property-value-native-window { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject arg3 = Reg.Register5; SObject[] sargv = ((SVL)arg3).elements; object[] args = new object [sargv.Length]; for (int i = 0; i < args.Length; ++i) { args[i] = ((ForeignBox)(sargv[i])).value; } object result; try { result = ((PropertyInfo) ((ForeignBox)arg1).value) .GetValue(((ForeignBox)arg2).value, args); } catch (Exception e) { Exn.error("ffi:invoke: error in foreign function: " + e); return; } Reg.Result = Factory.makeForeignBox (System.Windows.Forms.NativeWindow.FromHandle ((IntPtr)result)); return; } #else case 23: { Exn.error("ffi:invoke property-value as native-window not supported in this version"); return; } #endif case 24: // get-property-value-intptr { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject arg3 = Reg.Register5; SObject[] sargv = ((SVL)arg3).elements; object[] args = new object[sargv.Length]; for (int i = 0; i < args.Length; ++i) { args[i] = ((ForeignBox)(sargv[i])).value; } object result; try { result = ((PropertyInfo) ((ForeignBox)arg1).value) .GetValue(((ForeignBox)arg2).value, args); } catch (Exception e) { Exn.error ("ffi:invoke: error in foreign function: " + e); return; } Reg.Result = Factory.makeNumber((int)((IntPtr)result)); return; } case 25: // add-event-handler { SObject arg1 = Reg.Register3; // publisher SObject arg2 = Reg.Register4; // event-name SObject arg3 = Reg.Register5; // procedure (handler) try { // cast arguments to appropriate types object publisher = ((ForeignBox)arg1).value; string eventName = ((SByteVL)arg2).asString(); Procedure proc = (Procedure)(((ForeignBox)arg3).value); // get information about the event EventInfo ei = publisher.GetType().GetEvent(eventName); // add handler for the event ei.AddEventHandler(publisher, proc.makeEventHandler(ei)); } catch (Exception e) { Exn.error("ffi:add-event-handler: error in foreign function: " + e); return; } // return true if we successfully added handler Reg.Result = Factory.True; return; } case 26: // load-assembly(name, version, culture, publickey) { SObject arg1 = Reg.Register3; SObject arg2 = Reg.Register4; SObject arg3 = Reg.Register5; SObject arg4 = Reg.Register6; string name = ((SByteVL)arg1).asString(); string version = ((SByteVL)arg2).asString(); string culture = ((SByteVL)arg3).asString(); string publickey = ((SByteVL)arg4).asString(); Load.LoadAssembly(name, version, culture, publickey); Reg.Result = Factory.Unspecified; return; } } Exn.error("bad ffi syscall code"); return; }