2 // MakeMap.cs: Builds a C map of constants defined on C# land
5 // Miguel de Icaza (miguel@novell.com)
6 // Jonathan Pryor (jonpryor@vt.edu)
8 // (C) 2003 Novell, Inc.
9 // (C) 2004-2005 Jonathan Pryor
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections;
35 using System.Globalization;
36 using System.Reflection;
37 using System.Runtime.InteropServices;
39 delegate void CreateFileHandler (string assembly_name, string file_prefix);
40 delegate void AssemblyAttributesHandler (Assembly assembly);
41 delegate void TypeHandler (Type t, string ns, string fn);
42 delegate void CloseFileHandler (string file_prefix);
46 public static int Main (string [] args)
48 FileGenerator[] generators = new FileGenerator[]{
49 new HeaderFileGenerator (),
50 new SourceFileGenerator (),
51 new ConvertFileGenerator (),
52 new ConvertDocFileGenerator (),
53 new MphPrototypeFileGenerator (),
56 MakeMap composite = new MakeMap ();
57 foreach (FileGenerator g in generators) {
58 composite.FileCreators += new CreateFileHandler (g.CreateFile);
59 composite.AssemblyAttributesHandler +=
60 new AssemblyAttributesHandler (g.WriteAssemblyAttributes);
61 composite.TypeHandler += new TypeHandler (g.WriteType);
62 composite.FileClosers += new CloseFileHandler (g.CloseFile);
65 return composite.Run (args);
68 event CreateFileHandler FileCreators;
69 event AssemblyAttributesHandler AssemblyAttributesHandler;
70 event TypeHandler TypeHandler;
71 event CloseFileHandler FileClosers;
73 int Run (string[] args)
75 if (args.Length != 2){
76 Console.WriteLine ("Usage is: make-map assembly output");
80 string assembly_name = args[0];
81 string output = args[1];
83 FileCreators (assembly_name, output);
85 Assembly assembly = Assembly.LoadFrom (assembly_name);
86 AssemblyAttributesHandler (assembly);
88 Type [] exported_types = assembly.GetTypes ();
89 Array.Sort (exported_types, new TypeFullNameComparer ());
91 foreach (Type t in exported_types) {
92 string ns = t.Namespace;
93 if (ns == null || !ns.StartsWith ("Mono"))
95 string fn = GetNativeName (t.FullName);
96 ns = GetNativeName (ns);
98 TypeHandler (t, ns, fn);
100 FileClosers (output);
105 private class TypeFullNameComparer : IComparer {
106 public int Compare (object o1, object o2)
108 Type t1 = o1 as Type;
109 Type t2 = o2 as Type;
116 return CultureInfo.InvariantCulture.CompareInfo.Compare (
117 t1.FullName, t2.FullName, CompareOptions.Ordinal);
121 private class _MemberNameComparer : IComparer {
122 public int Compare (object o1, object o2)
124 MemberInfo m1 = o1 as MemberInfo;
125 MemberInfo m2 = o2 as MemberInfo;
132 return CultureInfo.InvariantCulture.CompareInfo.Compare (
133 m1.Name, m2.Name, CompareOptions.Ordinal);
137 private class _OrdinalStringComparer : IComparer {
138 public int Compare (object o1, object o2)
140 string s1 = o1 as string;
141 string s2 = o2 as string;
142 if (object.ReferenceEquals (s1, s2))
148 return CultureInfo.InvariantCulture.CompareInfo.Compare (s1, s2,
149 CompareOptions.Ordinal);
153 internal static IComparer MemberNameComparer = new _MemberNameComparer ();
154 internal static IComparer OrdinalStringComparer = new _OrdinalStringComparer ();
156 internal static string GetNativeName (string fn)
158 fn = fn.Replace ('.', '_');
159 if (fn.StartsWith ("Mono_Unix_Native"))
160 return fn.Replace ("Mono_Unix_Native", "Mono_Posix");
161 return fn.Replace ("Mono_Unix", "Mono_Posix");
165 abstract class FileGenerator {
166 public abstract void CreateFile (string assembly_name, string file_prefix);
168 public virtual void WriteAssemblyAttributes (Assembly assembly)
172 public abstract void WriteType (Type t, string ns, string fn);
173 public abstract void CloseFile (string file_prefix);
175 protected static void WriteHeader (StreamWriter s, string assembly)
177 WriteHeader (s, assembly, false);
180 protected static void WriteHeader (StreamWriter s, string assembly, bool noConfig)
184 " * This file was automatically generated by make-map from {0}.\n" +
186 " * DO NOT MODIFY.\n" +
190 s.WriteLine ("#include <config.h>");
195 protected static bool CanMapType (Type t, out bool bits)
197 object [] attributes = t.GetCustomAttributes (false);
201 foreach (object attr in attributes) {
202 if (attr.GetType ().Name == "MapAttribute")
204 if (attr.GetType ().Name == "FlagsAttribute")
210 protected static string GetNativeType (Type t)
214 ut = Enum.GetUnderlyingType (t).Name;
215 Type et = t.GetElementType ();
216 if (et != null && et.IsEnum)
217 ut = Enum.GetUnderlyingType (et).Name;
222 case "Boolean": type = "int"; break;
223 case "Byte": type = "unsigned char"; break;
224 case "SByte": type = "signed char"; break;
225 case "Int16": type = "short"; break;
226 case "UInt16": type = "unsigned short"; break;
227 case "Int32": type = "int"; break;
228 case "UInt32": type = "unsigned int"; break;
229 case "UInt32[]": type = "unsigned int*"; break;
230 case "Int64": type = "gint64"; break;
231 case "UInt64": type = "guint64"; break;
232 case "IntPtr": type = "void*"; break;
233 case "Byte[]": type = "void*"; break;
234 case "String": type = "const char*"; break;
235 case "StringBuilder": type = "char*"; break;
236 case "Void": type = "void"; break;
237 case "HandleRef": type = "void*"; break;
240 return string.Format ("{0}{1}", type,
241 t.IsByRef ? "*" : "");
242 return GetTypeName (t);
245 private static string GetTypeName (Type t)
247 if (t.Namespace.StartsWith ("System"))
248 return "int /* warning: unknown mapping for type: " + t.Name + " */";
249 string ts = "struct " +
250 MakeMap.GetNativeName (t.FullName).Replace ("+", "_").Replace ("&", "*")
251 .Replace ("[]", "*");
256 class HeaderFileGenerator : FileGenerator {
259 public override void CreateFile (string assembly_name, string file_prefix)
261 sh = File.CreateText (file_prefix + ".h");
262 WriteHeader (sh, assembly_name);
263 sh.WriteLine ("#ifndef INC_Mono_Posix_" + file_prefix + "_H");
264 sh.WriteLine ("#define INC_Mono_Posix_" + file_prefix + "_H\n");
265 sh.WriteLine ("#include <glib.h>\n");
266 sh.WriteLine ("G_BEGIN_DECLS\n");
269 public override void WriteType (Type t, string ns, string fn)
272 if (!CanMapType (t, out bits))
274 string etype = GetNativeType (t);
276 WriteLiteralValues (sh, t, fn);
277 sh.WriteLine ("int {1}_From{2} ({0} x, {0} *r);", etype, ns, t.Name);
278 sh.WriteLine ("int {1}_To{2} ({0} x, {0} *r);", etype, ns, t.Name);
282 static void WriteLiteralValues (StreamWriter sh, Type t, string n)
284 object inst = Activator.CreateInstance (t);
285 FieldInfo[] fields = t.GetFields ();
286 Array.Sort (fields, MakeMap.MemberNameComparer);
287 foreach (FieldInfo fi in fields) {
290 sh.WriteLine ("#define {0}_{1} 0x{2:x}", n, fi.Name, fi.GetValue (inst));
294 public override void CloseFile (string file_prefix)
296 sh.WriteLine ("G_END_DECLS\n");
297 sh.WriteLine ("#endif /* ndef INC_Mono_Posix_" + file_prefix + "_H */\n");
302 class SourceFileGenerator : FileGenerator {
305 public override void CreateFile (string assembly_name, string file_prefix)
307 sc = File.CreateText (file_prefix + ".c");
308 WriteHeader (sc, assembly_name);
310 if (file_prefix.IndexOf ("/") != -1)
311 file_prefix = file_prefix.Substring (file_prefix.IndexOf ("/") + 1);
312 sc.WriteLine ("#include \"{0}.h\"", file_prefix);
316 public override void WriteAssemblyAttributes (Assembly assembly)
318 object [] x = assembly.GetCustomAttributes (false);
319 Console.WriteLine ("Got: " + x.Length);
320 foreach (object aattr in assembly.GetCustomAttributes (false)) {
321 Console.WriteLine ("Got: " + aattr.GetType ().Name);
322 if (aattr.GetType ().Name == "HeaderAttribute"){
323 WriteDefines (sc, aattr);
324 WriteIncludes (sc, aattr);
329 static void WriteDefines (TextWriter writer, object o)
331 PropertyInfo prop = o.GetType ().GetProperty ("Defines");
333 throw new Exception ("Cannot find 'Defines' property");
335 MethodInfo method = prop.GetGetMethod ();
336 string [] defines = method.Invoke (o, null).ToString ().Split (',');
337 foreach (string def in defines) {
338 writer.WriteLine ("#ifndef {0}", def);
339 writer.WriteLine ("#define {0}", def);
340 writer.WriteLine ("#endif /* ndef {0} */", def);
344 static void WriteIncludes (TextWriter writer, object o)
346 PropertyInfo prop = o.GetType ().GetProperty ("Includes");
348 throw new Exception ("Cannot find 'Includes' property");
350 MethodInfo method = prop.GetGetMethod ();
351 string [] includes = method.Invoke (o, null).ToString ().Split (',');;
352 foreach (string inc in includes){
353 if (inc.Length > 3 &&
354 string.CompareOrdinal (inc, 0, "ah:", 0, 3) == 0) {
355 string i = inc.Substring (3);
356 writer.WriteLine ("#ifdef HAVE_" + (i.ToUpper ().Replace ("/", "_").Replace (".", "_")));
357 writer.WriteLine ("#include <{0}>", i);
358 writer.WriteLine ("#endif");
360 writer.WriteLine ("#include <{0}>", inc);
365 public override void WriteType (Type t, string ns, string fn)
368 if (!CanMapType (t, out bits))
370 string etype = GetNativeType (t);
372 WriteFromManagedType (t, ns, fn, etype, bits);
373 WriteToManagedType (t, ns, fn, etype, bits);
376 private void WriteFromManagedType (Type t, string ns, string fn, string etype, bool bits)
378 sc.WriteLine ("int {1}_From{2} ({0} x, {0} *r)", etype, ns, t.Name);
380 sc.WriteLine ("\t*r = 0;");
381 // For many values, 0 is a valid value, but doesn't have it's own symbol.
382 // Examples: Error (0 means "no error"), WaitOptions (0 means "no options").
383 // Make 0 valid for all conversions.
384 sc.WriteLine ("\tif (x == 0)\n\t\treturn 0;");
385 FieldInfo[] fields = t.GetFields ();
386 Array.Sort (fields, MakeMap.MemberNameComparer);
387 foreach (FieldInfo fi in fields) {
390 if (Attribute.GetCustomAttribute (fi,
391 typeof(ObsoleteAttribute), false) != null) {
392 sc.WriteLine ("\t/* {0}_{1} is obsolete; ignoring */", fn, fi.Name);
396 // properly handle case where [Flags] enumeration has helper
397 // synonyms. e.g. DEFFILEMODE and ACCESSPERMS for mode_t.
398 sc.WriteLine ("\tif ((x & {0}_{1}) == {0}_{1})", fn, fi.Name);
400 sc.WriteLine ("\tif (x == {0}_{1})", fn, fi.Name);
401 sc.WriteLine ("#ifdef {0}", fi.Name);
403 sc.WriteLine ("\t\t*r |= {1};", fn, fi.Name);
405 sc.WriteLine ("\t\t{{*r = {1}; return 0;}}", fn, fi.Name);
406 sc.WriteLine ("#else /* def {0} */\n\t\t{{errno = EINVAL; return -1;}}", fi.Name);
407 sc.WriteLine ("#endif /* ndef {0} */", fi.Name);
410 sc.WriteLine ("\treturn 0;");
412 sc.WriteLine ("\terrno = EINVAL; return -1;"); // return error if not matched
413 sc.WriteLine ("}\n");
416 private void WriteToManagedType (Type t, string ns, string fn, string etype, bool bits)
418 sc.WriteLine ("int {1}_To{2} ({0} x, {0} *r)", etype, ns, t.Name);
420 sc.WriteLine ("\t*r = 0;", etype);
421 // For many values, 0 is a valid value, but doesn't have it's own symbol.
422 // Examples: Error (0 means "no error"), WaitOptions (0 means "no options").
423 // Make 0 valid for all conversions.
424 sc.WriteLine ("\tif (x == 0)\n\t\treturn 0;");
425 FieldInfo[] fields = t.GetFields ();
426 Array.Sort (fields, MakeMap.MemberNameComparer);
427 foreach (FieldInfo fi in fields) {
430 sc.WriteLine ("#ifdef {0}", fi.Name);
432 // properly handle case where [Flags] enumeration has helper
433 // synonyms. e.g. DEFFILEMODE and ACCESSPERMS for mode_t.
434 sc.WriteLine ("\tif ((x & {1}) == {1})\n\t\t*r |= {0}_{1};", fn, fi.Name);
436 sc.WriteLine ("\tif (x == {1})\n\t\t{{*r = {0}_{1}; return 0;}}", fn, fi.Name);
437 sc.WriteLine ("#endif /* ndef {0} */", fi.Name);
440 sc.WriteLine ("\treturn 0;");
442 sc.WriteLine ("\terrno = EINVAL; return -1;");
443 sc.WriteLine ("}\n");
446 public override void CloseFile (string file_prefix)
452 class ConvertFileGenerator : FileGenerator {
455 public override void CreateFile (string assembly_name, string file_prefix)
457 scs = File.CreateText (file_prefix + ".cs");
458 WriteHeader (scs, assembly_name, true);
459 scs.WriteLine ("using System;");
460 scs.WriteLine ("using System.Runtime.InteropServices;");
461 scs.WriteLine ("using Mono.Unix.Native;\n");
462 scs.WriteLine ("namespace Mono.Unix.Native {\n");
463 scs.WriteLine ("\t[CLSCompliant (false)]");
464 scs.WriteLine ("\tpublic sealed /* static */ partial class NativeConvert");
465 scs.WriteLine ("\t{");
466 scs.WriteLine ("\t\tprivate NativeConvert () {}\n");
467 scs.WriteLine ("\t\tprivate const string LIB = \"MonoPosixHelper\";\n");
468 scs.WriteLine ("\t\tprivate static void ThrowArgumentException (object value)");
469 scs.WriteLine ("\t\t{");
470 scs.WriteLine ("\t\t\tthrow new ArgumentOutOfRangeException (\"value\", value,");
471 scs.WriteLine ("\t\t\t\tLocale.GetText (\"Current platform doesn't support this value.\"));");
472 scs.WriteLine ("\t\t}\n");
475 public override void WriteType (Type t, string ns, string fn)
478 if (!CanMapType (t, out bits))
481 string mtype = Enum.GetUnderlyingType(t).Name;
482 ObsoleteAttribute oa = (ObsoleteAttribute) Attribute.GetCustomAttribute (t,
483 typeof(ObsoleteAttribute), false);
484 string obsolete = "";
486 obsolete = string.Format ("[Obsolete (\"{0}\", {1})]\n\t\t",
487 oa.Message, oa.IsError ? "true" : "false");
489 scs.WriteLine ("\t\t{3}[DllImport (LIB, " +
490 "EntryPoint=\"{0}_From{1}\")]\n" +
491 "\t\tprivate static extern int From{1} ({1} value, out {2} rval);\n",
492 ns, t.Name, mtype, obsolete);
493 scs.WriteLine ("\t\t{3}public static bool TryFrom{1} ({1} value, out {2} rval)\n" +
495 "\t\t\treturn From{1} (value, out rval) == 0;\n" +
496 "\t\t}}\n", ns, t.Name, mtype, obsolete);
497 scs.WriteLine ("\t\t{2}public static {0} From{1} ({1} value)", mtype, t.Name, obsolete);
498 scs.WriteLine ("\t\t{");
499 scs.WriteLine ("\t\t\t{0} rval;", mtype);
500 scs.WriteLine ("\t\t\tif (From{0} (value, out rval) == -1)\n" +
501 "\t\t\t\tThrowArgumentException (value);", t.Name);
502 scs.WriteLine ("\t\t\treturn rval;");
503 scs.WriteLine ("\t\t}\n");
504 scs.WriteLine ("\t\t{3}[DllImport (LIB, " +
505 "EntryPoint=\"{0}_To{1}\")]\n" +
506 "\t\tprivate static extern int To{1} ({2} value, out {1} rval);\n",
507 ns, t.Name, mtype, obsolete);
508 scs.WriteLine ("\t\t{2}public static bool TryTo{1} ({0} value, out {1} rval)\n" +
510 "\t\t\treturn To{1} (value, out rval) == 0;\n" +
511 "\t\t}}\n", mtype, t.Name, obsolete);
512 scs.WriteLine ("\t\t{2}public static {1} To{1} ({0} value)", mtype, t.Name, obsolete);
513 scs.WriteLine ("\t\t{");
514 scs.WriteLine ("\t\t\t{0} rval;", t.Name);
515 scs.WriteLine ("\t\t\tif (To{0} (value, out rval) == -1)\n" +
516 "\t\t\t\tThrowArgumentException (value);", t.Name);
517 scs.WriteLine ("\t\t\treturn rval;");
518 scs.WriteLine ("\t\t}\n");
521 public override void CloseFile (string file_prefix)
523 scs.WriteLine ("\t}");
524 scs.WriteLine ("}\n");
529 class ConvertDocFileGenerator : FileGenerator {
532 public override void CreateFile (string assembly_name, string file_prefix)
534 scs = File.CreateText (file_prefix + ".xml");
535 scs.WriteLine (" <!-- BEGIN GENERATED CONTENT");
536 WriteHeader (scs, assembly_name, true);
537 scs.WriteLine (" -->");
540 public override void WriteType (Type t, string ns, string fn)
543 if (!CanMapType (t, out bits))
546 string type = GetCSharpType (t);
547 string mtype = Enum.GetUnderlyingType(t).FullName;
548 string member = t.Name;
549 string ftype = t.FullName;
551 string to_returns = "";
552 string to_remarks = "";
553 string to_exception = "";
556 to_returns = "<returns>An approximation of the equivalent managed value.</returns>";
557 to_remarks = @"<para>The current conversion functions are unable to determine
558 if a value in a <c>[Flags]</c>-marked enumeration <i>does not</i>
559 exist on the current platform. As such, if <paramref name=""value"" />
560 contains a flag value which the current platform doesn't support, it
561 will not be present in the managed value returned.</para>
562 <para>This should only be a problem if <paramref name=""value"" />
563 <i>was not</i> previously returned by
564 <see cref=""M:Mono.Unix.Native.NativeConvert.From" + member + "\" />.</para>\n";
567 to_returns = "<returns>The equivalent managed value.</returns>";
569 <exception cref=""T:System.ArgumentOutOfRangeException"">
570 <paramref name=""value"" /> has no equivalent managed value.
575 <Member MemberName=""TryFrom{1}"">
576 <MemberSignature Language=""C#"" Value=""public static bool TryFrom{1} ({0} value, out {2} rval);"" />
577 <MemberType>Method</MemberType>
579 <ReturnType>System.Boolean</ReturnType>
582 <Parameter Name=""value"" Type=""{0}"" />
583 <Parameter Name=""rval"" Type=""{3}&"" RefType=""out"" />
586 <param name=""value"">The managed value to convert.</param>
587 <param name=""rval"">The OS-specific equivalent value.</param>
588 <summary>Converts a <see cref=""T:{0}"" />
589 enumeration value to an OS-specific value.</summary>
590 <returns><see langword=""true"" /> if the conversion was successful;
591 otherwise, <see langword=""false"" />.</returns>
592 <remarks><para>This is an exception-safe alternative to
593 <see cref=""M:Mono.Unix.Native.NativeConvert.From{1}"" />.</para>
594 <para>If successful, this method stores the OS-specific equivalent
595 value of <paramref name=""value"" /> into <paramref name=""rval"" />.
596 Otherwise, <paramref name=""rval"" /> will contain <c>0</c>.</para>
598 <altmember cref=""M:Mono.Unix.Native.NativeConvert.From{1}"" />
599 <altmember cref=""M:Mono.Unix.Native.NativeConvert.To{1}"" />
600 <altmember cref=""M:Mono.Unix.Native.NativeConvert.TryTo{1}"" />
603 <Member MemberName=""From{1}"">
604 <MemberSignature Language=""C#"" Value=""public static {2} From{1} ({0} value);"" />
605 <MemberType>Method</MemberType>
607 <ReturnType>{3}</ReturnType>
610 <Parameter Name=""value"" Type=""{0}"" />
613 <param name=""value"">The managed value to convert.</param>
614 <summary>Converts a <see cref=""T:{0}"" />
615 to an OS-specific value.</summary>
616 <returns>The equivalent OS-specific value.</returns>
617 <exception cref=""T:System.ArgumentOutOfRangeException"">
618 <paramref name=""value"" /> has no equivalent OS-specific value.
621 <altmember cref=""M:Mono.Unix.Native.NativeConvert.To{1}"" />
622 <altmember cref=""M:Mono.Unix.Native.NativeConvert.TryFrom{1}"" />
623 <altmember cref=""M:Mono.Unix.Native.NativeConvert.TryTo{1}"" />
626 <Member MemberName=""TryTo{1}"">
627 <MemberSignature Language=""C#"" Value=""public static bool TryTo{1} ({2} value, out {0} rval);"" />
628 <MemberType>Method</MemberType>
630 <ReturnType>System.Boolean</ReturnType>
633 <Parameter Name=""value"" Type=""{3}"" />
634 <Parameter Name=""rval"" Type=""{0}&"" RefType=""out"" />
637 <param name=""value"">The OS-specific value to convert.</param>
638 <param name=""rval"">The managed equivalent value</param>
639 <summary>Converts an OS-specific value to a
640 <see cref=""T:{0}"" />.</summary>
641 <returns><see langword=""true"" /> if the conversion was successful;
642 otherwise, <see langword=""false"" />.</returns>
643 <remarks><para>This is an exception-safe alternative to
644 <see cref=""M:Mono.Unix.Native.NativeConvert.To{1}"" />.</para>
645 <para>If successful, this method stores the managed equivalent
646 value of <paramref name=""value"" /> into <paramref name=""rval"" />.
647 Otherwise, <paramref name=""rval"" /> will contain a <c>0</c>
648 cast to a <see cref=""T:{0}"" />.</para>
651 <altmember cref=""M:Mono.Unix.Native.NativeConvert.From{1}"" />
652 <altmember cref=""M:Mono.Unix.Native.NativeConvert.To{1}"" />
653 <altmember cref=""M:Mono.Unix.Native.NativeConvert.TryFrom{1}"" />
656 <Member MemberName=""To{1}"">
657 <MemberSignature Language=""C#"" Value=""public static {0} To{1} ({2} value);"" />
658 <MemberType>Method</MemberType>
660 <ReturnType>{0}</ReturnType>
663 <Parameter Name=""value"" Type=""{3}"" />
666 <param name=""value"">The OS-specific value to convert.</param>
667 <summary>Converts an OS-specific value to a
668 <see cref=""T:{0}"" />.</summary>
669 " + to_returns + "\n" +
674 <altmember cref=""M:Mono.Unix.Native.NativeConvert.From{1}"" />
675 <altmember cref=""M:Mono.Unix.Native.NativeConvert.TryFrom{1}"" />
676 <altmember cref=""M:Mono.Unix.Native.NativeConvert.TryTo{1}"" />
679 ", ftype, member, type, mtype
683 private string GetCSharpType (Type t)
687 ut = Enum.GetUnderlyingType (t).Name;
688 Type et = t.GetElementType ();
689 if (et != null && et.IsEnum)
690 ut = Enum.GetUnderlyingType (et).Name;
695 case "Boolean": type = "bool"; break;
696 case "Byte": type = "byte"; break;
697 case "SByte": type = "sbyte"; break;
698 case "Int16": type = "short"; break;
699 case "UInt16": type = "ushort"; break;
700 case "Int32": type = "int"; break;
701 case "UInt32": type = "uint"; break;
702 case "Int64": type = "long"; break;
703 case "UInt64": type = "ulong"; break;
709 public override void CloseFile (string file_prefix)
711 scs.WriteLine (" <!-- END GENERATED CONTENT -->");
716 class MphPrototypeFileGenerator : FileGenerator {
718 Hashtable methods = new Hashtable ();
719 Hashtable structs = new Hashtable ();
721 public override void CreateFile (string assembly_name, string file_prefix)
723 icall = File.CreateText (file_prefix + "-icalls.h");
724 WriteHeader (icall, assembly_name);
725 icall.WriteLine ("#ifndef INC_Mono_Posix_" + file_prefix + "_ICALLS_H");
726 icall.WriteLine ("#define INC_Mono_Posix_" + file_prefix + "_ICALLS_H\n");
727 icall.WriteLine ("#include <glib.h>\n");
728 icall.WriteLine ("G_BEGIN_DECLS\n");
730 // Kill warning about unused method
734 public override void WriteType (Type t, string ns, string fn)
736 BindingFlags bf = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
737 foreach (MethodInfo m in t.GetMethods (bf)) {
738 if ((m.Attributes & MethodAttributes.PinvokeImpl) == 0)
740 DllImportAttribute dia = GetDllImportInfo (m);
742 Console.WriteLine ("Unable to emit native prototype for P/Invoke " +
746 // we shouldn't declare prototypes for POSIX, etc. functions.
747 if (dia.Value != "MonoPosixHelper" || IsOnExcludeList (dia.EntryPoint))
749 methods [dia.EntryPoint] = m;
754 private static DllImportAttribute GetDllImportInfo (MethodInfo method)
756 // .NET 2.0 synthesizes pseudo-attributes such as DllImport
757 DllImportAttribute dia = (DllImportAttribute) Attribute.GetCustomAttribute (method,
758 typeof(DllImportAttribute), false);
762 // We're not on .NET 2.0; assume we're on Mono and use some internal
764 Type MonoMethod = Type.GetType ("System.Reflection.MonoMethod", false);
765 if (MonoMethod == null) {
766 Console.WriteLine ("cannot find MonoMethod");
769 MethodInfo GetDllImportAttribute =
770 MonoMethod.GetMethod ("GetDllImportAttribute",
771 BindingFlags.Static | BindingFlags.NonPublic);
772 if (GetDllImportAttribute == null) {
773 Console.WriteLine ("cannot find GetDllImportAttribute");
776 IntPtr mhandle = method.MethodHandle.Value;
777 return (DllImportAttribute) GetDllImportAttribute.Invoke (null,
778 new object[]{mhandle});
781 private static string[] ExcludeList = new string[]{
782 "Mono_Posix_Stdlib_snprintf",
785 private bool IsOnExcludeList (string method)
787 int idx = Array.BinarySearch (ExcludeList, method);
788 return (idx >= 0 && idx < ExcludeList.Length) ? true : false;
791 private void RecordStructs (MethodInfo method)
793 ParameterInfo[] parameters = method.GetParameters ();
794 foreach (ParameterInfo pi in parameters) {
795 string s = GetNativeType (pi.ParameterType);
796 if (s.StartsWith ("struct"))
801 public override void CloseFile (string file_prefix)
803 icall.WriteLine ("/*\n * Structure Declarations\n */");
804 foreach (string s in Sort (structs.Keys))
805 icall.WriteLine ("{0};", s.Replace ("*", ""));
809 icall.WriteLine ("/*\n * Function Declarations\n */");
810 foreach (string method in Sort (methods.Keys)) {
811 WriteMethodDeclaration ((MethodInfo) methods [method], method);
814 icall.WriteLine ("\nG_END_DECLS\n");
815 icall.WriteLine ("#endif /* ndef INC_Mono_Posix_" + file_prefix + "_ICALLS_H */\n");
819 private static IEnumerable Sort (ICollection c)
821 ArrayList al = new ArrayList (c);
822 al.Sort (MakeMap.OrdinalStringComparer);
826 private void WriteMethodDeclaration (MethodInfo method, string entryPoint)
828 icall.Write ("{0} ", GetNativeType (method.ReturnType));
829 icall.Write ("{0} ", entryPoint);
830 ParameterInfo[] parameters = method.GetParameters();
831 if (parameters.Length == 0) {
832 icall.WriteLine ("(void);");
835 if (parameters.Length > 0) {
837 WriteParameterDeclaration (parameters [0]);
839 for (int i = 1; i < parameters.Length; ++i) {
841 WriteParameterDeclaration (parameters [i]);
843 icall.WriteLine (");");
846 private void DumpTypeInfo (Type t)
851 icall.WriteLine ("\t\t/* Type Info for " + t.FullName + ":");
852 foreach (MemberInfo mi in typeof(Type).GetMembers()) {
853 icall.WriteLine ("\t\t\t{0}={1}", mi.Name, GetMemberValue (mi, t));
855 icall.WriteLine ("\t\t */");
858 private static string GetMemberValue (MemberInfo mi, Type t)
861 switch (mi.MemberType) {
862 case MemberTypes.Constructor:
863 case MemberTypes.Method: {
864 MethodBase b = (MethodBase) mi;
865 if (b.GetParameters().Length == 0)
866 return b.Invoke (t, new object[]{}).ToString();
867 return "<<cannot invoke>>";
869 case MemberTypes.Field:
870 return ((FieldInfo) mi).GetValue (t).ToString ();
871 case MemberTypes.Property: {
872 PropertyInfo pi = (PropertyInfo) mi;
874 return "<<cannot read>>";
875 return pi.GetValue (t, null).ToString ();
878 return "<<unknown value>>";
881 catch (Exception e) {
882 return "<<exception reading member: " + e.Message + ">>";
886 private void WriteParameterDeclaration (ParameterInfo pi)
888 // DumpTypeInfo (pi.ParameterType);
889 icall.Write ("{0} {1}", GetNativeType (pi.ParameterType), pi.Name);