LCOV - code coverage report
Current view: top level - vapigen - valagidlparser.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 77.0 % 2111 1625
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

            Line data    Source code
       1              : /* valagidlparser.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  Jürg Billeter
       4              :  * Copyright (C) 2006-2008  Raffaele Sandrini
       5              :  *
       6              :  * This library is free software; you can redistribute it and/or
       7              :  * modify it under the terms of the GNU Lesser General Public
       8              :  * License as published by the Free Software Foundation; either
       9              :  * version 2.1 of the License, or (at your option) any later version.
      10              : 
      11              :  * This library is distributed in the hope that it will be useful,
      12              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              : 
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this library; if not, write to the Free Software
      18              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      19              :  *
      20              :  * Author:
      21              :  *      Jürg Billeter <j@bitron.ch>
      22              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      23              :  */
      24              : 
      25              : using GLib;
      26              : 
      27              : /**
      28              :  * Code visitor parsing all GIDL files.
      29              :  */
      30          213 : public class Vala.GIdlParser : CodeVisitor {
      31           71 :         private CodeContext context;
      32              : 
      33           71 :         private SourceFile current_source_file;
      34              : 
      35           71 :         private SourceReference current_source_reference;
      36              :         
      37           71 :         private Namespace current_namespace;
      38           71 :         private TypeSymbol current_data_type;
      39           71 :         private Map<string,string> codenode_attributes_map;
      40           71 :         private Map<PatternSpec*,string> codenode_attributes_patterns;
      41           71 :         private Set<string> current_type_symbol_set;
      42              : 
      43           71 :         private Map<string,TypeSymbol> cname_type_map;
      44              : 
      45              :         static GLib.Regex type_from_string_regex;
      46              : 
      47              :         /**
      48              :          * Parse all source files in the specified code context and build a
      49              :          * code tree.
      50              :          *
      51              :          * @param context a code context
      52              :          */
      53           71 :         public void parse (CodeContext context) {
      54           71 :                 cname_type_map = new HashMap<string,TypeSymbol> (str_hash, str_equal);
      55              : 
      56           71 :                 this.context = context;
      57           71 :                 context.accept (this);
      58              : 
      59           71 :                 cname_type_map = null;
      60              :         }
      61              : 
      62         3305 :         public override void visit_namespace (Namespace ns) {
      63         3305 :                 ns.accept_children (this);
      64              :         }
      65              : 
      66        20843 :         public override void visit_class (Class cl) {
      67        20843 :                 visit_type (cl);
      68              :         }
      69              : 
      70         8066 :         public override void visit_struct (Struct st) {
      71         8066 :                 visit_type (st);
      72              :         }
      73              : 
      74         2840 :         public override void visit_interface (Interface iface) {
      75         2840 :                 visit_type (iface);
      76              :         }
      77              : 
      78        12608 :         public override void visit_enum (Enum en) {
      79        12608 :                 visit_type (en);
      80              :         }
      81              : 
      82         1513 :         public override void visit_error_domain (ErrorDomain ed) {
      83         1513 :                 visit_type (ed);
      84              :         }
      85              : 
      86        10813 :         public override void visit_delegate (Delegate d) {
      87        10813 :                 visit_type (d);
      88              :         }
      89              : 
      90        56683 :         private void visit_type (TypeSymbol t) {
      91        56683 :                 if (!cname_type_map.contains (get_cname (t))) {
      92        54215 :                         cname_type_map[get_cname (t)] = t;
      93              :                 }
      94              :         }
      95              : 
      96          577 :         public override void visit_source_file (SourceFile source_file) {
      97          577 :                 if (source_file.filename.has_suffix (".gi")) {
      98           25 :                         parse_file (source_file);
      99              :                 }
     100              :         }
     101              :         
     102           50 :         private void parse_file (SourceFile source_file) {
     103           25 :                 string metadata_filename = "%s.metadata".printf (source_file.filename.substring (0, source_file.filename.length - ".gi".length));
     104              : 
     105           25 :                 current_source_file = source_file;
     106              : 
     107           25 :                 codenode_attributes_map = new HashMap<string,string> (str_hash, str_equal);
     108           25 :                 codenode_attributes_patterns = new HashMap<PatternSpec*,string> (direct_hash, (EqualFunc<PatternSpec>) PatternSpec.equal);
     109              : 
     110           25 :                 if (FileUtils.test (metadata_filename, FileTest.EXISTS)) {
     111           25 :                         try {
     112              :                                 string metadata;
     113           25 :                                 FileUtils.get_contents (metadata_filename, out metadata, null);
     114              :                                 
     115         2432 :                                 foreach (unowned string line in metadata.split ("\n")) {
     116         2357 :                                         if (line.has_prefix ("#")) {
     117              :                                                 // ignore comment lines
     118           26 :                                                 continue;
     119              :                                         }
     120              : 
     121         2331 :                                         var tokens = line.split (" ", 2);
     122              : 
     123         2331 :                                         if (null == tokens[0]) {
     124          200 :                                                 continue;
     125              :                                         }
     126              : 
     127         2231 :                                         if (-1 != tokens[0].index_of_char ('*')) {
     128           48 :                                                 PatternSpec* pattern = new PatternSpec (tokens[0]);
     129           48 :                                                 codenode_attributes_patterns[pattern] = tokens[0];
     130              :                                         }
     131              :                                         
     132         2231 :                                         codenode_attributes_map[tokens[0]] = tokens[1];
     133              :                                 }
     134              :                         } catch (FileError e) {
     135            0 :                                 Report.error (null, "Unable to read metadata file: %s", e.message);
     136              :                         }
     137              :                 }
     138              :         
     139           75 :                 try {
     140           25 :                         var modules = Idl.parse_file (source_file.filename);
     141              :                         
     142           25 :                         current_source_reference = new SourceReference (source_file, SourceLocation (null, 0, 0), SourceLocation (null, 0, 0));
     143              :                         
     144           50 :                         foreach (weak IdlModule module in modules) {
     145           25 :                                 var ns = parse_module (module);
     146           25 :                                 if (ns != null) {
     147            9 :                                         context.root.add_namespace (ns);
     148              :                                 }
     149              :                         }
     150              :                 } catch (MarkupError e) {
     151            0 :                         Report.error (null, "Unable to parse GIDL file: %s", e.message);
     152              :                 }
     153              :         }
     154              : 
     155         1272 :         private string fix_type_name (string type_name, Symbol container) {
     156         1272 :                 var attributes = get_attributes (type_name);
     157         1272 :                 if (attributes != null) {
     158          791 :                         foreach (string attr in attributes) {
     159          208 :                                 var nv = attr.split ("=", 2);
     160          208 :                                 if (nv[0] == "name") {
     161            0 :                                         return eval (nv[1]);
     162              :                                 }
     163              :                         }
     164              :                 }
     165              : 
     166         1280 :                 if (type_name.has_prefix (container.name)) {
     167         1250 :                         return type_name.substring (container.name.length);
     168              :                 } else {
     169           22 :                         var cprefix = get_cprefix (container);
     170           22 :                         if (type_name.has_prefix (cprefix)) {
     171           14 :                                 return type_name.substring (cprefix.length);;
     172              :                         }
     173              :                 }
     174              : 
     175           16 :                 return type_name;
     176              :         }
     177              : 
     178         2628 :         private string fix_const_name (string const_name, Symbol container) {
     179         2628 :                 var pref = get_lower_case_cprefix (container).ascii_up ();
     180         2628 :                 if (const_name.has_prefix (pref)) {
     181         2579 :                         return const_name.substring (pref.length);
     182              :                 }
     183           98 :                 return const_name;
     184              :         }
     185              : 
     186         9185 :         private string get_cheader_filename (Symbol sym) {
     187         9185 :                 var cheader_filename = sym.get_attribute_string ("CCode", "cheader_filename");
     188         9185 :                 if (cheader_filename != null) {
     189         9185 :                         return cheader_filename;
     190              :                 }
     191         4896 :                 if (sym.parent_symbol != null) {
     192         3995 :                         return get_cheader_filename (sym.parent_symbol);
     193          901 :                 } else if (sym.source_reference != null) {
     194            0 :                         return sym.source_reference.file.get_cinclude_filename ();
     195              :                 }
     196          901 :                 return "";
     197              :         }
     198              : 
     199       135537 :         private string get_cname (Symbol sym, Symbol? container = null) {
     200       135537 :                 if (container == null) {
     201       128055 :                         container = sym.parent_symbol;
     202              :                 }
     203       135537 :                 var cname = sym.get_attribute_string ("CCode", "cname");
     204       135537 :                 if (cname != null) {
     205       135537 :                         return cname;
     206              :                 }
     207       120903 :                 if (sym is Method) {
     208         7482 :                         var name = sym.name;
     209         7482 :                         if (sym is CreationMethod) {
     210          435 :                                 if (name == null || name == ".new") {
     211          287 :                                         name = "new";
     212              :                                 } else {
     213          148 :                                         name = "new_%s".printf (name);
     214              :                                 }
     215              :                         }
     216         7482 :                         if (container != null) {
     217         7482 :                                 return "%s%s".printf (get_lower_case_cprefix (container), name);
     218              :                         } else {
     219            0 :                                 return name;
     220              :                         }
     221              :                 } else {
     222       113421 :                         if (container != null) {
     223       113421 :                                 return "%s%s".printf (get_cprefix (container), sym.name);
     224              :                         } else {
     225            0 :                                 return sym.name;
     226              :                         }
     227              :                 }
     228              :         }
     229              : 
     230            0 :         private string get_finish_cname (Method m) {
     231            0 :                 var finish_cname = m.get_attribute_string ("CCode", "finish_name");
     232            0 :                 if (finish_cname != null) {
     233            0 :                         return finish_cname;
     234              :                 }
     235            0 :                 var result = get_cname (m);
     236            0 :                 if (result.has_suffix ("_async")) {
     237            0 :                         result = result.substring (0, result.length - "_async".length);
     238              :                 }
     239            0 :                 return result + "_finish";
     240              :         }
     241              : 
     242        15767 :         private string get_lower_case_cname (Symbol sym) {
     243        15767 :                 var lower_case_csuffix = Symbol.camel_case_to_lower_case (sym.name);
     244        15767 :                 if (sym is ObjectTypeSymbol) {
     245              :                         // remove underscores in some cases to avoid conflicts of type macros
     246         6329 :                         if (lower_case_csuffix.has_prefix ("type_")) {
     247            0 :                                 lower_case_csuffix = "type" + lower_case_csuffix.substring ("type_".length);
     248         6329 :                         } else if (lower_case_csuffix.has_prefix ("is_")) {
     249            0 :                                 lower_case_csuffix = "is" + lower_case_csuffix.substring ("is_".length);
     250              :                         }
     251         6329 :                         if (lower_case_csuffix.has_suffix ("_class")) {
     252            0 :                                 lower_case_csuffix = lower_case_csuffix.substring (0, lower_case_csuffix.length - "_class".length) + "class";
     253              :                         }
     254              :                 }
     255        15767 :                 if (sym.parent_symbol != null) {
     256        14779 :                         return "%s%s".printf (get_lower_case_cprefix (sym.parent_symbol), lower_case_csuffix);
     257              :                 } else {
     258        15767 :                         return lower_case_csuffix;
     259              :                 }
     260              :         }
     261              : 
     262        25314 :         private string get_lower_case_cprefix (Symbol sym) {
     263        25314 :                 if (sym.name == null) {
     264         5971 :                         return "";
     265              :                 }
     266              :                 string cprefix;
     267        19343 :                 cprefix = sym.get_attribute_string ("CCode", "lower_case_cprefix");
     268        19343 :                 if (cprefix == null && (sym is ObjectTypeSymbol || sym is Struct)) {
     269         6498 :                         cprefix = sym.get_attribute_string ("CCode", "cprefix");
     270              :                 }
     271        19343 :                 if (cprefix != null) {
     272        25314 :                         return cprefix;
     273              :                 }
     274        15767 :                 return get_lower_case_cname (sym) + "_";
     275              :         }
     276              : 
     277       122100 :         public string get_cprefix (Symbol sym) {
     278       122100 :                 if (sym is ObjectTypeSymbol) {
     279            0 :                         return get_cname (sym);
     280       122100 :                 } else if (sym is Enum || sym is ErrorDomain) {
     281            0 :                         return "%s_".printf (get_lower_case_cname (sym).ascii_up ());
     282       122100 :                 } else if (sym is Namespace) {
     283       122100 :                         if (sym.name != null) {
     284       112875 :                                 var cprefix = sym.get_attribute_string ("CCode", "cprefix");
     285       112875 :                                 if (cprefix != null) {
     286       122100 :                                         return cprefix;
     287              :                                 }
     288        10499 :                                 if (sym.parent_symbol != null) {
     289         8657 :                                         return "%s%s".printf (get_cprefix (sym.parent_symbol), sym.name);
     290              :                                 } else {
     291         3684 :                                         return sym.name;
     292              :                                 }
     293              :                         } else {
     294         9225 :                                 return "";
     295              :                         }
     296            0 :                 } else if (sym.name != null) {
     297            0 :                         return sym.name;
     298              :                 }
     299            0 :                 return "";
     300              :         }
     301              : 
     302         7734 :         private string[] get_attributes_for_node (IdlNode node) {
     303              :                 string name;
     304              : 
     305         7734 :                 if (node.type == IdlNodeTypeId.FUNCTION) {
     306         3094 :                         name = ((IdlNodeFunction) node).symbol;
     307         6187 :                 } else if (node.type == IdlNodeTypeId.SIGNAL) {
     308            0 :                         name = "%s::%s".printf (get_cname (current_data_type), node.name);
     309         6187 :                 } else if (node.type == IdlNodeTypeId.PROPERTY) {
     310            0 :                         name = "%s:%s".printf (get_cname (current_data_type), node.name);
     311         6187 :                 } else if (node.type == IdlNodeTypeId.FIELD) {
     312            0 :                         name = "%s.%s".printf (get_cname (current_data_type), node.name);
     313              :                 } else {
     314        12374 :                         name = node.name;
     315              :                 }
     316              : 
     317         7734 :                 return get_attributes (name);
     318              :         }
     319              : 
     320         5195 :         private void add_symbol_to_container (Symbol container, Symbol sym) {
     321         5195 :                 if (container is Class) {
     322            0 :                         unowned Class cl = (Class) container;
     323              : 
     324            0 :                         if (sym is Class) {
     325            0 :                                 cl.add_class ((Class) sym);
     326            0 :                         } else if (sym is Constant) {
     327            0 :                                 cl.add_constant ((Constant) sym);
     328            0 :                         } else if (sym is Enum) {
     329            0 :                                 cl.add_enum ((Enum) sym);
     330            0 :                         } else if (sym is Field) {
     331            0 :                                 cl.add_field ((Field) sym);
     332            0 :                         } else if (sym is Method) {
     333            0 :                                 cl.add_method ((Method) sym);
     334            0 :                         } else if (sym is Property) {
     335            0 :                                 cl.add_property ((Property) sym);
     336            0 :                         } else if (sym is Signal) {
     337            0 :                                 cl.add_signal ((Signal) sym);
     338            0 :                         } else if (sym is Struct) {
     339            0 :                                 cl.add_struct ((Struct) sym);
     340              :                         }
     341         5195 :                 } else if (container is Enum) {
     342            0 :                         unowned Enum en = (Enum) container;
     343              : 
     344            0 :                         if (sym is EnumValue) {
     345            0 :                                 en.add_value ((EnumValue) sym);
     346            0 :                         } else if (sym is Constant) {
     347            0 :                                 en.add_constant ((Constant) sym);
     348            0 :                         } else if (sym is Method) {
     349            0 :                                 en.add_method ((Method) sym);
     350              :                         }
     351         5195 :                 } else if (container is Interface) {
     352            0 :                         unowned Interface iface = (Interface) container;
     353              : 
     354            0 :                         if (sym is Class) {
     355            0 :                                 iface.add_class ((Class) sym);
     356            0 :                         } else if (sym is Constant) {
     357            0 :                                 iface.add_constant ((Constant) sym);
     358            0 :                         } else if (sym is Enum) {
     359            0 :                                 iface.add_enum ((Enum) sym);
     360            0 :                         } else if (sym is Field) {
     361            0 :                                 iface.add_field ((Field) sym);
     362            0 :                         } else if (sym is Method) {
     363            0 :                                 iface.add_method ((Method) sym);
     364            0 :                         } else if (sym is Property) {
     365            0 :                                 iface.add_property ((Property) sym);
     366            0 :                         } else if (sym is Signal) {
     367            0 :                                 iface.add_signal ((Signal) sym);
     368            0 :                         } else if (sym is Struct) {
     369            0 :                                 iface.add_struct ((Struct) sym);
     370              :                         }
     371         5195 :                 } else if (container is Namespace) {
     372         5195 :                         unowned Namespace ns = (Namespace) container;
     373              : 
     374         5195 :                         if (sym is Namespace) {
     375            5 :                                 ns.add_namespace ((Namespace) sym);
     376         5190 :                         } else if (sym is Class) {
     377          553 :                                 ns.add_class ((Class) sym);
     378         4637 :                         } else if (sym is Constant) {
     379         2628 :                                 ns.add_constant ((Constant) sym);
     380         2009 :                         } else if (sym is Delegate) {
     381          166 :                                 ns.add_delegate ((Delegate) sym);
     382         1843 :                         } else if (sym is Enum) {
     383          376 :                                 ns.add_enum ((Enum) sym);
     384         1467 :                         } else if (sym is ErrorDomain) {
     385            7 :                                 ns.add_error_domain ((ErrorDomain) sym);
     386         1460 :                         } else if (sym is Field) {
     387            0 :                                 unowned Field field = (Field) sym;
     388            0 :                                 if (field.binding == MemberBinding.INSTANCE) {
     389            0 :                                         field.binding = MemberBinding.STATIC;
     390              :                                 }
     391            0 :                                 ns.add_field (field);
     392         1460 :                         } else if (sym is Interface) {
     393           17 :                                 ns.add_interface ((Interface) sym);
     394         1443 :                         } else if (sym is Method) {
     395         1381 :                                 unowned Method method = (Method) sym;
     396         1381 :                                 if (method.binding == MemberBinding.INSTANCE) {
     397            0 :                                         method.binding = MemberBinding.STATIC;
     398              :                                 }
     399         1381 :                                 ns.add_method (method);
     400           62 :                         } else if (sym is Namespace) {
     401            0 :                                 ns.add_namespace ((Namespace) sym);
     402           62 :                         } else if (sym is Struct) {
     403           62 :                                 ns.add_struct ((Struct) sym);
     404              :                         }
     405            0 :                 } else if (container is Struct) {
     406            0 :                         unowned Struct st = (Struct) container;
     407              : 
     408            0 :                         if (sym is Constant) {
     409            0 :                                 st.add_constant ((Constant) sym);
     410            0 :                         } else if (sym is Field) {
     411            0 :                                 st.add_field ((Field) sym);
     412            0 :                         } else if (sym is Method) {
     413            0 :                                 st.add_method ((Method) sym);
     414            0 :                         } else if (sym is Property) {
     415            0 :                                 st.add_property ((Property) sym);
     416              :                         }
     417              :                 }
     418              : 
     419         5195 :                 if (!(sym is Namespace) && container is Namespace) {
     420              :                         // set C headers
     421         5190 :                         sym.set_attribute_string ("CCode", "cheader_filename", get_cheader_filename (sym));
     422              :                 }
     423              :         }
     424              : 
     425         5439 :         private void parse_node (IdlNode node, IdlModule module, Symbol container) {
     426         5605 :                 if (node.type == IdlNodeTypeId.CALLBACK) {
     427          170 :                         var cb = parse_delegate ((IdlNodeFunction) node);
     428          170 :                         if (cb == null) {
     429              :                                 return;
     430              :                         }
     431          166 :                         cb.name = fix_type_name (cb.name, container);
     432          166 :                         add_symbol_to_container (container, cb);
     433          166 :                         current_source_file.add_node (cb);
     434              :                 } else if (node.type == IdlNodeTypeId.STRUCT) {
     435          364 :                         parse_struct ((IdlNodeStruct) node, container, module);
     436              :                 } else if (node.type == IdlNodeTypeId.UNION) {
     437            1 :                         parse_union ((IdlNodeUnion) node, container, module);
     438              :                 } else if (node.type == IdlNodeTypeId.BOXED) {
     439           34 :                         parse_boxed ((IdlNodeBoxed) node, container, module);
     440              :                 } else if (node.type == IdlNodeTypeId.ENUM) {
     441          318 :                         parse_enum ((IdlNodeEnum) node, container, module, false);
     442              :                 } else if (node.type == IdlNodeTypeId.FLAGS) {
     443           65 :                         parse_enum ((IdlNodeEnum) node, container, module, true);
     444              :                 } else if (node.type == IdlNodeTypeId.OBJECT) {
     445          301 :                         parse_object ((IdlNodeInterface) node, container, module);
     446              :                 } else if (node.type == IdlNodeTypeId.INTERFACE) {
     447           23 :                         parse_interface ((IdlNodeInterface) node, container, module);
     448         2628 :                 } else if (node.type == IdlNodeTypeId.CONSTANT) {
     449         2631 :                         var c = parse_constant ((IdlNodeConstant) node);
     450         2631 :                         if (c != null) {
     451         2628 :                                 c.name = fix_const_name (c.name, container);
     452         2628 :                                 add_symbol_to_container (container, c);
     453         2628 :                                 current_source_file.add_node (c);
     454              :                         }
     455         1381 :                 } else if (node.type == IdlNodeTypeId.FUNCTION) {
     456         1532 :                         var m = parse_function ((IdlNodeFunction) node);
     457         1532 :                         if (m != null) {
     458         1381 :                                 if (!(m is CreationMethod)) {
     459         1381 :                                         m.binding = MemberBinding.STATIC;
     460              :                                 }
     461         1381 :                                 add_symbol_to_container (container, m);
     462         1381 :                                 current_source_file.add_node (m);
     463              :                         }
     464              :                 }
     465              :         }
     466              : 
     467         2310 :         private Symbol? get_container_from_name (string name) {
     468         2310 :                 var path = name.split (".");
     469        45352 :                 Symbol? cp = current_namespace;
     470         2310 :                 if (cp.parent_symbol != context.root) {
     471           30 :                         cp = cp.parent_symbol;
     472              :                 }
     473              :                 Symbol? cc = null;
     474              : 
     475         4620 :                 foreach ( unowned string tok in path ) {
     476         2310 :                         cc = cp.scope.lookup (tok);
     477         2310 :                         if ( cc == null ) {
     478            5 :                                 cc = new Namespace (tok, current_source_reference);
     479            5 :                                 add_symbol_to_container (cp, cc);
     480              :                         }
     481         2310 :                         cp = cc;
     482              :                 }
     483              : 
     484         2310 :                 return cc;
     485              :         }
     486              : 
     487           25 :         private Namespace? parse_module (IdlModule module) {
     488           25 :                 Symbol sym = context.root.scope.lookup (module.name);
     489              :                 Namespace ns;
     490           25 :                 if (sym is Namespace) {
     491           16 :                         ns = (Namespace) sym;
     492           16 :                         if (ns.external_package) {
     493           25 :                                 ns.attributes = null;
     494           16 :                                 ns.source_reference = current_source_reference;
     495              :                         }
     496              :                 } else {
     497            9 :                         ns = new Namespace (module.name, current_source_reference);
     498              :                 }
     499              : 
     500           50 :                 current_namespace = ns;
     501              : 
     502           25 :                 var attributes = get_attributes (ns.name);
     503           25 :                 if (attributes != null) {
     504          180 :                         foreach (string attr in attributes) {
     505           52 :                                 var nv = attr.split ("=", 2);
     506           52 :                                 if (nv[0] == "cheader_filename") {
     507           24 :                                         ns.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
     508           28 :                                 } else if (nv[0] == "cprefix") {
     509            5 :                                         ns.set_attribute_string ("CCode", "cprefix", eval (nv[1]));
     510           23 :                                 } else if (nv[0] == "lower_case_cprefix") {
     511            5 :                                         ns.set_attribute_string ("CCode", "lower_case_cprefix",  eval (nv[1]));
     512           18 :                                 } else if (nv[0] == "gir_namespace") {
     513            5 :                                         ns.source_reference.file.gir_namespace = eval (nv[1]);
     514            5 :                                         ns.set_attribute_string ("CCode", "gir_namespace", eval (nv[1]));
     515           13 :                                 } else if (nv[0] == "gir_version") {
     516            5 :                                         ns.source_reference.file.gir_version = eval (nv[1]);
     517            5 :                                         ns.set_attribute_string ("CCode", "gir_version", eval (nv[1]));
     518            8 :                                 } else if (nv[0] == "deprecated") {
     519            0 :                                         if (eval (nv[1]) == "1") {
     520            0 :                                                 ns.set_attribute_bool ("Version", "deprecated", true);
     521              :                                         }
     522            8 :                                 } else if (nv[0] == "replacement") {
     523            8 :                                         ns.set_attribute_string ("Version", "replacement", eval (nv[1]));
     524            0 :                                 } else if (nv[0] == "deprecated_since") {
     525            0 :                                         ns.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
     526              :                                 }
     527              :                         }
     528              :                 }
     529              : 
     530           25 :                 var deferred = new ArrayList<unowned IdlNode> ();
     531              : 
     532        10903 :                 foreach (weak IdlNode node in module.entries) {
     533         5439 :                         bool is_deferred = false;
     534         5439 :                         var child_attributes = get_attributes_for_node (node);
     535         5439 :                         if (child_attributes != null) {
     536        12591 :                                 foreach (unowned string attr in child_attributes) {
     537         4950 :                                         var nv = attr.split ("=", 2);
     538         4950 :                                         if (nv[0] == "parent") {
     539         2295 :                                                 deferred.add (node);
     540         2295 :                                                 is_deferred = true;
     541              :                                         }
     542              :                                 }
     543              :                         }
     544              : 
     545         2691 :                         if (!is_deferred) {
     546         3144 :                                 parse_node (node, module, ns);
     547              :                         }
     548              :                 }
     549              : 
     550         2320 :                 foreach (unowned IdlNode node in deferred) {
     551         2295 :                         Symbol container = ns;
     552         2295 :                         var child_attributes = get_attributes_for_node (node);
     553         2295 :                         if (child_attributes != null) {
     554        11239 :                                 foreach (unowned string attr in child_attributes) {
     555         4472 :                                         var nv = attr.split ("=", 2);
     556         4472 :                                         if (nv[0] == "parent") {
     557         2295 :                                                 container = get_container_from_name (eval (nv[1]));
     558              :                                         }
     559              :                                 }
     560              :                         }
     561              : 
     562         2295 :                         if (container is Namespace) {
     563         2295 :                                 current_namespace = (Namespace) container;
     564              :                         } else {
     565            0 :                                 current_data_type = (TypeSymbol) container;
     566              :                         }
     567         2295 :                         parse_node (node, module, container);
     568         4590 :                         current_namespace = ns;
     569         2295 :                         current_data_type = null;
     570              :                 }
     571              : 
     572           25 :                 current_namespace = null;
     573              : 
     574           25 :                 if (sym is Namespace) {
     575           32 :                         return null;
     576              :                 }
     577           18 :                 return ns;
     578              :         }
     579              :         
     580          170 :         private Delegate? parse_delegate (IdlNodeFunction f_node) {
     581          170 :                 weak IdlNode node = (IdlNode) f_node;
     582              : 
     583          170 :                 var return_type = parse_param (f_node.result);
     584              : 
     585          170 :                 var cb = new Delegate (node.name, return_type, current_source_reference);
     586          170 :                 cb.access = SymbolAccessibility.PUBLIC;
     587          170 :                 cb.has_target = false;
     588              : 
     589          170 :                 bool check_has_target = true;
     590          170 :                 bool suppress_throws = false;
     591          170 :                 string? error_types = null;
     592              : 
     593          170 :                 var attributes = get_attributes (node.name);
     594          170 :                 if (attributes != null) {
     595           48 :                         foreach (string attr in attributes) {
     596           19 :                                 var nv = attr.split ("=", 2);
     597           19 :                                 if (nv[0] == "hidden") {
     598            4 :                                         if (eval (nv[1]) == "1") {
     599           12 :                                                 return null;
     600              :                                         }
     601           15 :                                 } else if (nv[0] == "cheader_filename") {
     602            1 :                                         cb.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
     603           14 :                                 } else if (nv[0] == "has_target") {
     604            5 :                                         if (eval (nv[1]) == "0") {
     605              :                                                 check_has_target = false;
     606            5 :                                         } else if (eval (nv[1]) == "1") {
     607            5 :                                                 cb.has_target = true;
     608              :                                         }
     609            9 :                                 } else if (nv[0] == "transfer_ownership") {
     610            3 :                                         if (eval (nv[1]) == "1") {
     611            3 :                                                 return_type.value_owned = true;
     612              :                                         }
     613            6 :                                 } else if (nv[0] == "is_array") {
     614            0 :                                         if (eval (nv[1]) == "1") {
     615            0 :                                                 return_type.value_owned = true;
     616            0 :                                                 return_type = new ArrayType (return_type, 1, return_type.source_reference);
     617            0 :                                                 cb.return_type = return_type;
     618              :                                         }
     619            6 :                                 } else if (nv[0] == "throws") {
     620            0 :                                         if (eval (nv[1]) == "0") {
     621           15 :                                                 suppress_throws = true;
     622              :                                         }
     623            6 :                                 } else if (nv[0] == "error_types") {
     624            0 :                                         error_types = eval (nv[1]);
     625            6 :                                 } else if (nv[0] == "array_length_type") {
     626            0 :                                         cb.set_attribute_string ("CCode", "array_length_type", eval (nv[1]));
     627            6 :                                 } else if (nv[0] == "type_name") {
     628            0 :                                         cb.return_type = return_type = parse_type_from_string (eval (nv[1]), return_type.value_owned);
     629            6 :                                 } else if (nv[0] == "deprecated") {
     630            1 :                                         if (eval (nv[1]) == "1") {
     631            1 :                                                 cb.set_attribute_bool ("Version", "deprecated", true);
     632              :                                         }
     633            5 :                                 } else if (nv[0] == "replacement") {
     634            0 :                                         cb.set_attribute_string ("Version", "replacement", eval (nv[1]));
     635            5 :                                 } else if (nv[0] == "deprecated_since") {
     636            1 :                                         cb.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
     637            4 :                                 } else if (nv[0] == "type_arguments") {
     638            0 :                                         parse_type_arguments_from_string (return_type, eval (nv[1]));
     639            4 :                                 } else if (nv[0] == "instance_pos") {
     640            2 :                                         cb.set_attribute_double ("CCode", "instance_pos", double.parse (eval (nv[1])));
     641            2 :                                 } else if (nv[0] == "type_parameters") {
     642            0 :                                         foreach (string type_param_name in eval (nv[1]).split (",")) {
     643            0 :                                                 cb.add_type_parameter (new TypeParameter (type_param_name, current_source_reference));
     644              :                                         }
     645            2 :                                 } else if (nv[0] == "experimental") {
     646            0 :                                         if (eval (nv[1]) == "1") {
     647            0 :                                                 cb.set_attribute_bool ("Version", "experimental", true);
     648              :                                         }
     649              :                                 }
     650              :                         }
     651              :                 }
     652              : 
     653          166 :                 uint remaining_params = f_node.parameters.length ();
     654          695 :                 foreach (weak IdlNodeParam param in f_node.parameters) {
     655          529 :                         weak IdlNode param_node = (IdlNode) param;
     656              : 
     657          969 :                         if (check_has_target && remaining_params == 1 && (param_node.name == "user_data" || param_node.name == "data")) {
     658              :                                 // hide user_data parameter for instance delegates
     659           88 :                                 cb.has_target = true;
     660              :                         } else {
     661              :                                 // check for GError parameter
     662          441 :                                 if (suppress_throws == false && param_is_exception (param)) {
     663            1 :                                         if (error_types == null)
     664            1 :                                                 cb.add_error_type (parse_type (param.type));
     665            1 :                                         remaining_params--;
     666            1 :                                         continue;
     667              :                                 }
     668              : 
     669          440 :                                 string param_name = param_node.name;
     670          440 :                                 if (param_name == "string") {
     671              :                                         // avoid conflict with string type
     672            1 :                                         param_name = "str";
     673          439 :                                 } else if (param_name == "self") {
     674              :                                         // avoid conflict with delegate target
     675            0 :                                         param_name = "_self";
     676              :                                 }
     677              : 
     678              :                                 ParameterDirection direction;
     679          440 :                                 var param_type = parse_param (param, out direction);
     680          440 :                                 var p = new Parameter (param_name, param_type, current_source_reference);
     681          440 :                                 p.direction = direction;
     682              : 
     683          440 :                                 bool hide_param = false;
     684          440 :                                 bool show_param = false;
     685          440 :                                 bool array_requested = false;
     686          440 :                                 bool out_requested = false;
     687          880 :                                 attributes = get_attributes ("%s.%s".printf (node.name, param_node.name));
     688          440 :                                 if (attributes != null) {
     689          134 :                                         foreach (string attr in attributes) {
     690           37 :                                                 var nv = attr.split ("=", 2);
     691           37 :                                                 if (nv[0] == "hidden") {
     692           10 :                                                         if (eval (nv[1]) == "1") {
     693              :                                                                 hide_param = true;
     694            0 :                                                         } else if (eval (nv[1]) == "0") {
     695            0 :                                                                 show_param = true;
     696              :                                                         }
     697           27 :                                                 } else if (nv[0] == "is_array") {
     698            7 :                                                         if (eval (nv[1]) == "1") {
     699            7 :                                                                 param_type.value_owned = true;
     700            7 :                                                                 param_type = new ArrayType (param_type, 1, param_type.source_reference);
     701            7 :                                                                 p.variable_type = param_type;
     702            7 :                                                                 if (!out_requested) {
     703            7 :                                                                         p.direction = ParameterDirection.IN;
     704              :                                                                 }
     705              :                                                                 array_requested = true;
     706              :                                                         }
     707           20 :                                                 } else if (nv[0] == "is_out") {
     708            2 :                                                         if (eval (nv[1]) == "1") {
     709            2 :                                                                 p.direction = ParameterDirection.OUT;
     710            2 :                                                                 out_requested = true;
     711            2 :                                                                 if (!array_requested && param_type is ArrayType) {
     712            0 :                                                                         var array_type = (ArrayType) param_type;
     713            0 :                                                                         param_type = array_type.element_type;
     714            0 :                                                                         p.variable_type = param_type;
     715              :                                                                 }
     716              :                                                         }
     717           18 :                                                 } else if (nv[0] == "is_ref") {
     718            2 :                                                         if (eval (nv[1]) == "1") {
     719            2 :                                                                 p.direction = ParameterDirection.REF;
     720            2 :                                                                 if (!array_requested && param_type is ArrayType) {
     721            0 :                                                                         var array_type = (ArrayType) param_type;
     722            0 :                                                                         param_type = array_type.element_type;
     723            0 :                                                                         p.variable_type = param_type;
     724              :                                                                 }
     725              :                                                         }
     726           16 :                                                 } else if (nv[0] == "takes_ownership") {
     727            0 :                                                         if (eval (nv[1]) == "1") {
     728            0 :                                                                 param_type.value_owned = true;
     729              :                                                         }
     730           16 :                                                 } else if (nv[0] == "nullable") {
     731            3 :                                                         if (eval (nv[1]) == "1") {
     732            3 :                                                                 param_type.nullable = true;
     733              :                                                         }
     734           13 :                                                 } else if (nv[0] == "type_arguments") {
     735            0 :                                                         parse_type_arguments_from_string (param_type, eval (nv[1]));
     736           13 :                                                 } else if (nv[0] == "no_array_length") {
     737            0 :                                                         if (eval (nv[1]) == "1") {
     738            0 :                                                                 p.set_attribute_bool ("CCode", "array_length", false);
     739              :                                                         }
     740           13 :                                                 } else if (nv[0] == "array_length_type") {
     741            2 :                                                         p.set_attribute_string ("CCode", "array_length_type", eval (nv[1]));
     742           11 :                                                 } else if (nv[0] == "array_null_terminated") {
     743            1 :                                                         if (eval (nv[1]) == "1") {
     744            1 :                                                                 p.set_attribute_bool ("CCode", "array_length", false);
     745            1 :                                                                 p.set_attribute_bool ("CCode", "array_null_terminated", true);
     746              :                                                         }
     747           10 :                                                 } else if (nv[0] == "type_name") {
     748            2 :                                                         p.variable_type = param_type = parse_type_from_string (eval (nv[1]), false);
     749              :                                                 }
     750              :                                         }
     751              :                                 }
     752              : 
     753          440 :                                 if (show_param || !hide_param) {
     754          430 :                                         cb.add_parameter (p);
     755              :                                 }
     756              :                         }
     757              : 
     758          528 :                         remaining_params--;
     759              :                 }
     760              : 
     761          166 :                 if (suppress_throws == false && error_types != null) {
     762            0 :                         var type_args = eval (error_types).split (",");
     763            0 :                         foreach (unowned string type_arg in type_args) {
     764            0 :                                 cb.add_error_type (parse_type_from_string (type_arg, true));
     765              :                         }
     766              :                 }
     767              : 
     768          332 :                 return cb;
     769              :         }
     770              : 
     771          399 :         private bool is_reference_type (string cname) {
     772          399 :                 var st_attributes = get_attributes (cname);
     773          399 :                 if (st_attributes != null) {
     774          321 :                         foreach (string attr in st_attributes) {
     775          115 :                                 var nv = attr.split ("=", 2);
     776          115 :                                 if (nv[0] == "is_value_type" && eval (nv[1]) == "1") {
     777          136 :                                         return false;
     778              :                                 }
     779              :                         }
     780              :                 }
     781          331 :                 return true;
     782              :         }
     783              : 
     784          702 :         private void parse_struct (IdlNodeStruct st_node, Symbol container, IdlModule module) {
     785          364 :                 weak IdlNode node = (IdlNode) st_node;
     786              :                 
     787          364 :                 if (st_node.deprecated) {
     788              :                         return;
     789              :                 }
     790              : 
     791          364 :                 string name = fix_type_name (node.name, container);
     792              : 
     793          702 :                 if (!is_reference_type (node.name)) {
     794           61 :                         var st = container.scope.lookup (name) as Struct;
     795          112 :                         if (st == null) {
     796           56 :                                 st = new Struct (name, current_source_reference);
     797           56 :                                 st.access = SymbolAccessibility.PUBLIC;
     798              : 
     799           56 :                                 var st_attributes = get_attributes (node.name);
     800           56 :                                 if (st_attributes != null) {
     801          302 :                                         foreach (string attr in st_attributes) {
     802           82 :                                                 var nv = attr.split ("=", 2);
     803           82 :                                                 if (nv[0] == "cheader_filename") {
     804            1 :                                                         st.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
     805           81 :                                                 } else if (nv[0] == "hidden") {
     806            0 :                                                         if (eval (nv[1]) == "1") {
     807            0 :                                                                 return;
     808              :                                                         }
     809           81 :                                                 } else if (nv[0] == "base_type") {
     810            0 :                                                         st.base_type = parse_type_string (eval (nv[1]));
     811           81 :                                                 } else if (nv[0] == "rank") {
     812            0 :                                                         st.rank = int.parse (eval (nv[1]));
     813           81 :                                                 } else if (nv[0] == "simple_type") {
     814            1 :                                                         if (eval (nv[1]) == "1") {
     815            1 :                                                                 st.set_simple_type (true);
     816              :                                                         }
     817           80 :                                                 } else if (nv[0] == "immutable") {
     818            0 :                                                         if (eval (nv[1]) == "1") {
     819            0 :                                                                 st.set_attribute ("Immutable", true);
     820              :                                                         }
     821           80 :                                                 } else if (nv[0] == "has_type_id") {
     822           20 :                                                         if (eval (nv[1]) == "0") {
     823           20 :                                                                 st.set_attribute_bool ("CCode", "has_type_id", false);
     824              :                                                         }
     825           60 :                                                 } else if (nv[0] == "type_id") {
     826            0 :                                                         st.set_attribute_string ("CCode", "type_id", eval (nv[1]));
     827           60 :                                                 } else if (nv[0] == "has_copy_function") {
     828            1 :                                                         if (eval (nv[1]) == "0") {
     829            1 :                                                                 st.set_attribute_bool ("CCode", "has_copy_function", false);
     830              :                                                         }
     831           59 :                                                 } else if (nv[0] == "deprecated") {
     832            1 :                                                         if (eval (nv[1]) == "1") {
     833            1 :                                                                 st.set_attribute_bool ("Version", "deprecated", true);
     834              :                                                         }
     835           58 :                                                 } else if (nv[0] == "replacement") {
     836            0 :                                                         st.set_attribute_string ("Version", "replacement", eval (nv[1]));
     837           58 :                                                 } else if (nv[0] == "deprecated_since") {
     838            1 :                                                         st.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
     839           57 :                                                 } else if (nv[0] == "has_destroy_function") {
     840            1 :                                                         if (eval (nv[1]) == "0") {
     841            1 :                                                                 st.set_attribute_bool ("CCode", "has_destroy_function", false);
     842              :                                                         }
     843           56 :                                                 } else if (nv[0] == "experimental") {
     844            0 :                                                         if (eval (nv[1]) == "1") {
     845            0 :                                                                 st.set_attribute_bool ("Version", "experimental", true);
     846              :                                                         }
     847              :                                                 }
     848              :                                         }
     849              :                                 }
     850              : 
     851           56 :                                 add_symbol_to_container (container, st);
     852           56 :                                 current_source_file.add_node (st);
     853              :                         }
     854              : 
     855           61 :                         current_data_type = st;
     856              : 
     857          474 :                         foreach (weak IdlNode member in st_node.members) {
     858          482 :                                 if (member.type == IdlNodeTypeId.FUNCTION) {
     859           74 :                                         var m = parse_function ((IdlNodeFunction) member);
     860           74 :                                         if (m != null) {
     861           69 :                                                 st.add_method (m);
     862              :                                         }
     863          670 :                                 } else if (member.type == IdlNodeTypeId.FIELD) {
     864          339 :                                         var f = parse_field ((IdlNodeField) member);
     865          339 :                                         if (f != null) {
     866          331 :                                                 st.add_field (f);
     867              :                                         }
     868              :                                 }
     869              :                         }
     870              : 
     871           61 :                         current_data_type = null;
     872              :                 } else {
     873          303 :                         bool ref_function_void = false;
     874          303 :                         string ref_function = null;
     875          303 :                         string unref_function = null;
     876          303 :                         string copy_function = null;
     877          303 :                         string free_function = null;
     878              : 
     879          303 :                         var cl = container.scope.lookup (name) as Class;
     880          550 :                         if (cl == null) {
     881          288 :                                 string base_class = null;
     882          288 :                                 bool is_fundamental = false;
     883              : 
     884          288 :                                 cl = new Class (name, current_source_reference);
     885          288 :                                 cl.access = SymbolAccessibility.PUBLIC;
     886              : 
     887          288 :                                 var cl_attributes = get_attributes (node.name);
     888          288 :                                 if (cl_attributes != null) {
     889           85 :                                         foreach (string attr in cl_attributes) {
     890           37 :                                                 var nv = attr.split ("=", 2);
     891           37 :                                                 if (nv[0] == "cheader_filename") {
     892            6 :                                                         cl.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
     893           31 :                                                 } else if (nv[0] == "base_class") {
     894            5 :                                                         base_class = eval (nv[1]);
     895           26 :                                                 } else if (nv[0] == "hidden") {
     896           26 :                                                         if (eval (nv[1]) == "1") {
     897           78 :                                                                 return;
     898              :                                                         }
     899            0 :                                                 } else if (nv[0] == "is_immutable") {
     900            0 :                                                         if (eval (nv[1]) == "1") {
     901            0 :                                                                 cl.set_attribute ("Immutable", true);
     902              :                                                         }
     903            0 :                                                 } else if (nv[0] == "const_cname") {
     904            0 :                                                         cl.set_attribute_string ("CCode", "const_cname", eval (nv[1]));
     905            0 :                                                 } else if (nv[0] == "is_fundamental") {
     906            0 :                                                         if (eval (nv[1]) == "1") {
     907           11 :                                                                 is_fundamental = true;
     908              :                                                         }
     909            0 :                                                 } else if (nv[0] == "abstract" && base_class != null) {
     910            0 :                                                         if (eval (nv[1]) == "1") {
     911            0 :                                                                 cl.is_abstract = true;
     912              :                                                         }
     913            0 :                                                 } else if (nv[0] == "free_function") {
     914            0 :                                                         free_function = eval (nv[1]);
     915            0 :                                                 } else if (nv[0] == "ref_function") {
     916            0 :                                                         ref_function = eval (nv[1]);
     917            0 :                                                 } else if (nv[0] == "unref_function") {
     918            0 :                                                         unref_function = eval (nv[1]);
     919            0 :                                                 } else if (nv[0] == "copy_function") {
     920            0 :                                                         copy_function = eval (nv[1]);
     921            0 :                                                 } else if (nv[0] == "ref_function_void") {
     922            0 :                                                         if (eval (nv[1]) == "1") {
     923           11 :                                                                 ref_function_void = true;
     924              :                                                         }
     925            0 :                                                 } else if (nv[0] == "deprecated") {
     926            0 :                                                         if (eval (nv[1]) == "1") {
     927            0 :                                                                 cl.set_attribute_bool ("Version", "deprecated", true);
     928              :                                                         }
     929            0 :                                                 } else if (nv[0] == "replacement") {
     930            0 :                                                         cl.set_attribute_string ("Version", "replacement", eval (nv[1]));
     931            0 :                                                 } else if (nv[0] == "deprecated_since") {
     932            0 :                                                         cl.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
     933            0 :                                                 } else if (nv[0] == "type_parameters") {
     934            0 :                                                         foreach (unowned string type_param_name in eval (nv[1]).split (",")) {
     935            0 :                                                                 cl.add_type_parameter (new TypeParameter (type_param_name, current_source_reference));
     936              :                                                         }
     937            0 :                                                 } else if (nv[0] == "experimental") {
     938            0 :                                                         if (eval (nv[1]) == "1") {
     939            0 :                                                                 cl.set_attribute_bool ("Version", "experimental", true);
     940              :                                                         }
     941            0 :                                                 } else if (nv[0] == "delegate_target_cname") {
     942            0 :                                                         cl.set_attribute_string ("CCode", "delegate_target_cname", eval (nv[1]));
     943              :                                                 }
     944              :                                         }
     945              :                                 }
     946              : 
     947          262 :                                 add_symbol_to_container (container, cl);
     948          262 :                                 current_source_file.add_node (cl);
     949              : 
     950          267 :                                 if (base_class != null) {
     951            5 :                                         var parent = parse_type_string (base_class);
     952            5 :                                         cl.add_base_type (parent);
     953              :                                 }
     954          519 :                                 if (base_class == null && !is_fundamental) {
     955          257 :                                         cl.set_attribute ("Compact", true);
     956              :                                 }
     957              :                         }
     958              : 
     959          554 :                         current_data_type = cl;
     960              : 
     961         3062 :                         foreach (weak IdlNode member in st_node.members) {
     962         2785 :                                 if (member.type == IdlNodeTypeId.FUNCTION) {
     963         1617 :                                         if ((ref_function == null) && (member.name == "ref")) {
     964           38 :                                                 ref_function = ((IdlNodeFunction) member).symbol;
     965           19 :                                                 ref_function_void = (parse_type (((IdlNodeFunction) member).result.type) is VoidType);
     966         1598 :                                         } else if ((unref_function == null) && (member.name == "unref")) {
     967           40 :                                                 unref_function = ((IdlNodeFunction) member).symbol;
     968         3046 :                                         } else if ((free_function == null) && (member.name == "free" || member.name == "destroy")) {
     969          100 :                                                 free_function = ((IdlNodeFunction) member).symbol;
     970              :                                         } else {
     971         1528 :                                                 if ((copy_function == null) && (member.name == "copy")) {
     972           24 :                                                         copy_function = ((IdlNodeFunction) member).symbol;
     973              :                                                 }
     974         1528 :                                                 var m = parse_function ((IdlNodeFunction) member);
     975         1528 :                                                 if (m != null) {
     976         1468 :                                                         cl.add_method (m);
     977              :                                                 }
     978              :                                         }
     979         2212 :                                 } else if (member.type == IdlNodeTypeId.FIELD) {
     980         1168 :                                         var f = parse_field ((IdlNodeField) member);
     981         1168 :                                         if (f != null) {
     982         1044 :                                                 cl.add_field (f);
     983              :                                         }
     984              :                                 }
     985              :                         }
     986              : 
     987          277 :                         if (ref_function != null) {
     988           19 :                                 cl.set_attribute_string ("CCode", "ref_function", ref_function);
     989           19 :                                 if (ref_function_void) {
     990            4 :                                         cl.set_attribute_bool ("CCode", "ref_function_void", ref_function_void);
     991              :                                 }
     992          258 :                         } else if (copy_function != null) {
     993           10 :                                 cl.set_attribute_string ("CCode", "copy_function", copy_function);
     994              :                         }
     995          277 :                         if (unref_function != null) {
     996           20 :                                 cl.set_attribute_string ("CCode", "unref_function", unref_function);
     997          257 :                         } else if (free_function != null && free_function != "%sfree".printf (get_lower_case_cprefix (cl))) {
     998           33 :                                 cl.set_attribute_string ("CCode", "free_function", free_function);
     999              :                         }
    1000              : 
    1001          277 :                         current_data_type = null;
    1002              :                 }
    1003              :         }
    1004              : 
    1005            2 :         private void parse_union (IdlNodeUnion un_node, Symbol container, IdlModule module) {
    1006            1 :                 weak IdlNode node = (IdlNode) un_node;
    1007              :                 
    1008            1 :                 if (un_node.deprecated) {
    1009              :                         return;
    1010              :                 }
    1011              : 
    1012            1 :                 string name = fix_type_name (node.name, container);
    1013              : 
    1014            2 :                 if (!is_reference_type (node.name)) {
    1015            1 :                         var st = container.scope.lookup (name) as Struct;
    1016            0 :                         if (st == null) {
    1017            0 :                                 st = new Struct (name, current_source_reference);
    1018            0 :                                 st.access = SymbolAccessibility.PUBLIC;
    1019              : 
    1020            0 :                                 var st_attributes = get_attributes (node.name);
    1021            0 :                                 if (st_attributes != null) {
    1022            0 :                                         foreach (string attr in st_attributes) {
    1023            0 :                                                 var nv = attr.split ("=", 2);
    1024            0 :                                                 if (nv[0] == "cheader_filename") {
    1025            0 :                                                         st.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
    1026            0 :                                                 } else if (nv[0] == "deprecated") {
    1027            0 :                                                         if (eval (nv[1]) == "1") {
    1028            0 :                                                                 st.set_attribute_bool ("Version", "deprecated", true);
    1029              :                                                         }
    1030            0 :                                                 } else if (nv[0] == "replacement") {
    1031            0 :                                                         st.set_attribute_string ("Version", "replacement", eval (nv[1]));
    1032            0 :                                                 } else if (nv[0] == "deprecated_since") {
    1033            0 :                                                         st.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
    1034            0 :                                                 } else if (nv[0] == "hidden") {
    1035            0 :                                                         if (eval (nv[1]) == "1") {
    1036            0 :                                                                 return;
    1037              :                                                         }
    1038            0 :                                                 } else if (nv[0] == "experimental") {
    1039            0 :                                                         if (eval (nv[1]) == "1") {
    1040            0 :                                                                 st.set_attribute_bool ("Version", "experimental", true);
    1041              :                                                         }
    1042              :                                                 }
    1043              :                                         }
    1044              :                                 }
    1045              : 
    1046            0 :                                 add_symbol_to_container (container, st);
    1047            0 :                                 current_source_file.add_node (st);
    1048              :                         }
    1049              : 
    1050            1 :                         current_data_type = st;
    1051              : 
    1052            4 :                         foreach (weak IdlNode member in un_node.members) {
    1053            3 :                                 if (member.type == IdlNodeTypeId.FUNCTION) {
    1054            0 :                                         var m = parse_function ((IdlNodeFunction) member);
    1055            0 :                                         if (m != null) {
    1056            0 :                                                 st.add_method (m);
    1057              :                                         }
    1058            3 :                                 } else if (member.type == IdlNodeTypeId.FIELD) {
    1059            3 :                                         var f = parse_field ((IdlNodeField) member);
    1060            3 :                                         if (f != null) {
    1061            0 :                                                 st.add_field (f);
    1062              :                                         }
    1063              :                                 }
    1064              :                         }
    1065              : 
    1066            1 :                         current_data_type = null;
    1067              :                 } else {
    1068            0 :                         var cl = container.scope.lookup (name) as Class;
    1069            0 :                         if (cl == null) {
    1070            0 :                                 cl = new Class (name, current_source_reference);
    1071            0 :                                 cl.access = SymbolAccessibility.PUBLIC;
    1072            0 :                                 cl.set_attribute ("Compact", true);
    1073              : 
    1074            0 :                                 var cl_attributes = get_attributes (node.name);
    1075            0 :                                 if (cl_attributes != null) {
    1076            0 :                                         foreach (string attr in cl_attributes) {
    1077            0 :                                                 var nv = attr.split ("=", 2);
    1078            0 :                                                 if (nv[0] == "cheader_filename") {
    1079            0 :                                                         cl.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
    1080            0 :                                                 } else if (nv[0] == "hidden") {
    1081            0 :                                                         if (eval (nv[1]) == "1") {
    1082            0 :                                                                 return;
    1083              :                                                         }
    1084              :                                                 }
    1085              :                                         }
    1086              :                                 }
    1087              : 
    1088            0 :                                 add_symbol_to_container (container, cl);
    1089            0 :                                 current_source_file.add_node (cl);
    1090              :                         }
    1091              : 
    1092            0 :                         current_data_type = cl;
    1093              : 
    1094            0 :                         bool ref_function_void = false;
    1095            0 :                         string ref_function = null;
    1096            0 :                         string unref_function = null;
    1097            0 :                         string copy_function = null;
    1098            0 :                         string free_function = null;
    1099              : 
    1100            0 :                         foreach (weak IdlNode member in un_node.members) {
    1101            0 :                                 if (member.type == IdlNodeTypeId.FUNCTION) {
    1102            0 :                                         if (member.name == "ref") {
    1103            0 :                                                 ref_function = ((IdlNodeFunction) member).symbol;
    1104            0 :                                                 ref_function_void = (parse_type (((IdlNodeFunction) member).result.type) is VoidType);
    1105            0 :                                         } else if (member.name == "unref") {
    1106            0 :                                                 unref_function = ((IdlNodeFunction) member).symbol;
    1107            0 :                                         } else if (member.name == "free" || member.name == "destroy") {
    1108            0 :                                                 free_function = ((IdlNodeFunction) member).symbol;
    1109              :                                         } else {
    1110            0 :                                                 if (member.name == "copy") {
    1111            0 :                                                         copy_function = ((IdlNodeFunction) member).symbol;
    1112              :                                                 }
    1113            0 :                                                 var m = parse_function ((IdlNodeFunction) member);
    1114            0 :                                                 if (m != null) {
    1115            0 :                                                         cl.add_method (m);
    1116              :                                                 }
    1117              :                                         }
    1118            0 :                                 } else if (member.type == IdlNodeTypeId.FIELD) {
    1119            0 :                                         var f = parse_field ((IdlNodeField) member);
    1120            0 :                                         if (f != null) {
    1121            0 :                                                 cl.add_field (f);
    1122              :                                         }
    1123              :                                 }
    1124              :                         }
    1125              : 
    1126            0 :                         if (ref_function != null) {
    1127            0 :                                 cl.set_attribute_string ("CCode", "ref_function", ref_function);
    1128            0 :                                 if (ref_function_void) {
    1129            0 :                                         cl.set_attribute_bool ("CCode", "ref_function_void", ref_function_void);
    1130              :                                 }
    1131            0 :                         } else if (copy_function != null) {
    1132            0 :                                 cl.set_attribute_string ("CCode", "copy_function", copy_function);
    1133              :                         }
    1134            0 :                         if (unref_function != null) {
    1135            0 :                                 cl.set_attribute_string ("CCode", "unref_function", unref_function);
    1136            0 :                         } else if (free_function != null && free_function != "%sfree".printf (get_lower_case_cprefix (cl))) {
    1137            0 :                                 cl.set_attribute_string ("CCode", "free_function", free_function);
    1138              :                         }
    1139              : 
    1140            0 :                         current_data_type = null;
    1141              :                 }
    1142              :         }
    1143              : 
    1144          102 :         private void parse_boxed (IdlNodeBoxed boxed_node, Symbol container, IdlModule module) {
    1145           34 :                 weak IdlNode node = (IdlNode) boxed_node;
    1146              : 
    1147           34 :                 string name = fix_type_name (node.name, container);
    1148              : 
    1149           34 :                 var node_attributes = get_attributes (node.name);
    1150           34 :                 if (node_attributes != null) {
    1151           53 :                         foreach (string attr in node_attributes) {
    1152           14 :                                 var nv = attr.split ("=", 2);
    1153           14 :                                 if (nv[0] == "hidden") {
    1154            0 :                                         return;
    1155              :                                 }
    1156              :                         }
    1157              :                 }
    1158              : 
    1159           68 :                 if (!is_reference_type (node.name)) {
    1160            6 :                         var st = container.scope.lookup (name) as Struct;
    1161           12 :                         if (st == null) {
    1162            6 :                                 st = new Struct (name, current_source_reference);
    1163            6 :                                 st.access = SymbolAccessibility.PUBLIC;
    1164              : 
    1165            6 :                                 var st_attributes = get_attributes (node.name);
    1166            6 :                                 if (st_attributes != null) {
    1167           24 :                                         foreach (string attr in st_attributes) {
    1168            6 :                                                 var nv = attr.split ("=", 2);
    1169            6 :                                                 if (nv[0] == "cheader_filename") {
    1170            0 :                                                         st.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
    1171            6 :                                                 } else if (nv[0] == "deprecated") {
    1172            0 :                                                         if (eval (nv[1]) == "1") {
    1173            0 :                                                                 st.set_attribute_bool ("Version", "deprecated", true);
    1174              :                                                         }
    1175            6 :                                                 } else if (nv[0] == "replacement") {
    1176            0 :                                                         st.set_attribute_string ("Version", "replacement", eval (nv[1]));
    1177            6 :                                                 } else if (nv[0] == "deprecated_since") {
    1178            0 :                                                         st.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
    1179            6 :                                                 } else if (nv[0] == "immutable") {
    1180            0 :                                                         if (eval (nv[1]) == "1") {
    1181            0 :                                                                 st.set_attribute ("Immutable", true);
    1182              :                                                         }
    1183            6 :                                                 } else if (nv[0] == "has_copy_function") {
    1184            0 :                                                         if (eval (nv[1]) == "0") {
    1185            0 :                                                                 st.set_attribute_bool ("CCode", "has_copy_function", false);
    1186              :                                                         }
    1187            6 :                                                 } else if (nv[0] == "has_destroy_function") {
    1188            0 :                                                         if (eval (nv[1]) == "0") {
    1189            0 :                                                                 st.set_attribute_bool ("CCode", "has_destroy_function", false);
    1190              :                                                         }
    1191            6 :                                                 } else if (nv[0] == "experimental") {
    1192            0 :                                                         if (eval (nv[1]) == "1") {
    1193            0 :                                                                 st.set_attribute_bool ("Version", "experimental", true);
    1194              :                                                         }
    1195              :                                                 }
    1196              :                                         }
    1197              :                                 }
    1198              : 
    1199            6 :                                 add_symbol_to_container (container, st);
    1200            6 :                                 current_source_file.add_node (st);
    1201              :                         }
    1202              :                 
    1203            6 :                         current_data_type = st;
    1204              : 
    1205          144 :                         foreach (weak IdlNode member in boxed_node.members) {
    1206          238 :                                 if (member.type == IdlNodeTypeId.FUNCTION) {
    1207          106 :                                         var m = parse_function ((IdlNodeFunction) member);
    1208          106 :                                         if (m != null) {
    1209          100 :                                                 st.add_method (m);
    1210              :                                         }
    1211           50 :                                 } else if (member.type == IdlNodeTypeId.FIELD) {
    1212           32 :                                         var f = parse_field ((IdlNodeField) member);
    1213           32 :                                         if (f != null) {
    1214           18 :                                                 st.add_field (f);
    1215              :                                         }
    1216              :                                 }
    1217              :                         }
    1218              : 
    1219            6 :                         current_data_type = null;
    1220              :                 } else {
    1221           28 :                         bool ref_function_void = false;
    1222           28 :                         string ref_function = null;
    1223           28 :                         string unref_function = null;
    1224           28 :                         string copy_function = null;
    1225           28 :                         string free_function = null;
    1226              : 
    1227           28 :                         var cl = container.scope.lookup (name) as Class;
    1228           75 :                         if (cl == null) {
    1229           25 :                                 string base_class = null;
    1230              : 
    1231           25 :                                 cl = new Class (name, current_source_reference);
    1232           25 :                                 cl.access = SymbolAccessibility.PUBLIC;
    1233           25 :                                 cl.set_attribute ("Compact", true);
    1234           25 :                                 if (boxed_node.gtype_init != null) {
    1235           25 :                                         cl.set_attribute_string ("CCode", "type_id", "%s ()".printf (boxed_node.gtype_init));
    1236              :                                 }
    1237              : 
    1238           25 :                                 var cl_attributes = get_attributes (node.name);
    1239           25 :                                 if (cl_attributes != null) {
    1240           21 :                                         foreach (string attr in cl_attributes) {
    1241            8 :                                                 var nv = attr.split ("=", 2);
    1242            8 :                                                 if (nv[0] == "cheader_filename") {
    1243            1 :                                                         cl.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
    1244            7 :                                                 } else if (nv[0] == "base_class") {
    1245            0 :                                                         base_class = eval (nv[1]);
    1246            7 :                                                 } else if (nv[0] == "is_immutable") {
    1247            2 :                                                         if (eval (nv[1]) == "1") {
    1248            2 :                                                                 cl.set_attribute ("Immutable", true);
    1249              :                                                         }
    1250            5 :                                                 } else if (nv[0] == "deprecated") {
    1251            0 :                                                         if (eval (nv[1]) == "1") {
    1252            0 :                                                                 cl.set_attribute_bool ("Version", "deprecated", true);
    1253              :                                                         }
    1254            5 :                                                 } else if (nv[0] == "replacement") {
    1255            0 :                                                         cl.set_attribute_string ("Version", "replacement", eval (nv[1]));
    1256            5 :                                                 } else if (nv[0] == "deprecated_since") {
    1257            0 :                                                         cl.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
    1258            5 :                                                 } else if (nv[0] == "const_cname") {
    1259            1 :                                                         cl.set_attribute_string ("CCode", "const_cname", eval (nv[1]));
    1260            4 :                                                 } else if (nv[0] == "free_function") {
    1261            0 :                                                         free_function = eval (nv[1]);
    1262            4 :                                                 } else if (nv[0] == "ref_function") {
    1263            0 :                                                         ref_function = eval (nv[1]);
    1264            4 :                                                 } else if (nv[0] == "unref_function") {
    1265            0 :                                                         unref_function = eval (nv[1]);
    1266            4 :                                                 } else if (nv[0] == "copy_function") {
    1267            0 :                                                         copy_function = eval (nv[1]);
    1268            4 :                                                 } else if (nv[0] == "ref_function_void") {
    1269            0 :                                                         if (eval (nv[1]) == "1") {
    1270            8 :                                                                 ref_function_void = true;
    1271              :                                                         }
    1272            4 :                                                 } else if (nv[0] == "experimental") {
    1273            0 :                                                         if (eval (nv[1]) == "1") {
    1274            0 :                                                                 cl.set_attribute_bool ("Version", "experimental", true);
    1275              :                                                         }
    1276              :                                                 }
    1277              :                                         }
    1278              :                                 }
    1279              : 
    1280           25 :                                 add_symbol_to_container (container, cl);
    1281           25 :                                 current_source_file.add_node (cl);
    1282              : 
    1283           25 :                                 if (base_class != null) {
    1284            0 :                                         var parent = parse_type_string (base_class);
    1285            0 :                                         cl.add_base_type (parent);
    1286              :                                 }
    1287              :                         }
    1288              : 
    1289           56 :                         current_data_type = cl;
    1290              : 
    1291          447 :                         foreach (weak IdlNode member in boxed_node.members) {
    1292          419 :                                 if (member.type == IdlNodeTypeId.FUNCTION) {
    1293          311 :                                         if (member.name == "ref") {
    1294           24 :                                                 ref_function = ((IdlNodeFunction) member).symbol;
    1295           12 :                                                 ref_function_void = (parse_type (((IdlNodeFunction) member).result.type) is VoidType);
    1296          299 :                                         } else if (member.name == "unref") {
    1297           24 :                                                 unref_function = ((IdlNodeFunction) member).symbol;
    1298          553 :                                         } else if (member.name == "free" || member.name == "destroy") {
    1299           24 :                                                 free_function = ((IdlNodeFunction) member).symbol;
    1300              :                                         } else {
    1301          275 :                                                 if (member.name == "copy") {
    1302           30 :                                                         copy_function = ((IdlNodeFunction) member).symbol;
    1303              :                                                 }
    1304          275 :                                                 var m = parse_function ((IdlNodeFunction) member);
    1305          275 :                                                 if (m != null) {
    1306          266 :                                                         cl.add_method (m);
    1307              :                                                 }
    1308              :                                         }
    1309          212 :                                 } else if (member.type == IdlNodeTypeId.FIELD) {
    1310          108 :                                         var f = parse_field ((IdlNodeField) member);
    1311          108 :                                         if (f != null) {
    1312          104 :                                                 cl.add_field (f);
    1313              :                                         }
    1314              :                                 }
    1315              :                         }
    1316              : 
    1317           28 :                         if (ref_function != null) {
    1318           12 :                                 cl.set_attribute_string ("CCode", "ref_function", ref_function);
    1319           12 :                                 if (ref_function_void) {
    1320            2 :                                         cl.set_attribute_bool ("CCode", "ref_function_void", ref_function_void);
    1321              :                                 }
    1322           16 :                         } else if (copy_function != null) {
    1323           11 :                                 cl.set_attribute_string ("CCode", "copy_function", copy_function);
    1324              :                         }
    1325           28 :                         if (unref_function != null) {
    1326           12 :                                 cl.set_attribute_string ("CCode", "unref_function", unref_function);
    1327           16 :                         } else if (free_function != null && free_function != "%sfree".printf (get_lower_case_cprefix (cl))) {
    1328            0 :                                 cl.set_attribute_string ("CCode", "free_function", free_function);
    1329              :                         }
    1330              : 
    1331           28 :                         current_data_type = null;
    1332              :                 }
    1333              :         }
    1334              :         
    1335         1149 :         private void parse_enum (IdlNodeEnum en_node, Symbol container, IdlModule module, bool is_flags) {
    1336          383 :                 weak IdlNode node = (IdlNode) en_node;
    1337          383 :                 string name = fix_type_name (node.name, container);
    1338          383 :                 bool existing = true;
    1339              : 
    1340          383 :                 var en = container.scope.lookup (name) as Enum;
    1341          383 :                 if (en == null) {
    1342          383 :                         en = new Enum (name, current_source_reference);
    1343          383 :                         en.access = SymbolAccessibility.PUBLIC;
    1344          383 :                         existing = false;
    1345              :                 } else {
    1346              :                         // ignore dummy enum values in -custom.vala files
    1347              :                         // they exist for syntactical reasons
    1348            0 :                         var dummy = (EnumValue) en.scope.lookup ("__DUMMY__");
    1349            0 :                         if (dummy != null) {
    1350            0 :                                 en.get_values ().remove (dummy);
    1351            0 :                                 en.scope.remove ("__DUMMY__");
    1352              :                         }
    1353              :                 }
    1354              : 
    1355          383 :                 if (en_node.gtype_name == null || en_node.gtype_name == "") {
    1356          114 :                         en.set_attribute_bool ("CCode", "has_type_id", false);
    1357              :                 }
    1358              :                 
    1359          383 :                 string common_prefix = null;
    1360              :                 
    1361         4945 :                 foreach (weak IdlNode value in en_node.values) {
    1362         2281 :                         var val_attributes = get_attributes (value.name);
    1363         2281 :                         bool is_hidden = false;
    1364         2281 :                         if (val_attributes != null) {
    1365           20 :                                 foreach (string attr in val_attributes) {
    1366            8 :                                         var nv = attr.split ("=", 2);
    1367            8 :                                         if (nv[0] == "hidden" && eval(nv[1]) == "1") {
    1368            8 :                                                 is_hidden = true;
    1369              :                                         }
    1370              :                                 }
    1371              :                         }
    1372              : 
    1373            4 :                         if (is_hidden) {
    1374            0 :                                 continue;
    1375              :                         }
    1376              : 
    1377         2281 :                         if (common_prefix == null) {
    1378          766 :                                 common_prefix = value.name;
    1379         2459 :                                 while (common_prefix.length > 0 && !common_prefix.has_suffix ("_")) {
    1380              :                                         // FIXME: could easily be made faster
    1381         2076 :                                         common_prefix = common_prefix.substring (0, common_prefix.length - 1);
    1382              :                                 }
    1383              :                         } else {
    1384         2372 :                                 while (!value.name.has_prefix (common_prefix)) {
    1385          474 :                                         common_prefix = common_prefix.substring (0, common_prefix.length - 1);
    1386              :                                 }
    1387              :                         }
    1388         2297 :                         while (common_prefix.length > 0 && (!common_prefix.has_suffix ("_") ||
    1389         2279 :                                (value.name.get_char (common_prefix.length).isdigit ()) && (value.name.length - common_prefix.length) <= 1)) {
    1390              :                                 // enum values may not consist solely of digits
    1391           16 :                                 common_prefix = common_prefix.substring (0, common_prefix.length - 1);
    1392              :                         }
    1393              :                 }
    1394              : 
    1395          383 :                 bool is_errordomain = false;
    1396              : 
    1397          383 :                 string cheader_filename = null;
    1398              : 
    1399          383 :                 var en_attributes = get_attributes (node.name);
    1400          383 :                 if (en_attributes != null) {
    1401           49 :                         foreach (string attr in en_attributes) {
    1402           17 :                                 var nv = attr.split ("=", 2);
    1403           17 :                                 if (nv[0] == "common_prefix") {
    1404            1 :                                         common_prefix = eval (nv[1]);
    1405           16 :                                 } else if (nv[0] == "cheader_filename") {
    1406            5 :                                         cheader_filename = eval (nv[1]);
    1407            5 :                                         en.set_attribute_string ("CCode", "cheader_filename", cheader_filename);
    1408           11 :                                 } else if (nv[0] == "hidden") {
    1409            0 :                                         if (eval (nv[1]) == "1") {
    1410            0 :                                                 return;
    1411              :                                         }
    1412           11 :                                 } else if (nv[0] == "deprecated") {
    1413            0 :                                         if (eval (nv[1]) == "1") {
    1414            0 :                                                 en.set_attribute_bool ("Version", "deprecated", true);
    1415              :                                         }
    1416           11 :                                 } else if (nv[0] == "default_value") {
    1417            0 :                                         en.set_attribute_string ("CCode", "default_value", eval (nv[1]));
    1418           11 :                                 } else if (nv[0] == "replacement") {
    1419            0 :                                         en.set_attribute_string ("Version", "replacement", eval (nv[1]));
    1420           11 :                                 } else if (nv[0] == "deprecated_since") {
    1421            0 :                                         en.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
    1422           11 :                                 } else if (nv[0] == "rename_to") {
    1423            0 :                                         en.name = eval (nv[1]);
    1424           11 :                                 } else if (nv[0] == "errordomain") {
    1425            7 :                                         if (eval (nv[1]) == "1") {
    1426           17 :                                                 is_errordomain = true;
    1427              :                                         }
    1428            4 :                                 } else if (nv[0] == "to_string") {
    1429            0 :                                         var return_type = new UnresolvedType ();
    1430            0 :                                         return_type.unresolved_symbol = new UnresolvedSymbol (null, "string");
    1431            0 :                                         return_type.value_owned = false;
    1432            0 :                                         var m = new Method ("to_string", return_type, current_source_reference);
    1433            0 :                                         m.access = SymbolAccessibility.PUBLIC;
    1434            0 :                                         m.set_attribute_string ("CCode", "cname", eval(nv[1]));
    1435            0 :                                         en.add_method (m);
    1436            4 :                                 } else if (nv[0] == "experimental") {
    1437            0 :                                         if (eval (nv[1]) == "1") {
    1438            0 :                                                 en.set_attribute_bool ("Version", "experimental", true);
    1439              :                                         }
    1440              :                                 }
    1441              :                         }
    1442              :                 }
    1443              : 
    1444          383 :                 en.set_attribute_string ("CCode", "cprefix", common_prefix);
    1445              :                 
    1446         4945 :                 foreach (weak IdlNode value2 in en_node.values) {
    1447         2281 :                         EnumValue ev = new EnumValue (value2.name.substring (common_prefix.length), null);
    1448              : 
    1449         2281 :                         var val_attributes = get_attributes (value2.name);
    1450         2281 :                         bool is_hidden = false;
    1451         2281 :                         if (val_attributes != null) {
    1452           28 :                                 foreach (string attr in val_attributes) {
    1453            8 :                                         var nv = attr.split ("=", 2);
    1454            8 :                                         if (nv[0] == "hidden" && eval(nv[1]) == "1") {
    1455              :                                                 is_hidden = true;
    1456            8 :                                         } else if (nv[0] == "deprecated") {
    1457            0 :                                                 if (eval (nv[1]) == "1") {
    1458            0 :                                                         ev.set_attribute_bool ("Version", "deprecated", true);
    1459              :                                                 }
    1460            8 :                                         }  else if (nv[0] == "replacement") {
    1461            0 :                                                 ev.set_attribute_string ("Version", "replacement", eval (nv[1]));
    1462            8 :                                         } else if (nv[0] == "deprecated_since") {
    1463            0 :                                                 ev.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
    1464              :                                         }
    1465              :                                 }
    1466              :                         }
    1467              : 
    1468            4 :                         if (!is_hidden) {
    1469         2281 :                                 en.add_value (ev);
    1470              :                         }
    1471              :                 }
    1472              : 
    1473          390 :                 if (is_errordomain) {
    1474            7 :                         var ed = new ErrorDomain (en.name, current_source_reference);
    1475            7 :                         ed.access = SymbolAccessibility.PUBLIC;
    1476            7 :                         ed.set_attribute_string ("CCode", "cprefix", common_prefix);
    1477              : 
    1478            7 :                         if (cheader_filename != null) {
    1479            0 :                                 ed.set_attribute_string ("CCode", "cheader_filename", cheader_filename);
    1480              :                         }
    1481              : 
    1482           71 :                         foreach (EnumValue ev in en.get_values ()) {
    1483           32 :                                 ed.add_code (new ErrorCode (ev.name));
    1484              :                         }
    1485              : 
    1486            7 :                         current_source_file.add_node (ed);
    1487            7 :                         if (!existing) {
    1488            7 :                                 add_symbol_to_container (container, ed);
    1489              :                         }
    1490              :                 } else {
    1491          376 :                         en.set_attribute ("Flags", is_flags);
    1492          376 :                         current_source_file.add_node (en);
    1493          376 :                         if (!existing) {
    1494          376 :                                 add_symbol_to_container (container, en);
    1495              :                         }
    1496              :                 }
    1497              :         }
    1498              :         
    1499          602 :         private void parse_object (IdlNodeInterface node, Symbol container, IdlModule module) {
    1500          301 :                 string name = fix_type_name (((IdlNode) node).name, container);
    1501              : 
    1502          301 :                 string base_class = null;
    1503              : 
    1504          301 :                 var cl = container.scope.lookup (name) as Class;
    1505          532 :                 if (cl == null) {
    1506          266 :                         cl = new Class (name, current_source_reference);
    1507          266 :                         cl.access = SymbolAccessibility.PUBLIC;
    1508              :                         
    1509          266 :                         var attributes = get_attributes (node.gtype_name);
    1510          266 :                         if (attributes != null) {
    1511          118 :                                 foreach (string attr in attributes) {
    1512           30 :                                         var nv = attr.split ("=", 2);
    1513           30 :                                         if (nv[0] == "cheader_filename") {
    1514           20 :                                                 cl.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
    1515           10 :                                         } else if (nv[0] == "base_class") {
    1516            1 :                                                 base_class = eval (nv[1]);
    1517            9 :                                         } else if (nv[0] == "hidden") {
    1518            0 :                                                 if (eval (nv[1]) == "1") {
    1519            0 :                                                         return;
    1520              :                                                 }
    1521            9 :                                         } else if (nv[0] == "type_check_function") {
    1522            3 :                                                 cl.set_attribute_string ("CCode", "type_check_function", eval (nv[1]));
    1523            6 :                                         } else if (nv[0] == "deprecated") {
    1524            2 :                                                 if (eval (nv[1]) == "1") {
    1525            2 :                                                         cl.set_attribute_bool ("Version", "deprecated", true);
    1526              :                                                 }
    1527            4 :                                         } else if (nv[0] == "replacement") {
    1528            0 :                                                 cl.set_attribute_string ("Version", "replacement", eval (nv[1]));
    1529            4 :                                         } else if (nv[0] == "deprecated_since") {
    1530            2 :                                                 cl.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
    1531            2 :                                         } else if (nv[0] == "type_id") {
    1532            0 :                                                 cl.set_attribute_string ("CCode", "type_id", eval (nv[1]));
    1533            2 :                                         } else if (nv[0] == "abstract") {
    1534            2 :                                                 if (eval (nv[1]) == "1") {
    1535            2 :                                                         cl.is_abstract = true;
    1536              :                                                 }
    1537            0 :                                         } else if (nv[0] == "experimental") {
    1538            0 :                                                 if (eval (nv[1]) == "1") {
    1539            0 :                                                         cl.set_attribute_bool ("Version", "experimental", true);
    1540              :                                                 }
    1541            0 :                                         } else if (nv[0] == "compact") {
    1542            0 :                                                 if (eval (nv[1]) == "1") {
    1543            0 :                                                         cl.set_attribute ("Compact", true);
    1544              :                                                 }
    1545            0 :                                         } else if (nv[0] == "ref_function") {
    1546            0 :                                                 cl.set_attribute_string ("CCode", "ref_function", eval (nv[1]));
    1547            0 :                                         } else if (nv[0] == "unref_function") {
    1548            0 :                                                 cl.set_attribute_string ("CCode", "unref_function", eval (nv[1]));
    1549            0 :                                         } else if (nv[0] == "copy_function") {
    1550            0 :                                                 cl.set_attribute_string ("CCode", "copy_function", eval (nv[1]));
    1551            0 :                                         } else if (nv[0] == "free_function") {
    1552            0 :                                                 cl.set_attribute_string ("CCode", "free_function", eval (nv[1]));
    1553              :                                         }
    1554              :                                 }
    1555              :                         }
    1556              : 
    1557          266 :                         add_symbol_to_container (container, cl);
    1558          266 :                         current_source_file.add_node (cl);
    1559              :                 }
    1560              : 
    1561          302 :                 if (base_class != null) {
    1562            1 :                         var parent = parse_type_string (base_class);
    1563            1 :                         cl.add_base_type (parent);
    1564          300 :                 } else if (node.parent != null) {
    1565          600 :                         if (!cl.is_compact) {
    1566          300 :                                 var parent = parse_type_string (node.parent);
    1567          300 :                                 cl.add_base_type (parent);
    1568              :                         }
    1569              :                 } else {
    1570            0 :                         var gobject_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "Object");
    1571            0 :                         cl.add_base_type (new UnresolvedType.from_symbol (gobject_symbol));
    1572              :                 }
    1573              :                 
    1574         1522 :                 foreach (string iface_name in node.interfaces) {
    1575          407 :                         bool skip_iface = false;
    1576              : 
    1577          407 :                         var attributes = get_attributes (iface_name);
    1578          407 :                         if (attributes != null) {
    1579            6 :                                 foreach (string attr in attributes) {
    1580            2 :                                         var nv = attr.split ("=", 2);
    1581            2 :                                         if (nv[0] == "hidden") {
    1582            0 :                                                 if (eval (nv[1]) == "1") {
    1583            2 :                                                         skip_iface = true;
    1584              :                                                 }
    1585              :                                         }
    1586              :                                 }
    1587              :                         }
    1588              : 
    1589            2 :                         if (skip_iface) {
    1590            0 :                                 continue;
    1591              :                         }
    1592              : 
    1593          407 :                         var iface = parse_type_string (iface_name);
    1594          407 :                         cl.add_base_type (iface);
    1595              :                 }
    1596              :                 
    1597          602 :                 current_data_type = cl;
    1598              :                 
    1599          301 :                 current_type_symbol_set = new HashSet<string> (str_hash, str_equal);
    1600          301 :                 var current_type_func_map = new HashMap<string,weak IdlNodeFunction> (str_hash, str_equal);
    1601          301 :                 var current_type_vfunc_map = new HashMap<string,string> (str_hash, str_equal);
    1602              :                 
    1603         7270 :                 foreach (weak IdlNode member in node.members) {
    1604         6969 :                         if (member.type == IdlNodeTypeId.FUNCTION) {
    1605         3957 :                                 current_type_func_map.set (member.name, (IdlNodeFunction) member);
    1606              :                         }
    1607         6969 :                         if (member.type == IdlNodeTypeId.VFUNC) {
    1608          199 :                                 current_type_vfunc_map.set (member.name, "1");
    1609              :                         }
    1610              :                 }
    1611              : 
    1612         7270 :                 foreach (weak IdlNode member in node.members) {
    1613         6969 :                         if (member.type == IdlNodeTypeId.FUNCTION) {
    1614              :                                 // Ignore if vfunc (handled below) 
    1615         7708 :                                 if (!current_type_vfunc_map.contains (member.name)) {
    1616         3890 :                                         var m = parse_function ((IdlNodeFunction) member);
    1617         3890 :                                         if (m != null) {
    1618         3751 :                                                 cl.add_method (m);
    1619              :                                         }
    1620              :                                 }
    1621         3179 :                         } else if (member.type == IdlNodeTypeId.VFUNC) {
    1622          199 :                                 var m = parse_virtual ((IdlNodeVFunc) member, current_type_func_map.get (member.name));
    1623          199 :                                 if (m != null) {
    1624          167 :                                         cl.add_method (m);
    1625              :                                 }
    1626         4181 :                         } else if (member.type == IdlNodeTypeId.PROPERTY) {
    1627         1369 :                                 var prop = parse_property ((IdlNodeProperty) member);
    1628         1369 :                                 if (prop != null) {
    1629         1368 :                                         cl.add_property (prop);
    1630              :                                 }
    1631         1875 :                         } else if (member.type == IdlNodeTypeId.SIGNAL) {
    1632          434 :                                 var sig = parse_signal ((IdlNodeSignal) member);
    1633          434 :                                 if (sig != null) {
    1634          431 :                                         cl.add_signal (sig);
    1635              :                                 }
    1636              :                         }
    1637              :                 }
    1638              :                 
    1639         7270 :                 foreach (weak IdlNode member in node.members) {
    1640         6969 :                         if (member.type == IdlNodeTypeId.FIELD) {
    1641         1684 :                                 if (!current_type_symbol_set.contains (member.name)) {
    1642          731 :                                         var f = parse_field ((IdlNodeField) member);
    1643          731 :                                         if (f != null) {
    1644          674 :                                                 cl.add_field (f);
    1645              :                                         }
    1646              :                                 }
    1647              :                         }
    1648              :                 }
    1649              :                 
    1650         3037 :                 foreach (Property prop in cl.get_properties ()) {
    1651         1368 :                         var getter = "get_%s".printf (prop.name);
    1652              :                         
    1653         1368 :                         if (prop.get_accessor != null && !current_type_symbol_set.contains (getter)) {
    1654          744 :                                 prop.set_attribute ("NoAccessorMethod", true);
    1655              :                         }
    1656              :                         
    1657         1368 :                         var setter = "set_%s".printf (prop.name);
    1658              :                         
    1659         1368 :                         if (prop.set_accessor != null && prop.set_accessor.writable
    1660         1188 :                             && !current_type_symbol_set.contains (setter)) {
    1661          680 :                                 prop.set_attribute ("NoAccessorMethod", true);
    1662              :                         }
    1663              : 
    1664         1368 :                         if (prop.has_attribute ("NoAccessorMethod") && prop.get_accessor != null) {
    1665          768 :                                 prop.get_accessor.value_type.value_owned = true;
    1666              :                         }
    1667              :                 }
    1668              : 
    1669          301 :                 handle_async_methods (cl);
    1670              : 
    1671          394 :                 if (cl.default_construction_method == null) {
    1672              :                         // always provide constructor in generated bindings
    1673              :                         // to indicate that implicit Object () chainup is allowed
    1674           93 :                         var cm = new CreationMethod (null, null, cl.source_reference);
    1675           93 :                         cm.has_construct_function = false;
    1676           93 :                         cm.access = SymbolAccessibility.PROTECTED;
    1677           93 :                         cl.add_method (cm);
    1678              :                 }
    1679              : 
    1680          301 :                 current_data_type = null;
    1681          301 :                 current_type_symbol_set = null;
    1682              :         }
    1683              : 
    1684           46 :         private void parse_interface (IdlNodeInterface node, Symbol container, IdlModule module) {
    1685           23 :                 string name = fix_type_name (node.gtype_name, container);
    1686              : 
    1687           23 :                 var iface = container.scope.lookup (name) as Interface;
    1688           34 :                 if (iface == null) {
    1689           17 :                         iface = new Interface (name, current_source_reference);
    1690           17 :                         iface.access = SymbolAccessibility.PUBLIC;
    1691              :                         
    1692           17 :                         var attributes = get_attributes (node.gtype_name);
    1693           17 :                         if (attributes != null) {
    1694            8 :                                 foreach (string attr in attributes) {
    1695            2 :                                         var nv = attr.split ("=", 2);
    1696            2 :                                         if (nv[0] == "cheader_filename") {
    1697            2 :                                                 iface.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
    1698            0 :                                         } else if (nv[0] == "hidden") {
    1699            0 :                                                 if (eval (nv[1]) == "1") {
    1700            0 :                                                         return;
    1701              :                                                 }
    1702            0 :                                         } else if (nv[0] == "type_cname") {
    1703            0 :                                                 iface.set_attribute_string ("CCode", "type_cname", eval (nv[1]));
    1704            0 :                                         } else if (nv[0] == "lower_case_csuffix") {
    1705            0 :                                                 iface.set_attribute_string ("CCode", "lower_case_csuffix", eval (nv[1]));
    1706              :                                         }
    1707              :                                 }
    1708              :                         }
    1709              :                         
    1710           49 :                         foreach (string prereq_name in node.prerequisites) {
    1711           16 :                                 var prereq = parse_type_string (prereq_name);
    1712           16 :                                 iface.add_prerequisite (prereq);
    1713              :                         }
    1714              : 
    1715           17 :                         add_symbol_to_container (container, iface);
    1716           17 :                         current_source_file.add_node (iface);
    1717              :                 }
    1718              : 
    1719           23 :                 current_data_type = iface;
    1720              : 
    1721           23 :                 current_type_symbol_set = new HashSet<string> (str_hash, str_equal);
    1722           23 :                 var current_type_func_map = new HashMap<string,weak IdlNodeFunction> (str_hash, str_equal);
    1723           23 :                 var current_type_vfunc_map = new HashMap<string,string> (str_hash, str_equal);
    1724              : 
    1725          561 :                 foreach (weak IdlNode member in node.members) {
    1726          538 :                         if (member.type == IdlNodeTypeId.FUNCTION) {
    1727          301 :                                 current_type_func_map.set (member.name, (IdlNodeFunction) member);
    1728              :                         }
    1729          538 :                         if (member.type == IdlNodeTypeId.VFUNC) {
    1730          150 :                                 current_type_vfunc_map.set (member.name, "1");
    1731              :                         }
    1732              :                 }
    1733              : 
    1734          561 :                 foreach (weak IdlNode member in node.members) {
    1735          538 :                         if (member.type == IdlNodeTypeId.FUNCTION) {
    1736              :                                 // Ignore if vfunc (handled below) 
    1737          433 :                                 if (!current_type_vfunc_map.contains (member.name)) {
    1738          157 :                                         var m = parse_function ((IdlNodeFunction) member, true);
    1739          157 :                                         if (m != null) {
    1740          132 :                                                 iface.add_method (m);
    1741              :                                         }
    1742              :                                 }
    1743          385 :                         } else if (member.type == IdlNodeTypeId.VFUNC) {
    1744          150 :                                 var m = parse_virtual ((IdlNodeVFunc) member, current_type_func_map.get (member.name), true);
    1745          150 :                                 if (m != null) {
    1746          148 :                                         iface.add_method (m);
    1747              :                                 }
    1748          131 :                         } else if (member.type == IdlNodeTypeId.PROPERTY) {
    1749           44 :                                 var prop = parse_property ((IdlNodeProperty) member);
    1750           44 :                                 if (prop != null) {
    1751           44 :                                         iface.add_property (prop);
    1752              :                                 }
    1753           86 :                         } else if (member.type == IdlNodeTypeId.SIGNAL) {
    1754           43 :                                 var sig = parse_signal ((IdlNodeSignal) member);
    1755           43 :                                 if (sig != null) {
    1756           43 :                                         iface.add_signal (sig);
    1757           43 :                                         sig.is_virtual = false;
    1758              :                                 }
    1759              :                         }
    1760              :                 }
    1761              : 
    1762          111 :                 foreach (Property prop in iface.get_properties ()) {
    1763           44 :                         var getter = "get_%s".printf (prop.name);
    1764              : 
    1765           44 :                         if (prop.get_accessor != null && !current_type_symbol_set.contains (getter)) {
    1766           15 :                                 prop.set_attribute ("NoAccessorMethod", true);
    1767              :                         }
    1768              : 
    1769           44 :                         var setter = "set_%s".printf (prop.name);
    1770              : 
    1771           44 :                         if (prop.set_accessor != null && prop.set_accessor.writable
    1772           42 :                             && !current_type_symbol_set.contains (setter)) {
    1773           15 :                                 prop.set_attribute ("NoAccessorMethod", true);
    1774              :                         }
    1775              : 
    1776           44 :                         if (prop.has_attribute ("NoAccessorMethod") && prop.get_accessor != null) {
    1777           15 :                                 prop.get_accessor.value_type.value_owned = true;
    1778              :                         }
    1779              :                 }
    1780              : 
    1781           23 :                 handle_async_methods (iface);
    1782              : 
    1783           23 :                 current_data_type = null;
    1784              :         }
    1785              : 
    1786          648 :         void handle_async_methods (ObjectTypeSymbol type_symbol) {
    1787          324 :                 Set<Method> finish_methods = new HashSet<Method> ();
    1788          324 :                 var methods = type_symbol.get_methods ();
    1789              : 
    1790         8902 :                 foreach (Method m in methods) {
    1791         4291 :                         if (m.coroutine) {
    1792              :                                 string finish_method_base;
    1793            2 :                                 if (m.name.has_suffix ("_async")) {
    1794            2 :                                         finish_method_base = m.name.substring (0, m.name.length - "_async".length);
    1795              :                                 } else {
    1796            0 :                                         finish_method_base = m.name;
    1797              :                                 }
    1798            2 :                                 var finish_method = type_symbol.scope.lookup (finish_method_base + "_finish") as Method;
    1799              : 
    1800              :                                 // check if the method is using non-standard finish method name
    1801            2 :                                 if (finish_method == null) {
    1802            0 :                                         var method_cname = get_finish_cname (m);
    1803            0 :                                         foreach (Method method in type_symbol.get_methods ()) {
    1804            0 :                                                 if (get_cname (method) == method_cname) {
    1805            0 :                                                         finish_method = method;
    1806            0 :                                                         break;
    1807              :                                                 }
    1808              :                                         }
    1809              :                                 }
    1810              : 
    1811            4 :                                 if (finish_method != null) {
    1812            2 :                                         m.return_type = finish_method.return_type.copy ();
    1813            2 :                                         var a = finish_method.get_attribute ("CCode");
    1814            0 :                                         if (a != null && a.has_argument ("array_length")) {
    1815            0 :                                                 m.set_attribute_bool ("CCode", "array_length", a.get_bool ("array_length"));
    1816              :                                         }
    1817            2 :                                         if (a != null && a.has_argument ("array_null_terminated")) {
    1818            0 :                                                 m.set_attribute_bool ("CCode", "array_null_terminated", a.get_bool ("array_null_terminated"));
    1819              :                                         }
    1820            6 :                                         foreach (var param in finish_method.get_parameters ()) {
    1821            2 :                                                 if (param.direction == ParameterDirection.OUT) {
    1822            0 :                                                         var async_param = param.copy ();
    1823            0 :                                                         if (m.scope.lookup (param.name) != null) {
    1824              :                                                                 // parameter name conflict
    1825            0 :                                                                 async_param.name += "_out";
    1826              :                                                         }
    1827            0 :                                                         m.add_parameter (async_param);
    1828              :                                                 }
    1829              :                                         }
    1830            2 :                                         var error_types = new ArrayList<DataType> ();
    1831            2 :                                         finish_method.get_error_types (error_types, m.source_reference);
    1832            6 :                                         foreach (DataType error_type in error_types) {
    1833            2 :                                                 m.add_error_type (error_type);
    1834              :                                         }
    1835            2 :                                         finish_methods.add (finish_method);
    1836              :                                 }
    1837              :                         }
    1838              :                 }
    1839              : 
    1840          652 :                 foreach (Method m in finish_methods)
    1841              :                 {
    1842            2 :                         type_symbol.scope.remove (m.name);
    1843            2 :                         methods.remove (m);
    1844              :                 }
    1845              :         }
    1846              :         
    1847        25673 :         private DataType? parse_type (IdlNodeType type_node, out ParameterDirection direction = null) {
    1848        25673 :                 direction = ParameterDirection.IN;
    1849              : 
    1850        25673 :                 var type = new UnresolvedType ();
    1851        25673 :                 if (type_node.tag == TypeTag.VOID) {
    1852         4611 :                         if (type_node.is_pointer) {
    1853          718 :                                 return new PointerType (new VoidType ());
    1854              :                         } else {
    1855         3893 :                                 return new VoidType ();
    1856              :                         }
    1857              :                 } else if (type_node.tag == TypeTag.BOOLEAN) {
    1858         2300 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "bool");
    1859              :                 } else if (type_node.tag == TypeTag.INT8) {
    1860           21 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "char");
    1861              :                 } else if (type_node.tag == TypeTag.UINT8) {
    1862           30 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "uchar");
    1863              :                 } else if (type_node.tag == TypeTag.INT16) {
    1864            4 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "int16");
    1865              :                 } else if (type_node.tag == TypeTag.UINT16) {
    1866           53 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "uint16");
    1867              :                 } else if (type_node.tag == TypeTag.INT32) {
    1868            0 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "int32");
    1869              :                 } else if (type_node.tag == TypeTag.UINT32) {
    1870           90 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "uint32");
    1871              :                 } else if (type_node.tag == TypeTag.INT64) {
    1872            5 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "int64");
    1873              :                 } else if (type_node.tag == TypeTag.UINT64) {
    1874            4 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "uint64");
    1875              :                 } else if (type_node.tag == TypeTag.INT) {
    1876         4356 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "int");
    1877              :                 } else if (type_node.tag == TypeTag.UINT) {
    1878          734 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "uint");
    1879              :                 } else if (type_node.tag == TypeTag.LONG) {
    1880            7 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "long");
    1881              :                 } else if (type_node.tag == TypeTag.ULONG) {
    1882           39 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "ulong");
    1883              :                 } else if (type_node.tag == TypeTag.SSIZE) {
    1884           19 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "ssize_t");
    1885              :                 } else if (type_node.tag == TypeTag.SIZE) {
    1886          114 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "size_t");
    1887              :                 } else if (type_node.tag == TypeTag.FLOAT) {
    1888          266 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "float");
    1889              :                 } else if (type_node.tag == TypeTag.DOUBLE) {
    1890          514 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "double");
    1891              :                 } else if (type_node.tag == TypeTag.UTF8) {
    1892         1737 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "string");
    1893              :                 } else if (type_node.tag == TypeTag.FILENAME) {
    1894            0 :                         type.unresolved_symbol = new UnresolvedSymbol (null, "string");
    1895              :                 } else if (type_node.tag == TypeTag.ARRAY) {
    1896           72 :                         var element_type = parse_type (type_node.parameter_type1);
    1897          144 :                         type = element_type as UnresolvedType;
    1898           72 :                         if (type == null) {
    1899            0 :                                 return element_type;
    1900              :                         }
    1901           72 :                         element_type.value_owned = true;
    1902           72 :                         return new ArrayType (element_type, 1, element_type.source_reference);
    1903              :                 } else if (type_node.tag == TypeTag.LIST) {
    1904          315 :                         type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "List");
    1905              :                 } else if (type_node.tag == TypeTag.SLIST) {
    1906           87 :                         type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "SList");
    1907              :                 } else if (type_node.tag == TypeTag.HASH) {
    1908           34 :                         type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "HashTable");
    1909              :                 } else if (type_node.tag == TypeTag.ERROR) {
    1910          182 :                         type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "Error");
    1911        10079 :                 } else if (type_node.unparsed.has_prefix ("cairo_device_t") || type_node.unparsed.has_prefix ("cairo_pattern_t") ||
    1912        10078 :                     type_node.unparsed.has_prefix ("cairo_surface_t")) {
    1913            6 :                         if (type_node.unparsed.has_prefix ("cairo_device_t")) {
    1914            0 :                                 type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "Cairo"), "Device");
    1915            6 :                         } else if (type_node.unparsed.has_prefix ("cairo_pattern_t")) {
    1916            1 :                                 type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "Cairo"), "Pattern");
    1917            5 :                         } else if (type_node.unparsed.has_prefix ("cairo_surface_t")) {
    1918            5 :                                 type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "Cairo"), "Surface");
    1919              :                         }
    1920            6 :                         if (type_node.unparsed.has_suffix ("**")) {
    1921        20807 :                                 direction = ParameterDirection.OUT;
    1922              :                         }
    1923        10073 :                 } else if (type_node.is_interface) {
    1924        10073 :                         var n = type_node.@interface;
    1925              :                         
    1926        10073 :                         if (n == "") {
    1927            0 :                                 return null;
    1928              :                         }
    1929              :                         
    1930        10073 :                         if (n.has_prefix ("const-")) {
    1931            0 :                                 n = n.substring ("const-".length);
    1932              :                         }
    1933              : 
    1934        10073 :                         if (type_node.is_pointer &&
    1935         7212 :                             (n == "gchar" || n == "char")) {
    1936         2182 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "string");
    1937         2182 :                                 if (type_node.unparsed.has_suffix ("**")) {
    1938         9890 :                                         direction = ParameterDirection.OUT;
    1939              :                                 }
    1940         7891 :                         } else if (n == "gunichar") {
    1941            5 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "unichar");
    1942         7886 :                         } else if (n == "gchar") {
    1943            3 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "char");
    1944         7883 :                         } else if (n == "guchar" || n == "guint8") {
    1945           56 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "uchar");
    1946           56 :                                 if (type_node.is_pointer) {
    1947           50 :                                         type.value_owned = true;
    1948           50 :                                         return new ArrayType (type, 1, type.source_reference);
    1949              :                                 }
    1950         7827 :                         } else if (n == "gushort") {
    1951            1 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "ushort");
    1952         7826 :                         } else if (n == "gshort") {
    1953            3 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "short");
    1954         7823 :                         } else if (n == "gconstpointer" || n == "void") {
    1955           42 :                                 return new PointerType (new VoidType ());
    1956         7781 :                         } else if (n == "goffset" || n == "off_t") {
    1957            0 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "int64");
    1958         7781 :                         } else if (n == "value_array") {
    1959            0 :                                 type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "ValueArray");
    1960         7781 :                         } else if (n == "time_t") {
    1961           53 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "time_t");
    1962         7728 :                         } else if (n == "socklen_t") {
    1963            0 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "uint32");
    1964         7728 :                         } else if (n == "mode_t") {
    1965            0 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "uint");
    1966         7728 :                         } else if (n == "gint" || n == "pid_t") {
    1967            2 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "int");
    1968         7726 :                         } else if (n == "unsigned" || n == "unsigned-int") {
    1969           92 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "uint");
    1970         7634 :                         } else if (n == "FILE") {
    1971            4 :                                 type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "FileStream");
    1972         7630 :                         } else if (n == "struct") {
    1973           19 :                                 return new PointerType (new VoidType ());
    1974         7611 :                         } else if (n == "iconv_t") {
    1975            0 :                                 return new PointerType (new VoidType ());
    1976         7611 :                         } else if (n == "GType") {
    1977           71 :                                 type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), "Type");
    1978           71 :                                 if (type_node.is_pointer) {
    1979            8 :                                         type.value_owned = true;
    1980            8 :                                         return new ArrayType (type, 1, type.source_reference);
    1981              :                                 }
    1982        15016 :                         } else if (n == "GStrv") {
    1983            9 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, "string");
    1984            9 :                                 type.value_owned = true;
    1985            9 :                                 return new ArrayType (type, 1, type.source_reference);
    1986              :                         } else {
    1987         7531 :                                 var named_type = parse_type_string (n);
    1988        15007 :                                 type = named_type as UnresolvedType;
    1989         7531 :                                 if (type == null) {
    1990           55 :                                         return named_type;
    1991              :                                 }
    1992         7476 :                                 if (is_simple_type (n)) {
    1993          129 :                                         if (type_node.is_pointer) {
    1994          117 :                                                 direction = ParameterDirection.OUT;
    1995              :                                         }
    1996         7347 :                                 } else if (type_node.unparsed.has_suffix ("**")) {
    1997          117 :                                         direction = ParameterDirection.OUT;
    1998              :                                 }
    1999              :                         }
    2000              :                 } else {
    2001            0 :                         print ("%d\n", type_node.tag);
    2002              :                 }
    2003        20807 :                 return type;
    2004              :         }
    2005              :         
    2006         7476 :         private bool is_simple_type (string type_name) {
    2007         7476 :                 var st = cname_type_map[type_name] as Struct;
    2008          462 :                 if (st != null && st.is_simple_type ()) {
    2009          129 :                         return true;
    2010              :                 }
    2011              : 
    2012         7347 :                 return false;
    2013              :         }
    2014              : 
    2015         8260 :         private DataType parse_type_string (string n) {
    2016         8260 :                 if (n == "va_list") {
    2017              :                         // unsupported
    2018           54 :                         return new PointerType (new VoidType ());
    2019              :                 }
    2020              : 
    2021         8206 :                 var type = new UnresolvedType ();
    2022              : 
    2023         8206 :                 var dt = cname_type_map[n];
    2024         8206 :                 if (dt != null) {
    2025         3496 :                         UnresolvedSymbol parent_symbol = null;
    2026         3496 :                         if (dt.parent_symbol.name != null) {
    2027         3477 :                                 parent_symbol = new UnresolvedSymbol (null, dt.parent_symbol.name);
    2028              :                         }
    2029         3496 :                         type.unresolved_symbol = new UnresolvedSymbol (parent_symbol, dt.name);
    2030         3496 :                         return type;
    2031              :                 }
    2032              : 
    2033         4710 :                 var type_attributes = get_attributes (n);
    2034              : 
    2035         4710 :                 string ns_name = null;
    2036              : 
    2037         4710 :                 if (null != type_attributes) {
    2038         4099 :                         foreach (string attr in type_attributes) {
    2039         1105 :                                 var nv = attr.split ("=", 2);
    2040              : 
    2041         1105 :                                 if (nv[0] == "cprefix") {
    2042            0 :                                         type.unresolved_symbol = new UnresolvedSymbol (null, n.substring (eval (nv[1]).length));
    2043         1105 :                                 } else if (nv[0] == "name") {
    2044            1 :                                         type.unresolved_symbol = new UnresolvedSymbol (null, eval (nv[1]));
    2045         1104 :                                 } else if (nv[0] == "namespace") {
    2046            0 :                                         ns_name = eval (nv[1]);
    2047         1104 :                                 } else if (nv[0] == "rename_to") {
    2048            0 :                                         type.unresolved_symbol = new UnresolvedSymbol (null, eval (nv[1]));
    2049              :                                 }
    2050              :                         }
    2051              :                 }
    2052              : 
    2053         4710 :                 if (type.unresolved_symbol != null) {
    2054            1 :                         if (type.unresolved_symbol.name == "pointer") {
    2055            2 :                                 return new PointerType (new VoidType ());
    2056              :                         }
    2057            0 :                         if (ns_name != null) {
    2058            0 :                                 type.unresolved_symbol.inner = new UnresolvedSymbol (null, ns_name);
    2059              :                         }
    2060            0 :                         return type;
    2061              :                 }
    2062              : 
    2063         4709 :                 if (n.has_prefix (current_namespace.name)) {
    2064         4636 :                         type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, current_namespace.name), n.substring (current_namespace.name.length));
    2065           73 :                 } else if (current_namespace.parent_symbol != null && current_namespace.parent_symbol.name != null && n.has_prefix (current_namespace.parent_symbol.name)) {
    2066            9 :                         type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, current_namespace.parent_symbol.name), n.substring (current_namespace.parent_symbol.name.length));
    2067          114 :                 } else if (n.has_prefix ("G")) {
    2068           14 :                         type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, "GLib"), n.substring (1));
    2069              :                 } else {
    2070           50 :                         var name_parts = n.split (".", 2);
    2071           50 :                         if (name_parts[1] == null) {
    2072           50 :                                 type.unresolved_symbol = new UnresolvedSymbol (null, name_parts[0]);
    2073              :                         } else {
    2074            0 :                                 type.unresolved_symbol = new UnresolvedSymbol (new UnresolvedSymbol (null, name_parts[0]), name_parts[1]);
    2075              :                         }
    2076              :                 }
    2077              : 
    2078         4709 :                 return type;
    2079              :         }
    2080              :         
    2081        18964 :         private DataType? parse_param (IdlNodeParam param, out ParameterDirection direction = null) {
    2082        18964 :                 var type = parse_type (param.type, out direction);
    2083              : 
    2084              :                 // disable for now as null_ok not yet correctly set
    2085              :                 // type.non_null = !param.null_ok;
    2086              :                 
    2087        18964 :                 return type;
    2088              :         }
    2089              : 
    2090          189 :         private UnresolvedSymbol? parse_symbol_from_string (string symbol_string, SourceReference? source_reference = null) {
    2091          189 :                 UnresolvedSymbol? sym = null;
    2092          593 :                 foreach (unowned string s in symbol_string.split (".")) {
    2093          215 :                         sym = new UnresolvedSymbol (sym, s, source_reference);
    2094              :                 }
    2095          189 :                 if (sym == null) {
    2096            0 :                         Report.error (source_reference, "a symbol must be specified");
    2097              :                 }
    2098              :                 return sym;
    2099              :         }
    2100              : 
    2101           96 :         private bool parse_type_arguments_from_string (DataType parent_type, string type_arguments, SourceReference? source_reference = null) {
    2102           96 :                 int type_arguments_length = (int) type_arguments.length;
    2103           96 :                 GLib.StringBuilder current = new GLib.StringBuilder.sized (type_arguments_length);
    2104              : 
    2105           96 :                 int depth = 0;
    2106         1137 :                 for (var c = 0 ; c < type_arguments_length ; c++) {
    2107         1041 :                         if (type_arguments[c] == '<' || type_arguments[c] == '[') {
    2108            0 :                                 depth++;
    2109            0 :                                 current.append_unichar (type_arguments[c]);
    2110         1041 :                         } else if (type_arguments[c] == '>' || type_arguments[c] == ']') {
    2111            0 :                                 depth--;
    2112            0 :                                 current.append_unichar (type_arguments[c]);
    2113         1041 :                         } else if (type_arguments[c] == ',') {
    2114            2 :                                 if (depth == 0) {
    2115            1 :                                         var dt = parse_type_from_string (current.str, true, source_reference);
    2116            1 :                                         if (dt == null) {
    2117            0 :                                                 return false;
    2118              :                                         }
    2119            1 :                                         parent_type.add_type_argument (dt);
    2120            1 :                                         current.truncate ();
    2121              :                                 } else {
    2122            0 :                                         current.append_unichar (type_arguments[c]);
    2123              :                                 }
    2124              :                         } else {
    2125         1040 :                                 current.append_unichar (type_arguments[c]);
    2126              :                         }
    2127              :                 }
    2128              : 
    2129           96 :                 var dt = parse_type_from_string (current.str, true, source_reference);
    2130           96 :                 if (dt == null) {
    2131            0 :                         return false;
    2132              :                 }
    2133           96 :                 parent_type.add_type_argument (dt);
    2134              : 
    2135           96 :                 return true;
    2136              :         }
    2137              : 
    2138          189 :         private DataType? parse_type_from_string (string type_string, bool owned_by_default, SourceReference? source_reference = null) {
    2139          189 :                 if (type_from_string_regex == null) {
    2140            0 :                         try {
    2141           13 :                                 type_from_string_regex = new GLib.Regex ("^(?:(owned|unowned|weak) +)?([0-9a-zA-Z_\\.]+)(?:<(.+)>)?(\\*+)?(\\[(,*)?\\])?(\\?)?$", GLib.RegexCompileFlags.ANCHORED | GLib.RegexCompileFlags.DOLLAR_ENDONLY | GLib.RegexCompileFlags.OPTIMIZE);
    2142              :                         } catch (GLib.RegexError e) {
    2143            0 :                                 GLib.error ("Unable to compile regex: %s", e.message);
    2144              :                         }
    2145              :                 }
    2146              : 
    2147              :                 GLib.MatchInfo match;
    2148          189 :                 if (!type_from_string_regex.match (type_string, 0, out match)) {
    2149            0 :                         Report.error (source_reference, "unable to parse type");
    2150            0 :                         return null;
    2151              :                 }
    2152              : 
    2153          189 :                 DataType? type = null;
    2154              : 
    2155          189 :                 var ownership_data = match.fetch (1);
    2156          189 :                 var type_name = match.fetch (2);
    2157          189 :                 var type_arguments_data = match.fetch (3);
    2158          189 :                 var pointers_data = match.fetch (4);
    2159          189 :                 var array_data = match.fetch (5);
    2160          189 :                 var array_dimension_data = match.fetch (6);
    2161          189 :                 var nullable_data = match.fetch (7);
    2162              : 
    2163          189 :                 var nullable = nullable_data != null && nullable_data.length > 0;
    2164              : 
    2165          189 :                 if (ownership_data == null && type_name == "void") {
    2166            0 :                         if (array_data == null && !nullable) {
    2167            0 :                                 type = new VoidType (source_reference);
    2168            0 :                                 if (pointers_data != null) {
    2169            0 :                                         for (int i=0; i < pointers_data.length; i++) {
    2170            0 :                                                 type = new PointerType (type);
    2171              :                                         }
    2172              :                                 }
    2173            0 :                                 return type;
    2174              :                         } else {
    2175            0 :                                 Report.error (source_reference, "invalid void type");
    2176            0 :                                 return null;
    2177              :                         }
    2178              :                 }
    2179              : 
    2180          189 :                 bool value_owned = owned_by_default;
    2181              : 
    2182          189 :                 if (ownership_data == "owned") {
    2183              :                         value_owned = true;
    2184          189 :                 } else if (ownership_data == "unowned") {
    2185           25 :                         value_owned = false;
    2186              :                 }
    2187              : 
    2188          189 :                 var sym = parse_symbol_from_string (type_name, source_reference);
    2189          189 :                 if (sym == null) {
    2190            0 :                         return null;
    2191              :                 }
    2192          189 :                 type = new UnresolvedType.from_symbol (sym, source_reference);
    2193              : 
    2194          189 :                 if (type_arguments_data != null && type_arguments_data.length > 0) {
    2195            5 :                         if (!parse_type_arguments_from_string (type, type_arguments_data, source_reference)) {
    2196            0 :                                 return null;
    2197              :                         }
    2198              :                 }
    2199              : 
    2200          189 :                 if (pointers_data != null) {
    2201          191 :                         for (int i=0; i < pointers_data.length; i++) {
    2202            2 :                                 type = new PointerType (type);
    2203              :                         }
    2204              :                 }
    2205              : 
    2206          189 :                 if (array_data != null && array_data.length > 0) {
    2207            6 :                         type.value_owned = true;
    2208            6 :                         type = new ArrayType (type, array_dimension_data.length + 1, source_reference);
    2209              :                 }
    2210              : 
    2211          189 :                 type.nullable = nullable;
    2212          189 :                 type.value_owned = value_owned;
    2213          189 :                 return type;
    2214              :         }
    2215              : 
    2216         7911 :         private Method? create_method (string name, string symbol, IdlNodeParam? res, GLib.List<IdlNodeParam>? parameters, bool is_constructor, bool is_interface) {
    2217         7911 :                 DataType return_type = null;
    2218         7911 :                 if (res != null) {
    2219         7911 :                         return_type = parse_param (res);
    2220              :                 }
    2221              :                 
    2222              :                 Method m;
    2223         7911 :                 if (!is_interface && (is_constructor || name.has_prefix ("new"))) {
    2224          469 :                         m = new CreationMethod (null, name, current_source_reference);
    2225          469 :                         m.has_construct_function = false;
    2226          469 :                         if (m.name == "new") {
    2227          313 :                                 m.name = null;
    2228          156 :                         } else if (m.name.has_prefix ("new_")) {
    2229          153 :                                 m.name = m.name.substring ("new_".length);
    2230              :                         }
    2231              :                         // For classes, check whether a creation method return type equals to the
    2232              :                         // type of the class created. If the types do not match (e.g. in most
    2233              :                         // gtk widgets) add an attribute to the creation method indicating the used
    2234              :                         // return type.
    2235          469 :                         if (current_data_type is Class && res != null) {
    2236          464 :                                 if ("%s*".printf (get_cname (current_data_type)) != res.type.unparsed) {
    2237          249 :                                         m.set_attribute_string ("CCode", "type", res.type.unparsed);
    2238              :                                 }
    2239              :                         }
    2240              :                 } else {
    2241         7442 :                         m = new Method (name, return_type, current_source_reference);
    2242              :                 }
    2243         7911 :                 m.access = SymbolAccessibility.PUBLIC;
    2244              : 
    2245         7911 :                 if (current_type_symbol_set != null) {
    2246         4411 :                         current_type_symbol_set.add (name);
    2247              :                 }
    2248              :                 
    2249        20509 :                 if (current_data_type != null) {
    2250         6379 :                         var sig_attributes = get_attributes ("%s::%s".printf (get_cname (current_data_type), name));
    2251         6379 :                         if (sig_attributes != null) {
    2252          186 :                                 foreach (string attr in sig_attributes) {
    2253           87 :                                         var nv = attr.split ("=", 2);
    2254           87 :                                         if (nv[0] == "has_emitter" && eval (nv[1]) == "1") {
    2255          240 :                                                 return null;
    2256              :                                         }
    2257              :                                 }
    2258              :                         }
    2259              :                 }
    2260              :                 
    2261         7831 :                 bool add_ellipsis = false;
    2262         7831 :                 bool suppress_throws = false;
    2263         7831 :                 string? error_types = null;
    2264         7831 :                 Symbol? container = null;
    2265              : 
    2266         7831 :                 var attributes = get_attributes (symbol);
    2267         7831 :                 if (attributes != null) {
    2268         2283 :                         foreach (string attr in attributes) {
    2269          943 :                                 var nv = attr.split ("=", 2);
    2270          943 :                                 if (nv[0] == "name") {
    2271           15 :                                         m.name = eval (nv[1]);
    2272          928 :                                 } else if (nv[0] == "hidden") {
    2273          349 :                                         if (eval (nv[1]) == "1") {
    2274         1047 :                                                 return null;
    2275              :                                         }
    2276          579 :                                 } else if (nv[0] == "ellipsis") {
    2277           22 :                                         if (eval (nv[1]) == "1") {
    2278          594 :                                                 add_ellipsis = true;
    2279              :                                         }
    2280          557 :                                 } else if (nv[0] == "printf_format") {
    2281            4 :                                         if (eval (nv[1]) == "1") {
    2282            4 :                                                 m.set_attribute ("PrintfFormat", true);
    2283              :                                         }
    2284          553 :                                 } else if (nv[0] == "transfer_ownership") {
    2285          213 :                                         if (eval (nv[1]) == "1") {
    2286          211 :                                                 return_type.value_owned = true;
    2287              :                                         }
    2288          340 :                                 } else if (nv[0] == "transfer_container") {
    2289            1 :                                         if (eval (nv[1]) == "1") {
    2290            1 :                                                 return_type.value_owned = true;
    2291            1 :                                                 if (return_type is ArrayType) {
    2292            1 :                                                         ((ArrayType) return_type).element_type.value_owned = false;
    2293              :                                                 }
    2294              :                                         }
    2295          339 :                                 } else if (nv[0] == "destroys_instance") {
    2296            0 :                                         if (eval (nv[1]) == "1") {
    2297            0 :                                                 m.set_attribute ("DestroysInstance", true, m.source_reference);
    2298              :                                         }
    2299          339 :                                 } else if (nv[0] == "returns_floating_reference") {
    2300            0 :                                         if (eval (nv[1]) == "1") {
    2301            0 :                                                 m.set_attribute_bool ("CCode", "returns_floating_reference", true);
    2302            0 :                                                 m.return_type.value_owned = true;
    2303              :                                         }
    2304          339 :                                 } else if (nv[0] == "nullable") {
    2305           52 :                                         if (eval (nv[1]) == "1" && !(return_type is VoidType)) {
    2306           52 :                                                 return_type.nullable = true;
    2307              :                                         }
    2308          287 :                                 } else if (nv[0] == "sentinel") {
    2309            9 :                                         m.set_attribute_string ("CCode", "sentinel", eval (nv[1]));
    2310          278 :                                 } else if (nv[0] == "is_array") {
    2311           29 :                                         if (eval (nv[1]) == "1") {
    2312           29 :                                                 return_type.value_owned = true;
    2313           29 :                                                 return_type = new ArrayType (return_type, 1, return_type.source_reference);
    2314           29 :                                                 m.return_type = return_type;
    2315              :                                         }
    2316          249 :                                 } else if (nv[0] == "is_pointer") {
    2317            0 :                                         if (eval (nv[1]) == "1") {
    2318            0 :                                                 return_type = new PointerType (return_type, return_type.source_reference);
    2319            0 :                                                 m.return_type = return_type;
    2320              :                                         }
    2321          249 :                                 } else if (nv[0] == "throws") {
    2322            0 :                                         if (eval (nv[1]) == "0") {
    2323          594 :                                                 suppress_throws = true;
    2324              :                                         }
    2325          249 :                                 } else if (nv[0] == "error_types") {
    2326            0 :                                         error_types = eval (nv[1]);
    2327          249 :                                 } else if (nv[0] == "no_array_length") {
    2328           13 :                                         if (eval (nv[1]) == "1") {
    2329           13 :                                                 m.set_attribute_bool ("CCode", "array_length", false);
    2330              :                                         }
    2331          236 :                                 } else if (nv[0] == "array_null_terminated") {
    2332           16 :                                         if (eval (nv[1]) == "1") {
    2333           16 :                                                 m.set_attribute_bool ("CCode", "array_length", false);
    2334           16 :                                                 m.set_attribute_bool ("CCode", "array_null_terminated", true);;
    2335              :                                         }
    2336          220 :                                 } else if (nv[0] == "array_length_type") {
    2337            7 :                                         m.set_attribute_string ("CCode", "array_length_type", eval (nv[1]));
    2338          213 :                                 } else if (nv[0] == "type_name") {
    2339           17 :                                         m.return_type = return_type = parse_type_from_string (eval (nv[1]), return_type.value_owned);
    2340          196 :                                 } else if (nv[0] == "ctype") {
    2341            1 :                                         m.set_attribute_string ("CCode", "type", eval (nv[1]));
    2342          195 :                                 } else if (nv[0] == "type_arguments") {
    2343           58 :                                         parse_type_arguments_from_string (return_type, eval (nv[1]));
    2344          137 :                                 } else if (nv[0] == "deprecated") {
    2345           42 :                                         if (eval (nv[1]) == "1") {
    2346           42 :                                                 m.set_attribute_bool ("Version", "deprecated", true);
    2347              :                                         }
    2348           95 :                                 } else if (nv[0] == "replacement") {
    2349            1 :                                         m.set_attribute_string ("Version", "replacement", eval (nv[1]));
    2350           94 :                                 } else if (nv[0] == "deprecated_since") {
    2351           44 :                                         m.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
    2352           50 :                                 } else if (nv[0] == "cheader_filename") {
    2353            4 :                                         m.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
    2354           46 :                                 } else if (nv[0] == "abstract") {
    2355            2 :                                         if (eval (nv[1]) == "1") {
    2356            2 :                                                 m.is_abstract = true;
    2357              :                                         }
    2358           44 :                                 } else if (nv[0] == "virtual") {
    2359           21 :                                         if (eval (nv[1]) == "1") {
    2360           18 :                                                 m.is_virtual = true;
    2361              :                                         }
    2362           23 :                                 } else if (nv[0] == "vfunc_name") {
    2363            1 :                                         m.set_attribute_string ("CCode", "vfunc_name", eval (nv[1]));
    2364           22 :                                 } else if (nv[0] == "finish_vfunc_name") {
    2365            0 :                                         m.set_attribute_string ("CCode", "finish_vfunc_name", eval (nv[1]));
    2366           22 :                                 } else if (nv[0] == "finish_name") {
    2367            0 :                                         m.set_attribute_string ("CCode", "finish_name", eval (nv[1]));
    2368           22 :                                 } else if (nv[0] == "async") {
    2369            0 :                                         if (eval (nv[1]) == "1") {
    2370              :                                                 // force async function, even if it doesn't end in _async
    2371            0 :                                                 m.coroutine = true;
    2372              :                                         }
    2373           37 :                                 } else if (nv[0] == "parent") {
    2374           15 :                                         container = get_container_from_name (eval (nv[1]));
    2375           15 :                                         var prefix = get_lower_case_cprefix (container);
    2376           15 :                                         if (symbol.has_prefix (prefix)) {
    2377           15 :                                                 m.name = symbol.substring (prefix.length);
    2378              :                                         }
    2379            7 :                                 } else if (nv[0] == "experimental") {
    2380            0 :                                         if (eval (nv[1]) == "1") {
    2381            0 :                                                 m.set_attribute_bool ("Version", "experimental", true);
    2382              :                                         }
    2383            7 :                                 } else if (nv[0] == "simple_generics") {
    2384            0 :                                         if (eval (nv[1]) == "1") {
    2385            0 :                                                 m.set_attribute_bool ("CCode", "simple_generics", true);
    2386              :                                         }
    2387              :                                 }
    2388              :                         }
    2389              :                 }
    2390              :         
    2391         7482 :                 bool first = true;
    2392         7482 :                 Parameter last_param = null;
    2393         7482 :                 DataType last_param_type = null;
    2394        22341 :                 foreach (weak IdlNodeParam param in parameters) {
    2395        14859 :                         weak IdlNode param_node = (IdlNode) param;
    2396              :                         
    2397        14859 :                         if (first) {
    2398         6910 :                                 first = false;
    2399         6910 :                                 if (!(m is CreationMethod) &&
    2400         6608 :                                     current_data_type != null &&
    2401         5493 :                                     param.type.is_interface &&
    2402         5398 :                                     (param_node.name == "self" ||
    2403         5354 :                                      param.type.@interface.has_suffix (get_cname (current_data_type)))) {
    2404              :                                         // instance method
    2405         5346 :                                         continue;
    2406         1752 :                                 } else if (!(m is CreationMethod) &&
    2407         1450 :                                     current_data_type != null &&
    2408          335 :                                     param.type.is_interface &&
    2409          240 :                                     (param_node.name == "klass" ||
    2410          236 :                                      param.type.@interface.has_suffix ("%sClass".printf(get_cname (current_data_type))))) {
    2411              :                                         // class method
    2412            6 :                                         m.binding = MemberBinding.CLASS;
    2413            6 :                                         if (m.name.has_prefix ("class_")) {
    2414            5 :                                                 m.name = m.name.substring ("class_".length, m.name.length - "class_".length);
    2415              :                                         }
    2416            6 :                                         continue;
    2417         1746 :                                 } else if (!(m is CreationMethod)) {
    2418              :                                         // static method
    2419         1444 :                                         m.binding = MemberBinding.STATIC;
    2420              :                                 }
    2421              :                         }
    2422              : 
    2423         9695 :                         if (param.type.@interface == "GAsyncReadyCallback" && (symbol.has_suffix ("_async") || m.coroutine)) {
    2424              :                                 // async method
    2425            2 :                                 m.coroutine = true;
    2426            2 :                                 continue;
    2427              :                         }
    2428              : 
    2429              :                         // check for GError parameter
    2430         9693 :                         if (suppress_throws == false && param_is_exception (param)) {
    2431          180 :                                 if (error_types == null)
    2432          180 :                                         m.add_error_type (parse_type (param.type));
    2433          180 :                                 continue;
    2434              :                         }
    2435              : 
    2436         9513 :                         string param_name = param_node.name;
    2437         9513 :                         if (param_name == "result") {
    2438              :                                 // avoid conflict with generated result variable
    2439            7 :                                 param_name = "_result";
    2440         9506 :                         } else if (param_name == "string") {
    2441              :                                 // avoid conflict with string type
    2442           17 :                                 param_name = "str";
    2443              :                         }
    2444              :                         ParameterDirection direction;
    2445         9513 :                         var param_type = parse_param (param, out direction);
    2446         9513 :                         var p = new Parameter (param_name, param_type, current_source_reference);
    2447         9513 :                         p.direction = direction;
    2448              : 
    2449         9513 :                         bool hide_param = false;
    2450         9513 :                         bool show_param = false;
    2451         9513 :                         bool set_array_length_pos = false;
    2452         9513 :                         double array_length_pos = 0;
    2453         9513 :                         bool set_delegate_target_pos = false;
    2454         9513 :                         double delegate_target_pos = 0;
    2455         9513 :                         bool array_requested = false;
    2456         9513 :                         bool out_requested = false;
    2457        19026 :                         attributes = get_attributes ("%s.%s".printf (symbol, param_node.name));
    2458         9513 :                         if (attributes != null) {
    2459         3456 :                                 foreach (string attr in attributes) {
    2460         1212 :                                         var nv = attr.split ("=", 2);
    2461         1212 :                                         if (nv[0] == "is_array") {
    2462           68 :                                                 if (eval (nv[1]) == "1") {
    2463           68 :                                                         param_type.value_owned = true;
    2464           68 :                                                         param_type = new ArrayType (param_type, 1, param_type.source_reference);
    2465           68 :                                                         p.variable_type = param_type;
    2466           68 :                                                         if (!out_requested) {
    2467           65 :                                                                 p.direction = ParameterDirection.IN;
    2468              :                                                         }
    2469              :                                                         array_requested = true;
    2470              :                                                 }
    2471         1144 :                                         } else if (nv[0] == "is_pointer") {
    2472            0 :                                                 if (eval (nv[1]) == "1") {
    2473            0 :                                                         param_type = new PointerType (param_type, return_type.source_reference);
    2474            0 :                                                         p.variable_type = param_type;
    2475            0 :                                                         if (!out_requested) {
    2476            0 :                                                                 p.direction = ParameterDirection.IN;
    2477              :                                                         }
    2478              :                                                 }
    2479         1144 :                                         } else if (nv[0] == "is_out") {
    2480          350 :                                                 if (eval (nv[1]) == "1") {
    2481          350 :                                                         p.direction = ParameterDirection.OUT;
    2482          350 :                                                         out_requested = true;
    2483          351 :                                                         if (!array_requested && param_type is ArrayType) {
    2484            1 :                                                                 var array_type = (ArrayType) param_type;
    2485            2 :                                                                 param_type = array_type.element_type;
    2486            1 :                                                                 p.variable_type = param_type;
    2487              :                                                         }
    2488              :                                                 }
    2489          794 :                                         } else if (nv[0] == "is_ref") {
    2490           62 :                                                 if (eval (nv[1]) == "1") {
    2491           62 :                                                         p.direction = ParameterDirection.REF;
    2492           62 :                                                         if (!array_requested && param_type is ArrayType) {
    2493            0 :                                                                 var array_type = (ArrayType) param_type;
    2494            0 :                                                                 param_type = array_type.element_type;
    2495            0 :                                                                 p.variable_type = param_type;
    2496              :                                                         }
    2497              :                                                 }
    2498          732 :                                         } else if (nv[0] == "nullable") {
    2499          309 :                                                 if (eval (nv[1]) == "1" && !(param_type is VoidType)) {
    2500          309 :                                                         param_type.nullable = true;
    2501              :                                                 }
    2502          423 :                                         } else if (nv[0] == "transfer_ownership") {
    2503           69 :                                                 if (eval (nv[1]) == "1") {
    2504           68 :                                                         param_type.value_owned = true;
    2505              :                                                 }
    2506          354 :                                         } else if (nv[0] == "takes_ownership") {
    2507            2 :                                                 if (eval (nv[1]) == "1") {
    2508            2 :                                                         param_type.value_owned = true;
    2509              :                                                 }
    2510          352 :                                         } else if (nv[0] == "value_owned") {
    2511            5 :                                                 if (eval (nv[1]) == "0") {
    2512            0 :                                                         param_type.value_owned = false;
    2513            5 :                                                 } else if (eval (nv[1]) == "1") {
    2514            5 :                                                         param_type.value_owned = true;
    2515              :                                                 }
    2516          347 :                                         } else if (nv[0] == "hidden") {
    2517          151 :                                                 if (eval (nv[1]) == "1") {
    2518              :                                                         hide_param = true;
    2519            5 :                                                 } else if (eval (nv[1]) == "0") {
    2520         1212 :                                                         show_param = true;
    2521              :                                                 }
    2522          196 :                                         } else if (nv[0] == "no_array_length") {
    2523           37 :                                                 if (eval (nv[1]) == "1") {
    2524           37 :                                                         p.set_attribute_bool ("CCode", "array_length", false);
    2525              :                                                 }
    2526          159 :                                         } else if (nv[0] == "array_length_type") {
    2527            3 :                                                 p.set_attribute_string ("CCode", "array_length_type", eval (nv[1]));
    2528          156 :                                         } else if (nv[0] == "array_null_terminated") {
    2529           13 :                                                 if (eval (nv[1]) == "1") {
    2530           13 :                                                         p.set_attribute_bool ("CCode", "array_length", false);
    2531           13 :                                                         p.set_attribute_bool ("CCode", "array_null_terminated", true);
    2532              :                                                 }
    2533          143 :                                         } else if (nv[0] == "array_length_pos") {
    2534           33 :                                                 set_array_length_pos = true;
    2535           33 :                                                 array_length_pos = double.parse (eval (nv[1]));
    2536          110 :                                         } else if (nv[0] == "delegate_target_pos") {
    2537            0 :                                                 set_delegate_target_pos = true;
    2538            0 :                                                 delegate_target_pos = double.parse (eval (nv[1]));
    2539          110 :                                         } else if (nv[0] == "type_name") {
    2540           26 :                                                 p.variable_type = param_type = parse_type_from_string (eval (nv[1]), false);
    2541           84 :                                         } else if (nv[0] == "ctype") {
    2542            7 :                                                 p.set_attribute_string ("CCode", "type", eval (nv[1]));
    2543           77 :                                         } else if (nv[0] == "scope") {
    2544           10 :                                                 p.set_attribute_string ("CCode", "scope", eval (nv[1]));
    2545           67 :                                         } else if (nv[0] == "type_arguments") {
    2546           25 :                                                 parse_type_arguments_from_string (param_type, eval (nv[1]));
    2547           74 :                                         } else if (nv[0] == "default_value") {
    2548           32 :                                                 var val = eval (nv[1]);
    2549           32 :                                                 if (val == "null") {
    2550           17 :                                                         p.initializer = new NullLiteral (param_type.source_reference);
    2551           15 :                                                 } else if (val == "true") {
    2552            4 :                                                         p.initializer = new BooleanLiteral (true, param_type.source_reference);
    2553           11 :                                                 } else if (val == "false") {
    2554            1 :                                                         p.initializer = new BooleanLiteral (false, param_type.source_reference);
    2555           10 :                                                 } else if (val == "") {
    2556            0 :                                                         p.initializer = new StringLiteral ("\"\"", param_type.source_reference);
    2557              :                                                 } else {
    2558           10 :                                                         if (int64.try_parse (val)) {
    2559            6 :                                                                 p.initializer = new IntegerLiteral (val, param_type.source_reference);
    2560              :                                                         } else {
    2561            4 :                                                                 if (double.try_parse (val)) {
    2562            3 :                                                                         p.initializer = new RealLiteral (val, param_type.source_reference);
    2563              :                                                                 } else {
    2564            1 :                                                                         if (val.has_prefix ("\"") && val.has_suffix ("\"")) {
    2565            0 :                                                                                 p.initializer = new StringLiteral (val, param_type.source_reference);
    2566              :                                                                         } else {
    2567            5 :                                                                                 foreach (unowned string member in val.split (".")) {
    2568            3 :                                                                                         p.initializer = new MemberAccess (p.initializer, member, param_type.source_reference);
    2569              :                                                                                 }
    2570              :                                                                         }
    2571              :                                                                 }
    2572              :                                                         }
    2573              :                                                 }
    2574              :                                         }
    2575              :                                 }
    2576              :                         }
    2577              : 
    2578         9513 :                         if (last_param != null && p.name == "n_" + last_param.name) {
    2579           53 :                                 if (!(last_param_type is ArrayType)) {
    2580              :                                         // last_param is array, p is array length
    2581           41 :                                         last_param_type.value_owned = true;
    2582           41 :                                         last_param_type = new ArrayType (last_param_type, 1, last_param_type.source_reference);
    2583           41 :                                         last_param.variable_type = last_param_type;
    2584           41 :                                         last_param.direction = ParameterDirection.IN;
    2585              :                                 }
    2586              : 
    2587              :                                 // hide array length param
    2588              :                                 hide_param = true;
    2589         9460 :                         } else if (last_param != null && p.name == "user_data") {
    2590              :                                 // last_param is delegate
    2591              : 
    2592              :                                 // hide deleate target param
    2593           91 :                                 hide_param = true;
    2594              :                         }
    2595              : 
    2596         9513 :                         if (show_param || !hide_param) {
    2597         9229 :                                 m.add_parameter (p);
    2598         9229 :                                 if (set_array_length_pos) {
    2599           33 :                                         p.set_attribute_double ("CCode", "array_length_pos", array_length_pos);
    2600              :                                 }
    2601         9229 :                                 if (set_delegate_target_pos) {
    2602            0 :                                         p.set_attribute_double ("CCode", "delegate_target_pos", delegate_target_pos);
    2603              :                                 }
    2604              :                         }
    2605              : 
    2606        19026 :                         last_param = p;
    2607        19026 :                         last_param_type = param_type;
    2608              :                 }
    2609              : 
    2610         7482 :                 if (suppress_throws == false && error_types != null) {
    2611            0 :                         var type_args = eval (error_types).split (",");
    2612            0 :                         foreach (unowned string type_arg in type_args) {
    2613            0 :                                 m.add_error_type (parse_type_from_string (type_arg, true));
    2614              :                         }
    2615              :                 }
    2616              : 
    2617         7482 :                 if (first && !(m is CreationMethod)) {
    2618              :                         // no parameters => static method
    2619          439 :                         m.binding = MemberBinding.STATIC;
    2620              :                 }
    2621              : 
    2622         7482 :                 if (last_param != null && last_param.name.has_prefix ("first_")) {
    2623           24 :                         last_param.ellipsis = true;
    2624         7458 :                 } else if (add_ellipsis) {
    2625           21 :                         m.add_parameter (new Parameter.with_ellipsis (current_source_reference));
    2626              :                 }
    2627              : 
    2628         7482 :                 if (container == null) {
    2629         7467 :                         container = current_data_type;
    2630         7467 :                         if (container == null) {
    2631         1366 :                                 container = current_namespace;
    2632              :                         }
    2633              :                 }
    2634         7482 :                 if (symbol != get_cname (m, container)) {
    2635          131 :                         m.set_attribute_string ("CCode", "cname", symbol);
    2636              :                 }
    2637              :                 
    2638        14964 :                 return m;
    2639              :         }
    2640              : 
    2641        10134 :         private bool param_is_exception (IdlNodeParam param) {
    2642        10134 :                 if (!param.type.is_error) {
    2643         9953 :                         return false;
    2644              :                 }
    2645          182 :                 var s = param.type.unparsed.chomp ();
    2646          182 :                 if (s.has_suffix ("**")) {
    2647          181 :                         return true;
    2648              :                 }
    2649            1 :                 return false;
    2650              :         }
    2651              : 
    2652         7562 :         private Method? parse_function (IdlNodeFunction f, bool is_interface = false) {
    2653         7562 :                 weak IdlNode node = (IdlNode) f;
    2654              :                 
    2655         7562 :                 if (f.deprecated) {
    2656            0 :                         return null;
    2657              :                 }
    2658              :         
    2659         7562 :                 return create_method (node.name, f.symbol, f.result, f.parameters, f.is_constructor, is_interface);
    2660              :         }
    2661              : 
    2662          349 :         private Method parse_virtual (IdlNodeVFunc v, IdlNodeFunction? func, bool is_interface = false) {
    2663          349 :                 weak IdlNode node = (IdlNode) v;
    2664          349 :                 string symbol = "%s%s".printf (get_lower_case_cprefix (current_data_type), node.name);
    2665              : 
    2666          349 :                 if (func != null) {
    2667          422 :                         symbol = func.symbol;
    2668              :                 }
    2669              : 
    2670          349 :                 Method m = create_method (node.name, symbol, v.result, func != null ? func.parameters : v.parameters, false, is_interface);
    2671          979 :                 if (m != null) {
    2672          315 :                         m.binding = MemberBinding.INSTANCE;
    2673          315 :                         m.is_virtual = !(m.is_abstract || is_interface);
    2674          315 :                         m.is_abstract = m.is_abstract || is_interface;
    2675              : 
    2676          315 :                         var attributes = get_attributes (symbol);
    2677          315 :                         if (attributes != null) {
    2678          195 :                                 foreach (string attr in attributes) {
    2679           51 :                                         var nv = attr.split ("=", 2);
    2680           51 :                                         if (nv[0] == "virtual") {
    2681           20 :                                                 if (eval (nv[1]) == "0") {
    2682            3 :                                                         m.is_virtual = false;
    2683            3 :                                                         m.is_abstract = false;
    2684              :                                                 } else {
    2685           17 :                                                         m.is_virtual = true;
    2686           17 :                                                         m.is_abstract = false;
    2687              :                                                 }
    2688              :                                         }
    2689              :                                 }
    2690              :                         }
    2691              : 
    2692          315 :                         if (func == null) {
    2693          105 :                                 m.set_attribute ("NoWrapper", true);
    2694              :                         }
    2695              :                 }
    2696              : 
    2697          349 :                 return m;
    2698              :         }
    2699              :         
    2700         1890 :         private string fix_prop_name (string name) {
    2701         1890 :                 var str = new StringBuilder ();
    2702              :                 
    2703         1890 :                 string i = name;
    2704              :                 
    2705        23515 :                 while (i.length > 0) {
    2706        21625 :                         unichar c = i.get_char ();
    2707        21625 :                         if (c == '-') {
    2708         1714 :                                 str.append_c ('_');
    2709              :                         } else {
    2710        19911 :                                 str.append_unichar (c);
    2711              :                         }
    2712              :                         
    2713        43250 :                         i = i.next_char ();
    2714              :                 }
    2715              :                 
    2716         3780 :                 return str.str;
    2717              :         }
    2718              : 
    2719         1413 :         private Property? parse_property (IdlNodeProperty prop_node) {
    2720         1413 :                 weak IdlNode node = (IdlNode) prop_node;
    2721              :                 
    2722         1413 :                 if (prop_node.deprecated) {
    2723            1 :                         return null;
    2724              :                 }
    2725              :                 
    2726         1413 :                 if (!prop_node.readable && !prop_node.writable) {
    2727              :                         // buggy GIDL definition
    2728            0 :                         prop_node.readable = true;
    2729            0 :                         prop_node.writable = true;
    2730              :                 }
    2731              :                 
    2732         1413 :                 var prop = new Property (fix_prop_name (node.name), parse_type (prop_node.type), null, null, current_source_reference);
    2733         1413 :                 prop.access = SymbolAccessibility.PUBLIC;
    2734         1413 :                 prop.interface_only = true;
    2735              : 
    2736         1413 :                 if (prop_node.type.is_interface && prop_node.type.interface == "GStrv") {
    2737            9 :                         prop.set_attribute_bool ("CCode", "array_length", false);
    2738            9 :                         prop.set_attribute_bool ("CCode", "array_null_terminated", true);
    2739              :                 }
    2740              : 
    2741         1413 :                 if (prop_node.readable) {
    2742         1358 :                         prop.get_accessor = new PropertyAccessor (true, false, false, prop.property_type.copy (), null, null);
    2743              :                 }
    2744         1413 :                 if (prop_node.writable) {
    2745         1330 :                         if (prop_node.construct_only) {
    2746          100 :                                 prop.set_accessor = new PropertyAccessor (false, false, true, prop.property_type.copy (), null, null);
    2747              :                         } else {
    2748         1230 :                                 prop.set_accessor = new PropertyAccessor (false, true, prop_node.@construct, prop.property_type.copy (), null, null);
    2749              :                         }
    2750              :                 }
    2751              : 
    2752              :                 // there is no information about the internal ownership so assume `owned` as default
    2753         1413 :                 prop.property_type.value_owned = true;
    2754              : 
    2755         1413 :                 var attributes = get_attributes ("%s:%s".printf (get_cname (current_data_type), node.name));
    2756         1413 :                 if (attributes != null) {
    2757           62 :                         foreach (string attr in attributes) {
    2758           16 :                                 var nv = attr.split ("=", 2);
    2759           16 :                                 if (nv[0] == "hidden") {
    2760            1 :                                         if (eval (nv[1]) == "1") {
    2761            3 :                                                 return null;
    2762              :                                         }
    2763           15 :                                 } else if (nv[0] == "type_arguments") {
    2764            1 :                                         parse_type_arguments_from_string (prop.property_type, eval (nv[1]));
    2765           14 :                                 } else if (nv[0] == "deprecated") {
    2766            0 :                                         if (eval (nv[1]) == "1") {
    2767            0 :                                                 prop.set_attribute_bool ("Version", "deprecated", true);
    2768              :                                         }
    2769           14 :                                 } else if (nv[0] == "replacement") {
    2770            0 :                                         prop.set_attribute_string ("Version", "replacement", eval (nv[1]));
    2771           14 :                                 } else if (nv[0] == "deprecated_since") {
    2772            0 :                                         prop.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
    2773           14 :                                 } else if (nv[0] == "accessor_method") {
    2774            8 :                                         if (eval (nv[1]) == "0") {
    2775            8 :                                                 prop.set_attribute ("NoAccessorMethod", true);
    2776              :                                         }
    2777            6 :                                 } else if (nv[0] == "owned_get") {
    2778            6 :                                         if (eval (nv[1]) == "1") {
    2779            6 :                                                 prop.get_accessor.value_type.value_owned = true;
    2780              :                                         }
    2781            0 :                                 } else if (nv[0] == "type_name") {
    2782            0 :                                         prop.property_type = parse_type_from_string (eval (nv[1]), false);
    2783            0 :                                 } else if (nv[0] == "experimental") {
    2784            0 :                                         if (eval (nv[1]) == "1") {
    2785            0 :                                                 prop.set_attribute_bool ("Version", "experimental", true);
    2786              :                                         }
    2787            0 :                                 } else if (nv[0] == "nullable") {
    2788            0 :                                         if (eval (nv[1]) == "1" && !(prop.property_type is VoidType)) {
    2789            0 :                                                 prop.property_type.nullable = true;
    2790              :                                         }
    2791            0 :                                 } else if (nv[0] == "abstract") {
    2792            0 :                                         if (eval (nv[1]) == "1") {
    2793            0 :                                                 prop.is_abstract = true;
    2794              :                                         }
    2795              :                                 }
    2796              :                         }
    2797              :                 }
    2798              : 
    2799         1412 :                 if (current_type_symbol_set != null) {
    2800         1412 :                         current_type_symbol_set.add (prop.name);
    2801              :                 }
    2802              :                 
    2803         1412 :                 return prop;
    2804              :         }
    2805              : 
    2806         2631 :         private Constant? parse_constant (IdlNodeConstant const_node) {
    2807         2631 :                 weak IdlNode node = (IdlNode) const_node;
    2808              :                 
    2809         2631 :                 var type = parse_type (const_node.type);
    2810         2631 :                 if (type == null) {
    2811            3 :                         return null;
    2812              :                 }
    2813              : 
    2814         2631 :                 var c = new Constant (node.name, type, null, current_source_reference);
    2815         2631 :                 c.external = true;
    2816              :                 
    2817         2631 :                 string[] attributes = get_attributes (node.name);
    2818         2631 :                 if (attributes != null) {
    2819        15655 :                         foreach (string attr in attributes) {
    2820         4459 :                                 var nv = attr.split ("=", 2);
    2821         4459 :                                 if (nv[0] == "cheader_filename") {
    2822         2176 :                                         c.set_attribute_string ("CCode", "cheader_filename", eval (nv[1]));
    2823         2283 :                                 } else if (nv[0] == "deprecated") {
    2824            0 :                                         if (eval (nv[1]) == "1") {
    2825            0 :                                                 c.set_attribute_bool ("Version", "deprecated", true);
    2826              :                                         }
    2827         2283 :                                 } else if (nv[0] == "replacement") {
    2828            0 :                                         c.set_attribute_string ("Version", "replacement", eval (nv[1]));
    2829         2283 :                                 } else if (nv[0] == "deprecated_since") {
    2830            0 :                                         c.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
    2831         2283 :                                 } else if (nv[0] == "hidden") {
    2832            3 :                                         if (eval (nv[1]) == "1") {
    2833            9 :                                                 return null;
    2834              :                                         }
    2835         2280 :                                 } else if (nv[0] == "experimental") {
    2836            0 :                                         if (eval (nv[1]) == "1") {
    2837            0 :                                                 c.set_attribute_bool ("Version", "experimental", true);
    2838              :                                         }
    2839              :                                 }
    2840              :                         }
    2841              :                 }
    2842              : 
    2843         2628 :                 c.access = SymbolAccessibility.PUBLIC;
    2844              :                 
    2845         5256 :                 return c;
    2846              :         }
    2847              : 
    2848         2381 :         private Field? parse_field (IdlNodeField field_node) {
    2849         2381 :                 weak IdlNode node = (IdlNode) field_node;
    2850         2381 :                 bool unhidden = false;
    2851              : 
    2852         2381 :                 var type = parse_type (field_node.type);
    2853         2381 :                 if (type == null) {
    2854          210 :                         return null;
    2855              :                 }
    2856              : 
    2857         2381 :                 string cheader_filename = null;
    2858         2381 :                 string ctype = null;
    2859         2381 :                 string array_length_cname = null;
    2860         2381 :                 string array_length_type = null;
    2861         2381 :                 bool array_null_terminated = false;
    2862         2381 :                 bool deprecated = false;
    2863         2381 :                 string deprecated_since = null;
    2864         2381 :                 string replacement = null;
    2865         2381 :                 bool experimental = false;
    2866         2381 :                 bool no_delegate_target = false;
    2867              : 
    2868         2381 :                 var attributes = get_attributes ("%s.%s".printf (get_cname (current_data_type), node.name));
    2869         2381 :                 if (attributes != null) {
    2870          388 :                         foreach (string attr in attributes) {
    2871          167 :                                 var nv = attr.split ("=", 2);
    2872          167 :                                 if (nv[0] == "hidden") {
    2873          100 :                                         if (eval (nv[1]) == "1") {
    2874          300 :                                                 return null;
    2875              :                                         } else {
    2876              :                                                 unhidden = true;
    2877              :                                         }
    2878           67 :                                 } else if (nv[0] == "is_array") {
    2879            7 :                                         if (eval (nv[1]) == "1") {
    2880            7 :                                                 type.value_owned = true;
    2881            7 :                                                 type = new ArrayType (type, 1, type.source_reference);
    2882              :                                         }
    2883           60 :                                 } else if (nv[0] == "weak") {
    2884           31 :                                         if (eval (nv[1]) == "0") {
    2885           31 :                                                 type.value_owned = true;
    2886              :                                         }
    2887           29 :                                 } else if (nv[0] == "value_owned") {
    2888            2 :                                         if (eval (nv[1]) == "0") {
    2889            2 :                                                 type.value_owned = false;
    2890            0 :                                         } else if (eval (nv[1]) == "1") {
    2891            0 :                                                 type.value_owned = true;
    2892              :                                         }
    2893           27 :                                 } else if (nv[0] == "type_name") {
    2894           11 :                                         type = parse_type_from_string (eval (nv[1]), true);
    2895           16 :                                 } else if (nv[0] == "type_arguments") {
    2896            7 :                                         parse_type_arguments_from_string (type, eval (nv[1]));
    2897            9 :                                 } else if (nv[0] == "deprecated") {
    2898            0 :                                         if (eval (nv[1]) == "1") {
    2899           67 :                                                 deprecated = true;
    2900              :                                         }
    2901            9 :                                 } else if (nv[0] == "replacement") {
    2902            0 :                                         replacement = eval (nv[1]);
    2903            9 :                                 } else if (nv[0] == "deprecated_since") {
    2904            0 :                                         deprecated_since = eval (nv[1]);
    2905            9 :                                 } else if (nv[0] == "cheader_filename") {
    2906            0 :                                         cheader_filename = eval (nv[1]);
    2907            9 :                                 } else if (nv[0] == "ctype") {
    2908            2 :                                         ctype = eval (nv[1]);
    2909            7 :                                 } else if (nv[0] == "array_null_terminated") {
    2910            3 :                                         if (eval (nv[1]) == "1") {
    2911           67 :                                                 array_null_terminated = true;
    2912              :                                         }
    2913            4 :                                 } else if (nv[0] == "array_length_cname") {
    2914            0 :                                         array_length_cname = eval (nv[1]);
    2915            4 :                                 } else if (nv[0] == "array_length_type") {
    2916            0 :                                         array_length_type = eval (nv[1]);
    2917            4 :                                 } else if (nv[0] == "no_delegate_target") {
    2918            2 :                                         if (eval (nv[1]) == "1") {
    2919           67 :                                                 no_delegate_target = true;
    2920              :                                         }
    2921            2 :                                 } else if (nv[0] == "experimental") {
    2922            0 :                                         if (eval (nv[1]) == "1") {
    2923           67 :                                                 experimental = true;
    2924              :                                         }
    2925              :                                 }
    2926              :                         }
    2927              :                 }
    2928              : 
    2929         2281 :                 if (node.name.has_prefix("_") && !unhidden) {
    2930          220 :                         return null;
    2931              :                 }
    2932              : 
    2933         2171 :                 if (current_type_symbol_set != null) {
    2934          674 :                         current_type_symbol_set.add (node.name);
    2935              :                 }
    2936              : 
    2937         2171 :                 string field_name = node.name;
    2938         2171 :                 if (field_name == "string") {
    2939              :                         // avoid conflict with string type
    2940            1 :                         field_name = "str";
    2941              :                 }
    2942              : 
    2943         2171 :                 var field = new Field (field_name, type, null, current_source_reference);
    2944         2171 :                 field.access = SymbolAccessibility.PUBLIC;
    2945              : 
    2946         2171 :                 if (field_name != node.name) {
    2947            1 :                         field.set_attribute_string ("CCode", "cname", node.name);
    2948              :                 }
    2949              : 
    2950         2171 :                 if (deprecated) {
    2951            0 :                         field.set_attribute_bool ("Version", "deprecated", true);
    2952              : 
    2953            0 :                         if (deprecated_since != null) {
    2954            0 :                                 field.set_attribute_string ("Version", "deprecated_since", deprecated_since);
    2955              :                         }
    2956              : 
    2957            0 :                         if (replacement != null) {
    2958            0 :                                 field.set_attribute_string ("Version", "replacement", replacement);
    2959              :                         }
    2960              :                 }
    2961              : 
    2962         2171 :                 if (experimental) {
    2963            0 :                         field.set_attribute_bool ("Version", "experimental", true);
    2964              :                 }
    2965              : 
    2966         2171 :                 if (ctype != null) {
    2967            2 :                         field.set_attribute_string ("CCode", "type", ctype);
    2968              :                 }
    2969              : 
    2970         2171 :                 if (cheader_filename != null) {
    2971            0 :                         field.set_attribute_string ("CCode", "cheader_filename", cheader_filename);
    2972              :                 }
    2973              : 
    2974         2171 :                 if (array_null_terminated) {
    2975            3 :                         field.set_attribute_bool ("CCode", "array_null_terminated", true);
    2976              :                 }
    2977              : 
    2978         2171 :                 if (array_length_cname != null || array_length_type != null) {
    2979            0 :                         if (array_length_cname != null) {
    2980            0 :                                 field.set_attribute_string ("CCode", "array_length_cname", array_length_cname);
    2981              :                         }
    2982            0 :                         if (array_length_type != null) {
    2983            0 :                                 field.set_attribute_string ("CCode", "array_length_type", array_length_type);
    2984              :                         }
    2985         2171 :                 } else if (field.variable_type is ArrayType) {
    2986           55 :                         field.set_attribute_bool ("CCode", "array_length", false);
    2987              :                 }
    2988              : 
    2989         2171 :                 if (no_delegate_target) {
    2990            2 :                         field.set_attribute_bool ("CCode", "delegate_target", false);
    2991              :                 }
    2992              : 
    2993         4342 :                 return field;
    2994              :         }
    2995              : 
    2996        59625 :         private string[]? get_attributes (string codenode) {
    2997        59625 :                 var attributes = codenode_attributes_map.get (codenode);
    2998              : 
    2999       101039 :                 if (attributes == null) {
    3000        48852 :                         var dot_required = (-1 != codenode.index_of_char ('.'));
    3001        48852 :                         var colon_required = (-1 != codenode.index_of_char (':'));
    3002              : 
    3003        48852 :                         var pattern_specs = codenode_attributes_patterns.get_keys ();
    3004       562104 :                         foreach (PatternSpec* pattern in pattern_specs) {
    3005       315679 :                                 var pspec = codenode_attributes_patterns[pattern];
    3006              : 
    3007       315679 :                                 if ((dot_required && -1 == pspec.index_of_char ('.')) ||
    3008       274418 :                                     (colon_required && -1 == pspec.index_of_char (':'))) {
    3009       103230 :                                         continue;
    3010              :                                 }
    3011              : 
    3012       212449 :                                 if (pattern->match_string (codenode)) {
    3013         7438 :                                         return get_attributes (pspec);
    3014              :                                 }
    3015              :                         }
    3016              :                 }
    3017              : 
    3018        41414 :                 if (attributes == null) {
    3019        41414 :                         return null;
    3020              :                 }
    3021              : 
    3022        10773 :                 GLib.SList<string> attr_list = new GLib.SList<string> ();
    3023        10773 :                 var attr = new GLib.StringBuilder.sized (attributes.length);
    3024        10773 :                 var attributes_len = attributes.length;
    3025        10773 :                 unowned string remaining = attributes;
    3026        10773 :                 bool quoted = false, escaped = false;
    3027       413032 :                 for (int b = 0 ; b < attributes_len ; b++) {
    3028       402259 :                         unichar c = remaining.get_char ();
    3029              : 
    3030       402259 :                         if (escaped) {
    3031            0 :                                 escaped = false;
    3032            0 :                                 attr.append_unichar (c);
    3033              :                         } else {
    3034       402259 :                                 if (c == '"') {
    3035        36622 :                                         attr.append_unichar (c);
    3036        36622 :                                         quoted = !quoted;
    3037       365637 :                                 } else if (c == '\\') {
    3038              :                                         escaped = true;
    3039       365637 :                                 } else if (!quoted && (c == ' ')) {
    3040        15080 :                                         attr_list.prepend (attr.str);
    3041         7540 :                                         attr.truncate (0);
    3042              :                                 } else {
    3043       358097 :                                         attr.append_unichar (c);
    3044              :                                 }
    3045              :                         }
    3046              : 
    3047       402259 :                         remaining = (string) ((char*) remaining + remaining.index_of_nth_char (1));
    3048              :                 }
    3049              : 
    3050        10773 :                 if (attr.len > 0) {
    3051        21544 :                         attr_list.prepend (attr.str);
    3052              :                 }
    3053              : 
    3054        10773 :                 var attrs = new string[attr_list.length ()];
    3055        10773 :                 unowned GLib.SList<string>? attr_i = attr_list;
    3056        29085 :                 for (int a = 0 ; a < attrs.length ; a++, attr_i = attr_i.next) {
    3057        36624 :                         attrs[(attrs.length - 1) - a] = attr_i.data;
    3058              :                 }
    3059              : 
    3060        29085 :                 return attrs;
    3061              :         }
    3062              :         
    3063         7372 :         private string eval (string s) {
    3064         7372 :                 return ((s.length >= 2) && s.has_prefix ("\"") && s.has_suffix ("\"")) ? s.substring (1, s.length - 2) : s;
    3065              :         }
    3066              : 
    3067          477 :         private Signal? parse_signal (IdlNodeSignal sig_node) {
    3068          477 :                 weak IdlNode node = (IdlNode) sig_node;
    3069              :                 
    3070          477 :                 if (sig_node.deprecated || sig_node.result == null) {
    3071            3 :                         return null;
    3072              :                 }
    3073              :                 
    3074          477 :                 var sig = new Signal (fix_prop_name (node.name), parse_param (sig_node.result), current_source_reference);
    3075          477 :                 sig.access = SymbolAccessibility.PUBLIC;
    3076              :                 
    3077          477 :                 var attributes = get_attributes ("%s::%s".printf (get_cname (current_data_type), sig.name));
    3078          562 :                 if (attributes != null) {
    3079              :                         string ns_name = null;
    3080          352 :                         foreach (string attr in attributes) {
    3081           90 :                                 var nv = attr.split ("=", 2);
    3082           90 :                                 if (nv[0] == "name") {
    3083            4 :                                         sig.set_attribute_string ("CCode", "cname", sig.name.replace ("_", "-"));
    3084            4 :                                         sig.name = eval (nv[1]);
    3085           86 :                                 } else if (nv[0] == "has_emitter" && eval (nv[1]) == "1") {
    3086           80 :                                         sig.set_attribute ("HasEmitter", true);
    3087            6 :                                 } else if (nv[0] == "hidden") {
    3088            3 :                                         if (eval (nv[1]) == "1") {
    3089            9 :                                                 return null;
    3090              :                                         }
    3091            3 :                                 } else if (nv[0] == "deprecated") {
    3092            0 :                                         if (eval (nv[1]) == "1") {
    3093            0 :                                                 sig.set_attribute_bool ("Version", "deprecated", true);
    3094              :                                         }
    3095            3 :                                 } else if (nv[0] == "replacement") {
    3096            0 :                                         sig.set_attribute_string ("Version", "replacement", eval (nv[1]));
    3097            3 :                                 } else if (nv[0] == "deprecated_since") {
    3098            0 :                                         sig.set_attribute_string ("Version", "deprecated_since", eval (nv[1]));
    3099            3 :                                 } else if (nv[0] == "transfer_ownership") {
    3100            1 :                                         if (eval (nv[1]) == "1") {
    3101            1 :                                                 sig.return_type.value_owned = true;
    3102              :                                         }
    3103            2 :                                 } else if (nv[0] == "namespace_name") {
    3104            0 :                                         ns_name = eval (nv[1]);
    3105            2 :                                 } else if (nv[0] == "type_name") {
    3106            0 :                                         sig.return_type = parse_type_from_string (eval (nv[1]), false);
    3107            2 :                                 } else if (nv[0] == "type_arguments") {
    3108            0 :                                         parse_type_arguments_from_string (sig.return_type, eval (nv[1]));
    3109            2 :                                 } else if (nv[0] == "experimental") {
    3110            2 :                                         if (eval (nv[1]) == "1") {
    3111            2 :                                                 sig.set_attribute_bool ("Version", "experimental", true);
    3112              :                                         }
    3113              :                                 }
    3114              :                         }
    3115           85 :                         if (ns_name != null) {
    3116            0 :                                 ((UnresolvedType) sig.return_type).unresolved_symbol.inner = new UnresolvedSymbol (null, ns_name);
    3117              :                         }
    3118              :                 }
    3119              : 
    3120          474 :                 sig.is_virtual = true;
    3121              : 
    3122          474 :                 bool first = true;
    3123              :                 
    3124         1854 :                 foreach (weak IdlNodeParam param in sig_node.parameters) {
    3125          927 :                         if (first) {
    3126              :                                 // ignore implicit first signal parameter (sender)
    3127          474 :                                 first = false;
    3128          474 :                                 continue;
    3129              :                         }
    3130              :                 
    3131          453 :                         weak IdlNode param_node = (IdlNode) param;
    3132              :                         
    3133              :                         ParameterDirection direction;
    3134          453 :                         var param_type = parse_param (param, out direction);
    3135          453 :                         var p = new Parameter (param_node.name, param_type, current_source_reference);
    3136          453 :                         p.direction = direction;
    3137              : 
    3138          453 :                         bool hide_param = false;
    3139          453 :                         bool show_param = false;
    3140          906 :                         attributes = get_attributes ("%s::%s.%s".printf (get_cname (current_data_type), sig.name, param_node.name));
    3141          499 :                         if (attributes != null) {
    3142              :                                 string ns_name = null;
    3143          208 :                                 foreach (string attr in attributes) {
    3144           81 :                                         var nv = attr.split ("=", 2);
    3145           81 :                                         if (nv[0] == "hidden") {
    3146            0 :                                                 if (eval (nv[1]) == "1") {
    3147              :                                                         hide_param = true;
    3148            0 :                                                 } else if (eval (nv[1]) == "0") {
    3149           81 :                                                         show_param = true;
    3150              :                                                 }
    3151           81 :                                         } else if (nv[0] == "is_array") {
    3152            0 :                                                 if (eval (nv[1]) == "1") {
    3153            0 :                                                         param_type.value_owned = true;
    3154            0 :                                                         param_type = new ArrayType (param_type, 1, param_type.source_reference);
    3155            0 :                                                         p.variable_type = param_type;
    3156            0 :                                                         p.direction = ParameterDirection.IN;
    3157              :                                                 }
    3158           81 :                                         } else if (nv[0] == "no_array_length") {
    3159            0 :                                                 if (eval (nv[1]) == "1") {
    3160            0 :                                                         p.set_attribute_bool ("CCode", "array_length", false);
    3161              :                                                 }
    3162           81 :                                         } else if (nv[0] == "array_length_type") {
    3163            0 :                                                 p.set_attribute_string ("CCode", "array_length_type", nv[1]);
    3164           81 :                                         } else if (nv[0] == "array_null_terminated") {
    3165            0 :                                                 if (eval (nv[1]) == "1") {
    3166            0 :                                                         p.set_attribute_bool ("CCode", "array_length", false);
    3167            0 :                                                         p.set_attribute_bool ("CCode", "array_null_terminated", true);
    3168              :                                                 }
    3169           81 :                                         } else if (nv[0] == "is_out") {
    3170            2 :                                                 if (eval (nv[1]) == "1") {
    3171            2 :                                                         p.direction = ParameterDirection.OUT;
    3172              :                                                 }
    3173           79 :                                         } else if (nv[0] == "is_ref") {
    3174            2 :                                                 if (eval (nv[1]) == "1") {
    3175            2 :                                                         p.direction = ParameterDirection.REF;
    3176              :                                                 }
    3177           77 :                                         } else if (nv[0] == "nullable") {
    3178            8 :                                                 if (eval (nv[1]) == "1" && !(param_type is VoidType)) {
    3179            8 :                                                         param_type.nullable = true;
    3180              :                                                 }
    3181           69 :                                         } else if (nv[0] == "transfer_ownership") {
    3182            0 :                                                 if (eval (nv[1]) == "1") {
    3183            0 :                                                         param_type.value_owned = true;
    3184              :                                                 }
    3185           69 :                                         } else if (nv[0] == "type_name") {
    3186           36 :                                                 p.variable_type = param_type = parse_type_from_string (eval (nv[1]), false);
    3187           33 :                                         } else if (nv[0] == "type_arguments") {
    3188            0 :                                                 parse_type_arguments_from_string (p.variable_type, eval (nv[1]));
    3189           33 :                                         } else if (nv[0] == "namespace_name") {
    3190           33 :                                                 ns_name = eval (nv[1]);
    3191              :                                         }
    3192              :                                 }
    3193           46 :                                 if (ns_name != null) {
    3194           33 :                                         ((UnresolvedType) param_type).unresolved_symbol.inner = new UnresolvedSymbol (null, ns_name);
    3195              :                                 }
    3196              :                         }
    3197              : 
    3198          453 :                         if (show_param || !hide_param) {
    3199          453 :                                 sig.add_parameter (p);
    3200              :                         }
    3201              :                 }
    3202              :                 
    3203          474 :                 return sig;
    3204              :         }
    3205              : }
    3206              : 
    3207              : // vim:sw=8 noet
        

Generated by: LCOV version 2.0-1