support multiple namespace mappings for binding really broken libraries
authorMathias Hasselmann <mathias.hasselmann@gmx.de>
Thu, 6 Sep 2007 08:18:15 +0000 (08:18 +0000)
committerMathias Hasselmann <hasselmm@src.gnome.org>
Thu, 6 Sep 2007 08:18:15 +0000 (08:18 +0000)
2007-09-06 Mathias Hasselmann <mathias.hasselmann@gmx.de>

* vala/valanamespace.vala, vapigen/valagidlparser.vala:
  support multiple namespace mappings for binding really broken
  libraries like gnet-2.0. support shell patterns to lookup attributes
  from metadata files. fixes bug 474145

svn path=/trunk/; revision=584

ChangeLog
vala/valanamespace.vala
vapigen/valagidlparser.vala

index 14e6368..3457be6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2007-09-06  Mathias Hasselmann  <mathias.hasselmann@gmx.de>
 
+       * vala/valanamespace.vala, vapigen/valagidlparser.vala:
+         support multiple namespace mappings for binding really broken
+         libraries like gnet-2.0. support shell patterns to lookup attributes
+         from metadata files. fixes bug 474145
+
+2007-09-06  Mathias Hasselmann  <mathias.hasselmann@gmx.de>
+
        * vapi/glib-2.0.vala: support for GPatternSpec
 
 2007-09-05  Mathias Hasselmann  <mathias.hasselmann@gmx.de>
index b723651..2ca667d 100644 (file)
@@ -40,8 +40,8 @@ public class Vala.Namespace : Symbol {
        private Gee.List<Constant> constants = new ArrayList<Constant> ();
        private Gee.List<Field> fields = new ArrayList<Field> ();
        private Gee.List<Method> methods = new ArrayList<Method> ();
-       
-       private string cprefix;
+
+       private Gee.List<string> cprefixes = new ArrayList<string> ();
        private string lower_case_cprefix;
        
        private Gee.List<string> cheader_filenames = new ArrayList<string> ();
@@ -242,24 +242,31 @@ public class Vala.Namespace : Symbol {
        }
        
        public override string! get_cprefix () {
-               if (cprefix == null) {
-                       if (name == null) {
-                               cprefix = "";
-                       } else {
-                               cprefix = name;
-                       }
+               if (cprefixes.size > 0) {
+                       return cprefixes[0];
+               } else if (null != name) {
+                       return name;
+               } else {
+                       return "";
                }
-               return cprefix;
+       }
+
+       public Gee.List<string> get_cprefixes () {
+               if (0 == cprefixes.size && null != name)
+                       cprefixes.add (name);
+
+               return cprefixes;
        }
 
        /**
-        * Sets the camel case string to be prepended to the name of members of
+        * Adds a camel case string to be prepended to the name of members of
         * this namespace when used in C code.
         *
-        * @param cprefix the camel case prefix to be used in C code
+        * @param cprefixes the camel case prefixes used in C code
         */
-       public void set_cprefix (string cprefix) {
-               this.cprefix = cprefix;
+       public void add_cprefix (string! cprefix) {
+               return_if_fail (cprefix.len() >= 1);
+               cprefixes.add (cprefix);
        }
 
        /**
@@ -325,7 +332,8 @@ public class Vala.Namespace : Symbol {
        
        private void process_ccode_attribute (Attribute! a) {
                if (a.has_argument ("cprefix")) {
-                       set_cprefix (a.get_string ("cprefix"));
+                       foreach(string name in a.get_string ("cprefix").split (","))
+                               add_cprefix (name);
                }
                if (a.has_argument ("lower_case_cprefix")) {
                        set_lower_case_cprefix (a.get_string ("lower_case_cprefix"));
index 1c85f41..93fa37b 100644 (file)
@@ -37,6 +37,7 @@ public class Vala.GIdlParser : CodeVisitor {
        private Namespace current_namespace;
        private DataType current_data_type;
        private Map<string,string> codenode_attributes_map;
+       private Map<pointer,string> codenode_attributes_patterns;
        private Gee.Set<string> current_type_symbol_set;
 
        private Map<string,DataType> cname_type_map;
@@ -98,7 +99,8 @@ public class Vala.GIdlParser : CodeVisitor {
                current_source_file = source_file;
 
                codenode_attributes_map = new HashMap<string,string> (str_hash, str_equal);
-               
+               codenode_attributes_patterns = new HashMap<pointer,string> (direct_hash, PatternSpec.equal);
+
                if (FileUtils.test (metadata_filename, FileTest.EXISTS)) {
                        try {
                                string metadata;
@@ -106,12 +108,18 @@ public class Vala.GIdlParser : CodeVisitor {
                                FileUtils.get_contents (metadata_filename, out metadata, out metadata_len);
                                
                                foreach (string line in metadata.split ("\n")) {
-                                       var line_parts = line.split (" ", 2);
-                                       if (line_parts[0] == null) {
+                                       var tokens = line.split (" ", 2);
+
+                                       if (null == tokens[0]) {
                                                continue;
                                        }
+
+                                       if (null != tokens[0].chr (-1, '*')) {
+                                               PatternSpec pattern = new PatternSpec (tokens[0]);
+                                               codenode_attributes_patterns[#pattern] = tokens[0];
+                                       }
                                        
-                                       codenode_attributes_map.set (line_parts[0], line_parts[1]);
+                                       codenode_attributes_map[tokens[0]] = tokens[1];
                                }
                        } catch (FileError e) {
                                Report.error (null, "Unable to read metadata file: %s".printf (e.message));
@@ -134,19 +142,26 @@ public class Vala.GIdlParser : CodeVisitor {
                }
        }
 
-       private string! fix_type_name (string! type_name, IdlModule! module) {
-               if (type_name.has_prefix (module.name)) {
-                       return type_name.offset (module.name.len ());
-               } else if (module.name == "GLib" && type_name.has_prefix ("G")) {
+       private string! fix_type_name (string! type_name, Namespace! ns) {
+               if (type_name.has_prefix (ns.name)) {
+                       return type_name.offset (ns.name.len ());
+               } else if (ns.name == "GLib" && type_name.has_prefix ("G")) {
                        return type_name.offset (1);
+               } else  {
+                       foreach (string name in ns.get_cprefixes ()) {
+                               if (type_name.has_prefix (name)) {
+                                       return type_name.offset (name.len ());
+                               }
+                       }
                }
+
                return type_name;
        }
 
-       private string! fix_const_name (string! const_name, IdlModule! module) {
-               if (const_name.has_prefix (module.name.up () + "_")) {
-                       return const_name.offset (module.name.len () + 1);
-               } else if (module.name == "GLib" && const_name.has_prefix ("G_")) {
+       private string! fix_const_name (string! const_name, Namespace! ns) {
+               if (const_name.has_prefix (ns.name.up () + "_")) {
+                       return const_name.offset (ns.name.len () + 1);
+               } else if (ns.name == "GLib" && const_name.has_prefix ("G_")) {
                        return const_name.offset (2);
                }
                return const_name;
@@ -171,7 +186,10 @@ public class Vala.GIdlParser : CodeVisitor {
                                if (nv[0] == "cheader_filename") {
                                        ns.set_cheader_filename (eval (nv[1]));
                                } else if (nv[0] == "cprefix") {
-                                       ns.set_cprefix (eval (nv[1]));
+                                       var cprefixes = eval (nv[1]).split (",");
+                                       foreach(string name in cprefixes) {
+                                               ns.add_cprefix (name);
+                                       }
                                } else if (nv[0] == "lower_case_cprefix") {
                                        ns.set_lower_case_cprefix (eval (nv[1]));
                                }
@@ -184,7 +202,7 @@ public class Vala.GIdlParser : CodeVisitor {
                                if (cb == null) {
                                        continue;
                                }
-                               cb.name = fix_type_name (cb.name, module);
+                               cb.name = fix_type_name (cb.name, ns);
                                ns.add_callback (cb);
                                current_source_file.add_node (cb);
                        } else if (node.type == IdlNodeTypeId.STRUCT) {
@@ -193,7 +211,7 @@ public class Vala.GIdlParser : CodeVisitor {
                                parse_boxed ((IdlNodeBoxed) node, ns, module);
                        } else if (node.type == IdlNodeTypeId.ENUM) {
                                var en = parse_enum ((IdlNodeEnum) node);
-                               en.name = fix_type_name (en.name, module);
+                               en.name = fix_type_name (en.name, ns);
                                ns.add_enum (en);
                                current_source_file.add_node (en);
                        } else if (node.type == IdlNodeTypeId.OBJECT) {
@@ -202,7 +220,7 @@ public class Vala.GIdlParser : CodeVisitor {
                                parse_interface ((IdlNodeInterface) node, ns, module);
                        } else if (node.type == IdlNodeTypeId.CONSTANT) {
                                var c = parse_constant ((IdlNodeConstant) node);
-                               c.name = fix_const_name (c.name, module);
+                               c.name = fix_const_name (c.name, ns);
                                ns.add_constant (c);
                                current_source_file.add_node (c);
                        } else if (node.type == IdlNodeTypeId.FUNCTION) {
@@ -271,7 +289,7 @@ public class Vala.GIdlParser : CodeVisitor {
                        return;
                }
 
-               string name = fix_type_name (node.name, module);
+               string name = fix_type_name (node.name, ns);
 
                if (!is_reference_type (node.name)) {
                        var st = ns.scope.lookup (name) as Struct;
@@ -389,7 +407,7 @@ public class Vala.GIdlParser : CodeVisitor {
        private void parse_boxed (IdlNodeBoxed! boxed_node, Namespace! ns, IdlModule! module) {
                weak IdlNode node = (IdlNode) boxed_node;
        
-               string name = fix_type_name (node.name, module);
+               string name = fix_type_name (node.name, ns);
 
                if (!is_reference_type (node.name)) {
                        var st = ns.scope.lookup (name) as Struct;
@@ -541,7 +559,7 @@ public class Vala.GIdlParser : CodeVisitor {
        }
        
        private void parse_object (IdlNodeInterface! node, Namespace! ns, IdlModule! module) {
-               string name = fix_type_name (node.gtype_name, module);
+               string name = fix_type_name (node.gtype_name, ns);
 
                string base_class = null;
 
@@ -653,7 +671,7 @@ public class Vala.GIdlParser : CodeVisitor {
        }
 
        private void parse_interface (IdlNodeInterface! node, Namespace! ns, IdlModule! module) {
-               string name = fix_type_name (node.gtype_name, module);
+               string name = fix_type_name (node.gtype_name, ns);
 
                var iface = ns.scope.lookup (name) as Interface;
                if (iface == null) {
@@ -864,6 +882,19 @@ public class Vala.GIdlParser : CodeVisitor {
                        return;
                }
 
+               var type_attributes = get_attributes (n);
+
+               if (null != type_attributes) {
+                       foreach (string attr in type_attributes) {
+                               var nv = attr.split ("=", 2);
+
+                               if (nv[0] == "cprefix") {
+                                       type.type_name = n.offset (eval (nv[1]).len ());
+                                       return;
+                               }
+                       }
+               }
+
                if (n == "HFONT" || n == "HGLOBAL" || n == "GStaticRecMutex" || n.has_suffix ("Class") || n == "va_list" || n.has_prefix ("LOGFONT") || n.has_prefix ("xml") || n == "GdkNativeWindow" || n == "GdkXEvent" || n == "GtkTextLayout" || n == "GstClockID" || n.has_prefix ("GstXml")) {
                        // unsupported
                        type.type_name = "pointer";
@@ -1192,7 +1223,27 @@ public class Vala.GIdlParser : CodeVisitor {
 
        [NoArrayLength]
        private string[] get_attributes (string! codenode) {
-               string attributes = codenode_attributes_map.get (codenode);
+               var attributes = codenode_attributes_map.get (codenode);
+
+               if (attributes == null) {
+                       var dot_required = (null != codenode.chr (-1, '.'));
+                       var colon_required = (null != codenode.chr (-1, ':'));
+
+                       var pattern_specs = codenode_attributes_patterns.get_keys ();
+                       foreach (weak PatternSpec pattern in pattern_specs) {
+                               var pspec = codenode_attributes_patterns[pattern];
+
+                               if ((dot_required && null == pspec.chr (-1, '.')) ||
+                                   (colon_required && null == pspec.chr (-1, ':'))) {
+                                       continue;
+                               }
+
+                               if (pattern.match_string (codenode)) {
+                                       return get_attributes (pspec);
+                               }
+                       }
+               }
+
                if (attributes == null) {
                        return null;
                }