~ubuntu-branches/ubuntu/hardy/vala/hardy

« back to all changes in this revision

Viewing changes to vapigen/valagidlparser.vala

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge, Marc-Andre Lureau, Sebastian Dröge
  • Date: 2007-10-15 14:37:51 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20071015143751-zy7hqcyjutdyfkg3
Tags: 0.1.4-1
[ Marc-Andre Lureau ]
* New Upstream Version
* debian/patches:
  + Remove patch no longer needed in 0.1.4
* debian/rules
  + Add xsltproc build dependency for the Vala manual.
  + Add libenchant-dev build dependency for enchant test case.
* debian/control, debian/vala-doc.install:
  + Add a "vala-doc" documentation package.

[ Sebastian Dröge ]
* debian/control:
  + Let vala-doc suggest valac/devhelp and don't depend on libvala0.
* debian/libvala-dev.install:
  + Add the new vapicheck utility.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 * This library is free software; you can redistribute it and/or
6
6
 * modify it under the terms of the GNU Lesser General Public
7
7
 * License as published by the Free Software Foundation; either
8
 
 * version 2 of the License, or (at your option) any later version.
 
8
 * version 2.1 of the License, or (at your option) any later version.
9
9
 
10
10
 * This library is distributed in the hope that it will be useful,
11
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34
34
 
35
35
        private SourceReference current_source_reference;
36
36
        
 
37
        private Namespace current_namespace;
37
38
        private DataType current_data_type;
38
39
        private Map<string,string> codenode_attributes_map;
 
40
        private Map<pointer,string> codenode_attributes_patterns;
39
41
        private Gee.Set<string> current_type_symbol_set;
40
42
 
 
43
        private Map<string,DataType> cname_type_map;
 
44
 
41
45
        /**
42
46
         * Parse all source files in the specified code context and build a
43
47
         * code tree.
45
49
         * @param context a code context
46
50
         */
47
51
        public void parse (CodeContext! context) {
 
52
                cname_type_map = new HashMap<string,DataType> (str_hash, str_equal);
 
53
 
48
54
                this.context = context;
49
55
                context.accept (this);
 
56
 
 
57
                cname_type_map = null;
 
58
        }
 
59
 
 
60
        public override void visit_namespace (Namespace! ns) {
 
61
                ns.accept_children (this);
 
62
        }
 
63
 
 
64
        public override void visit_class (Class! cl) {
 
65
                visit_type (cl);
 
66
        }
 
67
 
 
68
        public override void visit_struct (Struct! st) {
 
69
                visit_type (st);
 
70
        }
 
71
 
 
72
        public override void visit_interface (Interface! iface) {
 
73
                visit_type (iface);
 
74
        }
 
75
 
 
76
        public override void visit_enum (Enum! en) {
 
77
                visit_type (en);
 
78
        }
 
79
 
 
80
        public override void visit_callback (Callback! cb) {
 
81
                visit_type (cb);
 
82
        }
 
83
 
 
84
        private void visit_type (DataType! t) {
 
85
                if (!cname_type_map.contains (t.get_cname ())) {
 
86
                        cname_type_map[t.get_cname ()] = t;
 
87
                }
50
88
        }
51
89
 
52
90
        public override void visit_source_file (SourceFile! source_file) {
61
99
                current_source_file = source_file;
62
100
 
63
101
                codenode_attributes_map = new HashMap<string,string> (str_hash, str_equal);
64
 
                
 
102
                codenode_attributes_patterns = new HashMap<pointer,string> (direct_hash, PatternSpec.equal);
 
103
 
65
104
                if (FileUtils.test (metadata_filename, FileTest.EXISTS)) {
66
105
                        try {
67
106
                                string metadata;
69
108
                                FileUtils.get_contents (metadata_filename, out metadata, out metadata_len);
70
109
                                
71
110
                                foreach (string line in metadata.split ("\n")) {
72
 
                                        var line_parts = line.split (" ", 2);
73
 
                                        if (line_parts[0] == null) {
74
 
                                                continue;
 
111
                                        if (line.has_prefix ("#")) {
 
112
                                                // ignore comment lines
 
113
                                                continue;
 
114
                                        }
 
115
 
 
116
                                        var tokens = line.split (" ", 2);
 
117
 
 
118
                                        if (null == tokens[0]) {
 
119
                                                continue;
 
120
                                        }
 
121
 
 
122
                                        if (null != tokens[0].chr (-1, '*')) {
 
123
                                                PatternSpec pattern = new PatternSpec (tokens[0]);
 
124
                                                codenode_attributes_patterns[#pattern] = tokens[0];
75
125
                                        }
76
126
                                        
77
 
                                        codenode_attributes_map.set (line_parts[0], line_parts[1]);
 
127
                                        codenode_attributes_map[tokens[0]] = tokens[1];
78
128
                                }
79
129
                        } catch (FileError e) {
80
130
                                Report.error (null, "Unable to read metadata file: %s".printf (e.message));
97
147
                }
98
148
        }
99
149
 
100
 
        private string! fix_type_name (string! type_name, IdlModule! module) {
101
 
                if (type_name.has_prefix (module.name)) {
102
 
                        return type_name.offset (module.name.len ());
103
 
                } else if (module.name == "GLib" && type_name.has_prefix ("G")) {
 
150
        private string! fix_type_name (string! type_name, Namespace! ns) {
 
151
                var attributes = get_attributes (type_name);
 
152
                if (attributes != null) {
 
153
                        foreach (string attr in attributes) {
 
154
                                var nv = attr.split ("=", 2);
 
155
                                if (nv[0] == "name") {
 
156
                                        return eval (nv[1]);
 
157
                                }
 
158
                        }
 
159
                }
 
160
 
 
161
                if (type_name.has_prefix (ns.name)) {
 
162
                        return type_name.offset (ns.name.len ());
 
163
                } else if (ns.name == "GLib" && type_name.has_prefix ("G")) {
104
164
                        return type_name.offset (1);
 
165
                } else  {
 
166
                        string best_match = null;
 
167
                        foreach (string cprefix in ns.get_cprefixes ()) {
 
168
                                if (type_name.has_prefix (cprefix)) {
 
169
                                        if (best_match == null || cprefix.len () > best_match.len ())
 
170
                                                best_match = cprefix;
 
171
                                }
 
172
                        }
 
173
 
 
174
                        if (best_match != null) {
 
175
                                return type_name.offset (best_match.len ());;
 
176
                        }
105
177
                }
 
178
 
106
179
                return type_name;
107
180
        }
108
181
 
109
 
        private string! fix_const_name (string! const_name, IdlModule! module) {
110
 
                if (const_name.has_prefix (module.name.up () + "_")) {
111
 
                        return const_name.offset (module.name.len () + 1);
112
 
                } else if (module.name == "GLib" && const_name.has_prefix ("G_")) {
 
182
        private string! fix_const_name (string! const_name, Namespace! ns) {
 
183
                if (const_name.has_prefix (ns.name.up () + "_")) {
 
184
                        return const_name.offset (ns.name.len () + 1);
 
185
                } else if (ns.name == "GLib" && const_name.has_prefix ("G_")) {
113
186
                        return const_name.offset (2);
114
187
                }
115
188
                return const_name;
124
197
                } else {
125
198
                        ns = new Namespace (module.name, current_source_reference);
126
199
                }
127
 
                
 
200
 
 
201
                current_namespace = ns;
 
202
 
128
203
                var attributes = get_attributes (ns.name);
129
204
                if (attributes != null) {
130
205
                        foreach (string attr in attributes) {
132
207
                                if (nv[0] == "cheader_filename") {
133
208
                                        ns.set_cheader_filename (eval (nv[1]));
134
209
                                } else if (nv[0] == "cprefix") {
135
 
                                        ns.set_cprefix (eval (nv[1]));
 
210
                                        var cprefixes = eval (nv[1]).split (",");
 
211
                                        foreach(string name in cprefixes) {
 
212
                                                ns.add_cprefix (name);
 
213
                                        }
136
214
                                } else if (nv[0] == "lower_case_cprefix") {
137
215
                                        ns.set_lower_case_cprefix (eval (nv[1]));
138
216
                                }
145
223
                                if (cb == null) {
146
224
                                        continue;
147
225
                                }
148
 
                                cb.name = fix_type_name (cb.name, module);
 
226
                                cb.name = fix_type_name (cb.name, ns);
149
227
                                ns.add_callback (cb);
150
228
                                current_source_file.add_node (cb);
151
229
                        } else if (node.type == IdlNodeTypeId.STRUCT) {
152
 
                                var st = parse_struct ((IdlNodeStruct) node);
153
 
                                if (st == null) {
154
 
                                        continue;
155
 
                                }
156
 
                                st.name = fix_type_name (st.name, module);
157
 
                                ns.add_struct (st);
158
 
                                current_source_file.add_node (st);
 
230
                                parse_struct ((IdlNodeStruct) node, ns, module);
159
231
                        } else if (node.type == IdlNodeTypeId.BOXED) {
160
 
                                var st = parse_boxed ((IdlNodeBoxed) node);
161
 
                                st.name = fix_type_name (st.name, module);
162
 
                                ns.add_struct (st);
163
 
                                st.set_type_id (st.get_upper_case_cname ("TYPE_"));
164
 
                                current_source_file.add_node (st);
 
232
                                parse_boxed ((IdlNodeBoxed) node, ns, module);
165
233
                        } else if (node.type == IdlNodeTypeId.ENUM) {
166
234
                                var en = parse_enum ((IdlNodeEnum) node);
167
 
                                en.name = fix_type_name (en.name, module);
 
235
                                en.name = fix_type_name (en.name, ns);
168
236
                                ns.add_enum (en);
169
237
                                current_source_file.add_node (en);
170
238
                        } else if (node.type == IdlNodeTypeId.OBJECT) {
171
 
                                var cl = parse_object ((IdlNodeInterface) node);
172
 
                                cl.name = fix_type_name (cl.name, module);
173
 
                                ns.add_class (cl);
174
 
                                current_source_file.add_node (cl);
 
239
                                parse_object ((IdlNodeInterface) node, ns, module);
175
240
                        } else if (node.type == IdlNodeTypeId.INTERFACE) {
176
 
                                var iface = parse_interface ((IdlNodeInterface) node);
177
 
                                iface.name = fix_type_name (iface.name, module);
178
 
                                ns.add_interface (iface);
179
 
                                current_source_file.add_node (iface);
 
241
                                parse_interface ((IdlNodeInterface) node, ns, module);
180
242
                        } else if (node.type == IdlNodeTypeId.CONSTANT) {
181
243
                                var c = parse_constant ((IdlNodeConstant) node);
182
 
                                c.name = fix_const_name (c.name, module);
 
244
                                c.name = fix_const_name (c.name, ns);
183
245
                                ns.add_constant (c);
184
246
                                current_source_file.add_node (c);
185
247
                        } else if (node.type == IdlNodeTypeId.FUNCTION) {
191
253
                                }
192
254
                        }
193
255
                }
194
 
                
 
256
 
 
257
                current_namespace = null;
 
258
 
195
259
                if (sym is Namespace) {
196
260
                        return null;
197
261
                }
214
278
                }
215
279
        
216
280
                var cb = new Callback (node.name, parse_param (f_node.result), current_source_reference);
217
 
                cb.access = MemberAccessibility.PUBLIC;
 
281
                cb.access = SymbolAccessibility.PUBLIC;
218
282
                
219
283
                foreach (weak IdlNodeParam param in f_node.parameters) {
220
284
                        weak IdlNode param_node = (IdlNode) param;
225
289
                
226
290
                return cb;
227
291
        }
228
 
        
229
 
        private Struct parse_struct (IdlNodeStruct! st_node) {
 
292
 
 
293
        private bool is_reference_type (string! cname) {
 
294
                var st_attributes = get_attributes (cname);
 
295
                if (st_attributes != null) {
 
296
                        foreach (string attr in st_attributes) {
 
297
                                var nv = attr.split ("=", 2);
 
298
                                if (nv[0] == "is_value_type" && eval (nv[1]) == "1") {
 
299
                                        return false;
 
300
                                }
 
301
                        }
 
302
                }
 
303
                return true;
 
304
        }
 
305
 
 
306
        private void parse_struct (IdlNodeStruct! st_node, Namespace! ns, IdlModule! module) {
230
307
                weak IdlNode node = (IdlNode) st_node;
231
308
                
232
309
                if (st_node.deprecated) {
233
 
                        return null;
234
 
                }
235
 
        
236
 
                var st = new Struct (node.name, current_source_reference);
237
 
                st.access = MemberAccessibility.PUBLIC;
238
 
 
239
 
                st.set_is_reference_type (true);
240
 
                
241
 
                var st_attributes = get_attributes (node.name);
242
 
                if (st_attributes != null) {
243
 
                        foreach (string attr in st_attributes) {
244
 
                                var nv = attr.split ("=", 2);
245
 
                                if (nv[0] == "is_value_type" && eval (nv[1]) == "1") {
246
 
                                        st.set_is_reference_type (false);
247
 
                                }
248
 
                        }
249
 
                }
250
 
                
251
 
                current_data_type = st;
252
 
                
253
 
                foreach (weak IdlNode member in st_node.members) {
254
 
                        if (member.type == IdlNodeTypeId.FUNCTION) {
255
 
                                var m = parse_function ((IdlNodeFunction) member);
256
 
                                if (m != null) {
257
 
                                        st.add_method (m);
258
 
                                }
259
 
                        } else if (member.type == IdlNodeTypeId.FIELD) {
260
 
                                var f = parse_field ((IdlNodeField) member);
261
 
                                if (f != null) {
262
 
                                        st.add_field (f);
263
 
                                }
264
 
                        }
265
 
                }
266
 
 
267
 
                current_data_type = null;
268
 
                
269
 
                return st;
 
310
                        return;
 
311
                }
 
312
 
 
313
                string name = fix_type_name (node.name, ns);
 
314
 
 
315
                if (!is_reference_type (node.name)) {
 
316
                        var st = ns.scope.lookup (name) as Struct;
 
317
                        if (st == null) {
 
318
                                st = new Struct (name, current_source_reference);
 
319
                                st.access = SymbolAccessibility.PUBLIC;
 
320
 
 
321
                                var st_attributes = get_attributes (node.name);
 
322
                                if (st_attributes != null) {
 
323
                                        foreach (string attr in st_attributes) {
 
324
                                                var nv = attr.split ("=", 2);
 
325
                                                if (nv[0] == "cheader_filename") {
 
326
                                                        st.add_cheader_filename (eval (nv[1]));
 
327
                                                } else if (nv[0] == "hidden") {
 
328
                                                        if (eval (nv[1]) == "1") {
 
329
                                                                return;
 
330
                                                        }
 
331
                                                }
 
332
                                        }
 
333
                                }
 
334
 
 
335
                                ns.add_struct (st);
 
336
                                current_source_file.add_node (st);
 
337
                        }
 
338
 
 
339
                        current_data_type = st;
 
340
 
 
341
                        foreach (weak IdlNode member in st_node.members) {
 
342
                                if (member.type == IdlNodeTypeId.FUNCTION) {
 
343
                                        var m = parse_function ((IdlNodeFunction) member);
 
344
                                        if (m != null) {
 
345
                                                st.add_method (m);
 
346
                                        }
 
347
                                } else if (member.type == IdlNodeTypeId.FIELD) {
 
348
                                        var f = parse_field ((IdlNodeField) member);
 
349
                                        if (f != null) {
 
350
                                                st.add_field (f);
 
351
                                        }
 
352
                                }
 
353
                        }
 
354
 
 
355
                        current_data_type = null;
 
356
                } else {
 
357
                        var cl = ns.scope.lookup (name) as Class;
 
358
                        if (cl == null) {
 
359
                                cl = new Class (name, current_source_reference);
 
360
                                cl.access = SymbolAccessibility.PUBLIC;
 
361
 
 
362
                                var cl_attributes = get_attributes (node.name);
 
363
                                if (cl_attributes != null) {
 
364
                                        foreach (string attr in cl_attributes) {
 
365
                                                var nv = attr.split ("=", 2);
 
366
                                                if (nv[0] == "cheader_filename") {
 
367
                                                        cl.add_cheader_filename (eval (nv[1]));
 
368
                                                } else if (nv[0] == "hidden") {
 
369
                                                        if (eval (nv[1]) == "1") {
 
370
                                                                return;
 
371
                                                        }
 
372
                                                }
 
373
                                        }
 
374
                                }
 
375
 
 
376
                                ns.add_class (cl);
 
377
                                current_source_file.add_node (cl);
 
378
                        }
 
379
 
 
380
                        current_data_type = cl;
 
381
 
 
382
                        string ref_function = null;
 
383
                        string unref_function = null;
 
384
                        string copy_function = null;
 
385
                        string free_function = null;
 
386
 
 
387
                        foreach (weak IdlNode member in st_node.members) {
 
388
                                if (member.type == IdlNodeTypeId.FUNCTION) {
 
389
                                        if (member.name == "ref") {
 
390
                                                ref_function = ((IdlNodeFunction) member).symbol;
 
391
                                        } else if (member.name == "unref") {
 
392
                                                unref_function = ((IdlNodeFunction) member).symbol;
 
393
                                        } else if (member.name == "free" || member.name == "destroy") {
 
394
                                                free_function = ((IdlNodeFunction) member).symbol;
 
395
                                        } else {
 
396
                                                if (member.name == "copy") {
 
397
                                                        copy_function = ((IdlNodeFunction) member).symbol;
 
398
                                                }
 
399
                                                var m = parse_function ((IdlNodeFunction) member);
 
400
                                                if (m != null) {
 
401
                                                        cl.add_method (m);
 
402
                                                }
 
403
                                        }
 
404
                                } else if (member.type == IdlNodeTypeId.FIELD) {
 
405
                                        var f = parse_field ((IdlNodeField) member);
 
406
                                        if (f != null) {
 
407
                                                cl.add_field (f);
 
408
                                        }
 
409
                                }
 
410
                        }
 
411
 
 
412
                        if (ref_function != null) {
 
413
                                cl.set_ref_function (ref_function);
 
414
                        }
 
415
                        if (copy_function != null) {
 
416
                                cl.set_dup_function (copy_function);
 
417
                        }
 
418
                        if (unref_function != null) {
 
419
                                cl.set_unref_function (unref_function);
 
420
                        } else if (free_function != null) {
 
421
                                cl.set_free_function (free_function);
 
422
                        }
 
423
 
 
424
                        current_data_type = null;
 
425
                }
270
426
        }
271
427
        
272
 
        private Struct parse_boxed (IdlNodeBoxed! boxed_node) {
 
428
        private void parse_boxed (IdlNodeBoxed! boxed_node, Namespace! ns, IdlModule! module) {
273
429
                weak IdlNode node = (IdlNode) boxed_node;
274
430
        
275
 
                var st = new Struct (node.name, current_source_reference);
276
 
                st.access = MemberAccessibility.PUBLIC;
277
 
 
278
 
                st.set_is_reference_type (true);
279
 
 
280
 
                var st_attributes = get_attributes (node.name);
281
 
                if (st_attributes != null) {
282
 
                        foreach (string attr in st_attributes) {
283
 
                                var nv = attr.split ("=", 2);
284
 
                                if (nv[0] == "is_value_type" && eval (nv[1]) == "1") {
285
 
                                        st.set_is_reference_type (false);
286
 
                                }
287
 
                        }
288
 
                }
289
 
                
290
 
                current_data_type = st;
291
 
                
292
 
                foreach (weak IdlNode member in boxed_node.members) {
293
 
                        if (member.type == IdlNodeTypeId.FUNCTION) {
294
 
                                var m = parse_function ((IdlNodeFunction) member);
295
 
                                if (m != null) {
296
 
                                        st.add_method (m);
297
 
                                }
298
 
                        } else if (member.type == IdlNodeTypeId.FIELD) {
299
 
                                var f = parse_field ((IdlNodeField) member);
300
 
                                if (f != null) {
301
 
                                        st.add_field (f);
302
 
                                }
303
 
                        }
304
 
                }
305
 
 
306
 
                current_data_type = null;
307
 
                
308
 
                return st;
 
431
                string name = fix_type_name (node.name, ns);
 
432
 
 
433
                if (!is_reference_type (node.name)) {
 
434
                        var st = ns.scope.lookup (name) as Struct;
 
435
                        if (st == null) {
 
436
                                st = new Struct (name, current_source_reference);
 
437
                                st.access = SymbolAccessibility.PUBLIC;
 
438
 
 
439
                                var st_attributes = get_attributes (node.name);
 
440
                                if (st_attributes != null) {
 
441
                                        foreach (string attr in st_attributes) {
 
442
                                                var nv = attr.split ("=", 2);
 
443
                                                if (nv[0] == "cheader_filename") {
 
444
                                                        st.add_cheader_filename (eval (nv[1]));
 
445
                                                }
 
446
                                        }
 
447
                                }
 
448
 
 
449
                                ns.add_struct (st);
 
450
                                st.set_type_id (st.get_upper_case_cname ("TYPE_"));
 
451
                                current_source_file.add_node (st);
 
452
                        }
 
453
                
 
454
                        current_data_type = st;
 
455
 
 
456
                        foreach (weak IdlNode member in boxed_node.members) {
 
457
                                if (member.type == IdlNodeTypeId.FUNCTION) {
 
458
                                        var m = parse_function ((IdlNodeFunction) member);
 
459
                                        if (m != null) {
 
460
                                                st.add_method (m);
 
461
                                        }
 
462
                                } else if (member.type == IdlNodeTypeId.FIELD) {
 
463
                                        var f = parse_field ((IdlNodeField) member);
 
464
                                        if (f != null) {
 
465
                                                st.add_field (f);
 
466
                                        }
 
467
                                }
 
468
                        }
 
469
 
 
470
                        current_data_type = null;
 
471
                } else {
 
472
                        var cl = ns.scope.lookup (name) as Class;
 
473
                        if (cl == null) {
 
474
                                cl = new Class (name, current_source_reference);
 
475
                                cl.access = SymbolAccessibility.PUBLIC;
 
476
 
 
477
                                var cl_attributes = get_attributes (node.name);
 
478
                                if (cl_attributes != null) {
 
479
                                        foreach (string attr in cl_attributes) {
 
480
                                                var nv = attr.split ("=", 2);
 
481
                                                if (nv[0] == "cheader_filename") {
 
482
                                                        cl.add_cheader_filename (eval (nv[1]));
 
483
                                                }
 
484
                                        }
 
485
                                }
 
486
 
 
487
                                ns.add_class (cl);
 
488
                                cl.set_type_id (cl.get_upper_case_cname ("TYPE_"));
 
489
                                current_source_file.add_node (cl);
 
490
                        }
 
491
 
 
492
                        var parent = new TypeReference ();
 
493
                        parent.namespace_name = "GLib";
 
494
                        parent.type_name = "Boxed";
 
495
                        cl.add_base_type (parent);
 
496
 
 
497
                        current_data_type = cl;
 
498
 
 
499
                        string ref_function = null;
 
500
                        string unref_function = null;
 
501
                        string copy_function = null;
 
502
                        string free_function = null;
 
503
 
 
504
                        foreach (weak IdlNode member in boxed_node.members) {
 
505
                                if (member.type == IdlNodeTypeId.FUNCTION) {
 
506
                                        if (member.name == "ref") {
 
507
                                                ref_function = ((IdlNodeFunction) member).symbol;
 
508
                                        } else if (member.name == "unref") {
 
509
                                                unref_function = ((IdlNodeFunction) member).symbol;
 
510
                                        } else if (member.name == "free" || member.name == "destroy") {
 
511
                                                free_function = ((IdlNodeFunction) member).symbol;
 
512
                                        } else {
 
513
                                                if (member.name == "copy") {
 
514
                                                        copy_function = ((IdlNodeFunction) member).symbol;
 
515
                                                }
 
516
                                                var m = parse_function ((IdlNodeFunction) member);
 
517
                                                if (m != null) {
 
518
                                                        cl.add_method (m);
 
519
                                                }
 
520
                                        }
 
521
                                } else if (member.type == IdlNodeTypeId.FIELD) {
 
522
                                        var f = parse_field ((IdlNodeField) member);
 
523
                                        if (f != null) {
 
524
                                                cl.add_field (f);
 
525
                                        }
 
526
                                }
 
527
                        }
 
528
 
 
529
                        if (ref_function != null) {
 
530
                                cl.set_ref_function (ref_function);
 
531
                        }
 
532
                        if (copy_function != null) {
 
533
                                cl.set_dup_function (copy_function);
 
534
                        }
 
535
                        if (unref_function != null) {
 
536
                                cl.set_unref_function (unref_function);
 
537
                        } else if (free_function != null) {
 
538
                                cl.set_free_function (free_function);
 
539
                        }
 
540
 
 
541
                        current_data_type = null;
 
542
                }
309
543
        }
310
544
        
311
545
        private Enum parse_enum (IdlNodeEnum! en_node) {
312
546
                weak IdlNode node = (IdlNode) en_node;
313
547
        
314
548
                var en = new Enum (node.name, current_source_reference);
315
 
                en.access = MemberAccessibility.PUBLIC;
 
549
                en.access = SymbolAccessibility.PUBLIC;
316
550
                
317
551
                string common_prefix = null;
318
552
                
328
562
                                        common_prefix = common_prefix.ndup (common_prefix.size () - 1);
329
563
                                }
330
564
                        }
 
565
                        while (common_prefix.len () > 0 && (!common_prefix.has_suffix ("_") ||
 
566
                               (value.name.offset (common_prefix.size ()).get_char ().isdigit ()) && (value.name.len () - common_prefix.len ()) <= 1)) {
 
567
                                // enum values may not consist solely of digits
 
568
                                common_prefix = common_prefix.ndup (common_prefix.size () - 1);
 
569
                        }
331
570
                }
332
571
                
333
572
                en.set_cprefix (common_prefix);
340
579
                return en;
341
580
        }
342
581
        
343
 
        private Class parse_object (IdlNodeInterface! node) {
344
 
                var cl = new Class (node.gtype_name, current_source_reference);
345
 
                cl.access = MemberAccessibility.PUBLIC;
346
 
                
347
 
                var attributes = get_attributes (cl.name);
348
 
                if (attributes != null) {
349
 
                        foreach (string attr in attributes) {
350
 
                                var nv = attr.split ("=", 2);
351
 
                                if (nv[0] == "cheader_filename") {
352
 
                                        cl.add_cheader_filename (eval (nv[1]));
 
582
        private void parse_object (IdlNodeInterface! node, Namespace! ns, IdlModule! module) {
 
583
                string name = fix_type_name (node.gtype_name, ns);
 
584
 
 
585
                string base_class = null;
 
586
 
 
587
                var cl = ns.scope.lookup (name) as Class;
 
588
                if (cl == null) {
 
589
                        cl = new Class (name, current_source_reference);
 
590
                        cl.access = SymbolAccessibility.PUBLIC;
 
591
                        
 
592
                        var attributes = get_attributes (node.gtype_name);
 
593
                        if (attributes != null) {
 
594
                                foreach (string attr in attributes) {
 
595
                                        var nv = attr.split ("=", 2);
 
596
                                        if (nv[0] == "cheader_filename") {
 
597
                                                cl.add_cheader_filename (eval (nv[1]));
 
598
                                        } else if (nv[0] == "base_class") {
 
599
                                                base_class = eval (nv[1]);
 
600
                                        } else if (nv[0] == "hidden") {
 
601
                                                if (eval (nv[1]) == "1") {
 
602
                                                        return;
 
603
                                                }
 
604
                                        }
353
605
                                }
354
606
                        }
 
607
 
 
608
                        ns.add_class (cl);
 
609
                        current_source_file.add_node (cl);
355
610
                }
356
 
                
357
 
                if (node.parent != null) {
 
611
 
 
612
                if (base_class != null) {
 
613
                        var parent = new TypeReference ();
 
614
                        parse_type_string (parent, base_class);
 
615
                        cl.add_base_type (parent);
 
616
                } else if (node.parent != null) {
358
617
                        var parent = new TypeReference ();
359
618
                        parse_type_string (parent, node.parent);
360
619
                        cl.add_base_type (parent);
 
620
                } else {
 
621
                        var parent = new TypeReference ();
 
622
                        parent.namespace_name = "GLib";
 
623
                        parent.type_name = "Object";
 
624
                        cl.add_base_type (parent);
361
625
                }
362
626
                
363
627
                foreach (string iface_name in node.interfaces) {
425
689
                
426
690
                current_data_type = null;
427
691
                current_type_symbol_set = null;
428
 
                
429
 
                return cl;
430
692
        }
431
693
 
432
 
        private Interface parse_interface (IdlNodeInterface! node) {
433
 
                var iface = new Interface (node.gtype_name, current_source_reference);
434
 
                iface.access = MemberAccessibility.PUBLIC;
435
 
                
436
 
                var attributes = get_attributes (iface.name);
437
 
                if (attributes != null) {
438
 
                        foreach (string attr in attributes) {
439
 
                                var nv = attr.split ("=", 2);
440
 
                                if (nv[0] == "cheader_filename") {
441
 
                                        iface.add_cheader_filename (eval (nv[1]));
 
694
        private void parse_interface (IdlNodeInterface! node, Namespace! ns, IdlModule! module) {
 
695
                string name = fix_type_name (node.gtype_name, ns);
 
696
 
 
697
                var iface = ns.scope.lookup (name) as Interface;
 
698
                if (iface == null) {
 
699
                        iface = new Interface (name, current_source_reference);
 
700
                        iface.access = SymbolAccessibility.PUBLIC;
 
701
                        
 
702
                        var attributes = get_attributes (node.gtype_name);
 
703
                        if (attributes != null) {
 
704
                                foreach (string attr in attributes) {
 
705
                                        var nv = attr.split ("=", 2);
 
706
                                        if (nv[0] == "cheader_filename") {
 
707
                                                iface.add_cheader_filename (eval (nv[1]));
 
708
                                        }
442
709
                                }
443
710
                        }
444
 
                }
445
 
                
446
 
                foreach (string prereq_name in node.prerequisites) {
447
 
                        var prereq = new TypeReference ();
448
 
                        parse_type_string (prereq, prereq_name);
449
 
                        iface.add_prerequisite (prereq);
 
711
                        
 
712
                        foreach (string prereq_name in node.prerequisites) {
 
713
                                var prereq = new TypeReference ();
 
714
                                parse_type_string (prereq, prereq_name);
 
715
                                iface.add_prerequisite (prereq);
 
716
                        }
 
717
 
 
718
                        ns.add_interface (iface);
 
719
                        current_source_file.add_node (iface);
450
720
                }
451
721
 
452
722
                current_data_type = iface;
475
745
                }
476
746
 
477
747
                current_data_type = null;
478
 
                
479
 
                return iface;
480
748
        }
481
749
        
482
750
        private TypeReference parse_type (IdlNodeType! type_node) {
554
822
                        if (type_node.is_pointer &&
555
823
                            (n == "gchar" || n == "char")) {
556
824
                                type.type_name = "string";
 
825
                                if (type_node.unparsed.has_suffix ("**")) {
 
826
                                        type.is_out = true;
 
827
                                }
557
828
                        } else if (n == "gunichar") {
558
829
                                type.type_name = "unichar";
559
830
                        } else if (n == "gchar") {
576
847
                                type.type_name = "ValueArray";
577
848
                        } else if (n == "time_t") {
578
849
                                type.type_name = "ulong";
 
850
                        } else if (n == "mode_t") {
 
851
                                type.type_name = "uint";
579
852
                        } else if (n == "gint" || n == "pid_t") {
580
853
                                type.type_name = "int";
 
854
                        } else if (n == "unsigned" || n == "unsigned-int") {
 
855
                                type.type_name = "uint";
581
856
                        } else if (n == "FILE") {
582
857
                                type.namespace_name = "GLib";
583
858
                                type.type_name = "FileStream";
 
859
                        } else if (n == "GType") {
 
860
                                type.namespace_name = "GLib";
 
861
                                type.type_name = "Type";
 
862
                                if (type_node.is_pointer) {
 
863
                                        type.array_rank = 1;
 
864
                                }
584
865
                        } else {
585
866
                                parse_type_string (type, n);
586
867
                                if (type_node.is_pointer && is_value_type (n)) {
594
875
        }
595
876
        
596
877
        private bool is_value_type (string! type_name) {
597
 
                // FIXME only works if both types are in current package, e.g. doesn't work when Gtk uses GdkRectangle
598
878
                var type_attributes = get_attributes (type_name);
599
879
                if (type_attributes != null) {
 
880
                        // type in the same package
600
881
                        foreach (string attr in type_attributes) {
601
882
                                var nv = attr.split ("=", 2);
602
883
                                if (nv[0] == "is_value_type" && eval (nv[1]) == "1") {
603
884
                                        return true;
604
885
                                }
605
886
                        }
 
887
                } else {
 
888
                        // type in a dependency package
 
889
                        var dt = cname_type_map[type_name];
 
890
                        if (dt != null) {
 
891
                                return !dt.is_reference_type ();
 
892
                        }
606
893
                }
607
894
 
608
895
                return false;
609
896
        }
610
897
        
611
898
        private void parse_type_string (TypeReference! type, string! n) {
612
 
                // Generated GIDL misses explicit namespace specifier,
613
 
                // so try to guess namespace
614
 
                if (n.has_prefix ("H") || n.has_suffix ("Class") || n == "va_list" || n.has_prefix ("LOGFONT") || n.has_prefix ("xml")) {
 
899
                var dt = cname_type_map[n];
 
900
                if (dt != null) {
 
901
                        type.namespace_name = dt.parent_symbol.name;
 
902
                        type.type_name = dt.name;
 
903
                        return;
 
904
                }
 
905
 
 
906
                var type_attributes = get_attributes (n);
 
907
 
 
908
                if (null != type_attributes) {
 
909
                        foreach (string attr in type_attributes) {
 
910
                                var nv = attr.split ("=", 2);
 
911
 
 
912
                                if (nv[0] == "cprefix") {
 
913
                                        type.type_name = n.offset (eval (nv[1]).len ());
 
914
                                        return;
 
915
                                }
 
916
                        }
 
917
                }
 
918
 
 
919
                if (n == "HFONT" || n == "HGLOBAL" || n == "GStaticRecMutex" || n.has_suffix ("Class") || n == "va_list" || n.has_prefix ("LOGFONT") || n.has_prefix ("xml") || n == "GdkNativeWindow" || n == "GdkXEvent" || n == "GtkTextLayout" || n == "GstClockID" || n.has_prefix ("GstXml")) {
615
920
                        // unsupported
616
921
                        type.type_name = "pointer";
617
922
                } else if (n.has_prefix ("cairo")) {
624
929
                                type.namespace_name = null;
625
930
                                type.type_name = "pointer";
626
931
                        }
627
 
                } else if (n.has_prefix ("Atk")) {
628
 
                        type.namespace_name = "Atk";
629
 
                        type.type_name = n.offset ("Atk".len ());
630
 
                        if (type.type_name == "AttributeSet") {
631
 
                                type.namespace_name = "GLib";
632
 
                                type.type_name = "SList";
633
 
                        }
634
 
                } else if (n.has_prefix ("Gst")) {
635
 
                        type.namespace_name = "Gst";
636
 
                        type.type_name = n.offset ("Gst".len ());
637
 
                        if (type.type_name == "ClockTime") {
638
 
                                type.namespace_name = null;
639
 
                                type.type_name = "uint64";
640
 
                        } else if (type.type_name == "ClockTimeDiff") {
641
 
                                type.namespace_name = null;
642
 
                                type.type_name = "int64";
643
 
                        } else if (type.type_name == "ClockID" || type.type_name.has_prefix ("Xml")) {
644
 
                                type.namespace_name = null;
645
 
                                type.type_name = "pointer";
646
 
                        }
647
 
                } else if (n.has_prefix ("Gtk")) {
648
 
                        type.namespace_name = "Gtk";
649
 
                        type.type_name = n.offset ("Gtk".len ());
650
 
                        if (type.type_name == "TextLayout") {
651
 
                                type.namespace_name = null;
652
 
                                type.type_name = "pointer";
653
 
                        }
654
 
                } else if (n.has_prefix ("Gdk")) {
655
 
                        type.namespace_name = "Gdk";
656
 
                        type.type_name = n.offset ("Gdk".len ());
657
 
                        if (type.type_name == "NativeWindow" || type.type_name == "XEvent") {
658
 
                                type.namespace_name = null;
659
 
                                type.type_name = "pointer";
660
 
                        }
661
 
                } else if (n.has_prefix ("Pango")) {
662
 
                        type.namespace_name = "Pango";
663
 
                        type.type_name = n.offset ("Pango".len ());
664
 
                        if (type.type_name == "Glyph") {
665
 
                                type.namespace_name = null;
666
 
                                type.type_name = "uint";
667
 
                        } else if (type.type_name == "GlyphUnit") {
668
 
                                type.namespace_name = null;
669
 
                                type.type_name = "int";
670
 
                        }
671
 
                } else if (n.has_prefix ("Vte")) {
672
 
                        type.namespace_name = "Vte";
673
 
                        type.type_name = n.offset ("Vte".len ());
674
 
                } else if (n.has_prefix ("Goo")) {
675
 
                        type.namespace_name = "Goo";
676
 
                        type.type_name = n.offset ("Goo".len ());
 
932
                } else if (n == "AtkAttributeSet") {
 
933
                        type.namespace_name = "GLib";
 
934
                        type.type_name = "SList";
 
935
                } else if (n == "GstClockTime") {
 
936
                        type.type_name = "uint64";
 
937
                } else if (n == "GstClockTimeDiff") {
 
938
                        type.type_name = "int64";
 
939
                } else if (n == "PangoGlyph") {
 
940
                        type.type_name = "uint";
 
941
                } else if (n == "PangoGlyphUnit") {
 
942
                        type.type_name = "int";
 
943
                } else if (n == "ClutterFixed" || n == "ClutterUnit" || n == "ClutterAngle") {
 
944
                        type.type_name = "int32";
 
945
                } else if (n == "SoupProtocol") {
 
946
                        type.namespace_name = "GLib";
 
947
                        type.type_name = "Quark";
 
948
                } else if (n == "GStrv") {
 
949
                        type.type_name = "string";
 
950
                        type.array_rank = 1;
 
951
                } else if (n.has_prefix (current_namespace.name)) {
 
952
                        type.namespace_name = current_namespace.name;
 
953
                        type.type_name = n.offset (current_namespace.name.len ());
677
954
                } else if (n.has_prefix ("G")) {
678
955
                        type.namespace_name = "GLib";
679
 
                        type.type_name = n.offset ("G".len ());
680
 
                        if (type.type_name == "Strv") {
681
 
                                type.namespace_name = null;
682
 
                                type.type_name = "string";
683
 
                                type.array_rank = 1;
684
 
                        } else if (type.type_name == "StaticRecMutex") {
685
 
                                type.namespace_name = null;
686
 
                                type.type_name = "pointer";
687
 
                        }
 
956
                        type.type_name = n.offset (1);
688
957
                } else {
689
958
                        var name_parts = n.split (".", 2);
690
959
                        if (name_parts[1] == null) {
728
997
                } else {
729
998
                        m = new Method (node.name, return_type, current_source_reference);
730
999
                }
731
 
                m.access = MemberAccessibility.PUBLIC;
732
 
                
733
 
                m.is_virtual = is_virtual;
 
1000
                m.access = SymbolAccessibility.PUBLIC;
 
1001
 
 
1002
                m.is_virtual = is_virtual && !is_interface;
 
1003
                m.is_abstract = is_virtual && is_interface;
734
1004
                
735
1005
                // GIDL generator can't provide array parameter information yet
736
1006
                m.no_array_length = true;
740
1010
                }
741
1011
                
742
1012
                if (current_data_type != null) {
743
 
                        var sig_attributes = get_attributes ("%s::%s".printf (current_data_type.name, node.name));
 
1013
                        var sig_attributes = get_attributes ("%s::%s".printf (current_data_type.get_cname (), node.name));
744
1014
                        if (sig_attributes != null) {
745
1015
                                foreach (string attr in sig_attributes) {
746
1016
                                        var nv = attr.split ("=", 2);
757
1027
                if (attributes != null) {
758
1028
                        foreach (string attr in attributes) {
759
1029
                                var nv = attr.split ("=", 2);
760
 
                                if (nv[0] == "hidden") {
 
1030
                                if (nv[0] == "name") {
 
1031
                                        m.set_cname (m.name);
 
1032
                                        m.name = eval (nv[1]);
 
1033
                                } else if (nv[0] == "hidden") {
761
1034
                                        if (eval (nv[1]) == "1") {
762
1035
                                                return null;
763
1036
                                        }
765
1038
                                        if (eval (nv[1]) == "1") {
766
1039
                                                add_ellipsis = true;
767
1040
                                        }
 
1041
                                } else if (nv[0] == "transfer_ownership") {
 
1042
                                        if (eval (nv[1]) == "1") {
 
1043
                                                return_type.transfers_ownership = true;
 
1044
                                        }
 
1045
                                } else if (nv[0] == "sentinel") {
 
1046
                                        m.sentinel = eval (nv[1]);
768
1047
                                }
769
1048
                        }
770
1049
                }
778
1057
                        
779
1058
                        if (first) {
780
1059
                                first = false;
781
 
                                if (current_data_type != null &&
 
1060
                                if (!(m is CreationMethod) &&
 
1061
                                    current_data_type != null &&
782
1062
                                    param.type.is_interface &&
783
1063
                                    (param_node.name == "self" ||
784
 
                                     param.type.@interface.has_suffix (current_data_type.name))) {
 
1064
                                     param.type.@interface.has_suffix (current_data_type.get_cname ()))) {
785
1065
                                        // instance method
786
 
                                        
787
 
                                        if (!current_data_type.is_reference_type () &&
788
 
                                            param.type.is_pointer) {
789
 
                                                m.instance_by_reference = true;
790
 
                                        }
791
 
                                        
792
1066
                                        continue;
793
1067
                                } else {
794
1068
                                        // static method
795
1069
                                        m.instance = false;
796
1070
                                }
797
1071
                        }
 
1072
 
 
1073
                        if (param.type.is_error) {
 
1074
                                m.add_error_domain (parse_type (param.type));
 
1075
                                continue;
 
1076
                        }
798
1077
                        
799
1078
                        var p = new FormalParameter (param_node.name, parse_param (param));
800
1079
                        m.add_parameter (p);
801
1080
 
 
1081
                        var attributes = get_attributes ("%s.%s".printf (f.symbol, param_node.name));
 
1082
                        if (attributes != null) {
 
1083
                                foreach (string attr in attributes) {
 
1084
                                        var nv = attr.split ("=", 2);
 
1085
                                        if (nv[0] == "is_array") {
 
1086
                                                p.type_reference.array_rank = 1;
 
1087
                                                p.type_reference.is_out = false;
 
1088
                                        }
 
1089
                                }
 
1090
                        }
 
1091
 
802
1092
                        if (last_param != null && p.name == "n_" + last_param.name) {
803
1093
                                // last_param is array, p is array length
804
1094
                                last_param.type_reference.array_rank = 1;
870
1160
                }
871
1161
                
872
1162
                var prop = new Property (fix_prop_name (node.name), parse_type (prop_node.type), get_acc, set_acc, current_source_reference);
873
 
                prop.access = MemberAccessibility.PUBLIC;
 
1163
                prop.access = SymbolAccessibility.PUBLIC;
874
1164
                prop.interface_only = true;
875
 
                
 
1165
 
 
1166
                var attributes = get_attributes ("%s:%s".printf (current_data_type.get_cname (), node.name));
 
1167
                if (attributes != null) {
 
1168
                        foreach (string attr in attributes) {
 
1169
                                var nv = attr.split ("=", 2);
 
1170
                                if (nv[0] == "hidden") {
 
1171
                                        if (eval (nv[1]) == "1") {
 
1172
                                                return null;
 
1173
                                        }
 
1174
                                }
 
1175
                        }
 
1176
                }
 
1177
 
876
1178
                if (current_type_symbol_set != null) {
877
1179
                        current_type_symbol_set.add (prop.name);
878
1180
                }
905
1207
                        return null;
906
1208
                }
907
1209
 
908
 
                var attributes = get_attributes ("%s.%s".printf (current_data_type.name, node.name));
 
1210
                var attributes = get_attributes ("%s.%s".printf (current_data_type.get_cname (), node.name));
909
1211
                if (attributes != null) {
910
1212
                        foreach (string attr in attributes) {
911
1213
                                var nv = attr.split ("=", 2);
913
1215
                                        if (eval (nv[1]) == "1") {
914
1216
                                                return null;
915
1217
                                        }
 
1218
                                } else if (nv[0] == "is_array") {
 
1219
                                        if (eval (nv[1]) == "1") {
 
1220
                                                type.array_rank = 1;
 
1221
                                        }
 
1222
                                } else if (nv[0] == "weak") {
 
1223
                                        if (eval (nv[1]) == "0") {
 
1224
                                                type.takes_ownership = true;
 
1225
                                        }
916
1226
                                }
917
1227
                        }
918
1228
                }
922
1232
                }
923
1233
                
924
1234
                var field = new Field (node.name, type, null, current_source_reference);
925
 
                field.access = MemberAccessibility.PUBLIC;
 
1235
                field.access = SymbolAccessibility.PUBLIC;
926
1236
                
927
1237
                return field;
928
1238
        }
929
1239
 
930
1240
        [NoArrayLength]
931
1241
        private string[] get_attributes (string! codenode) {
932
 
                string attributes = codenode_attributes_map.get (codenode);
 
1242
                var attributes = codenode_attributes_map.get (codenode);
 
1243
 
 
1244
                if (attributes == null) {
 
1245
                        var dot_required = (null != codenode.chr (-1, '.'));
 
1246
                        var colon_required = (null != codenode.chr (-1, ':'));
 
1247
 
 
1248
                        var pattern_specs = codenode_attributes_patterns.get_keys ();
 
1249
                        foreach (weak PatternSpec pattern in pattern_specs) {
 
1250
                                var pspec = codenode_attributes_patterns[pattern];
 
1251
 
 
1252
                                if ((dot_required && null == pspec.chr (-1, '.')) ||
 
1253
                                    (colon_required && null == pspec.chr (-1, ':'))) {
 
1254
                                        continue;
 
1255
                                }
 
1256
 
 
1257
                                if (pattern.match_string (codenode)) {
 
1258
                                        return get_attributes (pspec);
 
1259
                                }
 
1260
                        }
 
1261
                }
 
1262
 
933
1263
                if (attributes == null) {
934
1264
                        return null;
935
1265
                }
949
1279
                }
950
1280
                
951
1281
                var sig = new Signal (fix_prop_name (node.name), parse_param (sig_node.result), current_source_reference);
952
 
                sig.access = MemberAccessibility.PUBLIC;
 
1282
                sig.access = SymbolAccessibility.PUBLIC;
953
1283
                
954
 
                var attributes = get_attributes ("%s::%s".printf (current_data_type.name, sig.name));
 
1284
                var attributes = get_attributes ("%s::%s".printf (current_data_type.get_cname (), sig.name));
955
1285
                if (attributes != null) {
956
1286
                        foreach (string attr in attributes) {
957
1287
                                var nv = attr.split ("=", 2);