Index: configure.in
===================================================================
--- configure.in	(revision 66758)
+++ configure.in	(working copy)
@@ -88,6 +88,14 @@
 asn1view/art/Makefile
 asn1view/gtk/Makefile
 asn1view/common/Makefile
+create-native-map/Makefile
+create-native-map/bin/Makefile
+create-native-map/lib/Makefile
+create-native-map/lib/create-native-map/Makefile
+create-native-map/lib/pkgconfig/Makefile
+create-native-map/lib/pkgconfig/create-native-map.pc
+create-native-map/man/Makefile
+create-native-map/src/Makefile
 ])
 
 echo "---"
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 66758)
+++ ChangeLog	(working copy)
@@ -1,3 +1,8 @@
+2006-10-18  Jonathan Pryor <jonpryor@vt.edu>
+
+	* configure.in: Add create-native-map program.
+	* Makefile.am: Build create-native-map.
+
 2006-01-16 Rafael Ferreira <raf@ophion.org>
 	* configure.in: updated to use gtk-sharp-2.0/gecko-sharp-2.0
 	this fixes bugs# 76054 & 76544 related to Pango bugs.
Index: create-native-map/lib/create-native-map/Makefile.am
===================================================================
--- create-native-map/lib/create-native-map/Makefile.am	(revision 0)
+++ create-native-map/lib/create-native-map/Makefile.am	(revision 0)
@@ -0,0 +1,2 @@
+# do nothing
+
Index: create-native-map/lib/pkgconfig/create-native-map.pc.in
===================================================================
--- create-native-map/lib/pkgconfig/create-native-map.pc.in	(revision 0)
+++ create-native-map/lib/pkgconfig/create-native-map.pc.in	(revision 0)
@@ -0,0 +1,13 @@
+prefix=${pcfiledir}/../..
+exec_prefix=${pcfiledir}/../..
+libdir=@libdir@
+includedir=${prefix}/include
+assemblies_dir=${libdir}/create-native-map
+Sources=${assemblies_dir}/MapAttribute.cs
+Programs=${assemblies_dir}/create-native-map.exe
+ 
+Name: create-native-map
+Description: C/C# Mapping Generator
+Version: @VERSION@
+Requires: 
+Libs: 
Index: create-native-map/lib/pkgconfig/Makefile.am
===================================================================
--- create-native-map/lib/pkgconfig/Makefile.am	(revision 0)
+++ create-native-map/lib/pkgconfig/Makefile.am	(revision 0)
@@ -0,0 +1,8 @@
+
+pkgconfigdir = $(prefix)/lib/pkgconfig
+pkgconfig_DATA = create-native-map.pc
+
+DISTCLEANFILES = create-native-map.pc
+
+EXTRA_DIST = create-native-map.pc.in
+
Index: create-native-map/lib/Makefile.am
===================================================================
--- create-native-map/lib/Makefile.am	(revision 0)
+++ create-native-map/lib/Makefile.am	(revision 0)
@@ -0,0 +1 @@
+SUBDIRS = create-native-map pkgconfig
Index: create-native-map/src/test.h.ref
===================================================================
--- create-native-map/src/test.h.ref	(revision 0)
+++ create-native-map/src/test.h.ref	(revision 0)
@@ -0,0 +1,147 @@
+/*
+ * This file was automatically generated by create-native-map from TestMap.dll.
+ *
+ * DO NOT MODIFY.
+ */
+
+#ifndef INC_TestMap_test_H
+#define INC_TestMap_test_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Public Macros
+ */
+#ifndef DefineMe
+#define DefineMe 42
+#endif /* ndef DefineMe */
+
+
+/*
+ * Public Includes
+ */
+#include <stdlib.h>
+
+/*
+ * Enumerations
+ */
+enum MakeMap_Test_TestEnum {
+	MakeMap_Test_TestEnum_Bar           = 0x00000001,
+	#define MakeMap_Test_TestEnum_Bar     MakeMap_Test_TestEnum_Bar
+	MakeMap_Test_TestEnum_Baz           = 0x00000002,
+	#define MakeMap_Test_TestEnum_Baz     MakeMap_Test_TestEnum_Baz
+	MakeMap_Test_TestEnum_Foo           = 0x00000000,
+	#define MakeMap_Test_TestEnum_Foo     MakeMap_Test_TestEnum_Foo
+	MakeMap_Test_TestEnum_Qux           = 0x00000003,
+	#define MakeMap_Test_TestEnum_Qux     MakeMap_Test_TestEnum_Qux
+};
+int MakeMap_Test_FromTestEnum (int x, int *r);
+int MakeMap_Test_ToTestEnum (int x, int *r);
+
+enum MakeMap_Rename_Colors {
+	MakeMap_Rename_Colors_Blue          = 0x00000001,
+	#define MakeMap_Rename_Colors_Blue    MakeMap_Rename_Colors_Blue
+	MakeMap_Rename_Colors_Green         = 0x00000002,
+	#define MakeMap_Rename_Colors_Green   MakeMap_Rename_Colors_Green
+	MakeMap_Rename_Colors_Red           = 0x00000000,
+	#define MakeMap_Rename_Colors_Red     MakeMap_Rename_Colors_Red
+};
+int MakeMap_Rename_FromColors (int x, int *r);
+int MakeMap_Rename_ToColors (int x, int *r);
+
+
+/*
+ * Managed Structure Declarations
+ */
+
+struct MakeMap_Test_Baz;
+struct MakeMap_Test_Foo;
+struct MakeMap_Test_FooHolder;
+struct MakeMap_Test_ForDelegate;
+struct MakeMap_Test_Qux;
+struct MakeMap_Rename_Stat;
+
+/*
+ * Inferred Structure Declarations
+ */
+
+struct foo;
+struct foo_holder;
+
+/*
+ * Delegate Declarations
+ */
+
+typedef void (*DelArrayBaz) (int i, struct MakeMap_Test_Baz** b);
+typedef void (*DelArrayFoo) (int i, struct MakeMap_Test_Foo* f);
+typedef void (*DelBaz) (int i, struct MakeMap_Test_Baz* b);
+typedef void (*DelFoo) (int i, struct MakeMap_Test_Foo f);
+typedef void (*DelRefArrayBaz) (int i, struct MakeMap_Test_Baz*** b);
+typedef void (*DelRefArrayFoo) (int i, struct MakeMap_Test_Foo** f);
+typedef void (*DelRefBaz) (int i, struct MakeMap_Test_Baz** b);
+typedef void (*DelRefFoo) (int i, struct MakeMap_Test_Foo* f);
+typedef char* (*MyDelegate) (int b1, unsigned char b2, signed char b3, short s1, unsigned short us1, int i1, unsigned int ui1, gint64 l1, guint64 ul1, void* p1, void* p2, const char* s2, char* sb1, void* h, struct MakeMap_Test_ForDelegate fd);
+
+/*
+ * Structures
+ */
+
+struct MakeMap_Test_Baz {
+	DelFoo         b1;
+	DelRefFoo      b2;
+	DelArrayFoo    b3;
+	DelRefArrayFoo b4;
+	DelBaz         b5;
+	DelRefBaz      b6;
+	DelArrayBaz    b7;
+	DelRefArrayBaz b8;
+};
+
+struct MakeMap_Test_Foo {
+	int    foo;
+	void*  p;
+	gint64 autoconf_me;
+};
+
+int
+MakeMap_Test_FromFoo (struct MakeMap_Test_Foo* from, struct foo *to);
+int
+MakeMap_Test_ToFoo (struct foo *from, struct MakeMap_Test_Foo* to);
+
+
+struct MakeMap_Test_FooHolder {
+	struct MakeMap_Test_Foo foo;   /* struct foo */
+	int                     mode;
+};
+
+int
+MakeMap_Test_FromFooHolder (struct MakeMap_Test_FooHolder* from, struct foo_holder *to);
+int
+MakeMap_Test_ToFooHolder (struct foo_holder *from, struct MakeMap_Test_FooHolder* to);
+
+
+struct MakeMap_Test_ForDelegate {
+	int i;
+};
+
+struct MakeMap_Test_Qux {
+	int                      i;
+	struct MakeMap_Test_Baz* b;
+};
+
+struct MakeMap_Rename_Stat {
+	gint64 st_atime_;  /* time_t */
+};
+
+
+/*
+ * Functions
+ */
+void UseQux (DelFoo b, struct MakeMap_Test_Qux** q);
+
+G_END_DECLS
+
+#endif /* ndef INC_Mono_Posix_test_H */
+
Index: create-native-map/src/TestMap.cs
===================================================================
--- create-native-map/src/TestMap.cs	(revision 0)
+++ create-native-map/src/TestMap.cs	(revision 0)
@@ -0,0 +1,93 @@
+// Test file for make-map.cs
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+// Make sure that a null namespace doesn't kill make-map
+class GlobalClass {}
+
+namespace MakeMap.Test {
+	struct ForDelegate {int i;}
+	[Map]
+	delegate string MyDelegate (
+			bool b1, byte b2, sbyte b3, short s1, ushort us1, 
+			int i1, uint ui1, long l1, ulong ul1, 
+			IntPtr p1, UIntPtr p2, string s2, StringBuilder sb1,
+			HandleRef h, ForDelegate fd);
+
+	[Map]
+	enum TestEnum {
+		Foo,
+		Bar,
+		Baz,
+		Qux,
+	}
+
+	[Map ("struct foo")]
+	struct Foo {
+		public int foo;
+
+		public IntPtr p;
+
+		// this should be within a #ifdef HAVE_AUTOCONF_ME block, due to
+		// --autoconf-member.
+		public long autoconf_me;
+	}
+
+	[Map ("struct foo_holder")]
+	struct FooHolder {
+		public Foo      foo;
+		public TestEnum mode;
+	}
+
+	delegate void DelFoo (int i, Foo f);
+	delegate void DelRefFoo (int i, ref Foo f);
+	delegate void DelArrayFoo (int i, Foo[] f);
+	delegate void DelRefArrayFoo (int i, ref Foo[] f);
+	delegate void DelBaz (int i, Baz b);
+	delegate void DelRefBaz (int i, ref Baz b);
+	delegate void DelArrayBaz (int i, Baz[] b);
+	delegate void DelRefArrayBaz (int i, ref Baz[] b);
+
+	[StructLayout (LayoutKind.Sequential)]
+	class Baz {
+		public DelFoo b1;
+		public DelRefFoo b2;
+		public DelArrayFoo b3;
+		public DelRefArrayFoo b4;
+		public DelBaz b5;
+		public DelRefBaz b6;
+		public DelArrayBaz b7;
+		public DelRefArrayBaz b8;
+	}
+
+	[StructLayout (LayoutKind.Sequential)]
+	class Qux {
+		public int i;
+		public Baz b;
+	}
+
+	class NativeMethods {
+		[DllImport ("NativeLib")]
+		private static extern void UseQux (DelFoo b, ref Qux q);
+
+		// This shouldn't appear in test.h, due to --exclude-native-symbol
+		[DllImport ("NativeLib")]
+		private static extern void exclude_native_symbol ();
+	}
+}
+
+// Testing namespace renaming; this should be NSTo within test.h
+namespace MakeMap.ToBeRenamed {
+	[Map]
+	class Stat {
+		// this should be st_atime_ in test.h due to --rename-member.
+		[Map ("time_t")] public long st_atime;
+	}
+
+	[Map]
+	enum Colors {
+		Red, Blue, Green
+	}
+}
+
Index: create-native-map/src/MapAttribute.cs
===================================================================
--- create-native-map/src/MapAttribute.cs	(revision 0)
+++ create-native-map/src/MapAttribute.cs	(revision 0)
@@ -0,0 +1,54 @@
+//
+// MapAttribute.cs
+//
+// Author:
+//   Miguel de Icaza (miguel@gnome.org)
+//
+// (C) Novell, Inc.  
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+
+[AttributeUsage (
+		AttributeTargets.Class    |
+		AttributeTargets.Delegate |
+		AttributeTargets.Enum     |
+		AttributeTargets.Field    |
+		AttributeTargets.Struct)]
+internal class MapAttribute : Attribute {
+	private string nativeType;
+
+	public MapAttribute ()
+	{
+	}
+
+	public MapAttribute (string nativeType)
+	{
+		this.nativeType = nativeType;
+	}
+
+	public string NativeType {
+		get {return nativeType;}
+	}
+}
+
Index: create-native-map/src/create-native-map.cs
===================================================================
--- create-native-map/src/create-native-map.cs	(revision 0)
+++ create-native-map/src/create-native-map.cs	(working copy)
@@ -1,5 +1,5 @@
 //
-// MakeMap.cs: Builds a C map of constants defined on C# land
+// create-native-map.cs: Builds a C map of constants defined on C# land
 //
 // Authors:
 //  Miguel de Icaza (miguel@novell.com)
@@ -30,12 +30,17 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 using System;
-using System.Collections;
+using System.Collections.Generic;
 using System.IO;
 using System.Globalization;
 using System.Reflection;
 using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Text.RegularExpressions;
 
+using Mono.Unix.Native;
+
 delegate void CreateFileHandler (string assembly_name, string file_prefix);
 delegate void AssemblyAttributesHandler (Assembly assembly);
 delegate void TypeHandler (Type t, string ns, string fn);
@@ -50,11 +55,28 @@
 			new SourceFileGenerator (),
 			new ConvertFileGenerator (),
 			new ConvertDocFileGenerator (),
-			new MphPrototypeFileGenerator (),
 		};
 
+		Configuration config = new Configuration ();
+		bool exit = false;
+		try {
+			exit = !config.Parse (args);
+		}
+		catch (Exception e) {
+			Console.WriteLine ("{0}: error: {1}", 
+					Environment.GetCommandLineArgs () [0], e.Message);
+			exit = true;
+		}
+		if (exit) {
+			Configuration.ShowHelp ();
+			return 1;
+		}
+
+		MapUtils.config = config;
+
 		MakeMap composite = new MakeMap ();
 		foreach (FileGenerator g in generators) {
+			g.Configuration = config;
 			composite.FileCreators += new CreateFileHandler (g.CreateFile);
 			composite.AssemblyAttributesHandler += 
 				new AssemblyAttributesHandler (g.WriteAssemblyAttributes);
@@ -62,7 +84,7 @@
 			composite.FileClosers += new CloseFileHandler (g.CloseFile);
 		}
 
-		return composite.Run (args);
+		return composite.Run (config);
 	}
 
 	event CreateFileHandler FileCreators;
@@ -70,43 +92,34 @@
 	event TypeHandler TypeHandler;
 	event CloseFileHandler FileClosers;
 
-	int Run (string[] args)
+	int Run (Configuration config)
 	{
-		if (args.Length != 2){
-			Console.WriteLine ("Usage is: make-map assembly output");
-			return 1;
-		}
-		
-		string assembly_name = args[0];
-		string output = args[1];
+		FileCreators (config.AssemblyFileName, config.OutputPrefix);
 
-		FileCreators (assembly_name, output);
-
-		Assembly assembly = Assembly.LoadFrom (assembly_name);
+		Assembly assembly = Assembly.LoadFrom (config.AssemblyFileName);
 		AssemblyAttributesHandler (assembly);
 		
 		Type [] exported_types = assembly.GetTypes ();
 		Array.Sort (exported_types, new TypeFullNameComparer ());
 			
 		foreach (Type t in exported_types) {
-			string ns = t.Namespace;
+			string ns = MapUtils.GetNamespace (t);
+			/*
 			if (ns == null || !ns.StartsWith ("Mono"))
 				continue;
-			string fn = GetNativeName (t.FullName);
-			ns = GetNativeName (ns);
+			 */
+			string fn = MapUtils.GetManagedType (t);
 
 			TypeHandler (t, ns, fn);
 		}
-		FileClosers (output);
+		FileClosers (config.OutputPrefix);
 
 		return 0;
 	}
 
-	private class TypeFullNameComparer : IComparer {
-		public int Compare (object o1, object o2)
+	private class TypeFullNameComparer : IComparer<Type> {
+		public int Compare (Type t1, Type t2)
 		{
-			Type t1 = o1 as Type;
-			Type t2 = o2 as Type;
 			if (t1 == t2)
 				return 0;
 			if (t1 == null)
@@ -117,12 +130,406 @@
 					t1.FullName, t2.FullName, CompareOptions.Ordinal);
 		}
 	}
+}
 
-	private class _MemberNameComparer : IComparer {
-		public int Compare (object o1, object o2)
+class Configuration {
+	Dictionary<string, string> renameMembers = new Dictionary<string, string> ();
+	Dictionary<string, string> renameNamespaces = new Dictionary<string, string> ();
+	List<string> libraries = new List<string>();
+	List<string> optionals = new List<string> ();
+	List<string> excludes  = new List<string> ();
+	List<string> iheaders  = new List<string> ();
+	List<string> pheaders  = new List<string> ();
+	List<string> imacros   = new List<string> ();
+	List<string> pmacros   = new List<string> ();
+	string assembly_name;
+	string output;
+
+	delegate void ArgumentHandler (Configuration c, string name, string value);
+	static Dictionary<string, ArgumentHandler> handlers;
+
+	static Configuration ()
+	{
+		handlers = new Dictionary <string, ArgumentHandler> ();
+		handlers ["autoconf-header"] = delegate (Configuration c, string name, string value) {
+			c.iheaders.Add ("ah:" + name);
+		};
+		handlers ["autoconf-member"] = delegate (Configuration c, string name, string value) {
+			c.optionals.Add (name);
+		};
+		handlers ["impl-header"]  = delegate (Configuration c, string name, string value) {
+			c.iheaders.Add (name);
+		};
+		handlers ["impl-macro"] = delegate (Configuration c, string name, string value) {
+			if (value != null)
+				name += "=" + value;
+			c.imacros.Add (name);
+		};
+		handlers ["library"] = delegate (Configuration c, string name, string value) {
+			c.libraries.Add (name);
+		};
+		handlers ["exclude-native-symbol"] = delegate (Configuration c, string name, string value) {
+			c.excludes.Add (name);
+		};
+		handlers ["public-header"] = delegate (Configuration c, string name, string value) {
+			c.pheaders.Add (name);
+		};
+		handlers ["public-macro"] = delegate (Configuration c, string name, string value) {
+			if (value != null)
+				name += "=" + value;
+			c.pmacros.Add (name);
+		};
+		handlers ["rename-member"] = delegate (Configuration c, string name, string value) {
+			if (value == null) {
+				throw new Exception ("missing rename value");
+			}
+			c.renameMembers [name] = value;
+		};
+		handlers ["rename-namespace"] = delegate (Configuration c, string name, string value) {
+			if (value == null) {
+				throw new Exception ("missing rename value");
+			}
+			value = value.Replace (".", "_");
+			c.renameNamespaces [name] = value;
+		};
+	}
+
+	public Configuration ()
+	{
+	}
+
+	public List<string> NativeLibraries {
+		get {return libraries;}
+	}
+
+	public List<string> AutoconfMembers {
+		get {return optionals;}
+	}
+
+	public List<string> NativeExcludeSymbols {
+		get {return excludes;}
+	}
+
+	public List<string> PublicHeaders {
+		get {return pheaders;}
+	}
+
+	public List<string> PublicMacros {
+		get {return pmacros;}
+	}
+
+	public List<string> ImplementationHeaders {
+		get {return iheaders;}
+	}
+
+	public List<string> ImplementationMacros {
+		get {return imacros;}
+	}
+
+	public IDictionary<string, string> MemberRenames {
+		get {return renameMembers;}
+	}
+
+	public IDictionary<string, string> NamespaceRenames {
+		get {return renameNamespaces;}
+	}
+
+	public string AssemblyFileName {
+		get {return assembly_name;}
+	}
+
+	public string OutputPrefix {
+		get {return output;}
+	}
+
+	const string NameValue = @"(?<Name>[^=]+)(=(?<Value>.*))?";
+	const string Argument  = @"^--(?<Argument>[\w-]+)([=:]" + NameValue + ")?$";
+
+	public bool Parse (string[] args)
+	{
+		Regex argRE = new Regex (Argument);
+		Regex valRE = new Regex (NameValue);
+
+		for (int i = 0; i < args.Length; ++i) {
+			Match m = argRE.Match (args [i]);
+			if (m.Success) {
+				string arg = m.Groups ["Argument"].Value;
+				if (arg == "help")
+					return false;
+				if (!m.Groups ["Name"].Success) {
+					if ((i+1) >= args.Length)
+						throw new Exception (
+								string.Format ("missing value for argument {0}", args [i]));
+					m = valRE.Match (args [++i]);
+					if (!m.Success) {
+						throw new Exception (
+								string.Format ("invalid value for argument {0}: {1}", 
+									args [i-1], args[i]));
+					}
+				}
+				string name  = m.Groups ["Name"].Value;
+				string value = m.Groups ["Value"].Success ? m.Groups ["Value"].Value : null;
+				if (handlers.ContainsKey (arg)) {
+					handlers [arg] (this, name, value);
+				}
+				else {
+					throw new Exception ("invalid argument " +  arg);
+				}
+			}
+			else if (assembly_name == null) {
+				assembly_name = args [i];
+			}
+			else {
+				output = args [i];
+			}
+		}
+
+		if (assembly_name == null)
+			throw new Exception ("missing ASSEMBLY");
+		if (output == null)
+			throw new Exception ("missing OUTPUT-PREFIX");
+
+		libraries.Sort ();
+		optionals.Sort ();
+		excludes.Sort ();
+
+		return true;
+	}
+
+	public static void ShowHelp ()
+	{
+		Console.WriteLine (
+				"Usage: create-native-map \n" +
+				"\t[--autoconf-header=HEADER]* \n" +
+				"\t[--autoconf-member=MEMBER]* \n" +
+				"\t[--exclude-native-symbol=SYMBOL]*\n" +
+				"\t[--impl-header=HEADER]* \n" +
+				"\t[--impl-macro=MACRO]* \n" +
+				"\t[--library=LIBRARY]+ \n" + 
+				"\t[--public-header=HEADER]* \n" +
+				"\t[--public-macro=MACRO]* \n" +
+				"\t[--rename-member=FROM=TO]* \n" + 
+				"\t[--rename-namespace=FROM=TO]*\n" +
+				"\tASSEMBLY OUTPUT-PREFIX"
+		);
+	}
+}
+
+static class MapUtils {
+	internal static Configuration config;
+
+	public static T GetCustomAttribute <T> (MemberInfo element) where T : Attribute
+	{
+		return (T) Attribute.GetCustomAttribute (element, typeof(T), true);
+	}
+
+	public static T GetCustomAttribute <T> (Assembly assembly) where T : Attribute
+	{
+		return (T) Attribute.GetCustomAttribute (assembly, typeof(T), true);
+	}
+
+	public static T[] GetCustomAttributes <T> (MemberInfo element) where T : Attribute
+	{
+		return (T[]) Attribute.GetCustomAttributes (element, typeof(T), true);
+	}
+
+	public static T[] GetCustomAttributes <T> (Assembly assembly) where T : Attribute
+	{
+		return (T[]) Attribute.GetCustomAttributes (assembly, typeof(T), true);
+	}
+
+	public static MapAttribute GetMapAttribute (ICustomAttributeProvider element)
+	{
+		foreach (object o in element.GetCustomAttributes (true)) {
+			if (!IsMapAttribute (o))
+				continue;
+			string nativeType   = GetPropertyValue (o, "NativeType");
+			MapAttribute map = nativeType == null 
+				? new MapAttribute () 
+				: new MapAttribute (nativeType);
+			return map;
+		}
+		return null;
+	}
+
+	private static bool IsMapAttribute (object o)
+	{
+		Type t = o.GetType ();
+		do {
+			if (t.Name == "MapAttribute") {
+				return true;
+			}
+			t = t.BaseType;
+		} while (t != null);
+		return false;
+	}
+
+	private static string GetPropertyValue (object o, string property)
+	{
+		PropertyInfo p = o.GetType().GetProperty (property);
+		if (p == null)
+			return null;
+		if (!p.CanRead)
+			return null;
+		object v = p.GetValue (o, new object[0]);
+		string s = v == null ? null : v.ToString ();
+		if (s != null)
+			return s.Length == 0 ? null : s;
+		return null;
+	}
+
+	public static bool IsIntegralType (Type t)
+	{
+		return t == typeof(byte) || t == typeof(sbyte) || t == typeof(char) ||
+			t == typeof(short) || t == typeof(ushort) || 
+			t == typeof(int) || t == typeof(uint) || 
+			t == typeof(long) || t == typeof(ulong);
+	}
+
+	public static bool IsBlittableType (Type t)
+	{
+		return IsIntegralType (t) || t == typeof(IntPtr) || t == typeof(UIntPtr);
+	}
+
+	public static string GetNativeType (Type t)
+	{
+		Type et = GetElementType (t);
+		string ut = et.Name;
+		if (et.IsEnum)
+			ut = Enum.GetUnderlyingType (et).Name;
+
+		string type = null;
+
+		switch (ut) {
+			case "Boolean":       type = "int";             break;
+			case "Byte":          type = "unsigned char";   break;
+			case "SByte":         type = "signed char";     break;
+			case "Int16":         type = "short";           break;
+			case "UInt16":        type = "unsigned short";  break;
+			case "Int32":         type = "int";             break;
+			case "UInt32":        type = "unsigned int";    break;
+			case "Int64":         type = "gint64";          break;
+			case "UInt64":        type = "guint64";         break;
+			case "IntPtr":        type = "void*";           break;
+			case "UIntPtr":       type = "void*";           break;
+			case "String":        type = "const char";      break; /* ref type */
+			case "StringBuilder": type = "char";            break; /* ref type */
+			case "Void":          type = "void";            break;
+			case "HandleRef":     type = "void*";           break;
+		}
+		bool isDelegate = IsDelegate (t);
+		if (type == null)
+			type = isDelegate ? t.Name : GetStructName (t);
+		if (!et.IsValueType && !isDelegate) {
+			type += "*";
+		}
+		while (t.HasElementType) {
+			t = t.GetElementType ();
+			type += "*";
+		}
+		return type;
+		//return (t.IsByRef || t.IsArray || (!t.IsValueType && !isDelegate)) ? type + "*" : type;
+	}
+
+	public static bool IsDelegate (Type t)
+	{
+		return typeof(Delegate).IsAssignableFrom (t);
+	}
+
+	private static string GetStructName (Type t)
+	{
+		t = GetElementType (t);
+		return "struct " + GetManagedType (t);
+	}
+
+	public static Type GetElementType (Type t)
+	{
+		while (t.HasElementType) {
+			t = t.GetElementType ();
+		}
+		return t;
+	}
+
+	public static string GetNamespace (Type t)
+	{
+		if (t.Namespace == null)
+			return "";
+		if (config.NamespaceRenames.ContainsKey (t.Namespace))
+			return config.NamespaceRenames [t.Namespace];
+#if false
+		/* this is legacy behavior; Mono.Posix.dll should be fixed to use
+		 * MapAttribute.ExportPrefix so we don't need this hack anymore */
+		if (t.Namespace == "Mono.Unix.Native" || t.Namespace == "Mono.Unix")
+			return "Mono_Posix";
+#endif
+		return t.Namespace.Replace ('.', '_');
+	}
+
+	public static string GetManagedType (Type t)
+	{
+		string ns = GetNamespace (t);
+		string tn = 
+			(t.DeclaringType != null ? t.DeclaringType.Name + "_" : "") + t.Name;
+		return ns + "_" + tn;
+	}
+
+	public static string GetNativeType (FieldInfo field)
+	{
+		MapAttribute map = 
+			GetMapAttribute (field)
+			??
+			GetMapAttribute (field.FieldType);
+		if (map != null)
+			return map.NativeType;
+		return null;
+	}
+
+	public static string GetFunctionDeclaration (string name, MethodInfo method)
+	{
+		StringBuilder sb = new StringBuilder ();
+#if false
+		Console.WriteLine (t);
+		foreach (object o in t.GetMembers ())
+			Console.WriteLine ("\t" + o);
+#endif
+		sb.Append (method.ReturnType == typeof(string) 
+				? "char*" 
+				: MapUtils.GetNativeType (method.ReturnType));
+		sb.Append (" ").Append (name).Append (" (");
+
+
+		ParameterInfo[] parameters = method.GetParameters();
+		if (parameters.Length == 0) {
+			sb.Append ("void");
+		}
+		else {
+			if (parameters.Length > 0) {
+				WriteParameterDeclaration (sb, parameters [0]);
+			}
+			for (int i = 1; i < parameters.Length; ++i) {
+				sb.Append (", ");
+				WriteParameterDeclaration (sb, parameters [i]);
+			}
+		}
+		sb.Append (")");
+		return sb.ToString ();
+	}
+
+	private static void WriteParameterDeclaration (StringBuilder sb, ParameterInfo pi)
+	{
+		// DumpTypeInfo (pi.ParameterType);
+		string nt = GetNativeType (pi.ParameterType);
+		sb.AppendFormat ("{0} {1}", nt, pi.Name);
+	}
+
+	internal class _MemberNameComparer : IComparer<MemberInfo>, IComparer <FieldInfo> {
+		public int Compare (FieldInfo m1, FieldInfo m2)
 		{
-			MemberInfo m1 = o1 as MemberInfo;
-			MemberInfo m2 = o2 as MemberInfo;
+			return Compare ((MemberInfo) m1, (MemberInfo) m2);
+		}
+
+		public int Compare (MemberInfo m1, MemberInfo m2)
+		{
 			if (m1 == m2)
 				return 0;
 			if (m1 == null)
@@ -134,11 +541,9 @@
 		}
 	}
 
-	private class _OrdinalStringComparer : IComparer {
-		public int Compare (object o1, object o2)
+	private class _OrdinalStringComparer : IComparer<string> {
+		public int Compare (string s1, string s2)
 		{
-			string s1 = o1 as string;
-			string s2 = o2 as string;
 			if (object.ReferenceEquals (s1, s2))
 				return 0;
 			if (s1 == null)
@@ -150,19 +555,18 @@
 		}
 	}
 
-	internal static IComparer MemberNameComparer = new _MemberNameComparer ();
-	internal static IComparer OrdinalStringComparer = new _OrdinalStringComparer ();
+	internal static _MemberNameComparer MemberNameComparer = new _MemberNameComparer ();
+	internal static IComparer<string> OrdinalStringComparer = new _OrdinalStringComparer ();
+}
 
-	internal static string GetNativeName (string fn)
-	{
-		fn = fn.Replace ('.', '_');
-		if (fn.StartsWith ("Mono_Unix_Native"))
-			return fn.Replace ("Mono_Unix_Native", "Mono_Posix");
-		return fn.Replace ("Mono_Unix", "Mono_Posix");
+abstract class FileGenerator {
+	private Configuration config;
+
+	public Configuration Configuration {
+		get {return config;}
+		set {config = value;}
 	}
-}
 
-abstract class FileGenerator {
 	public abstract void CreateFile (string assembly_name, string file_prefix);
 
 	public virtual void WriteAssemblyAttributes (Assembly assembly)
@@ -181,126 +585,452 @@
 	{
 		s.WriteLine (
 			"/*\n" +
-			" * This file was automatically generated by make-map from {0}.\n" +
+			" * This file was automatically generated by create-native-map from {0}.\n" +
 			" *\n" +
 			" * DO NOT MODIFY.\n" +
 			" */",
 			assembly);
 		if (!noConfig) {
+			s.WriteLine ("#ifdef HAVE_CONFIG_H");
 			s.WriteLine ("#include <config.h>");
+			s.WriteLine ("#endif /* ndef HAVE_CONFIG_H */");
 		}
 		s.WriteLine ();
 	}
 
-	protected static bool CanMapType (Type t, out bool bits)
+	protected static bool CanMapType (Type t)
 	{
-		object [] attributes = t.GetCustomAttributes (false);
-		bool map = false;
-		bits = false;
-		
-		foreach (object attr in attributes) {
-			if (attr.GetType ().Name == "MapAttribute")
-				map = true;
-			if (attr.GetType ().Name == "FlagsAttribute")
-				bits = true;
-		}
-		return map;
+		return MapUtils.GetMapAttribute (t) != null;
 	}
 
-	protected static string GetNativeType (Type t)
+	protected static bool IsFlagsEnum (Type t)
 	{
-		string ut = t.Name;
-		if (t.IsEnum)
-			ut = Enum.GetUnderlyingType (t).Name;
-		Type et = t.GetElementType ();
-		if (et != null && et.IsEnum)
-			ut = Enum.GetUnderlyingType (et).Name;
+		return t.IsEnum && 
+			MapUtils.GetCustomAttributes <FlagsAttribute> (t).Length > 0;
+	}
 
-		string type = null;
+	protected static void SortFieldsInOffsetOrder (Type t, FieldInfo[] fields)
+	{
+		Array.Sort (fields, delegate (FieldInfo f1, FieldInfo f2) {
+				long o1 = (long) Marshal.OffsetOf (f1.DeclaringType, f1.Name);
+				long o2 = (long) Marshal.OffsetOf (f2.DeclaringType, f2.Name);
+				return o1.CompareTo (o2);
+		});
+	}
 
-		switch (ut) {
-			case "Boolean":       type = "int";             break;
-			case "Byte":          type = "unsigned char";   break;
-			case "SByte":         type = "signed char";     break;
-			case "Int16":         type = "short";           break;
-			case "UInt16":        type = "unsigned short";  break;
-			case "Int32":         type = "int";             break;
-			case "UInt32":        type = "unsigned int";    break;
-			case "UInt32[]":      type = "unsigned int*";   break;
-			case "Int64":         type = "gint64";          break;
-			case "UInt64":        type = "guint64";         break;
-			case "IntPtr":        type = "void*";           break;
-			case "Byte[]":        type = "void*";           break;
-			case "String":        type = "const char*";     break;
-			case "StringBuilder": type = "char*";           break;
-			case "Void":          type = "void";            break;
-			case "HandleRef":     type = "void*";           break;
+	protected static void WriteMacroDefinition (TextWriter writer, string macro)
+	{
+		if (macro == null || macro.Length == 0)
+			return;
+		string[] val = macro.Split ('=');
+		writer.WriteLine ("#ifndef {0}", val [0]);
+		writer.WriteLine ("#define {0}{1}", val [0], 
+				val.Length > 1 ? " " + val [1] : "");
+		writer.WriteLine ("#endif /* ndef {0} */", val [0]);
+		writer.WriteLine ();
+	}
+
+	private static Regex includeRegex = new Regex (@"^(?<AutoHeader>ah:)?(?<Include>(""|<)(?<IncludeFile>.*)(""|>))$");
+
+	protected static void WriteIncludeDeclaration (TextWriter writer, string inc)
+	{
+		if (inc == null || inc.Length == 0)
+			return;
+		Match m = includeRegex.Match (inc);
+		if (!m.Groups ["Include"].Success) {
+			Console.WriteLine ("warning: invalid PublicIncludeFile: {0}", inc);
+			return;
 		}
-		if (type != null)
-			return string.Format ("{0}{1}", type,
-					t.IsByRef ? "*" : "");
-		return GetTypeName (t);
+		if (m.Success && m.Groups ["AutoHeader"].Success) {
+			string i = m.Groups ["IncludeFile"].Value;
+			string def = "HAVE_" + i.ToUpper ().Replace ("/", "_").Replace (".", "_");
+			writer.WriteLine ("#ifdef {0}", def);
+			writer.WriteLine ("#include {0}", m.Groups ["Include"]);
+			writer.WriteLine ("#endif /* ndef {0} */", def);
+		}
+		else
+			writer.WriteLine ("#include {0}", m.Groups ["Include"]);
 	}
 
-	private static string GetTypeName (Type t)
+	protected string GetNativeMemberName (FieldInfo field)
 	{
-		if (t.Namespace.StartsWith ("System"))
-			return "int /* warning: unknown mapping for type: " + t.Name + " */";
-		string ts = "struct " +
-			MakeMap.GetNativeName (t.FullName).Replace ("+", "_").Replace ("&", "*")
-				.Replace ("[]", "*");
-		return ts;
+		if (!Configuration.MemberRenames.ContainsKey (field.Name))
+			return field.Name;
+		return Configuration.MemberRenames [field.Name];
 	}
 }
 
 class HeaderFileGenerator : FileGenerator {
 	StreamWriter sh;
+	string assembly_file;
+	Dictionary<string, MethodInfo>  methods   = new Dictionary <string, MethodInfo> ();
+	Dictionary<string, Type>        structs   = new Dictionary <string, Type> ();
+	Dictionary<string, MethodInfo>  delegates = new Dictionary <string, MethodInfo> ();
+	List<string>                    decls     = new List <string> ();
 
 	public override void CreateFile (string assembly_name, string file_prefix)
 	{
 		sh = File.CreateText (file_prefix + ".h");
-		WriteHeader (sh, assembly_name);
-		sh.WriteLine ("#ifndef INC_Mono_Posix_" + file_prefix + "_H");
-		sh.WriteLine ("#define INC_Mono_Posix_" + file_prefix + "_H\n");
-		sh.WriteLine ("#include <glib/gtypes.h>\n");
+		file_prefix = file_prefix.Replace ("../", "").Replace ("/", "_");
+		this.assembly_file = assembly_name = Path.GetFileName (assembly_name);
+		WriteHeader (sh, assembly_name, true);
+		assembly_name = assembly_name.Replace (".dll", "").Replace (".", "_");
+		sh.WriteLine ("#ifndef INC_" + assembly_name + "_" + file_prefix + "_H");
+		sh.WriteLine ("#define INC_" + assembly_name + "_" + file_prefix + "_H\n");
+		sh.WriteLine ("#include <glib.h>\n");
 		sh.WriteLine ("G_BEGIN_DECLS\n");
+
+		// Kill warning about unused method
+		DumpTypeInfo (null);
 	}
 
+	public override void WriteAssemblyAttributes (Assembly assembly)
+	{
+		sh.WriteLine ("/*\n * Public Macros\n */");
+		foreach (string def in Configuration.PublicMacros) {
+			WriteMacroDefinition (sh, def);
+		}
+		sh.WriteLine ();
+
+		sh.WriteLine ("/*\n * Public Includes\n */");
+		foreach (string inc in Configuration.PublicHeaders) {
+			WriteIncludeDeclaration (sh, inc);
+		}
+		sh.WriteLine ();
+
+		sh.WriteLine ("/*\n * Enumerations\n */");
+	}
+
 	public override void WriteType (Type t, string ns, string fn)
 	{
-		bool bits;
-		if (!CanMapType (t, out bits))
+		WriteEnum (t, ns, fn);
+		CacheStructs (t, ns, fn);
+		CacheExternalMethods (t, ns, fn);
+	}
+
+	private void WriteEnum (Type t, string ns, string fn)
+	{
+		if (!CanMapType (t) || !t.IsEnum)
 			return;
-		string etype = GetNativeType (t);
 
+		string etype = MapUtils.GetNativeType (t);
+
 		WriteLiteralValues (sh, t, fn);
 		sh.WriteLine ("int {1}_From{2} ({0} x, {0} *r);", etype, ns, t.Name);
 		sh.WriteLine ("int {1}_To{2} ({0} x, {0} *r);", etype, ns, t.Name);
+		Configuration.NativeExcludeSymbols.Add (
+				string.Format ("{1}_From{2}", etype, ns, t.Name));
+		Configuration.NativeExcludeSymbols.Add (
+				string.Format ("{1}_To{2}", etype, ns, t.Name));
+		Configuration.NativeExcludeSymbols.Sort ();
 		sh.WriteLine ();
 	}
 
 	static void WriteLiteralValues (StreamWriter sh, Type t, string n)
 	{
 		object inst = Activator.CreateInstance (t);
+		int max_field_length = 0;
 		FieldInfo[] fields = t.GetFields ();
-		Array.Sort (fields, MakeMap.MemberNameComparer);
+		Array.Sort (fields, delegate (FieldInfo f1, FieldInfo f2) {
+				max_field_length = Math.Max (max_field_length, f1.Name.Length);
+				max_field_length = Math.Max (max_field_length, f2.Name.Length);
+				return MapUtils.MemberNameComparer.Compare (f1, f2);
+		});
+		max_field_length += 1 + n.Length;
+		sh.WriteLine ("enum {0} {{", n);
 		foreach (FieldInfo fi in fields) {
 			if (!fi.IsLiteral)
 				continue;
-			sh.WriteLine ("#define {0}_{1} 0x{2:x}", n, fi.Name, fi.GetValue (inst));
+			string e = n + "_" + fi.Name;
+			sh.WriteLine ("\t{0,-" + max_field_length + "}       = 0x{1:x},", 
+					e, fi.GetValue (inst));
+			sh.WriteLine ("\t#define {0,-" + max_field_length + "} {0}", e);
 		}
+		sh.WriteLine ("};");
 	}
 
+
+	private void CacheStructs (Type t, string ns, string fn)
+	{
+		if (t.IsEnum)
+			return;
+		MapAttribute map = MapUtils.GetMapAttribute (t);
+		if (map != null) {
+			if (map.NativeType != null && map.NativeType.Length > 0)
+				decls.Add (map.NativeType);
+			RecordTypes (t);
+		}
+	}
+
+	private void CacheExternalMethods (Type t, string ns, string fn)
+	{
+		BindingFlags bf = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+		foreach (MethodInfo m in t.GetMethods (bf)) {
+			if ((m.Attributes & MethodAttributes.PinvokeImpl) == 0)
+				continue;
+			DllImportAttribute dia = GetDllImportInfo (m);
+			if (dia == null) {
+				Console.WriteLine ("warning: unable to emit native prototype for P/Invoke " + 
+						"method: {0}", m);
+				continue;
+			}
+			// we shouldn't declare prototypes for POSIX, etc. functions.
+			if (Configuration.NativeLibraries.BinarySearch (dia.Value) < 0 ||
+					IsOnExcludeList (dia.EntryPoint))
+				continue;
+			methods [dia.EntryPoint] = m;
+			RecordTypes (m);
+		}
+	}
+
+	private static DllImportAttribute GetDllImportInfo (MethodInfo method)
+	{
+		// .NET 2.0 synthesizes pseudo-attributes such as DllImport
+		DllImportAttribute dia = MapUtils.GetCustomAttribute <DllImportAttribute> (method);
+		if (dia != null)
+			return dia;
+
+		// We're not on .NET 2.0; assume we're on Mono and use some internal
+		// methods...
+		Type MonoMethod = Type.GetType ("System.Reflection.MonoMethod", false);
+		if (MonoMethod == null) {
+			Console.WriteLine ("warning: cannot find MonoMethod");
+			return null;
+		}
+		MethodInfo GetDllImportAttribute = 
+			MonoMethod.GetMethod ("GetDllImportAttribute", 
+					BindingFlags.Static | BindingFlags.NonPublic);
+		if (GetDllImportAttribute == null) {
+			Console.WriteLine ("warning: cannot find GetDllImportAttribute");
+			return null;
+		}
+		IntPtr mhandle = method.MethodHandle.Value;
+		return (DllImportAttribute) GetDllImportAttribute.Invoke (null, 
+				new object[]{mhandle});
+	}
+
+	private bool IsOnExcludeList (string method)
+	{
+		int idx = Configuration.NativeExcludeSymbols.BinarySearch (method);
+		return (idx < 0) ? false : true;
+	}
+
+	private void RecordTypes (MethodInfo method)
+	{
+		ParameterInfo[] parameters = method.GetParameters ();
+		foreach (ParameterInfo pi in parameters) {
+			RecordTypes (pi.ParameterType);
+		}
+	}
+
+	private void RecordTypes (Type st)
+	{
+		if (typeof(Delegate).IsAssignableFrom (st) && !delegates.ContainsKey (st.Name)) {
+			MethodInfo mi = st.GetMethod ("Invoke");
+			delegates [st.Name] = mi;
+			RecordTypes (mi);
+			return;
+		}
+		Type et = MapUtils.GetElementType (st);
+		string s = MapUtils.GetNativeType (et);
+		if (s.StartsWith ("struct ") && !structs.ContainsKey (et.Name)) {
+			structs [et.Name] = et;
+			foreach (FieldInfo fi in et.GetFields (BindingFlags.Instance | 
+					BindingFlags.Public | BindingFlags.NonPublic)) {
+				RecordTypes (fi.FieldType);
+			}
+		}
+	}
+
 	public override void CloseFile (string file_prefix)
 	{
-		sh.WriteLine ("G_END_DECLS\n");
+		IEnumerable<string> structures = Sort (structs.Keys);
+		sh.WriteLine ();
+		sh.WriteLine ("/*\n * Managed Structure Declarations\n */\n");
+		foreach (string s in structures) {
+			sh.WriteLine ("struct {0};", MapUtils.GetManagedType (structs [s]));
+		}
+		sh.WriteLine ();
+
+		sh.WriteLine ("/*\n * Inferred Structure Declarations\n */\n");
+		foreach (string s in decls) {
+			sh.WriteLine ("{0};", s);
+		}
+		sh.WriteLine ();
+
+		sh.WriteLine ("/*\n * Delegate Declarations\n */\n");
+		foreach (string s in Sort (delegates.Keys)) {
+			sh.WriteLine ("typedef {0};",
+					MapUtils.GetFunctionDeclaration ("(*" + s + ")", delegates [s]));
+		}
+		sh.WriteLine ();
+
+		sh.WriteLine ("/*\n * Structures\n */\n");
+		foreach (string s in structures) {
+			WriteStructDeclarations (s);
+		}
+		sh.WriteLine ();
+
+		sh.WriteLine ("/*\n * Functions\n */");
+		foreach (string method in Configuration.NativeExcludeSymbols) {
+			if (methods.ContainsKey (method))
+				methods.Remove (method);
+		}
+		foreach (string method in Sort (methods.Keys)) {
+			WriteMethodDeclaration ((MethodInfo) methods [method], method);
+		}
+
+		sh.WriteLine ("\nG_END_DECLS\n");
 		sh.WriteLine ("#endif /* ndef INC_Mono_Posix_" + file_prefix + "_H */\n");
 		sh.Close ();
 	}
+
+	private static IEnumerable<string> Sort (ICollection<string> c)
+	{
+		List<string> al = new List<string> (c);
+		al.Sort (MapUtils.OrdinalStringComparer);
+		return al;
+	}
+
+	private void WriteStructDeclarations (string s)
+	{
+		Type t = structs [s];
+#if false
+		if (!t.Assembly.CodeBase.EndsWith (this.assembly_file)) {
+			return;
+		}
+#endif
+		sh.WriteLine ("struct {0} {{", MapUtils.GetManagedType (t));
+		FieldInfo[] fields = t.GetFields (BindingFlags.Instance | 
+				BindingFlags.Public | BindingFlags.NonPublic);
+		int max_type_len = 0, max_name_len = 0, max_native_len = 0;
+		Array.ForEach (fields, delegate (FieldInfo f) {
+				max_type_len    = Math.Max (max_type_len, HeaderFileGenerator.GetType (f.FieldType).Length);
+				max_name_len    = Math.Max (max_name_len, GetNativeMemberName (f).Length);
+				string native_type = MapUtils.GetNativeType (f);
+				if (native_type != null)
+					max_native_len  = Math.Max (max_native_len, native_type.Length);
+		});
+		SortFieldsInOffsetOrder (t, fields);
+		foreach (FieldInfo field in fields) {
+			string fname = GetNativeMemberName (field);
+			sh.Write ("\t{0,-" + max_type_len + "} {1};", 
+					GetType (field.FieldType), fname);
+			string native_type = MapUtils.GetNativeType (field);
+			if (native_type != null) {
+				sh.Write (new string (' ', max_name_len - fname.Length));
+				sh.Write ("  /* {0,-" + max_native_len + "} */", native_type);
+			}
+			sh.WriteLine ();
+		}
+		sh.WriteLine ("};");
+		MapAttribute map = MapUtils.GetMapAttribute (t);
+		if (map != null && map.NativeType != null && map.NativeType.Length != 0 &&
+				t.Assembly.CodeBase.EndsWith (this.assembly_file)) {
+			sh.WriteLine ();
+			sh.WriteLine (
+					"int\n{0}_From{1} ({3}{4} from, {2} *to);\n" + 
+					"int\n{0}_To{1} ({2} *from, {3}{4} to);\n",
+					MapUtils.GetNamespace (t), t.Name, map.NativeType, 
+					MapUtils.GetNativeType (t), t.IsValueType ? "*" : "");
+			Configuration.NativeExcludeSymbols.Add (
+					string.Format ("{0}_From{1}", MapUtils.GetNamespace (t), t.Name));
+			Configuration.NativeExcludeSymbols.Add (
+					string.Format ("{0}_To{1}", MapUtils.GetNamespace (t), t.Name));
+			Configuration.NativeExcludeSymbols.Sort ();
+		}
+		sh.WriteLine ();
+	}
+
+	private static string GetType (Type t)
+	{
+		if (typeof(Delegate).IsAssignableFrom (t))
+			return t.Name;
+		return MapUtils.GetNativeType (t);
+	}
+
+	private void WriteMethodDeclaration (MethodInfo method, string entryPoint)
+	{
+		if (method.ReturnType.IsClass) {
+			Console.WriteLine ("warning: {0} has a return type of {1}, which is a reference type",
+					entryPoint, method.ReturnType.FullName);
+		}
+		sh.Write (MapUtils.GetFunctionDeclaration (entryPoint, method));
+		sh.WriteLine (";");
+
+#if false
+		sh.WriteLine ("{0} ", method.ReturnType == typeof(string) 
+				? "char*" 
+				: MapUtils.GetNativeType (method.ReturnType));
+		sh.Write ("{0} ", entryPoint);
+		ParameterInfo[] parameters = method.GetParameters();
+		if (parameters.Length == 0) {
+			sh.WriteLine ("(void);");
+			return;
+		}
+		if (parameters.Length > 0) {
+			sh.Write ("(");
+			WriteParameterDeclaration (parameters [0]);
+		}
+		for (int i = 1; i < parameters.Length; ++i) {
+			sh.Write (", ");
+			WriteParameterDeclaration (parameters [i]);
+		}
+		sh.WriteLine (");");
+#endif
+	}
+
+	private void DumpTypeInfo (Type t)
+	{
+		if (t == null)
+			return;
+
+		sh.WriteLine ("\t\t/* Type Info for " + t.FullName + ":");
+		foreach (MemberInfo mi in typeof(Type).GetMembers()) {
+			sh.WriteLine ("\t\t\t{0}={1}", mi.Name, GetMemberValue (mi, t));
+		}
+		sh.WriteLine ("\t\t */");
+	}
+
+	private static string GetMemberValue (MemberInfo mi, Type t)
+	{
+		try {
+		switch (mi.MemberType) {
+			case MemberTypes.Constructor:
+			case MemberTypes.Method: {
+				MethodBase b = (MethodBase) mi;
+				if (b.GetParameters().Length == 0)
+					return b.Invoke (t, new object[]{}).ToString();
+				return "<<cannot invoke>>";
+			}
+			case MemberTypes.Field:
+				return ((FieldInfo) mi).GetValue (t).ToString ();
+			case MemberTypes.Property: {
+				PropertyInfo pi = (PropertyInfo) mi;
+				if (!pi.CanRead)
+					return "<<cannot read>>";
+				return pi.GetValue (t, null).ToString ();
+			}
+			default:
+				return "<<unknown value>>";
+		}
+		}
+		catch (Exception e) {
+			return "<<exception reading member: " + e.Message + ">>";
+		}
+	}
+
+	private void WriteParameterDeclaration (ParameterInfo pi)
+	{
+		// DumpTypeInfo (pi.ParameterType);
+		string nt = MapUtils.GetNativeType (pi.ParameterType);
+		sh.Write ("{0} {1}", nt, pi.Name);
+	}
 }
 
 class SourceFileGenerator : FileGenerator {
 	StreamWriter sc;
+	string file_prefix;
 
 	public override void CreateFile (string assembly_name, string file_prefix)
 	{
@@ -309,87 +1039,140 @@
 
 		if (file_prefix.IndexOf ("/") != -1)
 			file_prefix = file_prefix.Substring (file_prefix.IndexOf ("/") + 1);
-		sc.WriteLine ("#include \"{0}.h\"", file_prefix);
+		this.file_prefix = file_prefix;
+		sc.WriteLine ("#include <stdlib.h>");
+		sc.WriteLine ("#include <string.h>");
 		sc.WriteLine ();
 	}
 
 	public override void WriteAssemblyAttributes (Assembly assembly)
 	{
-		object [] x = assembly.GetCustomAttributes (false);
-		Console.WriteLine ("Got: " + x.Length);
-		foreach (object aattr in assembly.GetCustomAttributes (false)) {
-			Console.WriteLine ("Got: " + aattr.GetType ().Name);
-			if (aattr.GetType ().Name == "HeaderAttribute"){
-				WriteDefines (sc, aattr);
-				WriteIncludes (sc, aattr);
-			}
+		sc.WriteLine ("/*\n * Implementation Macros\n */");
+		foreach (string def in Configuration.ImplementationMacros) {
+			WriteMacroDefinition (sc, def);
 		}
-	}
+		sc.WriteLine ();
 
-	static void WriteDefines (TextWriter writer, object o)
-	{
-		PropertyInfo prop = o.GetType ().GetProperty ("Defines");
-		if (prop == null)
-			throw new Exception ("Cannot find 'Defines' property");
-
-		MethodInfo method = prop.GetGetMethod ();
-		string [] defines = method.Invoke (o, null).ToString ().Split (',');
-		foreach (string def in defines) {
-			writer.WriteLine ("#ifndef {0}", def);
-			writer.WriteLine ("#define {0}", def);
-			writer.WriteLine ("#endif /* ndef {0} */", def);
+		sc.WriteLine ("/*\n * Implementation Includes\n */");
+		foreach (string inc in Configuration.ImplementationHeaders) {
+			WriteIncludeDeclaration (sc, inc);
 		}
-	}
+		sc.WriteLine ();
 
-	static void WriteIncludes (TextWriter writer, object o)
-	{
-		PropertyInfo prop = o.GetType ().GetProperty ("Includes");
-		if (prop == null)
-			throw new Exception ("Cannot find 'Includes' property");
+		sc.WriteLine ("#include \"{0}.h\"", file_prefix);
 
-		MethodInfo method = prop.GetGetMethod ();
-		string [] includes = method.Invoke (o, null).ToString ().Split (',');;
-		foreach (string inc in includes){
-			if (inc.Length > 3 && 
-					string.CompareOrdinal (inc, 0, "ah:", 0, 3) == 0) {
-				string i = inc.Substring (3);
-				writer.WriteLine ("#ifdef HAVE_" + (i.ToUpper ().Replace ("/", "_").Replace (".", "_")));
-				writer.WriteLine ("#include <{0}>", i);
-				writer.WriteLine ("#endif");
-			} else 
-				writer.WriteLine ("#include <{0}>", inc);
-		}
-		writer.WriteLine ();
+		sc.WriteLine (@"
+#include <errno.h>    /* errno, EOVERFLOW */
+#include <glib.h>     /* g* types, g_assert_not_reached() */
+
+/* returns TRUE if @type is an unsigned type */
+#define _cnm_integral_type_is_unsigned(type) \
+    (sizeof(type) == sizeof(gint8)           \
+      ? (((type)-1) > G_MAXINT8)             \
+      : sizeof(type) == sizeof(gint16)       \
+        ? (((type)-1) > G_MAXINT16)          \
+        : sizeof(type) == sizeof(gint32)     \
+          ? (((type)-1) > G_MAXINT32)        \
+          : sizeof(type) == sizeof(gint64)   \
+            ? (((type)-1) > G_MAXINT64)      \
+            : (g_assert_not_reached (), 0))
+
+/* returns the minimum value of @type as a gint64 */
+#define _cnm_integral_type_min(type)          \
+    (_cnm_integral_type_is_unsigned (type)    \
+      ? 0                                     \
+      : sizeof(type) == sizeof(gint8)         \
+        ? G_MININT8                           \
+        : sizeof(type) == sizeof(gint16)      \
+          ? G_MININT16                        \
+          : sizeof(type) == sizeof(gint32)    \
+            ? G_MININT32                      \
+            : sizeof(type) == sizeof(gint64)  \
+              ? G_MININT64                    \
+              : (g_assert_not_reached (), 0))
+
+/* returns the maximum value of @type as a guint64 */
+#define _cnm_integral_type_max(type)            \
+    (_cnm_integral_type_is_unsigned (type)      \
+      ? sizeof(type) == sizeof(gint8)           \
+        ? G_MAXUINT8                            \
+        : sizeof(type) == sizeof(gint16)        \
+          ? G_MAXUINT16                         \
+          : sizeof(type) == sizeof(gint32)      \
+            ? G_MAXUINT32                       \
+            : sizeof(type) == sizeof(gint64)    \
+              ? G_MAXUINT64                     \
+              : (g_assert_not_reached (), 0)    \
+      : sizeof(type) == sizeof(gint8)           \
+          ? G_MAXINT8                           \
+          : sizeof(type) == sizeof(gint16)      \
+            ? G_MAXINT16                        \
+            : sizeof(type) == sizeof(gint32)    \
+              ? G_MAXINT32                      \
+              : sizeof(type) == sizeof(gint64)  \
+                ? G_MAXINT64                    \
+                : (g_assert_not_reached (), 0))
+
+#ifdef DEBUG
+#define _cnm_dump_(to_t,from)                                            \
+  printf (""# %s -> %s: min=%llx; max=%llx; value=%llx; lt=%i; l0=%i; gt=%i; e=%i\n"", \
+    #from, #to_t,                                                        \
+    (gint64) (_cnm_integral_type_min(to_t)),                             \
+    (gint64) (_cnm_integral_type_max (to_t)),                            \
+    (gint64) (from),                                                     \
+    (_cnm_integral_type_min (to_t) <= from),                             \
+    (from < 0),                                                          \
+    /* (_cnm_integral_type_max (to_t) >= from) */                        \
+    (from <= _cnm_integral_type_max (to_t)),                             \
+    ((_cnm_integral_type_min(to_t) >= from) &&                           \
+          ((from < 0) ? 1 : (from <= _cnm_integral_type_max(to_t))))     \
+  )
+#else
+#define _cnm_dump_(to_t, from) do {} while (0)
+#endif
+
+#define _cnm_return_val_if_overflow(to_t,from,val)  G_STMT_START {   \
+    if (!(_cnm_integral_type_min(to_t) <= from &&                    \
+          ((from < 0) || (from <= _cnm_integral_type_max(to_t))))) { \
+      _cnm_dump_(to_t, from);                                        \
+      errno = EOVERFLOW;                                             \
+      return (val);                                                  \
+    }                                                                \
+  } G_STMT_END
+");
 	}
 
 	public override void WriteType (Type t, string ns, string fn)
 	{
-		bool bits;
-		if (!CanMapType (t, out bits))
+		if (!CanMapType (t))
 			return;
-		string etype = GetNativeType (t);
 
-		WriteFromManagedType (t, ns, fn, etype, bits);
-		WriteToManagedType (t, ns, fn, etype, bits);
+		string etype = MapUtils.GetNativeType (t);
+
+		if (t.IsEnum) {
+			bool bits = IsFlagsEnum (t);
+
+			WriteFromManagedEnum (t, ns, fn, etype, bits);
+			WriteToManagedEnum (t, ns, fn, etype, bits);
+		}
+		else {
+			WriteFromManagedClass (t, ns, fn, etype);
+			WriteToManagedClass (t, ns, fn, etype);
+		}
 	}
 
-	private void WriteFromManagedType (Type t, string ns, string fn, string etype, bool bits)
+	private void WriteFromManagedEnum (Type t, string ns, string fn, string etype, bool bits)
 	{
 		sc.WriteLine ("int {1}_From{2} ({0} x, {0} *r)", etype, ns, t.Name);
 		sc.WriteLine ("{");
 		sc.WriteLine ("\t*r = 0;");
-		// For many values, 0 is a valid value, but doesn't have it's own symbol.
-		// Examples: Error (0 means "no error"), WaitOptions (0 means "no options").
-		// Make 0 valid for all conversions.
-		sc.WriteLine ("\tif (x == 0)\n\t\treturn 0;");
 		FieldInfo[] fields = t.GetFields ();
-		Array.Sort (fields, MakeMap.MemberNameComparer);
+		Array.Sort<FieldInfo> (fields, MapUtils.MemberNameComparer);
 		foreach (FieldInfo fi in fields) {
 			if (!fi.IsLiteral)
 				continue;
-			if (Attribute.GetCustomAttribute (fi, 
-				typeof(ObsoleteAttribute), false) != null) {
-				sc.WriteLine ("\t/* {0}_{1} is obsolete; ignoring */", fn, fi.Name);
+			if (MapUtils.GetCustomAttribute<ObsoleteAttribute> (fi) != null) {
+				sc.WriteLine ("\t/* {0}_{1} is obsolete or optional; ignoring */", fn, fi.Name);
 				continue;
 			}
 			if (bits)
@@ -406,6 +1189,10 @@
 			sc.WriteLine ("#else /* def {0} */\n\t\t{{errno = EINVAL; return -1;}}", fi.Name);
 			sc.WriteLine ("#endif /* ndef {0} */", fi.Name);
 		}
+		// For many values, 0 is a valid value, but doesn't have it's own symbol.
+		// Examples: Error (0 means "no error"), WaitOptions (0 means "no options").
+		// Make 0 valid for all conversions.
+		sc.WriteLine ("\tif (x == 0)\n\t\treturn 0;");
 		if (bits)
 			sc.WriteLine ("\treturn 0;");
 		else
@@ -413,7 +1200,7 @@
 		sc.WriteLine ("}\n");
 	}
 
-	private void WriteToManagedType (Type t, string ns, string fn, string etype, bool bits)
+	private void WriteToManagedEnum (Type t, string ns, string fn, string etype, bool bits)
 	{
 		sc.WriteLine ("int {1}_To{2} ({0} x, {0} *r)", etype, ns, t.Name);
 		sc.WriteLine ("{");
@@ -423,7 +1210,7 @@
 		// Make 0 valid for all conversions.
 		sc.WriteLine ("\tif (x == 0)\n\t\treturn 0;");
 		FieldInfo[] fields = t.GetFields ();
-		Array.Sort (fields, MakeMap.MemberNameComparer);
+		Array.Sort<FieldInfo> (fields, MapUtils.MemberNameComparer);
 		foreach (FieldInfo fi in fields) {
 			if (!fi.IsLiteral)
 				continue;
@@ -443,6 +1230,138 @@
 		sc.WriteLine ("}\n");
 	}
 
+	private void WriteFromManagedClass (Type t, string ns, string fn, string etype)
+	{
+		MapAttribute map = MapUtils.GetMapAttribute (t);
+		if (map == null || map.NativeType == null || map.NativeType.Length == 0)
+			return;
+		sc.WriteLine ("int\n{0}_From{1} (struct {0}_{1} *from, {2} *to)",
+				MapUtils.GetNamespace (t), t.Name, map.NativeType);
+		WriteManagedClassConversion (t, delegate (FieldInfo field) {
+				MapAttribute ft = MapUtils.GetMapAttribute (field);
+				if (ft != null)
+					return ft.NativeType;
+				return MapUtils.GetNativeType (field.FieldType);
+			},
+			delegate (FieldInfo field) {
+				return GetNativeMemberName (field);
+			},
+			delegate (FieldInfo field) {
+				return field.Name;
+			},
+			delegate (FieldInfo field) {
+				return string.Format ("{0}_From{1}",
+					MapUtils.GetNamespace (field.FieldType),
+					field.FieldType.Name);
+			}
+		);
+	}
+
+	private delegate string GetFromType (FieldInfo field);
+	private delegate string GetToFieldName (FieldInfo field);
+	private delegate string GetFromFieldName (FieldInfo field);
+	private delegate string GetFieldCopyMethod (FieldInfo field);
+
+	private void WriteManagedClassConversion (Type t, GetFromType gft, 
+			GetFromFieldName gffn, GetToFieldName gtfn, GetFieldCopyMethod gfc)
+	{
+		MapAttribute map = MapUtils.GetMapAttribute (t);
+		sc.WriteLine ("{");
+		FieldInfo[] fields = GetFieldsToCopy (t);
+		SortFieldsInOffsetOrder (t, fields);
+		int max_len = 0;
+		foreach (FieldInfo f in fields) {
+			max_len = Math.Max (max_len, f.Name.Length);
+			if (!MapUtils.IsIntegralType (f.FieldType))
+				continue;
+			string d = GetAutoconfDefine (map, f);
+			if (d != null)
+				sc.WriteLine ("#ifdef " + d);
+			sc.WriteLine ("\t_cnm_return_val_if_overflow ({0}, from->{1}, -1);",
+					gft (f), gffn (f));
+			if (d != null)
+				sc.WriteLine ("#endif /* ndef " + d + " */");
+		}
+		sc.WriteLine ("\n\tmemset (to, 0, sizeof(*to));\n");
+		foreach (FieldInfo f in fields) {
+			string d = GetAutoconfDefine (map, f);
+			if (d != null)
+				sc.WriteLine ("#ifdef " + d);
+			if (MapUtils.IsBlittableType (f.FieldType)) {
+				sc.WriteLine ("\tto->{0,-" + max_len + "} = from->{1};", 
+						gtfn (f), gffn (f));
+			}
+			else if (f.FieldType.IsEnum) {
+				sc.WriteLine ("\tif ({0} (from->{1}, &to->{2}) != 0) {{", gfc (f),
+						gffn (f), gtfn (f));
+				sc.WriteLine ("\t\treturn -1;");
+				sc.WriteLine ("\t}");
+			}
+			else if (f.FieldType.IsValueType) {
+				sc.WriteLine ("\tif ({0} (&from->{1}, &to->{2}) != 0) {{", gfc (f),
+						gffn (f), gtfn (f));
+				sc.WriteLine ("\t\treturn -1;");
+				sc.WriteLine ("\t}");
+			}
+			if (d != null)
+				sc.WriteLine ("#endif /* ndef " + d + " */");
+		}
+		sc.WriteLine ();
+		sc.WriteLine ("\treturn 0;");
+		sc.WriteLine ("}\n");
+		sc.WriteLine ();
+	}
+
+	private void WriteToManagedClass (Type t, string ns, string fn, string etype)
+	{
+		MapAttribute map = MapUtils.GetMapAttribute (t);
+		if (map == null || map.NativeType == null || map.NativeType.Length == 0)
+			return;
+		sc.WriteLine ("int\n{0}_To{1} ({2} *from, struct {0}_{1} *to)", 
+				MapUtils.GetNamespace (t), t.Name, map.NativeType);
+		WriteManagedClassConversion (t, delegate (FieldInfo field) {
+				return MapUtils.GetNativeType (field.FieldType);
+			},
+			delegate (FieldInfo field) {
+				return field.Name;
+			},
+			delegate (FieldInfo field) {
+				return GetNativeMemberName (field);
+			},
+			delegate (FieldInfo field) {
+				return string.Format ("{0}_To{1}",
+					MapUtils.GetNamespace (field.FieldType),
+					field.FieldType.Name);
+			}
+		);
+	}
+
+	private static FieldInfo[] GetFieldsToCopy (Type t)
+	{
+		FieldInfo[] fields = t.GetFields (BindingFlags.Instance | 
+				BindingFlags.Public | BindingFlags.NonPublic);
+		int count = 0;
+		for (int i = 0; i < fields.Length; ++i)
+			if (MapUtils.GetCustomAttribute <NonSerializedAttribute> (fields [i]) == null)
+				++count;
+		FieldInfo[] rf = new FieldInfo [count];
+		for (int i = 0, j = 0; i < fields.Length; ++i) {
+			if (MapUtils.GetCustomAttribute <NonSerializedAttribute> (fields [i]) == null)
+				rf [j++] = fields [i];
+		}
+		return rf;
+	}
+
+	private string GetAutoconfDefine (MapAttribute typeMap, FieldInfo field)
+	{
+		if (Configuration.AutoconfMembers.BinarySearch (field.Name) < 0 &&
+				Configuration.AutoconfMembers.BinarySearch (field.DeclaringType.Name + "." + field.Name) < 0)
+			return null;
+		return string.Format ("HAVE_{0}_{1}", 
+				typeMap.NativeType.ToUpperInvariant().Replace (" ", "_"),
+				field.Name.ToUpperInvariant ());
+	}
+
 	public override void CloseFile (string file_prefix)
 	{
 		sc.Close ();
@@ -460,11 +1379,10 @@
 		scs.WriteLine ("using System.Runtime.InteropServices;");
 		scs.WriteLine ("using Mono.Unix.Native;\n");
 		scs.WriteLine ("namespace Mono.Unix.Native {\n");
-		scs.WriteLine ("\t[CLSCompliant (false)]");
 		scs.WriteLine ("\tpublic sealed /* static */ partial class NativeConvert");
 		scs.WriteLine ("\t{");
 		scs.WriteLine ("\t\tprivate NativeConvert () {}\n");
-		scs.WriteLine ("\t\tprivate const string LIB = \"MonoPosixHelper\";\n");
+		scs.WriteLine ("\t\tprivate const string LIB = \"{0}\";\n", Configuration.NativeLibraries[0]);
 		scs.WriteLine ("\t\tprivate static void ThrowArgumentException (object value)");
 		scs.WriteLine ("\t\t{");
 		scs.WriteLine ("\t\t\tthrow new ArgumentOutOfRangeException (\"value\", value,");
@@ -474,50 +1392,94 @@
 
 	public override void WriteType (Type t, string ns, string fn)
 	{
-		bool bits;
-		if (!CanMapType (t, out bits))
+		if (!CanMapType (t))
 			return;
+		if (t.IsEnum)
+			WriteEnum (t, ns, fn);
+		else
+			WriteStruct (t, ns, fn);
+	}
 
+	private void WriteEnum (Type t, string ns, string fn)
+	{
 		string mtype = Enum.GetUnderlyingType(t).Name;
-		ObsoleteAttribute oa = (ObsoleteAttribute) Attribute.GetCustomAttribute (t, 
-					typeof(ObsoleteAttribute), false);
+		ObsoleteAttribute oa = MapUtils.GetCustomAttribute <ObsoleteAttribute> (t);
 		string obsolete = "";
 		if (oa != null) {
 			obsolete = string.Format ("[Obsolete (\"{0}\", {1})]\n\t\t",
 					oa.Message, oa.IsError ? "true" : "false");
 		}
-		scs.WriteLine ("\t\t{3}[DllImport (LIB, " + 
-			"EntryPoint=\"{0}_From{1}\")]\n" +
-			"\t\tprivate static extern int From{1} ({1} value, out {2} rval);\n",
-			ns, t.Name, mtype, obsolete);
-		scs.WriteLine ("\t\t{3}public static bool TryFrom{1} ({1} value, out {2} rval)\n" +
-			"\t\t{{\n" +
-			"\t\t\treturn From{1} (value, out rval) == 0;\n" +
-			"\t\t}}\n", ns, t.Name, mtype, obsolete);
-		scs.WriteLine ("\t\t{2}public static {0} From{1} ({1} value)", mtype, t.Name, obsolete);
-		scs.WriteLine ("\t\t{");
-		scs.WriteLine ("\t\t\t{0} rval;", mtype);
-		scs.WriteLine ("\t\t\tif (From{0} (value, out rval) == -1)\n" + 
-				"\t\t\t\tThrowArgumentException (value);", t.Name);
-		scs.WriteLine ("\t\t\treturn rval;");
-		scs.WriteLine ("\t\t}\n");
-		scs.WriteLine ("\t\t{3}[DllImport (LIB, " + 
-			"EntryPoint=\"{0}_To{1}\")]\n" +
-			"\t\tprivate static extern int To{1} ({2} value, out {1} rval);\n",
-			ns, t.Name, mtype, obsolete);
-		scs.WriteLine ("\t\t{2}public static bool TryTo{1} ({0} value, out {1} rval)\n" +
-			"\t\t{{\n" +
-			"\t\t\treturn To{1} (value, out rval) == 0;\n" +
-			"\t\t}}\n", mtype, t.Name, obsolete);
-		scs.WriteLine ("\t\t{2}public static {1} To{1} ({0} value)", mtype, t.Name, obsolete);
-		scs.WriteLine ("\t\t{");
-		scs.WriteLine ("\t\t\t{0} rval;", t.Name);
-		scs.WriteLine ("\t\t\tif (To{0} (value, out rval) == -1)\n" + 
-				"\t\t\t\tThrowArgumentException (value);", t.Name);
-		scs.WriteLine ("\t\t\treturn rval;");
-		scs.WriteLine ("\t\t}\n");
+		scs.WriteLine (
+				"\t\t{0}[DllImport (LIB, EntryPoint=\"{1}_From{2}\")]\n" +
+				"\t\tprivate static extern int From{2} ({2} value, out {3} rval);\n" +
+				"\n" +
+				"\t\t{0}public static bool TryFrom{2} ({2} value, out {3} rval)\n" +
+				"\t\t{{\n" +
+				"\t\t\treturn From{2} (value, out rval) == 0;\n" +
+				"\t\t}}\n" +
+				"\n" +
+				"\t\t{0}public static {3} From{2} ({2} value)\n" +
+				"\t\t{{\n" +
+				"\t\t\t{3} rval;\n" +
+				"\t\t\tif (From{2} (value, out rval) == -1)\n" + 
+				"\t\t\t\tThrowArgumentException (value);\n" +
+				"\t\t\treturn rval;\n" +
+				"\t\t}}\n" +
+				"\n" +
+				"\t\t{0}[DllImport (LIB, EntryPoint=\"{1}_To{2}\")]\n" +
+				"\t\tprivate static extern int To{2} ({3} value, out {2} rval);\n" +
+				"\n" +
+				"\t\t{0}public static bool TryTo{2} ({3} value, out {2} rval)\n" +
+				"\t\t{{\n" +
+				"\t\t\treturn To{2} (value, out rval) == 0;\n" +
+				"\t\t}}\n" +
+				"\n" +
+				"\t\t{0}public static {2} To{2} ({3} value)\n" +
+				"\t\t{{\n" +
+				"\t\t\t{2} rval;\n" +
+				"\t\t\tif (To{2} (value, out rval) == -1)\n" + 
+				"\t\t\t\tThrowArgumentException (value);\n" +
+				"\t\t\treturn rval;\n" +
+				"\t\t}}\n",
+			obsolete, ns, t.Name, mtype
+		);
 	}
 
+	private void WriteStruct (Type t, string ns, string fn)
+	{
+		if (MapUtils.IsDelegate (t))
+			return;
+		MapAttribute map = MapUtils.GetMapAttribute (t);
+		if (map == null || map.NativeType == null || map.NativeType.Length == 0)
+			return;
+		ObsoleteAttribute oa = MapUtils.GetCustomAttribute <ObsoleteAttribute> (t);
+		string obsolete = "";
+		if (oa != null) {
+			obsolete = string.Format ("[Obsolete (\"{0}\", {1})]\n\t\t",
+					oa.Message, oa.IsError ? "true" : "false");
+		}
+		string _ref = t.IsValueType ? "ref " : "";
+		string _out = t.IsValueType ? "out " : "";
+		scs.WriteLine (
+				"\t\t{0}[DllImport (LIB, EntryPoint=\"{1}_From{2}\")]\n" +
+				"\t\tprivate static extern int From{2} ({3}{2} source, IntPtr destination);\n" +
+				"\n" +
+				"\t\t{0}public static bool TryCopy ({3}{2} source, IntPtr destination)\n" +
+				"\t\t{{\n" +
+				"\t\t\treturn From{2} ({3}source, destination) == 0;\n" +
+				"\t\t}}\n" +
+				"\n" +
+				"\t\t{0}[DllImport (LIB, EntryPoint=\"{1}_To{2}\")]\n" +
+				"\t\tprivate static extern int To{2} (IntPtr source, {4}{2} destination);\n" +
+				"\n" +
+				"\t\t{0}public static bool TryCopy (IntPtr source, {4}{2} destination)\n" +
+				"\t\t{{\n" +
+				"\t\t\treturn To{2} (source, {4}destination) == 0;\n" +
+				"\t\t}}\n",
+			obsolete, ns, t.Name, _ref, _out
+		);
+	}
+
 	public override void CloseFile (string file_prefix)
 	{
 		scs.WriteLine ("\t}");
@@ -539,10 +1501,11 @@
 
 	public override void WriteType (Type t, string ns, string fn)
 	{
-		bool bits;
-		if (!CanMapType (t, out bits))
+		if (!CanMapType (t) || !t.IsEnum)
 			return;
 
+		bool bits = IsFlagsEnum (t);
+
 		string type = GetCSharpType (t);
 		string mtype = Enum.GetUnderlyingType(t).FullName;
 		string member = t.Name;
@@ -713,181 +1676,4 @@
 	}
 }
 
-class MphPrototypeFileGenerator : FileGenerator {
-	StreamWriter icall;
-	Hashtable methods = new Hashtable ();
-	Hashtable structs = new Hashtable ();
-
-	public override void CreateFile (string assembly_name, string file_prefix)
-	{
-		icall = File.CreateText (file_prefix + "-icalls.h");
-		WriteHeader (icall, assembly_name);
-		icall.WriteLine ("#ifndef INC_Mono_Posix_" + file_prefix + "_ICALLS_H");
-		icall.WriteLine ("#define INC_Mono_Posix_" + file_prefix + "_ICALLS_H\n");
-		icall.WriteLine ("#include <glib/gtypes.h>\n");
-		icall.WriteLine ("G_BEGIN_DECLS\n");
-
-		// Kill warning about unused method
-		DumpTypeInfo (null);
-	}
-
-	public override void WriteType (Type t, string ns, string fn)
-	{
-		BindingFlags bf = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
-		foreach (MethodInfo m in t.GetMethods (bf)) {
-			if ((m.Attributes & MethodAttributes.PinvokeImpl) == 0)
-				continue;
-			DllImportAttribute dia = GetDllImportInfo (m);
-			if (dia == null) {
-				Console.WriteLine ("Unable to emit native prototype for P/Invoke " + 
-						"method: {0}", m);
-				continue;
-			}
-			// we shouldn't declare prototypes for POSIX, etc. functions.
-			if (dia.Value != "MonoPosixHelper" || IsOnExcludeList (dia.EntryPoint))
-				continue;
-			methods [dia.EntryPoint] = m;
-			RecordStructs (m);
-		}
-	}
-
-	private static DllImportAttribute GetDllImportInfo (MethodInfo method)
-	{
-		// .NET 2.0 synthesizes pseudo-attributes such as DllImport
-		DllImportAttribute dia = (DllImportAttribute) Attribute.GetCustomAttribute (method, 
-					typeof(DllImportAttribute), false);
-		if (dia != null)
-			return dia;
-
-		// We're not on .NET 2.0; assume we're on Mono and use some internal
-		// methods...
-		Type MonoMethod = Type.GetType ("System.Reflection.MonoMethod", false);
-		if (MonoMethod == null) {
-			Console.WriteLine ("cannot find MonoMethod");
-			return null;
-		}
-		MethodInfo GetDllImportAttribute = 
-			MonoMethod.GetMethod ("GetDllImportAttribute", 
-					BindingFlags.Static | BindingFlags.NonPublic);
-		if (GetDllImportAttribute == null) {
-			Console.WriteLine ("cannot find GetDllImportAttribute");
-			return null;
-		}
-		IntPtr mhandle = method.MethodHandle.Value;
-		return (DllImportAttribute) GetDllImportAttribute.Invoke (null, 
-				new object[]{mhandle});
-	}
-
-	private static string[] ExcludeList = new string[]{
-		"Mono_Posix_Stdlib_snprintf",
-	};
-
-	private bool IsOnExcludeList (string method)
-	{
-		int idx = Array.BinarySearch (ExcludeList, method);
-		return (idx >= 0 && idx < ExcludeList.Length) ? true : false;
-	}
-
-	private void RecordStructs (MethodInfo method)
-	{
-		ParameterInfo[] parameters = method.GetParameters ();
-		foreach (ParameterInfo pi in parameters) {
-			string s = GetNativeType (pi.ParameterType);
-			if (s.StartsWith ("struct"))
-				structs [s] = s;
-		}
-	}
-
-	public override void CloseFile (string file_prefix)
-	{
-		icall.WriteLine ("/*\n * Structure Declarations\n */");
-		foreach (string s in Sort (structs.Keys))
-			icall.WriteLine ("{0};", s.Replace ("*", ""));
-
-		icall.WriteLine ();
-
-		icall.WriteLine ("/*\n * Function Declarations\n */");
-		foreach (string method in Sort (methods.Keys)) {
-			WriteMethodDeclaration ((MethodInfo) methods [method], method);
-		}
-
-		icall.WriteLine ("\nG_END_DECLS\n");
-		icall.WriteLine ("#endif /* ndef INC_Mono_Posix_" + file_prefix + "_ICALLS_H */\n");
-		icall.Close ();
-	}
-
-	private static IEnumerable Sort (ICollection c)
-	{
-		ArrayList al = new ArrayList (c);
-		al.Sort (MakeMap.OrdinalStringComparer);
-		return al;
-	}
-
-	private void WriteMethodDeclaration (MethodInfo method, string entryPoint)
-	{
-		icall.Write ("{0} ", GetNativeType (method.ReturnType));
-		icall.Write ("{0} ", entryPoint);
-		ParameterInfo[] parameters = method.GetParameters();
-		if (parameters.Length == 0) {
-			icall.WriteLine ("(void);");
-			return;
-		}
-		if (parameters.Length > 0) {
-			icall.Write ("(");
-			WriteParameterDeclaration (parameters [0]);
-		}
-		for (int i = 1; i < parameters.Length; ++i) {
-			icall.Write (", ");
-			WriteParameterDeclaration (parameters [i]);
-		}
-		icall.WriteLine (");");
-	}
-
-	private void DumpTypeInfo (Type t)
-	{
-		if (t == null)
-			return;
-
-		icall.WriteLine ("\t\t/* Type Info for " + t.FullName + ":");
-		foreach (MemberInfo mi in typeof(Type).GetMembers()) {
-			icall.WriteLine ("\t\t\t{0}={1}", mi.Name, GetMemberValue (mi, t));
-		}
-		icall.WriteLine ("\t\t */");
-	}
-
-	private static string GetMemberValue (MemberInfo mi, Type t)
-	{
-		try {
-		switch (mi.MemberType) {
-			case MemberTypes.Constructor:
-			case MemberTypes.Method: {
-				MethodBase b = (MethodBase) mi;
-				if (b.GetParameters().Length == 0)
-					return b.Invoke (t, new object[]{}).ToString();
-				return "<<cannot invoke>>";
-			}
-			case MemberTypes.Field:
-				return ((FieldInfo) mi).GetValue (t).ToString ();
-			case MemberTypes.Property: {
-				PropertyInfo pi = (PropertyInfo) mi;
-				if (!pi.CanRead)
-					return "<<cannot read>>";
-				return pi.GetValue (t, null).ToString ();
-			}
-			default:
-				return "<<unknown value>>";
-		}
-		}
-		catch (Exception e) {
-			return "<<exception reading member: " + e.Message + ">>";
-		}
-	}
-
-	private void WriteParameterDeclaration (ParameterInfo pi)
-	{
-		// DumpTypeInfo (pi.ParameterType);
-		icall.Write ("{0} {1}", GetNativeType (pi.ParameterType), pi.Name);
-	}
-}
-
 // vim: noexpandtab
Index: create-native-map/src/test.xml.ref
===================================================================
--- create-native-map/src/test.xml.ref	(revision 0)
+++ create-native-map/src/test.xml.ref	(revision 0)
@@ -0,0 +1,225 @@
+    <!-- BEGIN GENERATED CONTENT
+/*
+ * This file was automatically generated by create-native-map from TestMap.dll.
+ *
+ * DO NOT MODIFY.
+ */
+
+      -->
+
+    <Member MemberName="TryFromTestEnum">
+      <MemberSignature Language="C#" Value="public static bool TryFromTestEnum (MakeMap.Test.TestEnum value, out int rval);" />
+      <MemberType>Method</MemberType>
+      <ReturnValue>
+        <ReturnType>System.Boolean</ReturnType>
+      </ReturnValue>
+      <Parameters>
+        <Parameter Name="value" Type="MakeMap.Test.TestEnum" />
+        <Parameter Name="rval" Type="System.Int32&amp;" RefType="out" />
+      </Parameters>
+      <Docs>
+        <param name="value">The managed value to convert.</param>
+        <param name="rval">The OS-specific equivalent value.</param>
+        <summary>Converts a <see cref="T:MakeMap.Test.TestEnum" /> 
+          enumeration value to an OS-specific value.</summary>
+        <returns><see langword="true" /> if the conversion was successful; 
+        otherwise, <see langword="false" />.</returns>
+        <remarks><para>This is an exception-safe alternative to 
+        <see cref="M:Mono.Unix.Native.NativeConvert.FromTestEnum" />.</para>
+        <para>If successful, this method stores the OS-specific equivalent
+        value of <paramref name="value" /> into <paramref name="rval" />.
+        Otherwise, <paramref name="rval" /> will contain <c>0</c>.</para>
+        </remarks>
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.FromTestEnum" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.ToTestEnum" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryToTestEnum" />
+      </Docs>
+    </Member>
+    <Member MemberName="FromTestEnum">
+      <MemberSignature Language="C#" Value="public static int FromTestEnum (MakeMap.Test.TestEnum value);" />
+      <MemberType>Method</MemberType>
+      <ReturnValue>
+        <ReturnType>System.Int32</ReturnType>
+      </ReturnValue>
+      <Parameters>
+        <Parameter Name="value" Type="MakeMap.Test.TestEnum" />
+      </Parameters>
+      <Docs>
+        <param name="value">The managed value to convert.</param>
+        <summary>Converts a <see cref="T:MakeMap.Test.TestEnum" /> 
+          to an OS-specific value.</summary>
+        <returns>The equivalent OS-specific value.</returns>
+        <exception cref="T:System.ArgumentOutOfRangeException">
+          <paramref name="value" /> has no equivalent OS-specific value.
+        </exception>
+        <remarks></remarks>
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.ToTestEnum" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryFromTestEnum" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryToTestEnum" />
+      </Docs>
+    </Member>
+    <Member MemberName="TryToTestEnum">
+      <MemberSignature Language="C#" Value="public static bool TryToTestEnum (int value, out MakeMap.Test.TestEnum rval);" />
+      <MemberType>Method</MemberType>
+      <ReturnValue>
+        <ReturnType>System.Boolean</ReturnType>
+      </ReturnValue>
+      <Parameters>
+        <Parameter Name="value" Type="System.Int32" />
+        <Parameter Name="rval" Type="MakeMap.Test.TestEnum&amp;" RefType="out" />
+      </Parameters>
+      <Docs>
+        <param name="value">The OS-specific value to convert.</param>
+        <param name="rval">The managed equivalent value</param>
+        <summary>Converts an OS-specific value to a 
+          <see cref="T:MakeMap.Test.TestEnum" />.</summary>
+        <returns><see langword="true" /> if the conversion was successful; 
+        otherwise, <see langword="false" />.</returns>
+        <remarks><para>This is an exception-safe alternative to 
+        <see cref="M:Mono.Unix.Native.NativeConvert.ToTestEnum" />.</para>
+        <para>If successful, this method stores the managed equivalent
+        value of <paramref name="value" /> into <paramref name="rval" />.
+        Otherwise, <paramref name="rval" /> will contain a <c>0</c>
+        cast to a <see cref="T:MakeMap.Test.TestEnum" />.</para>
+                </remarks>
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.FromTestEnum" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.ToTestEnum" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryFromTestEnum" />
+      </Docs>
+    </Member>
+    <Member MemberName="ToTestEnum">
+      <MemberSignature Language="C#" Value="public static MakeMap.Test.TestEnum ToTestEnum (int value);" />
+      <MemberType>Method</MemberType>
+      <ReturnValue>
+        <ReturnType>MakeMap.Test.TestEnum</ReturnType>
+      </ReturnValue>
+      <Parameters>
+        <Parameter Name="value" Type="System.Int32" />
+      </Parameters>
+      <Docs>
+        <param name="value">The OS-specific value to convert.</param>
+        <summary>Converts an OS-specific value to a 
+          <see cref="T:MakeMap.Test.TestEnum" />.</summary>
+					<returns>The equivalent managed value.</returns>
+
+        <exception cref="T:System.ArgumentOutOfRangeException">
+          <paramref name="value" /> has no equivalent managed value.
+        </exception>
+        <remarks>
+        
+        </remarks>
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.FromTestEnum" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryFromTestEnum" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryToTestEnum" />
+      </Docs>
+    </Member>
+
+
+    <Member MemberName="TryFromColors">
+      <MemberSignature Language="C#" Value="public static bool TryFromColors (MakeMap.ToBeRenamed.Colors value, out int rval);" />
+      <MemberType>Method</MemberType>
+      <ReturnValue>
+        <ReturnType>System.Boolean</ReturnType>
+      </ReturnValue>
+      <Parameters>
+        <Parameter Name="value" Type="MakeMap.ToBeRenamed.Colors" />
+        <Parameter Name="rval" Type="System.Int32&amp;" RefType="out" />
+      </Parameters>
+      <Docs>
+        <param name="value">The managed value to convert.</param>
+        <param name="rval">The OS-specific equivalent value.</param>
+        <summary>Converts a <see cref="T:MakeMap.ToBeRenamed.Colors" /> 
+          enumeration value to an OS-specific value.</summary>
+        <returns><see langword="true" /> if the conversion was successful; 
+        otherwise, <see langword="false" />.</returns>
+        <remarks><para>This is an exception-safe alternative to 
+        <see cref="M:Mono.Unix.Native.NativeConvert.FromColors" />.</para>
+        <para>If successful, this method stores the OS-specific equivalent
+        value of <paramref name="value" /> into <paramref name="rval" />.
+        Otherwise, <paramref name="rval" /> will contain <c>0</c>.</para>
+        </remarks>
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.FromColors" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.ToColors" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryToColors" />
+      </Docs>
+    </Member>
+    <Member MemberName="FromColors">
+      <MemberSignature Language="C#" Value="public static int FromColors (MakeMap.ToBeRenamed.Colors value);" />
+      <MemberType>Method</MemberType>
+      <ReturnValue>
+        <ReturnType>System.Int32</ReturnType>
+      </ReturnValue>
+      <Parameters>
+        <Parameter Name="value" Type="MakeMap.ToBeRenamed.Colors" />
+      </Parameters>
+      <Docs>
+        <param name="value">The managed value to convert.</param>
+        <summary>Converts a <see cref="T:MakeMap.ToBeRenamed.Colors" /> 
+          to an OS-specific value.</summary>
+        <returns>The equivalent OS-specific value.</returns>
+        <exception cref="T:System.ArgumentOutOfRangeException">
+          <paramref name="value" /> has no equivalent OS-specific value.
+        </exception>
+        <remarks></remarks>
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.ToColors" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryFromColors" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryToColors" />
+      </Docs>
+    </Member>
+    <Member MemberName="TryToColors">
+      <MemberSignature Language="C#" Value="public static bool TryToColors (int value, out MakeMap.ToBeRenamed.Colors rval);" />
+      <MemberType>Method</MemberType>
+      <ReturnValue>
+        <ReturnType>System.Boolean</ReturnType>
+      </ReturnValue>
+      <Parameters>
+        <Parameter Name="value" Type="System.Int32" />
+        <Parameter Name="rval" Type="MakeMap.ToBeRenamed.Colors&amp;" RefType="out" />
+      </Parameters>
+      <Docs>
+        <param name="value">The OS-specific value to convert.</param>
+        <param name="rval">The managed equivalent value</param>
+        <summary>Converts an OS-specific value to a 
+          <see cref="T:MakeMap.ToBeRenamed.Colors" />.</summary>
+        <returns><see langword="true" /> if the conversion was successful; 
+        otherwise, <see langword="false" />.</returns>
+        <remarks><para>This is an exception-safe alternative to 
+        <see cref="M:Mono.Unix.Native.NativeConvert.ToColors" />.</para>
+        <para>If successful, this method stores the managed equivalent
+        value of <paramref name="value" /> into <paramref name="rval" />.
+        Otherwise, <paramref name="rval" /> will contain a <c>0</c>
+        cast to a <see cref="T:MakeMap.ToBeRenamed.Colors" />.</para>
+                </remarks>
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.FromColors" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.ToColors" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryFromColors" />
+      </Docs>
+    </Member>
+    <Member MemberName="ToColors">
+      <MemberSignature Language="C#" Value="public static MakeMap.ToBeRenamed.Colors ToColors (int value);" />
+      <MemberType>Method</MemberType>
+      <ReturnValue>
+        <ReturnType>MakeMap.ToBeRenamed.Colors</ReturnType>
+      </ReturnValue>
+      <Parameters>
+        <Parameter Name="value" Type="System.Int32" />
+      </Parameters>
+      <Docs>
+        <param name="value">The OS-specific value to convert.</param>
+        <summary>Converts an OS-specific value to a 
+          <see cref="T:MakeMap.ToBeRenamed.Colors" />.</summary>
+					<returns>The equivalent managed value.</returns>
+
+        <exception cref="T:System.ArgumentOutOfRangeException">
+          <paramref name="value" /> has no equivalent managed value.
+        </exception>
+        <remarks>
+        
+        </remarks>
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.FromColors" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryFromColors" />
+        <altmember cref="M:Mono.Unix.Native.NativeConvert.TryToColors" />
+      </Docs>
+    </Member>
+
+    <!-- END GENERATED CONTENT -->
Index: create-native-map/src/Makefile.am
===================================================================
--- create-native-map/src/Makefile.am	(revision 0)
+++ create-native-map/src/Makefile.am	(revision 0)
@@ -0,0 +1,61 @@
+
+CNM_FILES = \
+	create-native-map.cs \
+	MapAttribute.cs 
+
+TM_FILES = \
+	MapAttribute.cs \
+	TestMap.cs 
+
+cnm_build_sources = $(addprefix $(srcdir)/, $(CNM_FILES))
+tm_build_sources  = $(addprefix $(srcdir)/, $(TM_FILES))
+
+EXE = ../lib/create-native-map/create-native-map.exe
+
+REFS = -r:Mono.Posix.dll
+
+all: $(EXE)
+
+$(EXE) : $(cnm_build_sources)
+	$(GMCS) $(MCS_FLAGS) -d:TRACE -debug+ -out:$@ -target:exe $(REFS) $(cnm_build_sources)
+
+assemblydir = $(prefix)/lib/create-native-map
+assembly_DATA = $(EXE) MapAttribute.cs
+
+check: $(PROGRAM) TestMap.dll
+
+TestMap.dll: $(tm_build_sources) $(PROGRAM)
+	$(MCS) -debug+ -out:$@ -t:library $(tm_build_sources)
+
+test_output = test.c test.h test.cs test.xml
+
+$(test_output): TestMap.dll $(EXE)
+	../bin/create-native-map                                \
+		--autoconf-member autoconf_me                         \
+		--autoconf-header='<unistd.h>'                        \
+		--public-header='<stdlib.h>'                          \
+		--public-macro=DefineMe=42                            \
+		--impl-header='<stdio.h>'                             \
+		--impl-header='"foo.h"'                               \
+		--impl-macro='FOO="foo"'                              \
+		--exclude-native-symbol=exclude_native_symbol         \
+		--library=NativeLib                                   \
+		--rename-member=st_atime=st_atime_                    \
+		--rename-namespace=MakeMap.ToBeRenamed=MakeMap_Rename \
+		$< test
+
+check: $(test_output)
+	for f in test.c test.h test.cs test.xml ; do \
+		diff -rup $$f.ref $$f ; \
+	done
+
+check-update:
+	for f in test.c test.h test.cs test.xml ; do \
+		mv $$f $$f.ref ; \
+	done
+
+libtest.so: test.c
+	gcc -shared -o $@ $^ -I.. `pkg-config --libs --cflags glib-2.0`
+
+CLEANFILES = $(EXE) $(EXE).mdb TestMap.dll TestMap.dll.mdb libtest.so
+
Index: create-native-map/src/test.c.ref
===================================================================
--- create-native-map/src/test.c.ref	(revision 0)
+++ create-native-map/src/test.c.ref	(revision 0)
@@ -0,0 +1,285 @@
+/*
+ * This file was automatically generated by create-native-map from TestMap.dll.
+ *
+ * DO NOT MODIFY.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* ndef HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Implementation Macros
+ */
+#ifndef FOO
+#define FOO "foo"
+#endif /* ndef FOO */
+
+
+/*
+ * Implementation Includes
+ */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* ndef HAVE_UNISTD_H */
+#include <stdio.h>
+#include "foo.h"
+
+#include "test.h"
+
+#include <errno.h>    /* errno, EOVERFLOW */
+#include <glib.h>     /* g* types, g_assert_not_reached() */
+
+/* returns TRUE if @type is an unsigned type */
+#define _cnm_integral_type_is_unsigned(type) \
+    (sizeof(type) == sizeof(gint8)           \
+      ? (((type)-1) > G_MAXINT8)             \
+      : sizeof(type) == sizeof(gint16)       \
+        ? (((type)-1) > G_MAXINT16)          \
+        : sizeof(type) == sizeof(gint32)     \
+          ? (((type)-1) > G_MAXINT32)        \
+          : sizeof(type) == sizeof(gint64)   \
+            ? (((type)-1) > G_MAXINT64)      \
+            : (g_assert_not_reached (), 0))
+
+/* returns the minimum value of @type as a gint64 */
+#define _cnm_integral_type_min(type)          \
+    (_cnm_integral_type_is_unsigned (type)    \
+      ? 0                                     \
+      : sizeof(type) == sizeof(gint8)         \
+        ? G_MININT8                           \
+        : sizeof(type) == sizeof(gint16)      \
+          ? G_MININT16                        \
+          : sizeof(type) == sizeof(gint32)    \
+            ? G_MININT32                      \
+            : sizeof(type) == sizeof(gint64)  \
+              ? G_MININT64                    \
+              : (g_assert_not_reached (), 0))
+
+/* returns the maximum value of @type as a guint64 */
+#define _cnm_integral_type_max(type)            \
+    (_cnm_integral_type_is_unsigned (type)      \
+      ? sizeof(type) == sizeof(gint8)           \
+        ? G_MAXUINT8                            \
+        : sizeof(type) == sizeof(gint16)        \
+          ? G_MAXUINT16                         \
+          : sizeof(type) == sizeof(gint32)      \
+            ? G_MAXUINT32                       \
+            : sizeof(type) == sizeof(gint64)    \
+              ? G_MAXUINT64                     \
+              : (g_assert_not_reached (), 0)    \
+      : sizeof(type) == sizeof(gint8)           \
+          ? G_MAXINT8                           \
+          : sizeof(type) == sizeof(gint16)      \
+            ? G_MAXINT16                        \
+            : sizeof(type) == sizeof(gint32)    \
+              ? G_MAXINT32                      \
+              : sizeof(type) == sizeof(gint64)  \
+                ? G_MAXINT64                    \
+                : (g_assert_not_reached (), 0))
+
+#ifdef DEBUG
+#define _cnm_dump_(to_t,from)                                            \
+  printf ("# %s -> %s: min=%llx; max=%llx; value=%llx; lt=%i; l0=%i; gt=%i; e=%i\n", \
+    #from, #to_t,                                                        \
+    (gint64) (_cnm_integral_type_min(to_t)),                             \
+    (gint64) (_cnm_integral_type_max (to_t)),                            \
+    (gint64) (from),                                                     \
+    (_cnm_integral_type_min (to_t) <= from),                             \
+    (from < 0),                                                          \
+    /* (_cnm_integral_type_max (to_t) >= from) */                        \
+    (from <= _cnm_integral_type_max (to_t)),                             \
+    ((_cnm_integral_type_min(to_t) >= from) &&                           \
+          ((from < 0) ? 1 : (from <= _cnm_integral_type_max(to_t))))     \
+  )
+#else
+#define _cnm_dump_(to_t, from) do {} while (0)
+#endif
+
+#define _cnm_return_val_if_overflow(to_t,from,val)  G_STMT_START {   \
+    if (!(_cnm_integral_type_min(to_t) <= from &&                    \
+          ((from < 0) || (from <= _cnm_integral_type_max(to_t))))) { \
+      _cnm_dump_(to_t, from);                                        \
+      errno = EOVERFLOW;                                             \
+      return (val);                                                  \
+    }                                                                \
+  } G_STMT_END
+
+int
+MakeMap_Test_FromFoo (struct MakeMap_Test_Foo *from, struct foo *to)
+{
+	_cnm_return_val_if_overflow (int, from->foo, -1);
+#ifdef HAVE_STRUCT_FOO_AUTOCONF_ME
+	_cnm_return_val_if_overflow (gint64, from->autoconf_me, -1);
+#endif /* ndef HAVE_STRUCT_FOO_AUTOCONF_ME */
+
+	memset (to, 0, sizeof(*to));
+
+	to->foo         = from->foo;
+	to->p           = from->p;
+#ifdef HAVE_STRUCT_FOO_AUTOCONF_ME
+	to->autoconf_me = from->autoconf_me;
+#endif /* ndef HAVE_STRUCT_FOO_AUTOCONF_ME */
+
+	return 0;
+}
+
+
+int
+MakeMap_Test_ToFoo (struct foo *from, struct MakeMap_Test_Foo *to)
+{
+	_cnm_return_val_if_overflow (int, from->foo, -1);
+#ifdef HAVE_STRUCT_FOO_AUTOCONF_ME
+	_cnm_return_val_if_overflow (gint64, from->autoconf_me, -1);
+#endif /* ndef HAVE_STRUCT_FOO_AUTOCONF_ME */
+
+	memset (to, 0, sizeof(*to));
+
+	to->foo         = from->foo;
+	to->p           = from->p;
+#ifdef HAVE_STRUCT_FOO_AUTOCONF_ME
+	to->autoconf_me = from->autoconf_me;
+#endif /* ndef HAVE_STRUCT_FOO_AUTOCONF_ME */
+
+	return 0;
+}
+
+
+int
+MakeMap_Test_FromFooHolder (struct MakeMap_Test_FooHolder *from, struct foo_holder *to)
+{
+
+	memset (to, 0, sizeof(*to));
+
+	if (MakeMap_Test_FromFoo (&from->foo, &to->foo) != 0) {
+		return -1;
+	}
+	if (MakeMap_Test_FromTestEnum (from->mode, &to->mode) != 0) {
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int
+MakeMap_Test_ToFooHolder (struct foo_holder *from, struct MakeMap_Test_FooHolder *to)
+{
+
+	memset (to, 0, sizeof(*to));
+
+	if (MakeMap_Test_ToFoo (&from->foo, &to->foo) != 0) {
+		return -1;
+	}
+	if (MakeMap_Test_ToTestEnum (from->mode, &to->mode) != 0) {
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int MakeMap_Test_FromTestEnum (int x, int *r)
+{
+	*r = 0;
+	if (x == MakeMap_Test_TestEnum_Bar)
+#ifdef Bar
+		{*r = Bar; return 0;}
+#else /* def Bar */
+		{errno = EINVAL; return -1;}
+#endif /* ndef Bar */
+	if (x == MakeMap_Test_TestEnum_Baz)
+#ifdef Baz
+		{*r = Baz; return 0;}
+#else /* def Baz */
+		{errno = EINVAL; return -1;}
+#endif /* ndef Baz */
+	if (x == MakeMap_Test_TestEnum_Foo)
+#ifdef Foo
+		{*r = Foo; return 0;}
+#else /* def Foo */
+		{errno = EINVAL; return -1;}
+#endif /* ndef Foo */
+	if (x == MakeMap_Test_TestEnum_Qux)
+#ifdef Qux
+		{*r = Qux; return 0;}
+#else /* def Qux */
+		{errno = EINVAL; return -1;}
+#endif /* ndef Qux */
+	if (x == 0)
+		return 0;
+	errno = EINVAL; return -1;
+}
+
+int MakeMap_Test_ToTestEnum (int x, int *r)
+{
+	*r = 0;
+	if (x == 0)
+		return 0;
+#ifdef Bar
+	if (x == Bar)
+		{*r = MakeMap_Test_TestEnum_Bar; return 0;}
+#endif /* ndef Bar */
+#ifdef Baz
+	if (x == Baz)
+		{*r = MakeMap_Test_TestEnum_Baz; return 0;}
+#endif /* ndef Baz */
+#ifdef Foo
+	if (x == Foo)
+		{*r = MakeMap_Test_TestEnum_Foo; return 0;}
+#endif /* ndef Foo */
+#ifdef Qux
+	if (x == Qux)
+		{*r = MakeMap_Test_TestEnum_Qux; return 0;}
+#endif /* ndef Qux */
+	errno = EINVAL; return -1;
+}
+
+int MakeMap_Rename_FromColors (int x, int *r)
+{
+	*r = 0;
+	if (x == MakeMap_Rename_Colors_Blue)
+#ifdef Blue
+		{*r = Blue; return 0;}
+#else /* def Blue */
+		{errno = EINVAL; return -1;}
+#endif /* ndef Blue */
+	if (x == MakeMap_Rename_Colors_Green)
+#ifdef Green
+		{*r = Green; return 0;}
+#else /* def Green */
+		{errno = EINVAL; return -1;}
+#endif /* ndef Green */
+	if (x == MakeMap_Rename_Colors_Red)
+#ifdef Red
+		{*r = Red; return 0;}
+#else /* def Red */
+		{errno = EINVAL; return -1;}
+#endif /* ndef Red */
+	if (x == 0)
+		return 0;
+	errno = EINVAL; return -1;
+}
+
+int MakeMap_Rename_ToColors (int x, int *r)
+{
+	*r = 0;
+	if (x == 0)
+		return 0;
+#ifdef Blue
+	if (x == Blue)
+		{*r = MakeMap_Rename_Colors_Blue; return 0;}
+#endif /* ndef Blue */
+#ifdef Green
+	if (x == Green)
+		{*r = MakeMap_Rename_Colors_Green; return 0;}
+#endif /* ndef Green */
+#ifdef Red
+	if (x == Red)
+		{*r = MakeMap_Rename_Colors_Red; return 0;}
+#endif /* ndef Red */
+	errno = EINVAL; return -1;
+}
+
Index: create-native-map/src/test.cs.ref
===================================================================
--- create-native-map/src/test.cs.ref	(revision 0)
+++ create-native-map/src/test.cs.ref	(revision 0)
@@ -0,0 +1,123 @@
+/*
+ * This file was automatically generated by create-native-map from TestMap.dll.
+ *
+ * DO NOT MODIFY.
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using Mono.Unix.Native;
+
+namespace Mono.Unix.Native {
+
+	public sealed /* static */ partial class NativeConvert
+	{
+		private NativeConvert () {}
+
+		private const string LIB = "NativeLib";
+
+		private static void ThrowArgumentException (object value)
+		{
+			throw new ArgumentOutOfRangeException ("value", value,
+				Locale.GetText ("Current platform doesn't support this value."));
+		}
+
+		[DllImport (LIB, EntryPoint="MakeMap_Test_FromFoo")]
+		private static extern int FromFoo (ref Foo source, IntPtr destination);
+
+		public static bool TryCopy (ref Foo source, IntPtr destination)
+		{
+			return FromFoo (ref source, destination) == 0;
+		}
+
+		[DllImport (LIB, EntryPoint="MakeMap_Test_ToFoo")]
+		private static extern int ToFoo (IntPtr source, out Foo destination);
+
+		public static bool TryCopy (IntPtr source, out Foo destination)
+		{
+			return ToFoo (source, out destination) == 0;
+		}
+
+		[DllImport (LIB, EntryPoint="MakeMap_Test_FromFooHolder")]
+		private static extern int FromFooHolder (ref FooHolder source, IntPtr destination);
+
+		public static bool TryCopy (ref FooHolder source, IntPtr destination)
+		{
+			return FromFooHolder (ref source, destination) == 0;
+		}
+
+		[DllImport (LIB, EntryPoint="MakeMap_Test_ToFooHolder")]
+		private static extern int ToFooHolder (IntPtr source, out FooHolder destination);
+
+		public static bool TryCopy (IntPtr source, out FooHolder destination)
+		{
+			return ToFooHolder (source, out destination) == 0;
+		}
+
+		[DllImport (LIB, EntryPoint="MakeMap_Test_FromTestEnum")]
+		private static extern int FromTestEnum (TestEnum value, out Int32 rval);
+
+		public static bool TryFromTestEnum (TestEnum value, out Int32 rval)
+		{
+			return FromTestEnum (value, out rval) == 0;
+		}
+
+		public static Int32 FromTestEnum (TestEnum value)
+		{
+			Int32 rval;
+			if (FromTestEnum (value, out rval) == -1)
+				ThrowArgumentException (value);
+			return rval;
+		}
+
+		[DllImport (LIB, EntryPoint="MakeMap_Test_ToTestEnum")]
+		private static extern int ToTestEnum (Int32 value, out TestEnum rval);
+
+		public static bool TryToTestEnum (Int32 value, out TestEnum rval)
+		{
+			return ToTestEnum (value, out rval) == 0;
+		}
+
+		public static TestEnum ToTestEnum (Int32 value)
+		{
+			TestEnum rval;
+			if (ToTestEnum (value, out rval) == -1)
+				ThrowArgumentException (value);
+			return rval;
+		}
+
+		[DllImport (LIB, EntryPoint="MakeMap_Rename_FromColors")]
+		private static extern int FromColors (Colors value, out Int32 rval);
+
+		public static bool TryFromColors (Colors value, out Int32 rval)
+		{
+			return FromColors (value, out rval) == 0;
+		}
+
+		public static Int32 FromColors (Colors value)
+		{
+			Int32 rval;
+			if (FromColors (value, out rval) == -1)
+				ThrowArgumentException (value);
+			return rval;
+		}
+
+		[DllImport (LIB, EntryPoint="MakeMap_Rename_ToColors")]
+		private static extern int ToColors (Int32 value, out Colors rval);
+
+		public static bool TryToColors (Int32 value, out Colors rval)
+		{
+			return ToColors (value, out rval) == 0;
+		}
+
+		public static Colors ToColors (Int32 value)
+		{
+			Colors rval;
+			if (ToColors (value, out rval) == -1)
+				ThrowArgumentException (value);
+			return rval;
+		}
+
+	}
+}
+
Index: create-native-map/ChangeLog
===================================================================
--- create-native-map/ChangeLog	(revision 0)
+++ create-native-map/ChangeLog	(revision 0)
@@ -0,0 +1,46 @@
+2006-09-01  Jonathan Pryor  <jonpryor@vt.edu>
+
+	* Makefile.am, lib/Makefile.am: Added; build subdirectories.
+	* bin/create-native-map: Script to startup 
+	  `dirname`/../lib/create-native-map/create-native-map.exe.
+	* bin/Makefile.am: Added; install $bindir/create-native-map.
+	* lib/create-native-map/Makefile.am: Added; present to make sure
+	  $top_builddir/lib/create-native-map is created.
+	* lib/pkgconfig/create-native-map.pc.in: Aded; pkgconfig file to copy an
+	  installed version of create-native-map.exe & MapAttribute.cs.
+	* lib/pkgconfig/Makfile.am: Added; install the create-native-map.pc file.
+	* man/create-native-map.1: Man page for create-native-map.
+	* man/Makefile.am: Added; install the man page.
+	* src/create-native-map.cs:
+	  - Moved from mcs/class/Mono.Posix/Mono.Unix.Native/make-map.cs
+	  - check for t.Namespace==null before looking using
+	    Configuration.NamespaceRenames (Dictionary`2 doesn't like null keys);
+	  - HeaderFileGenerator needs to know about member renames (so it uses the
+	    renamed member in conversion code);
+	  - Clean up enumeration generation for readablility.
+	  - Generate structure declarations for [Map]-decorated types and types used
+	    within a [DllImport]-marked method.
+	  - Warnings should be prefixed with "warning: ".
+		- Don't generate function prototypes for already-generated functions (e.g.
+	    if we emit a prototype for Mono_Posix_ToFilePermissions, don't
+	    re-declare that function later because we found a DllImport for it).
+	  - Add new arguments: --autoconf-member, --exclude-native-symbol, 
+	    --library, --rename-member, --rename-namespace.
+	    These are to:
+	    - Allow native structure members to only be accessed if an Autoconf
+	      macro is defined (--autoconf-member)
+	    - Modify the C "namespace" of types/functions (--rename-namespace)
+	    - Specify the DllImport library that prototypes should be generated for
+	      (--library)
+	    - Exclude symbols from the function declaration system
+	      (--exclude-native-symbol)
+	    - Member renaming (--rename-member).  
+	      (Curse you glibc making st_atime a macro!)
+	* src/Makefile.am: Added; build create-native-map.exe; test cases.
+	* src/MapAttribute.cs: Added; the attribute that create-native-map looks
+	  for, and should be copied into projects using create-native-map.
+	* src/TestMap.cs: Added; test case for create-native-map.exe
+	* src/test.c.ref, src/test.cs.ref, src/test.h.ref, src/test.xml.ref: Added; 
+	  expected create-native-map.exe output for TestMap.cs.
+	* ChangeLog: Started.
+
Index: create-native-map/bin/create-native-map
===================================================================
--- create-native-map/bin/create-native-map	(revision 0)
+++ create-native-map/bin/create-native-map	(revision 0)
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+bindir=`dirname "$0"`
+libdir="$bindir/../lib/create-native-map"
+
+exec mono "$libdir/create-native-map.exe" "$@"
+

Property changes on: create-native-map/bin/create-native-map
___________________________________________________________________
Name: svn:executable
   + *

Index: create-native-map/bin/Makefile.am
===================================================================
--- create-native-map/bin/Makefile.am	(revision 0)
+++ create-native-map/bin/Makefile.am	(revision 0)
@@ -0,0 +1,7 @@
+
+bin_SCRIPTS = create-native-map
+
+create-native-map:
+	cp $(srcdir)/create-native-map .
+	chmod +x $@
+
Index: create-native-map/Makefile.am
===================================================================
--- create-native-map/Makefile.am	(revision 0)
+++ create-native-map/Makefile.am	(revision 0)
@@ -0,0 +1 @@
+SUBDIRS = bin src lib man
Index: create-native-map/man/create-native-map.1
===================================================================
--- create-native-map/man/create-native-map.1	(revision 0)
+++ create-native-map/man/create-native-map.1	(revision 0)
@@ -0,0 +1,559 @@
+.\" 
+.\" create-native-map manual page.
+.\" (C) 2006 Jonathan Pryor
+.\" Author:
+.\"   Jonathan Pryor (jonpryor@vt.edu)
+.\"
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.TH "create-native-map" 1
+.SH NAME
+create-native-map \- C/C# Mapping Creator
+.SH SYNOPSIS
+.B create-native-map
+[OPTIONS]* ASSEMBLY-FILE-NAME OUPUT-PREFIX
+.SH OPTIONS
+.TP
+.I \--autoconf-header=HEADER
+.I HEADER
+is a header file name in the syntax typically used with the C 
+.I #include
+statement, e.g.
+.I "#include <stdio.h>"
+or 
+.I "#include ""local.h"""
+\.
+.Sp
+An Autoconf-formatted macro is generated from the include name, and a
+.I #include
+directive is wrapped within a
+.I #ifdef
+block for the Autoconf macro within the generated
+.I .c
+file.
+.Sp
+For example,
+.I "--autoconf-header=<stdio.h>"
+would generate the code:
+.nf
+
+	#ifndef HAVE_STDIO_H
+	#include <stdio.h>
+	#endif /* ndef HAVE_STDIO_H */
+
+.fi
+.TP
+.I \--autoconf-member=MEMBER
+Specify that any access to 
+.I MEMBER
+should be wrapped within a 
+.I #ifdef HAVE_MEMBER
+block.
+.I MEMBER
+can be either a 
+.I field-name
+or a 
+.I class-name
+\.
+.I field-name
+combination.
+.Sp
+For example, given the C# declaration:
+.nf
+
+	[Mono.Unix.Native.Map ("struct dirent")]
+	struct Dirent {
+		public long d_off;
+	}
+
+.fi
+then
+.I "--autoconf-member=d_off"
+would generate the code similar to:
+.nf
+
+	int
+	ToDirent (struct dirent *from, struct Dirent *to)
+	{
+	#ifdef HAVE_STRUCT_DIRENT_D_OFF
+		to->d_off = from->d_off;
+	#endif /* ndef HAVE_STRUCT_DIRENT_D_OFF */
+	}
+
+.fi
+.TP
+.I \--exclude-native-symbol=SYMBOL
+.I SYMBOL
+is a 
+.I [DllImport]
+-marked method that should
+.I not
+have a prototype generated for it.
+.TP
+.I \--impl-header=HEADER
+Insert a 
+.I #include
+statement within the generated 
+.I .c
+file for 
+.I HEADER
+\.
+.Sp
+For example, 
+.I "--impl-header=<stdlib.h>"
+generates
+.nf
+
+	#include <stdlib.h>
+
+.fi
+.TP
+.I \--impl-macro=MACRO
+Insert a
+.I #define
+statement within the generated
+.I .c
+file.  
+.I MACRO
+can contain a 
+.I "="
+to separate the macro name from the macro value.
+.Sp
+For example,
+.I "--impl-macro=FOO=42"
+generates
+.nf
+
+	#define FOO 42
+
+.fi
+.TP
+.I \--library=LIBRARY
+Create prototypes for
+.I [DllImport]
+-marked methods which reference the native library
+.I LIBRARY
+into the generated 
+.I .h
+file.
+.TP
+.I \--public-header=HEADER
+Insert a 
+.I #include
+statement within the generated 
+.I .h
+file for 
+.I HEADER
+\.
+.Sp
+For example, 
+.I "--public-header=<stdlib.h>"
+generates
+.nf
+
+	#include <stdlib.h>
+
+.fi
+.TP
+.I \--public-macro=MACRO
+Insert a
+.I #define
+statement within the generated
+.I .h
+file.  
+.I MACRO
+can contain a 
+.I "="
+to separate the macro name from the macro value.
+.Sp
+For example,
+.I "--public-macro=FOO=42"
+generates
+.nf
+
+	#define FOO 42
+
+.fi
+.TP
+.I \--rename-member=FROM=TO
+This is used when 
+.I FROM
+is a C macro, and thus must be altered in order to be used sanely.  All 
+generated references to the managed representation will use 
+.I TO 
+instead of
+.I FROM
+\.
+.Sp
+For example, given the C# declaration:
+.nf
+
+	[Mono.Unix.Native.Map ("struct stat")]
+	struct Stat {
+		public long st_atime;
+	}
+
+.fi
+and the argument
+.I "--rename-member=st_atime=st_atime_"
+, the generated 
+.I .h
+file would contain:
+.nf
+
+	struct Stat {
+		gint64 st_atime_;
+	};
+
+.fi
+(note the altered field name), while the generated
+.I .c
+file would contain:
+.nf
+
+	ToStat (struct stat *from, struct Stat *to)
+	{
+		to->st_atime_ = from->st_atime;
+	}
+
+.fi
+.TP
+.I \--rename-namespace=FROM=TO
+By default, the C "namespace" (symbol prefix) is the C# namespace; types 
+within the C# namespace 
+.I Mono.Unix.Native
+would be in the C "namespace"
+.I Mono_Unix_Native
+\.
+Use 
+.I "--rename-namespace"
+to modify the default, e.g.
+.I "--rename-namespace=Mono.Unix.Native=Mono_Posix"
+\.
+This should be avoided if possible.  You should instead use the
+.I Mono.Unix.Native.MapAttribute.NativeSymbolPrefix 
+property instead, e.g.
+.nf
+
+	[Mono.Unix.Native.Map (NativeSymbolPrefix="Mono_Posix")]
+	struct Stat {
+		public long st_atime;
+	}
+
+.fi
+.PP
+.SH DESCRIPTION
+.I create-native-map
+is a program for a specific scenario: keeping code which is tightly coupled
+between C and C# in sync with each other, based upon the C# types.
+.PP
+Platform Invoke is only useful if the managed code knows the exact types
+and layout of all unmanaged structures it uses.  This is usually the case
+on Windows, but it is
+.I not
+the case on Unix.  For example,
+.I "struct stat"
+makes use of types with sizes that will vary from platform to platform
+(or even based on the compiler macros defined!).  For example,
+.I off_t
+is usually a signed 32-bit integer on ILP32 platforms, but may be a
+signed 64-bit integer on LP64 platforms, but may also be a 64-bit signed
+integer on ILP32 platforms if the
+.I "_FILE_OFFSET_BITS"
+macro has the value 64.
+In short, everything is flexible within Unix, and managed code can't deal
+with such flexibility.
+.PP
+Thus, the niche for 
+.I create-native-map
+: assume a fixed ABI that managed code can target, and generate code to 
+"thunk" the managed representations to the corresponding native representations.
+This needs to be done for 
+.I everything
+that can vary between platforms and compiler flags, from enumeration values
+(
+.I SIGBUS
+has the value 10 on FreeBSD but 7 on Linux) to structure members (how big is 
+.I off_t
+?).
+.PP
+.I create-native-map
+will inspect 
+.I ASSEMBLY-FILE-NAME
+and output the following files:
+.RS
+.ne 8
+.TP
+.I OUTPUT-PREFIX.h
+Contains enumeration values, class and structure declarations, 
+delegate declarations, and 
+.I [DllImport]
+-marked methods (from the library specified by
+.I \--library
+) within the assembly
+.I ASSEMBLY-FILE-NAME
+\.
+.TP
+.I OUTPUT-PREFIX.c
+Contains the implementation of enumeration and structure conversion functions.
+.TP
+.I OUTPUT-PREFIX.cs
+Contains a partial class
+.I NativeConvert
+containing enumeration translation methods.
+.TP
+.I OUTPUT-PREFIX.xml
+Generates ECMA XML documentation stubs for the enumeration translation methods in
+.I OUTPUT-PREFIX.cs
+\.
+.ne
+.RE
+.PP
+.I create-native-map
+primarily looks for 
+.I Mono.Unix.Native.MapAttribute
+-decorated types, and makes use of two 
+.I MapAttribute
+properties:
+.RS
+.ne 8
+.TP
+.I NativeType
+Contains the corresponding C type.  Only useful if applied to classes, structures,
+and fields.
+.TP
+.I NativeSymbolPrefix
+Contains the C "namespace" for generated enumerations, structures, and functions.
+If this is not specified, the C "namespace" defaults to the managed namespace
+or the appropriate namespace rename provided by
+.I "--rename-namespace"
+..
+.ne
+.RE
+.PP
+The
+.I MapAttribute
+attribute can be specified on classes, structures, delegates, fields, and
+enumerations.
+.TP
+Delegates
+Code generation for delegates ignores the 
+.I MapAttribute.NativeType
+property, and generates a function pointer 
+.I typedef
+that best matches the delegate declaration into the
+.I .h
+file.
+.Sp
+For example,
+.nf
+
+	[Map (NativeSymbolPrefix="Foo")]
+	delegate string MyCallback (string s);
+
+.fi
+generates the 
+.I typedef
+:
+.nf
+
+	typedef char* (*Foo_MyCallback) (const char *s);
+
+.fi
+.TP
+Classes and Structures
+A 
+.I [Map]
+-decorated class or structure will get a C structure declaration within the
+.I .h
+file:
+.nf
+
+	[Map]
+	struct Foo {
+		public int i;
+	}
+
+.fi
+becomes
+.nf
+
+	struct Foo {
+		public int i;
+	};
+
+.fi
+If the 
+.I MapAttribute.NativeType
+property is set, then conversion functions will be declared within the
+.I .h
+file and created within the
+.I .c
+file:
+.nf
+
+	[Map ("struct stat", NativeSymbolPrefix="Foo")]
+	struct Stat {
+		public uint st_uid;
+	}
+
+.fi
+becomes
+.nf
+
+	/* The .h file */
+	struct Foo_Stat {
+		unsigned int st_uid;
+	};
+	int
+	Foo_FromStat (struct Foo_Stat *from, struct stat *to);
+	int
+	Foo_ToStat (struct stat *to, sxtruct Foo_Stat *to);
+
+	/* The .c file */
+	int
+	Foo_FromStat (struct Foo_Stat *from, struct stat *to)
+	{
+		memset (to, 0, sizeof(*to);
+		to->st_uid = from->st_uid;
+		return 0;
+	}
+
+	int
+	Foo_ToStat (struct stat *to, sxtruct Foo_Stat *to)
+	{
+		memset (to, 0, sizeof(*to);
+		to->st_uid = from->st_uid;
+		return 0;
+	}
+
+.fi
+.TP
+Fields
+If a field (1) has the
+.I MapAttribute
+attribute, and (2) has the
+.I MapAttribute.NativeType
+property set, then the specified native type will be used for overflow
+checking.  For example:
+.nf
+
+	[Map ("struct stat", NativeSymbolPrefix="Foo")]
+	struct Stat {
+		[Map ("off_t")] public long st_size;
+	}
+
+.fi
+generates
+.nf
+
+	/* The .h file */
+	struct Foo_Stat {
+		gint64 st_size;
+	};
+	int
+	Foo_FromStat (struct Foo_Stat *from, struct stat *to);
+	int
+	Foo_ToStat (struct stat *to, sxtruct Foo_Stat *to);
+
+	/* The .c file */
+	int
+	Foo_FromStat (struct Foo_Stat *from, struct stat *to)
+	{
+		_cnm_return_val_if_overflow (off_t, from->st_size, -1);
+
+		memset (to, 0, sizeof(*to);
+		to->st_size = from->st_size;
+		return 0;
+	}
+
+	int
+	Foo_ToStat (struct stat *to, sxtruct Foo_Stat *to)
+	{
+		_cnm_return_val_if_overflow (gint64, from->st_size, -1);
+
+		memset (to, 0, sizeof(*to);
+		to->st_size = from->st_size;
+		return 0;
+	}
+
+.fi
+This is useful for better error checking within the conversion functions.
+.I MapAttribute.NativeType
+is required for this as there is no other way to know what the native type is
+(without parsing the system header files...).
+.TP
+Enumerations
+Generates a C enumeration and macros for each of the members within the enumeration.
+.I To
+and 
+.I From
+functions are also declared in the 
+.I .h
+file and implemented in the 
+.I .c
+file.
+.Sp
+For example,
+.nf
+
+	[Map (NativeSymbolPrefix="Foo")]
+	enum Errno {
+		EINVAL
+	}
+
+.fi
+would generate the following in the 
+.I .h
+file:
+.nf
+
+	enum Foo_Errno {
+		Foo_Errno_EINVAL          = 0,
+		#define Foo_Errno_EINVAL    Foo_Errno_EINVAL
+	};
+	int Foo_FromErrno (int from, int *to);
+	int Foo_ToErrno (int from, int *to);
+
+.fi
+and generates the following in the the
+.I .c
+file:
+.nf
+
+	int
+	Foo_FromErrno (int from, int *to)
+	{
+		*to = 0;
+		if (from == Foo_Errno_EPERM)
+	#ifdef EINVAL 
+			{*to = EINVAL;}
+	#else
+			{errno = EINVAL; return -1;}
+	#endif
+		return 0;
+	}
+
+	int
+	Foo_ToErrno (int from, int *to)
+	{
+		*to = 0;
+	#ifdef EINVAL
+		if (from == EINVAL)
+			{*to = Foo_Errno_EPERM; return 0;}
+	#endif
+		return -1;
+	}
+
+.fi
+Different code will be generated if the managed enum is a 
+.I [Flags]
+-decorated enumeration (to account for bitwise flags), but
+this is the basic idea.
+.PP
+.SH MAILING LISTS
+Visit http://lists.ximian.com/mailman/listinfo/mono-devel-list for details.
+.SH WEB SITE
+Visit http://www.mono-project.com for details
Index: create-native-map/man/Makefile.am
===================================================================
--- create-native-map/man/Makefile.am	(revision 0)
+++ create-native-map/man/Makefile.am	(revision 0)
@@ -0,0 +1,5 @@
+
+man_MANS = create-native-map.1
+
+EXTRA_DIST = $(man_MANS)
+
Index: Makefile.am
===================================================================
--- Makefile.am	(revision 66758)
+++ Makefile.am	(working copy)
@@ -1,2 +1,2 @@
-SUBDIRS= po gnunit docbrowser asn1view
+SUBDIRS= po gnunit docbrowser asn1view create-native-map
 
