Index: compiler/valacompiler.vala
===================================================================
--- compiler/valacompiler.vala	(révision 2444)
+++ compiler/valacompiler.vala	(copie de travail)
@@ -34,6 +34,7 @@
 	[NoArrayLength]
 	static string[] vapi_directories;
 	static string library;
+	static string typelib_version;
 	[CCode (array_length = false, array_null_terminated = true)]
 	[NoArrayLength]
 	static string[] packages;
@@ -65,6 +66,7 @@
 		{ "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, ref vapi_directories, "Look for package bindings in DIRECTORY", "DIRECTORY..." },
 		{ "pkg", 0, 0, OptionArg.STRING_ARRAY, ref packages, "Include binding for PACKAGE", "PACKAGE..." },
 		{ "library", 0, 0, OptionArg.STRING, ref library, "Library name", "NAME" },
+		{ "typelib", 0, 0, OptionArg.STRING, ref typelib_version, "Typelib version", "VERSION" },
 		{ "basedir", 'b', 0, OptionArg.FILENAME, ref basedir, "Base source directory", "DIRECTORY" },
 		{ "directory", 'd', 0, OptionArg.FILENAME, ref directory, "Output directory", "DIRECTORY" },
 		{ "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null },
@@ -306,19 +308,21 @@
 
 			interface_writer.write_file (context, vapi_filename);
 
-
+			library = null;
+		}
+		
+		if (typelib_version != null) {
 			var gir_writer = new GIRWriter ();
-			string gir_filename = "%s.gir".printf (library);
+			string typelib_directory = ".";
 
 			// put .gir file in current directory unless -d has been explicitly specified
-			if (directory != null && !Path.is_absolute (gir_filename)) {
-				gir_filename = "%s%c%s".printf (context.directory, Path.DIR_SEPARATOR, gir_filename);
+			if (directory != null) {
+				typelib_directory = context.directory;
 			}
 
-			gir_writer.write_file (context, gir_filename);
-
-
-			library = null;
+			gir_writer.write_files (context, typelib_directory, typelib_version);
+			
+			typelib_version = null;
 		}
 
 		if (!ccode_only) {
Index: gobject/valagirwriter.vala
===================================================================
--- gobject/valagirwriter.vala	(révision 2444)
+++ gobject/valagirwriter.vala	(copie de travail)
@@ -28,12 +28,16 @@
  */
 public class Vala.GIRWriter : CodeVisitor {
 	private CodeContext context;
+	private string directory;
+	private string version;
 	
 	FileStream stream;
+	private string long_namespace_name;
 	
 	int indent;
 
 	private TypeSymbol gobject_type;
+	private TypeSymbol string_type;
 
 	/**
 	 * Writes the public interface of the specified code context into the
@@ -42,24 +46,17 @@
 	 * @param context  a code context
 	 * @param filename a relative or absolute filename
 	 */
-	public void write_file (CodeContext context, string filename) {
+	public void write_files (CodeContext context, string directory, string version) {
 		this.context = context;
+		this.directory = directory;
+		this.version = version;
 
 		var root_symbol = context.root;
 		var glib_ns = root_symbol.scope.lookup ("GLib");
 		gobject_type = (TypeSymbol) glib_ns.scope.lookup ("Object");
+		string_type = (TypeSymbol) root_symbol.scope.lookup("string");
 
-		stream = FileStream.open (filename, "w");
-
-		stream.printf ("<?xml version=\"1.0\"?>\n");
-
-		stream.printf ("<repository version=\"1.0\">\n");
-
 		context.accept (this);
-
-		stream.printf ("</repository>\n");
-
-		stream = null;
 	}
 
 	public override void visit_namespace (Namespace ns) {
@@ -73,22 +70,62 @@
 			return;
 		}
 
+		long_namespace_name = ns.name;
 		if (ns.parent_symbol.name != null) {
-			// nested namespace
-			// not supported in GIR at the moment
-			return;
+			Namespace parent = (Namespace) ns.parent_symbol;
+			while (parent.name != null) {
+				long_namespace_name = parent.name + "_" + long_namespace_name;
+				parent = (Namespace) parent.parent_symbol;
+			}
 		}
+		
+		ns.accept_children (this);
 
-		write_indent ();
-		stream.printf ("<namespace name=\"%s\" version=\"1.0\">\n", ns.name);
+		if (stream != null) {
+			indent--;
+			write_indent ();
+			stream.printf ("</namespace>\n");
+			
+			write_footer();
+			
+			stream = null;
+		}
+	}
+	
+	private void write_header() {
+		stream.printf ("<?xml version=\"1.0\"?>\n");
+
+		stream.printf ("<repository version=\"1.0\"");
+		stream.printf (" xmlns=\"http://www.gtk.org/introspection/core/1.0\"");
+		stream.printf (" xmlns:c=\"http://www.gtk.org/introspection/c/1.0\"");
+		stream.printf (" xmlns:glib=\"http://www.gtk.org/introspection/glib/1.0\"");
+		stream.printf (">\n");
 		indent++;
-
-		ns.accept_children (this);
-
-		indent--;
+		
 		write_indent ();
-		stream.printf ("</namespace>\n");
+		stream.printf ("<include name=\"GLib\" version=\"2.0\"/>\n");
+		write_indent ();
+		stream.printf ("<include name=\"GObject\" version=\"2.0\"/>\n");
 	}
+	
+	private void write_footer() {
+		indent--;
+		stream.printf ("</repository>\n");
+	}
+	
+	private void check_stream() {
+		if (stream == null) {
+			string filename = "%s%c%s-%s.gir".printf (
+				directory, Path.DIR_SEPARATOR, long_namespace_name, version);
+			stream = FileStream.open (filename, "w");
+			
+			write_header();
+			
+			write_indent ();
+			stream.printf ("<namespace name=\"%s\" version=\"%s\">\n", long_namespace_name, version);
+			indent++;
+		}
+	}
 
 	public override void visit_class (Class cl) {
 		if (cl.external_package) {
@@ -98,6 +135,8 @@
 		if (!check_accessibility (cl)) {
 			return;
 		}
+		
+		check_stream();
 
 		if (cl.is_subtype_of (gobject_type)) {
 			write_indent ();
@@ -105,6 +144,7 @@
 			stream.printf (" parent=\"%s\"", cl.base_class.get_full_name ());
 			stream.printf (" glib:type-name=\"%s\"", cl.get_cname ());
 			stream.printf (" glib:get-type=\"%sget_type\"", cl.get_lower_case_cprefix ());
+			write_node_attributes(cl);
 			stream.printf (">\n");
 			indent++;
 
@@ -137,6 +177,7 @@
 		} else {
 			write_indent ();
 			stream.printf ("<record name=\"%s\"", cl.name);
+			write_node_attributes(cl);
 			stream.printf (">\n");
 			indent++;
 
@@ -157,8 +198,11 @@
 			return;
 		}
 
+		check_stream();
+		
 		write_indent ();
 		stream.printf ("<record name=\"%s\"", st.name);
+		write_node_attributes(st);
 		stream.printf (">\n");
 		indent++;
 
@@ -178,12 +222,15 @@
 			return;
 		}
 
+		check_stream();
+		
 		write_indent ();
 		stream.printf ("<interface name=\"%s\"", iface.name);
+		stream.printf (" glib:type-name=\"%s\"", iface.get_cname ());
 		stream.printf (" glib:get-type=\"%sget_type\"", iface.get_lower_case_cprefix ());
+		write_node_attributes(iface);
 		stream.printf (">\n");
 		indent++;
-
 		// write prerequisites
 		if (iface.get_prerequisites ().size > 0) {
 			write_indent ();
@@ -224,9 +271,12 @@
 			return;
 		}
 
+		check_stream();
+		
 		write_indent ();
 		stream.printf ("<enumeration name=\"%s\"", en.name);
 		stream.printf (" c:type=\"%s\"", en.get_cname ());
+		stream.printf (" glib:type-name=\"%s\"", en.get_cname ());
 		stream.printf (" glib:get-type=\"%sget_type\"", en.get_lower_case_cprefix ());
 		stream.printf (">\n");
 		indent++;
@@ -252,6 +302,8 @@
 			return;
 		}
 
+		check_stream();
+		
 		write_indent ();
 		stream.printf ("<errordomain name=\"%s\"", edomain.get_cname ());
 		stream.printf (">\n");
@@ -277,7 +329,7 @@
 		if (!check_accessibility (c)) {
 			return;
 		}
-
+		
 		write_indent ();
 		stream.printf ("<constant name=\"%s\"/>\n", c.get_cname ());
 	}
@@ -292,7 +344,9 @@
 		}
 
 		write_indent ();
-		stream.printf ("<field name=\"%s\">\n", f.get_cname ());
+		stream.printf ("<field name=\"%s\"", f.get_cname ());
+		write_node_attributes(f);
+		stream.printf (">\n");
 		indent++;
 
 		write_type (f.field_type);
@@ -307,7 +361,7 @@
 		stream.printf ("<parameters>\n");
 		indent++;
 
-		if (instance_type != null) {
+		/*if (instance_type != null) {
 			write_indent ();
 			stream.printf ("<parameter name=\"self\">\n");
 			indent++;
@@ -317,7 +371,7 @@
 			indent--;
 			write_indent ();
 			stream.printf ("</parameter>\n");
-		}
+		}*/
 
 		foreach (FormalParameter param in params) {
 			write_indent ();
@@ -338,6 +392,8 @@
 				// normal in paramter
 				if (param.parameter_type.value_owned) {
 					stream.printf (" transfer-ownership=\"full\"");
+				} else {
+					stream.printf (" transfer-ownership=\"none\"");
 				}
 			}
 			stream.printf (">\n");
@@ -390,6 +446,7 @@
 
 		write_indent ();
 		stream.printf ("<method name=\"%s\" c:identifier=\"%s\"", m.name, m.get_cname ());
+		write_node_attributes(m);
 		stream.printf (">\n");
 		indent++;
 
@@ -418,6 +475,7 @@
 
 		write_indent ();
 		stream.printf ("<constructor name=\"%s\" c:identifier=\"%s\"", m.name, m.get_cname ());
+		write_node_attributes(m);
 		stream.printf (">\n");
 		indent++;
 
@@ -443,6 +501,7 @@
 		if (prop.set_accessor != null) {
 			stream.printf (" writable=\"1\"");
 		}
+		write_node_attributes(prop);
 		stream.printf (">\n");
 		indent++;
 
@@ -460,6 +519,7 @@
 		
 		write_indent ();
 		stream.printf ("<glib:signal name=\"%s\"", sig.get_cname ());
+		write_node_attributes(sig);
 		stream.printf (">\n");
 		indent++;
 
@@ -485,6 +545,8 @@
 		stream.printf ("<return-value");
 		if (type.value_owned) {
 			stream.printf (" transfer-ownership=\"full\"");
+		} else {
+			stream.printf (" transfer-ownership=\"none\"");
 		}
 		stream.printf (">\n");
 		indent++;
@@ -511,12 +573,63 @@
 			stream.printf ("</array>\n");
 		} else if (type is VoidType) {
 			write_indent ();
-			stream.printf ("<type name=\"none\"/>\n");
+			stream.printf ("<type name=\"none\" c:type=\"void\"/>\n");
+		} else if (type.data_type == string_type) {
+			write_indent ();
+			stream.printf ("<type name=\"utf8\" c:type=\"char*\"/>\n");
 		} else {
 			write_indent ();
-			stream.printf ("<type name=\"%s\"/>\n", type.to_string ());
+			stream.printf ("<type name=\"%s\"  c:type=\"%s\"/>\n", escape_type_name(type.to_string ()), type.get_cname ());
 		}
 	}
+	
+	private void write_node_attributes(CodeNode node) {
+		foreach (Attribute attr in node.attributes) {
+			string name = camel_case_to_lower_case(attr.name);
+			stream.printf (" xmlns:%s=\"http://www.gtk.org/introspection/%s/1.0\"", name, name);
+			foreach (string arg_name in attr.args.get_keys()) {
+				string value = null;
+				
+				var arg = attr.args.get (arg_name);
+				if (arg is StringLiteral) {
+					var lit = arg as StringLiteral;
+					if (lit != null) {
+						value = lit.eval ();
+						value.replace("\"", "\\\"");
+					}
+				} else if (arg is RealLiteral) {
+					var lit = (RealLiteral) arg;
+					value = lit.value;
+				} else if (arg is IntegerLiteral) {
+					var lit = (IntegerLiteral) arg;
+					value = lit.value;
+				} else if (arg is UnaryExpression) {
+					var unary = (UnaryExpression) arg;
+					if (unary.operator == UnaryOperator.MINUS) {
+						if (unary.inner is RealLiteral) {
+							var lit = (RealLiteral) unary.inner;
+							value = "-" + lit.value;
+						} else if (unary.inner is IntegerLiteral) {
+							var lit = (IntegerLiteral) unary.inner;
+							value = "-" + lit.value;
+						}
+					}
+				}
+				
+				if (value != null) {
+					stream.printf (" %s:%s=\"%s\"", name, camel_case_to_lower_case(arg_name), value);
+				}
+			}
+		}
+	}
+	
+	private string camel_case_to_lower_case(string name) {
+		return Symbol.camel_case_to_lower_case(name).replace("_", "-");
+	}
+	
+	private string escape_type_name(string name) {
+		return name.replace("<", "&lt;").replace(">", "&gt;").replace("&", "&amp;");
+	}
 
 	private bool check_accessibility (Symbol sym) {
 		if (sym.access == SymbolAccessibility.PUBLIC ||
