3 * Copyright (C) 2006-2010 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
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.
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.
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
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
28 * Code visitor parsing all GIDL files.
30 public class Vala
.GIdlParser
: CodeVisitor
{
31 private CodeContext context
;
33 private SourceFile current_source_file
;
35 private SourceReference current_source_reference
;
37 private Namespace current_namespace
;
38 private TypeSymbol current_data_type
;
39 private Map
<string,string> codenode_attributes_map
;
40 private Map
<PatternSpec
*,string> codenode_attributes_patterns
;
41 private Set
<string> current_type_symbol_set
;
43 private Map
<string,TypeSymbol
> cname_type_map
;
45 static GLib
.Regex type_from_string_regex
;
48 * Parse all source files in the specified code context and build a
51 * @param context a code context
53 public void parse (CodeContext context
) {
54 cname_type_map
= new HashMap
<string,TypeSymbol
> (str_hash
, str_equal
);
56 this
.context
= context
;
57 context
.accept (this
);
59 cname_type_map
= null;
62 public override void visit_namespace (Namespace ns
) {
63 ns
.accept_children (this
);
66 public override void visit_class (Class cl
) {
70 public override void visit_struct (Struct st
) {
74 public override void visit_interface (Interface iface
) {
78 public override void visit_enum (Enum en
) {
82 public override void visit_error_domain (ErrorDomain ed
) {
86 public override void visit_delegate (Delegate d
) {
90 private void visit_type (TypeSymbol t
) {
91 if (!cname_type_map
.contains (t
.get_cname ())) {
92 cname_type_map
[t
.get_cname ()] = t
;
96 public override void visit_source_file (SourceFile source_file
) {
97 if (source_file
.filename
.has_suffix (".gi")) {
98 parse_file (source_file
);
102 private void parse_file (SourceFile source_file
) {
103 string metadata_filename
= "%s.metadata".printf (source_file
.filename
.substring (0, source_file
.filename
.length
- ".gi".length
));
105 current_source_file
= source_file
;
107 codenode_attributes_map
= new HashMap
<string,string> (str_hash
, str_equal
);
108 codenode_attributes_patterns
= new HashMap
<PatternSpec
*,string> (direct_hash
, (EqualFunc
) PatternSpec
.equal
);
110 if (FileUtils
.test (metadata_filename
, FileTest
.EXISTS
)) {
113 FileUtils
.get_contents (metadata_filename
, out metadata
, null);
115 foreach (string line
in metadata
.split ("\n")) {
116 if (line
.has_prefix ("#")) {
117 // ignore comment lines
121 var tokens
= line
.split (" ", 2);
123 if (null == tokens
[0]) {
127 if (-1 != tokens
[0].index_of_char ('*')) {
128 PatternSpec
* pattern
= new
PatternSpec (tokens
[0]);
129 codenode_attributes_patterns
[pattern
] = tokens
[0];
132 codenode_attributes_map
[tokens
[0]] = tokens
[1];
134 } catch (FileError e
) {
135 Report
.error (null, "Unable to read metadata file: %s".printf (e
.message
));
140 var modules
= Idl
.parse_file (source_file
.filename
);
142 current_source_reference
= new
SourceReference (source_file
);
144 foreach (weak IdlModule module
in modules
) {
145 var ns
= parse_module (module
);
147 context
.root
.add_namespace (ns
);
150 } catch (MarkupError e
) {
151 Report
.error (null, "Unable to parse GIDL file: %s".printf (e
.message
));
155 private string fix_type_name (string type_name
, Symbol container
) {
156 var attributes
= get_attributes (type_name
);
157 if (attributes
!= null) {
158 foreach (string attr
in attributes
) {
159 var nv
= attr
.split ("=", 2);
160 if (nv
[0] == "name") {
166 if (type_name
.has_prefix (container
.name
)) {
167 return type_name
.substring (container
.name
.length
);
168 } else if (container
.name
== "GLib" && type_name
.has_prefix ("G")) {
169 return type_name
.substring (1);
171 string best_match
= null;
172 if (container is Namespace
) {
173 foreach (string cprefix
in ((Namespace
) container
).get_cprefixes ()) {
174 if (type_name
.has_prefix (cprefix
)) {
175 if (best_match
== null || cprefix
.length
> best_match
.length
)
176 best_match
= cprefix
;
180 best_match
= container
.get_cprefix ();
183 if (best_match
!= null) {
184 return type_name
.substring (best_match
.length
);;
191 private string fix_const_name (string const_name
, Symbol container
) {
192 var pref
= container
.get_lower_case_cprefix ().up ();
193 if (const_name
.has_prefix (pref
)) {
194 return const_name
.substring (pref
.length
);
199 private string[] get_attributes_for_node (IdlNode node
) {
202 if (node
.type
== IdlNodeTypeId
.FUNCTION
) {
203 name
= ((IdlNodeFunction
) node
).symbol
;
204 } else if (node
.type
== IdlNodeTypeId
.SIGNAL
) {
205 name
= "%s::%s".printf (current_data_type
.get_cname (), node
.name
);
206 } else if (node
.type
== IdlNodeTypeId
.PROPERTY
) {
207 name
= "%s:%s".printf (current_data_type
.get_cname (), node
.name
);
208 } else if (node
.type
== IdlNodeTypeId
.FIELD
) {
209 name
= "%s.%s".printf (current_data_type
.get_cname (), node
.name
);
214 return get_attributes (name
);
217 private void add_symbol_to_container (Symbol container
, Symbol sym
) {
218 if (container is Class
) {
219 unowned Class cl
= (Class
) container
;
222 cl
.add_class ((Class
) sym
);
223 } else if (sym is Constant
) {
224 cl
.add_constant ((Constant
) sym
);
225 } else if (sym is Enum
) {
226 cl
.add_enum ((Enum
) sym
);
227 } else if (sym is Field
) {
228 cl
.add_field ((Field
) sym
);
229 } else if (sym is Method
) {
230 cl
.add_method ((Method
) sym
);
231 } else if (sym is Property
) {
232 cl
.add_property ((Property
) sym
);
233 } else if (sym is Signal
) {
234 cl
.add_signal ((Signal
) sym
);
235 } else if (sym is Struct
) {
236 cl
.add_struct ((Struct
) sym
);
238 } else if (container is Enum
) {
239 unowned Enum en
= (Enum
) container
;
241 if (sym is EnumValue
) {
242 en
.add_value ((EnumValue
) sym
);
243 } else if (sym is Constant
) {
244 en
.add_constant ((Constant
) sym
);
245 } else if (sym is Method
) {
246 en
.add_method ((Method
) sym
);
248 } else if (container is Interface
) {
249 unowned Interface iface
= (Interface
) container
;
252 iface
.add_class ((Class
) sym
);
253 } else if (sym is Constant
) {
254 iface
.add_constant ((Constant
) sym
);
255 } else if (sym is Enum
) {
256 iface
.add_enum ((Enum
) sym
);
257 } else if (sym is Field
) {
258 iface
.add_field ((Field
) sym
);
259 } else if (sym is Method
) {
260 iface
.add_method ((Method
) sym
);
261 } else if (sym is Property
) {
262 iface
.add_property ((Property
) sym
);
263 } else if (sym is Signal
) {
264 iface
.add_signal ((Signal
) sym
);
265 } else if (sym is Struct
) {
266 iface
.add_struct ((Struct
) sym
);
268 } else if (container is Namespace
) {
269 unowned Namespace ns
= (Namespace
) container
;
271 if (sym is Namespace
) {
272 ns
.add_namespace ((Namespace
) sym
);
273 } else if (sym is Class
) {
274 ns
.add_class ((Class
) sym
);
275 } else if (sym is Constant
) {
276 ns
.add_constant ((Constant
) sym
);
277 } else if (sym is Delegate
) {
278 ns
.add_delegate ((Delegate
) sym
);
279 } else if (sym is Enum
) {
280 ns
.add_enum ((Enum
) sym
);
281 } else if (sym is ErrorDomain
) {
282 ns
.add_error_domain ((ErrorDomain
) sym
);
283 } else if (sym is Field
) {
284 ns
.add_field ((Field
) sym
);
285 } else if (sym is Interface
) {
286 ns
.add_interface ((Interface
) sym
);
287 } else if (sym is Method
) {
288 ns
.add_method ((Method
) sym
);
289 } else if (sym is Namespace
) {
290 ns
.add_namespace ((Namespace
) sym
);
291 } else if (sym is Struct
) {
292 ns
.add_struct ((Struct
) sym
);
294 } else if (container is Struct
) {
295 unowned Struct st
= (Struct
) container
;
297 if (sym is Constant
) {
298 st
.add_constant ((Constant
) sym
);
299 } else if (sym is Field
) {
300 st
.add_field ((Field
) sym
);
301 } else if (sym is Method
) {
302 st
.add_method ((Method
) sym
);
303 } else if (sym is Property
) {
304 st
.add_property ((Property
) sym
);
309 private void parse_node (IdlNode node
, IdlModule module
, Symbol container
) {
310 if (node
.type
== IdlNodeTypeId
.CALLBACK
) {
311 var cb
= parse_delegate ((IdlNodeFunction
) node
);
315 cb
.name
= fix_type_name (cb
.name
, container
);
316 add_symbol_to_container (container
, cb
);
317 current_source_file
.add_node (cb
);
318 } else if (node
.type
== IdlNodeTypeId
.STRUCT
) {
319 parse_struct ((IdlNodeStruct
) node
, container
, module
);
320 } else if (node
.type
== IdlNodeTypeId
.UNION
) {
321 parse_union ((IdlNodeUnion
) node
, container
, module
);
322 } else if (node
.type
== IdlNodeTypeId
.BOXED
) {
323 parse_boxed ((IdlNodeBoxed
) node
, container
, module
);
324 } else if (node
.type
== IdlNodeTypeId
.ENUM
) {
325 parse_enum ((IdlNodeEnum
) node
, container
, module
, false);
326 } else if (node
.type
== IdlNodeTypeId
.FLAGS
) {
327 parse_enum ((IdlNodeEnum
) node
, container
, module
, true);
328 } else if (node
.type
== IdlNodeTypeId
.OBJECT
) {
329 parse_object ((IdlNodeInterface
) node
, container
, module
);
330 } else if (node
.type
== IdlNodeTypeId
.INTERFACE
) {
331 parse_interface ((IdlNodeInterface
) node
, container
, module
);
332 } else if (node
.type
== IdlNodeTypeId
.CONSTANT
) {
333 var c
= parse_constant ((IdlNodeConstant
) node
);
335 c
.name
= fix_const_name (c
.name
, container
);
336 add_symbol_to_container (container
, c
);
337 current_source_file
.add_node (c
);
339 } else if (node
.type
== IdlNodeTypeId
.FUNCTION
) {
340 var m
= parse_function ((IdlNodeFunction
) node
);
342 m
.binding
= MemberBinding
.STATIC
;
343 add_symbol_to_container (container
, m
);
344 current_source_file
.add_node (m
);
349 private Symbol?
get_container_from_name (string name
) {
350 var path
= name
.split (".");
351 Symbol? cp
= current_namespace
;
354 foreach ( unowned
string tok
in path
) {
355 cc
= cp
.scope
.lookup (tok
) as Symbol
;
357 cc
= new
Namespace (tok
, current_source_reference
);
358 ((Namespace
) cc
).add_cprefix (cp
.get_cprefix () + tok
);
359 add_symbol_to_container (cp
, cc
);
367 private Namespace?
parse_module (IdlModule module
) {
368 Symbol sym
= context
.root
.scope
.lookup (module
.name
);
370 if (sym is Namespace
) {
371 ns
= (Namespace
) sym
;
372 if (ns
.external_package
) {
373 ns
.attributes
= null;
374 ns
.source_reference
= current_source_reference
;
377 ns
= new
Namespace (module
.name
, current_source_reference
);
380 current_namespace
= ns
;
382 var attributes
= get_attributes (ns
.name
);
383 if (attributes
!= null) {
384 foreach (string attr
in attributes
) {
385 var nv
= attr
.split ("=", 2);
386 if (nv
[0] == "cheader_filename") {
387 ns
.set_cheader_filename (eval (nv
[1]));
388 } else if (nv
[0] == "cprefix") {
389 var cprefixes
= eval (nv
[1]).split (",");
390 foreach(string name
in cprefixes
) {
391 ns
.add_cprefix (name
);
393 } else if (nv
[0] == "lower_case_cprefix") {
394 ns
.set_lower_case_cprefix (eval (nv
[1]));
395 } else if (nv
[0] == "gir_namespace") {
396 ns
.source_reference
.file
.gir_namespace
= eval (nv
[1]);
397 } else if (nv
[0] == "gir_version") {
398 ns
.source_reference
.file
.gir_version
= eval (nv
[1]);
403 var deferred
= new ArrayList
<unowned IdlNode
> ();
405 foreach (weak IdlNode node
in module
.entries
) {
406 bool is_deferred
= false;
407 var child_attributes
= get_attributes_for_node (node
);
408 if (child_attributes
!= null) {
409 foreach (unowned
string attr
in child_attributes
) {
410 var nv
= attr
.split ("=", 2);
411 if (nv
[0] == "parent") {
419 parse_node (node
, module
, ns
);
423 foreach (unowned IdlNode node
in deferred
) {
424 Symbol container
= ns
;
425 var child_attributes
= get_attributes_for_node (node
);
426 if (child_attributes
!= null) {
427 foreach (unowned
string attr
in child_attributes
) {
428 var nv
= attr
.split ("=", 2);
429 if (nv
[0] == "parent") {
430 container
= get_container_from_name (eval (nv
[1]));
435 parse_node (node
, module
, container
);
438 current_namespace
= null;
440 if (sym is Namespace
) {
446 private Delegate?
parse_delegate (IdlNodeFunction f_node
) {
447 weak IdlNode node
= (IdlNode
) f_node
;
449 var return_type
= parse_param (f_node
.result
);
451 var cb
= new
Delegate (node
.name
, return_type
, current_source_reference
);
452 cb
.access
= SymbolAccessibility
.PUBLIC
;
454 bool check_has_target
= true;
455 bool suppress_throws
= false;
456 string? error_types
= null;
458 var attributes
= get_attributes (node
.name
);
459 if (attributes
!= null) {
460 foreach (string attr
in attributes
) {
461 var nv
= attr
.split ("=", 2);
462 if (nv
[0] == "hidden") {
463 if (eval (nv
[1]) == "1") {
466 } else if (nv
[0] == "cheader_filename") {
467 cb
.add_cheader_filename (eval (nv
[1]));
468 } else if (nv
[0] == "has_target") {
469 if (eval (nv
[1]) == "0") {
470 check_has_target
= false;
471 } else if (eval (nv
[1]) == "1") {
472 cb
.has_target
= true;
474 } else if (nv
[0] == "transfer_ownership") {
475 if (eval (nv
[1]) == "1") {
476 return_type
.value_owned
= true;
478 } else if (nv
[0] == "is_array") {
479 if (eval (nv
[1]) == "1") {
480 return_type
= new
ArrayType (return_type
, 1, return_type
.source_reference
);
481 cb
.return_type
= return_type
;
483 } else if (nv
[0] == "throws") {
484 if (eval (nv
[1]) == "0") {
485 suppress_throws
= true;
487 } else if (nv
[0] == "error_types") {
488 error_types
= eval (nv
[1]);
489 } else if (nv
[0] == "array_length_type") {
490 cb
.array_length_type
= eval (nv
[1]);
491 } else if (nv
[0] == "type_name") {
492 cb
.return_type
= return_type
= parse_type_from_string (eval (nv
[1]), return_type
.value_owned
);
493 } else if (nv
[0] == "deprecated") {
494 if (eval (nv
[1]) == "1") {
495 cb
.deprecated
= true;
497 } else if (nv
[0] == "replacement") {
498 cb
.replacement
= eval (nv
[1]);
499 } else if (nv
[0] == "deprecated_since") {
500 cb
.deprecated_since
= eval (nv
[1]);
501 } else if (nv
[0] == "type_arguments") {
502 parse_type_arguments_from_string (return_type
, eval (nv
[1]));
503 } else if (nv
[0] == "instance_pos") {
504 cb
.cinstance_parameter_position
= double.parse (eval (nv
[1]));
505 } else if (nv
[0] == "type_parameters") {
506 foreach (string type_param_name
in eval (nv
[1]).split (",")) {
507 cb
.add_type_parameter (new
TypeParameter (type_param_name
, current_source_reference
));
509 } else if (nv
[0] == "experimental") {
510 if (eval (nv
[1]) == "1") {
511 cb
.experimental
= true;
517 uint remaining_params
= f_node
.parameters
.length ();
518 foreach (weak IdlNodeParam param
in f_node
.parameters
) {
519 weak IdlNode param_node
= (IdlNode
) param
;
521 if (check_has_target
&& remaining_params
== 1 && (param_node
.name
== "user_data" || param_node
.name
== "data")) {
522 // hide user_data parameter for instance delegates
523 cb
.has_target
= true;
525 // check for GError parameter
526 if (suppress_throws
== false && param_is_exception (param
)) {
527 if (error_types
== null)
528 cb
.add_error_type (parse_type (param
.type
));
533 string param_name
= param_node
.name
;
534 if (param_name
== "string") {
535 // avoid conflict with string type
537 } else if (param_name
== "self") {
538 // avoid conflict with delegate target
539 param_name
= "_self";
542 ParameterDirection direction
;
543 var param_type
= parse_param (param
, out direction
);
544 var p
= new
Parameter (param_name
, param_type
);
545 p
.direction
= direction
;
547 bool hide_param
= false;
548 bool show_param
= false;
549 bool array_requested
= false;
550 bool out_requested
= false;
551 attributes
= get_attributes ("%s.%s".printf (node
.name
, param_node
.name
));
552 if (attributes
!= null) {
553 foreach (string attr
in attributes
) {
554 var nv
= attr
.split ("=", 2);
555 if (nv
[0] == "hidden") {
556 if (eval (nv
[1]) == "1") {
558 } else if (eval (nv
[1]) == "0") {
561 } else if (nv
[0] == "is_array") {
562 if (eval (nv
[1]) == "1") {
563 param_type
= new
ArrayType (param_type
, 1, param_type
.source_reference
);
564 p
.variable_type
= param_type
;
565 if (!out_requested
) {
566 p
.direction
= ParameterDirection
.IN
;
568 array_requested
= true;
570 } else if (nv
[0] == "is_out") {
571 if (eval (nv
[1]) == "1") {
572 p
.direction
= ParameterDirection
.OUT
;
573 out_requested
= true;
574 if (!array_requested
&& param_type is ArrayType
) {
575 var array_type
= (ArrayType
) param_type
;
576 param_type
= array_type
.element_type
;
577 p
.variable_type
= param_type
;
580 } else if (nv
[0] == "is_ref") {
581 if (eval (nv
[1]) == "1") {
582 p
.direction
= ParameterDirection
.REF
;
583 if (!array_requested
&& param_type is ArrayType
) {
584 var array_type
= (ArrayType
) param_type
;
585 param_type
= array_type
.element_type
;
586 p
.variable_type
= param_type
;
589 } else if (nv
[0] == "takes_ownership") {
590 if (eval (nv
[1]) == "1") {
591 param_type
.value_owned
= true;
593 } else if (nv
[0] == "nullable") {
594 if (eval (nv
[1]) == "1") {
595 param_type
.nullable
= true;
597 } else if (nv
[0] == "type_arguments") {
598 parse_type_arguments_from_string (param_type
, eval (nv
[1]));
599 } else if (nv
[0] == "no_array_length") {
600 if (eval (nv
[1]) == "1") {
601 p
.no_array_length
= true;
603 } else if (nv
[0] == "array_length_type") {
604 p
.array_length_type
= eval (nv
[1]);
605 } else if (nv
[0] == "array_null_terminated") {
606 if (eval (nv
[1]) == "1") {
607 p
.no_array_length
= true;
608 p
.array_null_terminated
= true;
610 } else if (nv
[0] == "type_name") {
611 p
.variable_type
= param_type
= parse_type_from_string (eval (nv
[1]), false);
616 if (show_param
|| !hide_param
) {
617 cb
.add_parameter (p
);
624 if (suppress_throws
== false && error_types
!= null) {
625 var type_args
= eval (error_types
).split (",");
626 foreach (string type_arg
in type_args
) {
627 cb
.add_error_type (parse_type_from_string (type_arg
, true));
634 private bool is_reference_type (string cname
) {
635 var st_attributes
= get_attributes (cname
);
636 if (st_attributes
!= null) {
637 foreach (string attr
in st_attributes
) {
638 var nv
= attr
.split ("=", 2);
639 if (nv
[0] == "is_value_type" && eval (nv
[1]) == "1") {
647 private void parse_struct (IdlNodeStruct st_node
, Symbol container
, IdlModule module
) {
648 weak IdlNode node
= (IdlNode
) st_node
;
650 if (st_node
.deprecated
) {
654 string name
= fix_type_name (node
.name
, container
);
656 if (!is_reference_type (node
.name
)) {
657 var st
= container
.scope
.lookup (name
) as Struct
;
659 st
= new
Struct (name
, current_source_reference
);
660 st
.access
= SymbolAccessibility
.PUBLIC
;
662 var st_attributes
= get_attributes (node
.name
);
663 if (st_attributes
!= null) {
664 foreach (string attr
in st_attributes
) {
665 var nv
= attr
.split ("=", 2);
666 if (nv
[0] == "cheader_filename") {
667 st
.add_cheader_filename (eval (nv
[1]));
668 } else if (nv
[0] == "hidden") {
669 if (eval (nv
[1]) == "1") {
672 } else if (nv
[0] == "base_type") {
673 st
.base_type
= parse_type_string (eval (nv
[1]));
674 } else if (nv
[0] == "rank") {
675 st
.set_rank (int.parse (eval (nv
[1])));
676 } else if (nv
[0] == "simple_type") {
677 if (eval (nv
[1]) == "1") {
678 st
.set_simple_type (true);
680 } else if (nv
[0] == "immutable") {
681 if (eval (nv
[1]) == "1") {
682 st
.is_immutable
= true;
684 } else if (nv
[0] == "has_type_id") {
685 if (eval (nv
[1]) == "0") {
686 st
.has_type_id
= false;
688 } else if (nv
[0] == "type_id") {
689 st
.set_type_id (eval (nv
[1]));
690 } else if (nv
[0] == "has_copy_function") {
691 if (eval (nv
[1]) == "0") {
692 st
.has_copy_function
= false;
694 } else if (nv
[0] == "deprecated") {
695 if (eval (nv
[1]) == "1") {
696 st
.deprecated
= true;
698 } else if (nv
[0] == "replacement") {
699 st
.replacement
= eval (nv
[1]);
700 } else if (nv
[0] == "deprecated_since") {
701 st
.deprecated_since
= eval (nv
[1]);
702 } else if (nv
[0] == "has_destroy_function") {
703 if (eval (nv
[1]) == "0") {
704 st
.has_destroy_function
= false;
706 } else if (nv
[0] == "experimental") {
707 if (eval (nv
[1]) == "1") {
708 st
.experimental
= true;
714 add_symbol_to_container (container
, st
);
715 current_source_file
.add_node (st
);
718 current_data_type
= st
;
720 foreach (weak IdlNode member
in st_node
.members
) {
721 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
722 var m
= parse_function ((IdlNodeFunction
) member
);
726 } else if (member
.type
== IdlNodeTypeId
.FIELD
) {
727 var f
= parse_field ((IdlNodeField
) member
);
734 current_data_type
= null;
736 bool ref_function_void
= false;
737 string ref_function
= null;
738 string unref_function
= null;
739 string copy_function
= null;
740 string free_function
= null;
742 var cl
= container
.scope
.lookup (name
) as Class
;
744 string base_class
= null;
746 cl
= new
Class (name
, current_source_reference
);
747 cl
.access
= SymbolAccessibility
.PUBLIC
;
748 cl
.is_compact
= true;
750 var cl_attributes
= get_attributes (node
.name
);
751 if (cl_attributes
!= null) {
752 foreach (string attr
in cl_attributes
) {
753 var nv
= attr
.split ("=", 2);
754 if (nv
[0] == "cheader_filename") {
755 cl
.add_cheader_filename (eval (nv
[1]));
756 } else if (nv
[0] == "base_class") {
757 base_class
= eval (nv
[1]);
758 } else if (nv
[0] == "hidden") {
759 if (eval (nv
[1]) == "1") {
762 } else if (nv
[0] == "is_immutable") {
763 if (eval (nv
[1]) == "1") {
764 cl
.is_immutable
= true;
766 } else if (nv
[0] == "const_cname") {
767 cl
.const_cname
= eval (nv
[1]);
768 } else if (nv
[0] == "is_fundamental") {
769 if (eval (nv
[1]) == "1") {
770 cl
.is_compact
= false;
772 } else if (nv
[0] == "abstract" && base_class
!= null) {
773 if (eval (nv
[1]) == "1") {
774 cl
.is_abstract
= true;
776 } else if (nv
[0] == "free_function") {
777 free_function
= eval (nv
[1]);
778 } else if (nv
[0] == "ref_function") {
779 ref_function
= eval (nv
[1]);
780 } else if (nv
[0] == "unref_function") {
781 unref_function
= eval (nv
[1]);
782 } else if (nv
[0] == "copy_function") {
783 copy_function
= eval (nv
[1]);
784 } else if (nv
[0] == "ref_function_void") {
785 if (eval (nv
[1]) == "1") {
786 ref_function_void
= true;
788 } else if (nv
[0] == "deprecated") {
789 if (eval (nv
[1]) == "1") {
790 cl
.deprecated
= true;
792 } else if (nv
[0] == "replacement") {
793 cl
.replacement
= eval (nv
[1]);
794 } else if (nv
[0] == "deprecated_since") {
795 cl
.deprecated_since
= eval (nv
[1]);
796 } else if (nv
[0] == "type_parameters") {
797 foreach (string type_param_name
in eval (nv
[1]).split (",")) {
798 cl
.add_type_parameter (new
TypeParameter (type_param_name
, current_source_reference
));
800 } else if (nv
[0] == "experimental") {
801 if (eval (nv
[1]) == "1") {
802 cl
.experimental
= true;
808 add_symbol_to_container (container
, cl
);
809 current_source_file
.add_node (cl
);
811 if (base_class
!= null) {
812 var parent
= parse_type_string (base_class
);
813 cl
.add_base_type (parent
);
817 current_data_type
= cl
;
819 foreach (weak IdlNode member
in st_node
.members
) {
820 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
821 if ((ref_function
== null) && (member
.name
== "ref")) {
822 ref_function
= ((IdlNodeFunction
) member
).symbol
;
823 ref_function_void
= (parse_type (((IdlNodeFunction
) member
).result
.type
) is VoidType
);
824 } else if ((unref_function
== null) && (member
.name
== "unref")) {
825 unref_function
= ((IdlNodeFunction
) member
).symbol
;
826 } else if ((free_function
== null) && (member
.name
== "free" || member
.name
== "destroy")) {
827 free_function
= ((IdlNodeFunction
) member
).symbol
;
829 if ((copy_function
== null) && (member
.name
== "copy")) {
830 copy_function
= ((IdlNodeFunction
) member
).symbol
;
832 var m
= parse_function ((IdlNodeFunction
) member
);
837 } else if (member
.type
== IdlNodeTypeId
.FIELD
) {
838 var f
= parse_field ((IdlNodeField
) member
);
845 if (ref_function
!= null) {
846 cl
.set_ref_function (ref_function
);
847 cl
.ref_function_void
= ref_function_void
;
849 if (copy_function
!= null) {
850 cl
.set_dup_function (copy_function
);
852 if (unref_function
!= null) {
853 cl
.set_unref_function (unref_function
);
854 } else if (free_function
!= null) {
855 cl
.set_free_function (free_function
);
858 current_data_type
= null;
862 private void parse_union (IdlNodeUnion un_node
, Symbol container
, IdlModule module
) {
863 weak IdlNode node
= (IdlNode
) un_node
;
865 if (un_node
.deprecated
) {
869 string name
= fix_type_name (node
.name
, container
);
871 if (!is_reference_type (node
.name
)) {
872 var st
= container
.scope
.lookup (name
) as Struct
;
874 st
= new
Struct (name
, current_source_reference
);
875 st
.access
= SymbolAccessibility
.PUBLIC
;
877 var st_attributes
= get_attributes (node
.name
);
878 if (st_attributes
!= null) {
879 foreach (string attr
in st_attributes
) {
880 var nv
= attr
.split ("=", 2);
881 if (nv
[0] == "cheader_filename") {
882 st
.add_cheader_filename (eval (nv
[1]));
883 } else if (nv
[0] == "deprecated") {
884 if (eval (nv
[1]) == "1") {
885 st
.deprecated
= true;
887 } else if (nv
[0] == "replacement") {
888 st
.replacement
= eval (nv
[1]);
889 } else if (nv
[0] == "deprecated_since") {
890 st
.deprecated_since
= eval (nv
[1]);
891 } else if (nv
[0] == "hidden") {
892 if (eval (nv
[1]) == "1") {
895 } else if (nv
[0] == "experimental") {
896 if (eval (nv
[1]) == "1") {
897 st
.experimental
= true;
903 add_symbol_to_container (container
, st
);
904 current_source_file
.add_node (st
);
907 current_data_type
= st
;
909 foreach (weak IdlNode member
in un_node
.members
) {
910 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
911 var m
= parse_function ((IdlNodeFunction
) member
);
915 } else if (member
.type
== IdlNodeTypeId
.FIELD
) {
916 var f
= parse_field ((IdlNodeField
) member
);
923 current_data_type
= null;
925 var cl
= container
.scope
.lookup (name
) as Class
;
927 cl
= new
Class (name
, current_source_reference
);
928 cl
.access
= SymbolAccessibility
.PUBLIC
;
929 cl
.is_compact
= true;
931 var cl_attributes
= get_attributes (node
.name
);
932 if (cl_attributes
!= null) {
933 foreach (string attr
in cl_attributes
) {
934 var nv
= attr
.split ("=", 2);
935 if (nv
[0] == "cheader_filename") {
936 cl
.add_cheader_filename (eval (nv
[1]));
937 } else if (nv
[0] == "hidden") {
938 if (eval (nv
[1]) == "1") {
945 add_symbol_to_container (container
, cl
);
946 current_source_file
.add_node (cl
);
949 current_data_type
= cl
;
951 bool ref_function_void
= false;
952 string ref_function
= null;
953 string unref_function
= null;
954 string copy_function
= null;
955 string free_function
= null;
957 foreach (weak IdlNode member
in un_node
.members
) {
958 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
959 if (member
.name
== "ref") {
960 ref_function
= ((IdlNodeFunction
) member
).symbol
;
961 ref_function_void
= (parse_type (((IdlNodeFunction
) member
).result
.type
) is VoidType
);
962 } else if (member
.name
== "unref") {
963 unref_function
= ((IdlNodeFunction
) member
).symbol
;
964 } else if (member
.name
== "free" || member
.name
== "destroy") {
965 free_function
= ((IdlNodeFunction
) member
).symbol
;
967 if (member
.name
== "copy") {
968 copy_function
= ((IdlNodeFunction
) member
).symbol
;
970 var m
= parse_function ((IdlNodeFunction
) member
);
975 } else if (member
.type
== IdlNodeTypeId
.FIELD
) {
976 var f
= parse_field ((IdlNodeField
) member
);
983 if (ref_function
!= null) {
984 cl
.set_ref_function (ref_function
);
985 cl
.ref_function_void
= ref_function_void
;
987 if (copy_function
!= null) {
988 cl
.set_dup_function (copy_function
);
990 if (unref_function
!= null) {
991 cl
.set_unref_function (unref_function
);
992 } else if (free_function
!= null) {
993 cl
.set_free_function (free_function
);
996 current_data_type
= null;
1000 private void parse_boxed (IdlNodeBoxed boxed_node
, Symbol container
, IdlModule module
) {
1001 weak IdlNode node
= (IdlNode
) boxed_node
;
1003 string name
= fix_type_name (node
.name
, container
);
1005 var node_attributes
= get_attributes (node
.name
);
1006 if (node_attributes
!= null) {
1007 foreach (string attr
in node_attributes
) {
1008 var nv
= attr
.split ("=", 2);
1009 if (nv
[0] == "hidden") {
1015 if (!is_reference_type (node
.name
)) {
1016 var st
= container
.scope
.lookup (name
) as Struct
;
1018 st
= new
Struct (name
, current_source_reference
);
1019 st
.access
= SymbolAccessibility
.PUBLIC
;
1021 var st_attributes
= get_attributes (node
.name
);
1022 if (st_attributes
!= null) {
1023 foreach (string attr
in st_attributes
) {
1024 var nv
= attr
.split ("=", 2);
1025 if (nv
[0] == "cheader_filename") {
1026 st
.add_cheader_filename (eval (nv
[1]));
1027 } else if (nv
[0] == "deprecated") {
1028 if (eval (nv
[1]) == "1") {
1029 st
.deprecated
= true;
1031 } else if (nv
[0] == "replacement") {
1032 st
.replacement
= eval (nv
[1]);
1033 } else if (nv
[0] == "deprecated_since") {
1034 st
.deprecated_since
= eval (nv
[1]);
1035 } else if (nv
[0] == "immutable") {
1036 if (eval (nv
[1]) == "1") {
1037 st
.is_immutable
= true;
1039 } else if (nv
[0] == "has_copy_function") {
1040 if (eval (nv
[1]) == "0") {
1041 st
.has_copy_function
= false;
1043 } else if (nv
[0] == "has_destroy_function") {
1044 if (eval (nv
[1]) == "0") {
1045 st
.has_destroy_function
= false;
1047 } else if (nv
[0] == "experimental") {
1048 if (eval (nv
[1]) == "1") {
1049 st
.experimental
= true;
1055 add_symbol_to_container (container
, st
);
1056 st
.set_type_id (st
.get_upper_case_cname ("TYPE_"));
1057 current_source_file
.add_node (st
);
1060 current_data_type
= st
;
1062 foreach (weak IdlNode member
in boxed_node
.members
) {
1063 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
1064 var m
= parse_function ((IdlNodeFunction
) member
);
1068 } else if (member
.type
== IdlNodeTypeId
.FIELD
) {
1069 var f
= parse_field ((IdlNodeField
) member
);
1076 current_data_type
= null;
1078 bool ref_function_void
= false;
1079 string ref_function
= null;
1080 string unref_function
= null;
1081 string copy_function
= null;
1082 string free_function
= null;
1084 var cl
= container
.scope
.lookup (name
) as Class
;
1086 string base_class
= null;
1088 cl
= new
Class (name
, current_source_reference
);
1089 cl
.access
= SymbolAccessibility
.PUBLIC
;
1090 cl
.is_compact
= true;
1092 var cl_attributes
= get_attributes (node
.name
);
1093 if (cl_attributes
!= null) {
1094 foreach (string attr
in cl_attributes
) {
1095 var nv
= attr
.split ("=", 2);
1096 if (nv
[0] == "cheader_filename") {
1097 cl
.add_cheader_filename (eval (nv
[1]));
1098 } else if (nv
[0] == "base_class") {
1099 base_class
= eval (nv
[1]);
1100 } else if (nv
[0] == "is_immutable") {
1101 if (eval (nv
[1]) == "1") {
1102 cl
.is_immutable
= true;
1104 } else if (nv
[0] == "deprecated") {
1105 if (eval (nv
[1]) == "1") {
1106 cl
.deprecated
= true;
1108 } else if (nv
[0] == "replacement") {
1109 cl
.replacement
= eval (nv
[1]);
1110 } else if (nv
[0] == "deprecated_since") {
1111 cl
.deprecated_since
= eval (nv
[1]);
1112 } else if (nv
[0] == "const_cname") {
1113 cl
.const_cname
= eval (nv
[1]);
1114 } else if (nv
[0] == "free_function") {
1115 free_function
= eval (nv
[1]);
1116 } else if (nv
[0] == "ref_function") {
1117 ref_function
= eval (nv
[1]);
1118 } else if (nv
[0] == "unref_function") {
1119 unref_function
= eval (nv
[1]);
1120 } else if (nv
[0] == "copy_function") {
1121 copy_function
= eval (nv
[1]);
1122 } else if (nv
[0] == "ref_function_void") {
1123 if (eval (nv
[1]) == "1") {
1124 ref_function_void
= true;
1126 } else if (nv
[0] == "experimental") {
1127 if (eval (nv
[1]) == "1") {
1128 cl
.experimental
= true;
1134 add_symbol_to_container (container
, cl
);
1135 cl
.set_type_id (cl
.get_upper_case_cname ("TYPE_"));
1136 current_source_file
.add_node (cl
);
1138 if (base_class
!= null) {
1139 var parent
= parse_type_string (base_class
);
1140 cl
.add_base_type (parent
);
1144 current_data_type
= cl
;
1146 foreach (weak IdlNode member
in boxed_node
.members
) {
1147 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
1148 if (member
.name
== "ref") {
1149 ref_function
= ((IdlNodeFunction
) member
).symbol
;
1150 ref_function_void
= (parse_type (((IdlNodeFunction
) member
).result
.type
) is VoidType
);
1151 } else if (member
.name
== "unref") {
1152 unref_function
= ((IdlNodeFunction
) member
).symbol
;
1153 } else if (member
.name
== "free" || member
.name
== "destroy") {
1154 free_function
= ((IdlNodeFunction
) member
).symbol
;
1156 if (member
.name
== "copy") {
1157 copy_function
= ((IdlNodeFunction
) member
).symbol
;
1159 var m
= parse_function ((IdlNodeFunction
) member
);
1164 } else if (member
.type
== IdlNodeTypeId
.FIELD
) {
1165 var f
= parse_field ((IdlNodeField
) member
);
1172 if (ref_function
!= null) {
1173 cl
.set_ref_function (ref_function
);
1174 cl
.ref_function_void
= ref_function_void
;
1176 if (copy_function
!= null) {
1177 cl
.set_dup_function (copy_function
);
1179 if (unref_function
!= null) {
1180 cl
.set_unref_function (unref_function
);
1181 } else if (free_function
!= null) {
1182 cl
.set_free_function (free_function
);
1185 current_data_type
= null;
1189 private void parse_enum (IdlNodeEnum en_node
, Symbol container
, IdlModule module
, bool is_flags
) {
1190 weak IdlNode node
= (IdlNode
) en_node
;
1191 string name
= fix_type_name (node
.name
, container
);
1192 bool existing
= true;
1194 var en
= container
.scope
.lookup (name
) as Enum
;
1196 en
= new
Enum (name
, current_source_reference
);
1197 en
.access
= SymbolAccessibility
.PUBLIC
;
1200 // ignore dummy enum values in -custom.vala files
1201 // they exist for syntactical reasons
1202 var dummy
= (EnumValue
) en
.scope
.lookup ("__DUMMY__");
1203 if (dummy
!= null) {
1204 en
.get_values ().remove (dummy
);
1205 en
.scope
.remove ("__DUMMY__");
1209 en
.has_type_id
= (en_node
.gtype_name
!= null && en_node
.gtype_name
!= "");
1211 string common_prefix
= null;
1213 foreach (weak IdlNode value
in en_node
.values
) {
1214 var val_attributes
= get_attributes (value
.name
);
1215 bool is_hidden
= false;
1216 if (val_attributes
!= null) {
1217 foreach (string attr
in val_attributes
) {
1218 var nv
= attr
.split ("=", 2);
1219 if (nv
[0] == "hidden" && eval(nv
[1]) == "1") {
1229 if (common_prefix
== null) {
1230 common_prefix
= value
.name
;
1231 while (common_prefix
.length
> 0 && !common_prefix
.has_suffix ("_")) {
1232 // FIXME: could easily be made faster
1233 common_prefix
= common_prefix
.substring (0, common_prefix
.length
- 1);
1236 while (!value
.name
.has_prefix (common_prefix
)) {
1237 common_prefix
= common_prefix
.substring (0, common_prefix
.length
- 1);
1240 while (common_prefix
.length
> 0 && (!common_prefix
.has_suffix ("_") ||
1241 (value
.name
.get_char (common_prefix
.length
).isdigit ()) && (value
.name
.length
- common_prefix
.length
) <= 1)) {
1242 // enum values may not consist solely of digits
1243 common_prefix
= common_prefix
.substring (0, common_prefix
.length
- 1);
1247 bool is_errordomain
= false;
1249 var cheader_filenames
= new ArrayList
<string> ();
1251 var en_attributes
= get_attributes (node
.name
);
1252 if (en_attributes
!= null) {
1253 foreach (string attr
in en_attributes
) {
1254 var nv
= attr
.split ("=", 2);
1255 if (nv
[0] == "common_prefix") {
1256 common_prefix
= eval (nv
[1]);
1257 } else if (nv
[0] == "cheader_filename") {
1258 cheader_filenames
.add (eval (nv
[1]));
1259 en
.add_cheader_filename (eval (nv
[1]));
1260 } else if (nv
[0] == "hidden") {
1261 if (eval (nv
[1]) == "1") {
1264 } else if (nv
[0] == "deprecated") {
1265 if (eval (nv
[1]) == "1") {
1266 en
.deprecated
= true;
1268 } else if (nv
[0] == "replacement") {
1269 en
.replacement
= eval (nv
[1]);
1270 } else if (nv
[0] == "deprecated_since") {
1271 en
.deprecated_since
= eval (nv
[1]);
1272 } else if (nv
[0] == "rename_to") {
1273 en
.name
= eval (nv
[1]);
1274 } else if (nv
[0] == "errordomain") {
1275 if (eval (nv
[1]) == "1") {
1276 is_errordomain
= true;
1278 } else if (nv
[0] == "to_string") {
1279 var return_type
= new
UnresolvedType ();
1280 return_type
.unresolved_symbol
= new
UnresolvedSymbol (null, "string");
1281 return_type
.value_owned
= false;
1282 var m
= new
Method ("to_string", return_type
, current_source_reference
);
1283 m
.access
= SymbolAccessibility
.PUBLIC
;
1284 m
.set_cname (eval(nv
[1]));
1286 } else if (nv
[0] == "experimental") {
1287 if (eval (nv
[1]) == "1") {
1288 en
.experimental
= true;
1294 en
.set_cprefix (common_prefix
);
1296 foreach (weak IdlNode value2
in en_node
.values
) {
1297 var val_attributes
= get_attributes (value2
.name
);
1298 bool is_hidden
= false;
1299 if (val_attributes
!= null) {
1300 foreach (string attr
in val_attributes
) {
1301 var nv
= attr
.split ("=", 2);
1302 if (nv
[0] == "hidden" && eval(nv
[1]) == "1") {
1309 var ev
= new
EnumValue (value2
.name
.substring (common_prefix
.length
), null);
1314 if (is_errordomain
) {
1315 var ed
= new
ErrorDomain (en
.name
, current_source_reference
);
1316 ed
.access
= SymbolAccessibility
.PUBLIC
;
1317 ed
.set_cprefix (common_prefix
);
1319 foreach (string filename
in cheader_filenames
) {
1320 ed
.add_cheader_filename (filename
);
1323 foreach (EnumValue ev
in en
.get_values ()) {
1324 ed
.add_code (new
ErrorCode (ev
.name
));
1327 current_source_file
.add_node (ed
);
1329 add_symbol_to_container (container
, ed
);
1332 en
.is_flags
= is_flags
;
1333 current_source_file
.add_node (en
);
1335 add_symbol_to_container (container
, en
);
1340 private void parse_object (IdlNodeInterface node
, Symbol container
, IdlModule module
) {
1341 string name
= fix_type_name (((IdlNode
) node
).name
, container
);
1343 string base_class
= null;
1345 var cl
= container
.scope
.lookup (name
) as Class
;
1347 cl
= new
Class (name
, current_source_reference
);
1348 cl
.access
= SymbolAccessibility
.PUBLIC
;
1350 var attributes
= get_attributes (node
.gtype_name
);
1351 if (attributes
!= null) {
1352 foreach (string attr
in attributes
) {
1353 var nv
= attr
.split ("=", 2);
1354 if (nv
[0] == "cheader_filename") {
1355 cl
.add_cheader_filename (eval (nv
[1]));
1356 } else if (nv
[0] == "base_class") {
1357 base_class
= eval (nv
[1]);
1358 } else if (nv
[0] == "hidden") {
1359 if (eval (nv
[1]) == "1") {
1362 } else if (nv
[0] == "type_check_function") {
1363 cl
.type_check_function
= eval (nv
[1]);
1364 } else if (nv
[0] == "deprecated") {
1365 if (eval (nv
[1]) == "1") {
1366 cl
.deprecated
= true;
1368 } else if (nv
[0] == "replacement") {
1369 cl
.replacement
= eval (nv
[1]);
1370 } else if (nv
[0] == "deprecated_since") {
1371 cl
.deprecated_since
= eval (nv
[1]);
1372 } else if (nv
[0] == "type_id") {
1373 cl
.set_type_id (eval (nv
[1]));
1374 } else if (nv
[0] == "abstract") {
1375 if (eval (nv
[1]) == "1") {
1376 cl
.is_abstract
= true;
1378 } else if (nv
[0] == "experimental") {
1379 if (eval (nv
[1]) == "1") {
1380 cl
.experimental
= true;
1386 add_symbol_to_container (container
, cl
);
1387 current_source_file
.add_node (cl
);
1390 if (base_class
!= null) {
1391 var parent
= parse_type_string (base_class
);
1392 cl
.add_base_type (parent
);
1393 } else if (node
.parent
!= null) {
1394 var parent
= parse_type_string (node
.parent
);
1395 cl
.add_base_type (parent
);
1397 var gobject_symbol
= new
UnresolvedSymbol (new
UnresolvedSymbol (null, "GLib"), "Object");
1398 cl
.add_base_type (new UnresolvedType
.from_symbol (gobject_symbol
));
1401 foreach (string iface_name
in node
.interfaces
) {
1402 bool skip_iface
= false;
1404 var attributes
= get_attributes (iface_name
);
1405 if (attributes
!= null) {
1406 foreach (string attr
in attributes
) {
1407 var nv
= attr
.split ("=", 2);
1408 if (nv
[0] == "hidden") {
1409 if (eval (nv
[1]) == "1") {
1420 var iface
= parse_type_string (iface_name
);
1421 cl
.add_base_type (iface
);
1424 current_data_type
= cl
;
1426 current_type_symbol_set
= new HashSet
<string> (str_hash
, str_equal
);
1427 var current_type_func_map
= new HashMap
<string,weak IdlNodeFunction
> (str_hash
, str_equal
);
1428 var current_type_vfunc_map
= new HashMap
<string,string> (str_hash
, str_equal
);
1430 foreach (weak IdlNode member
in node
.members
) {
1431 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
1432 current_type_func_map
.set (member
.name
, (IdlNodeFunction
) member
);
1434 if (member
.type
== IdlNodeTypeId
.VFUNC
) {
1435 current_type_vfunc_map
.set (member
.name
, "1");
1439 foreach (weak IdlNode member
in node
.members
) {
1440 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
1441 // Ignore if vfunc (handled below)
1442 if (!current_type_vfunc_map
.contains (member
.name
)) {
1443 var m
= parse_function ((IdlNodeFunction
) member
);
1448 } else if (member
.type
== IdlNodeTypeId
.VFUNC
) {
1449 var m
= parse_virtual ((IdlNodeVFunc
) member
, current_type_func_map
.get (member
.name
));
1453 } else if (member
.type
== IdlNodeTypeId
.PROPERTY
) {
1454 var prop
= parse_property ((IdlNodeProperty
) member
);
1456 cl
.add_property (prop
);
1458 } else if (member
.type
== IdlNodeTypeId
.SIGNAL
) {
1459 var sig
= parse_signal ((IdlNodeSignal
) member
);
1461 cl
.add_signal (sig
);
1466 foreach (weak IdlNode member
in node
.members
) {
1467 if (member
.type
== IdlNodeTypeId
.FIELD
) {
1468 if (!current_type_symbol_set
.contains (member
.name
)) {
1469 var f
= parse_field ((IdlNodeField
) member
);
1477 foreach (Property prop
in cl
.get_properties ()) {
1478 var getter
= "get_%s".printf (prop
.name
);
1480 if (prop
.get_accessor
!= null && !current_type_symbol_set
.contains (getter
)) {
1481 prop
.no_accessor_method
= true;
1484 var setter
= "set_%s".printf (prop
.name
);
1486 if (prop
.set_accessor
!= null && prop
.set_accessor
.writable
1487 && !current_type_symbol_set
.contains (setter
)) {
1488 prop
.no_accessor_method
= true;
1491 if (prop
.no_accessor_method
&& prop
.get_accessor
!= null) {
1492 prop
.get_accessor
.value_type
.value_owned
= true;
1496 handle_async_methods (cl
);
1498 if (cl
.default_construction_method
== null) {
1499 // always provide constructor in generated bindings
1500 // to indicate that implicit Object () chainup is allowed
1501 var cm
= new
CreationMethod (null, null, cl
.source_reference
);
1502 cm
.has_construct_function
= false;
1503 cm
.access
= SymbolAccessibility
.PROTECTED
;
1507 current_data_type
= null;
1508 current_type_symbol_set
= null;
1511 private void parse_interface (IdlNodeInterface node
, Symbol container
, IdlModule module
) {
1512 string name
= fix_type_name (node
.gtype_name
, container
);
1514 var iface
= container
.scope
.lookup (name
) as Interface
;
1515 if (iface
== null) {
1516 iface
= new
Interface (name
, current_source_reference
);
1517 iface
.access
= SymbolAccessibility
.PUBLIC
;
1519 var attributes
= get_attributes (node
.gtype_name
);
1520 if (attributes
!= null) {
1521 foreach (string attr
in attributes
) {
1522 var nv
= attr
.split ("=", 2);
1523 if (nv
[0] == "cheader_filename") {
1524 iface
.add_cheader_filename (eval (nv
[1]));
1525 } else if (nv
[0] == "type_cname") {
1526 iface
.set_type_cname (eval (nv
[1]));
1527 } else if (nv
[0] == "lower_case_csuffix") {
1528 iface
.set_lower_case_csuffix (eval (nv
[1]));
1533 foreach (string prereq_name
in node
.prerequisites
) {
1534 var prereq
= parse_type_string (prereq_name
);
1535 iface
.add_prerequisite (prereq
);
1538 add_symbol_to_container (container
, iface
);
1539 current_source_file
.add_node (iface
);
1542 current_data_type
= iface
;
1544 var current_type_func_map
= new HashMap
<string,weak IdlNodeFunction
> (str_hash
, str_equal
);
1545 var current_type_vfunc_map
= new HashMap
<string,string> (str_hash
, str_equal
);
1547 foreach (weak IdlNode member
in node
.members
) {
1548 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
1549 current_type_func_map
.set (member
.name
, (IdlNodeFunction
) member
);
1551 if (member
.type
== IdlNodeTypeId
.VFUNC
) {
1552 current_type_vfunc_map
.set (member
.name
, "1");
1556 foreach (weak IdlNode member
in node
.members
) {
1557 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
1558 // Ignore if vfunc (handled below)
1559 if (!current_type_vfunc_map
.contains (member
.name
)) {
1560 var m
= parse_function ((IdlNodeFunction
) member
, true);
1562 iface
.add_method (m
);
1565 } else if (member
.type
== IdlNodeTypeId
.VFUNC
) {
1566 var m
= parse_virtual ((IdlNodeVFunc
) member
, current_type_func_map
.get (member
.name
), true);
1568 iface
.add_method (m
);
1570 } else if (member
.type
== IdlNodeTypeId
.PROPERTY
) {
1571 var prop
= parse_property ((IdlNodeProperty
) member
);
1573 iface
.add_property (prop
);
1575 } else if (member
.type
== IdlNodeTypeId
.SIGNAL
) {
1576 var sig
= parse_signal ((IdlNodeSignal
) member
);
1578 iface
.add_signal (sig
);
1579 sig
.is_virtual
= false;
1584 handle_async_methods (iface
);
1586 current_data_type
= null;
1589 void handle_async_methods (ObjectTypeSymbol type_symbol
) {
1590 Set
<Method
> finish_methods
= new HashSet
<Method
> ();
1591 var methods
= type_symbol
.get_methods ();
1593 foreach (Method m
in methods
) {
1595 string finish_method_base
;
1596 if (m
.name
.has_suffix ("_async")) {
1597 finish_method_base
= m
.name
.substring (0, m
.name
.length
- "_async".length
);
1599 finish_method_base
= m
.name
;
1601 var finish_method
= type_symbol
.scope
.lookup (finish_method_base
+ "_finish") as Method
;
1603 // check if the method is using non-standard finish method name
1604 if (finish_method
== null) {
1605 var method_cname
= m
.get_finish_cname ();
1606 foreach (Method method
in type_symbol
.get_methods ()) {
1607 if (method
.get_cname () == method_cname
) {
1608 finish_method
= method
;
1614 if (finish_method
!= null) {
1615 m
.return_type
= finish_method
.return_type
.copy ();
1616 m
.no_array_length
= finish_method
.no_array_length
;
1617 m
.array_null_terminated
= finish_method
.array_null_terminated
;
1618 foreach (var param
in finish_method
.get_parameters ()) {
1619 if (param
.direction
== ParameterDirection
.OUT
) {
1620 var async_param
= param
.copy ();
1621 if (m
.scope
.lookup (param
.name
) != null) {
1622 // parameter name conflict
1623 async_param
.name
+= "_out";
1625 m
.add_parameter (async_param
);
1628 foreach (DataType error_type
in finish_method
.get_error_types ()) {
1629 m
.add_error_type (error_type
.copy ());
1631 finish_methods
.add (finish_method
);
1636 foreach (Method m
in finish_methods
)
1638 type_symbol
.scope
.remove (m
.name
);
1643 private DataType?
parse_type (IdlNodeType type_node
, out ParameterDirection direction
= null) {
1644 ParameterDirection dir
= ParameterDirection
.IN
;
1646 var type
= new
UnresolvedType ();
1647 if (type_node
.tag
== TypeTag
.VOID
) {
1648 if (type_node
.is_pointer
) {
1649 return new
PointerType (new
VoidType ());
1651 return new
VoidType ();
1653 } else if (type_node
.tag
== TypeTag
.BOOLEAN
) {
1654 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "bool");
1655 } else if (type_node
.tag
== TypeTag
.INT8
) {
1656 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "char");
1657 } else if (type_node
.tag
== TypeTag
.UINT8
) {
1658 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "uchar");
1659 } else if (type_node
.tag
== TypeTag
.INT16
) {
1660 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "int16");
1661 } else if (type_node
.tag
== TypeTag
.UINT16
) {
1662 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "uint16");
1663 } else if (type_node
.tag
== TypeTag
.INT32
) {
1664 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "int32");
1665 } else if (type_node
.tag
== TypeTag
.UINT32
) {
1666 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "uint32");
1667 } else if (type_node
.tag
== TypeTag
.INT64
) {
1668 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "int64");
1669 } else if (type_node
.tag
== TypeTag
.UINT64
) {
1670 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "uint64");
1671 } else if (type_node
.tag
== TypeTag
.INT
) {
1672 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "int");
1673 } else if (type_node
.tag
== TypeTag
.UINT
) {
1674 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "uint");
1675 } else if (type_node
.tag
== TypeTag
.LONG
) {
1676 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "long");
1677 } else if (type_node
.tag
== TypeTag
.ULONG
) {
1678 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "ulong");
1679 } else if (type_node
.tag
== TypeTag
.SSIZE
) {
1680 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "ssize_t");
1681 } else if (type_node
.tag
== TypeTag
.SIZE
) {
1682 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "size_t");
1683 } else if (type_node
.tag
== TypeTag
.FLOAT
) {
1684 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "float");
1685 } else if (type_node
.tag
== TypeTag
.DOUBLE
) {
1686 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "double");
1687 } else if (type_node
.tag
== TypeTag
.UTF8
) {
1688 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "string");
1689 } else if (type_node
.tag
== TypeTag
.FILENAME
) {
1690 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "string");
1691 } else if (type_node
.tag
== TypeTag
.ARRAY
) {
1692 var element_type
= parse_type (type_node
.parameter_type1
);
1693 type
= element_type as UnresolvedType
;
1695 return element_type
;
1697 return new
ArrayType (element_type
, 1, element_type
.source_reference
);
1698 } else if (type_node
.tag
== TypeTag
.LIST
) {
1699 type
.unresolved_symbol
= new
UnresolvedSymbol (new
UnresolvedSymbol (null, "GLib"), "List");
1700 } else if (type_node
.tag
== TypeTag
.SLIST
) {
1701 type
.unresolved_symbol
= new
UnresolvedSymbol (new
UnresolvedSymbol (null, "GLib"), "SList");
1702 } else if (type_node
.tag
== TypeTag
.HASH
) {
1703 type
.unresolved_symbol
= new
UnresolvedSymbol (new
UnresolvedSymbol (null, "GLib"), "HashTable");
1704 } else if (type_node
.tag
== TypeTag
.ERROR
) {
1705 type
.unresolved_symbol
= new
UnresolvedSymbol (new
UnresolvedSymbol (null, "GLib"), "Error");
1706 } else if (type_node
.is_interface
) {
1707 var n
= type_node
.@
interface;
1713 if (n
.has_prefix ("const-")) {
1714 n
= n
.substring ("const-".length
);
1717 if (type_node
.is_pointer
&&
1718 (n
== "gchar" || n
== "char")) {
1719 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "string");
1720 if (type_node
.unparsed
.has_suffix ("**")) {
1721 dir
= ParameterDirection
.OUT
;
1723 } else if (n
== "gunichar") {
1724 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "unichar");
1725 } else if (n
== "gchar") {
1726 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "char");
1727 } else if (n
== "guchar" || n
== "guint8") {
1728 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "uchar");
1729 if (type_node
.is_pointer
) {
1730 return new
ArrayType (type
, 1, type
.source_reference
);
1732 } else if (n
== "gushort") {
1733 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "ushort");
1734 } else if (n
== "gshort") {
1735 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "short");
1736 } else if (n
== "gconstpointer" || n
== "void") {
1737 return new
PointerType (new
VoidType ());
1738 } else if (n
== "goffset" || n
== "off_t") {
1739 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "int64");
1740 } else if (n
== "value_array") {
1741 type
.unresolved_symbol
= new
UnresolvedSymbol (new
UnresolvedSymbol (null, "GLib"), "ValueArray");
1742 } else if (n
== "time_t") {
1743 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "ulong");
1744 } else if (n
== "socklen_t") {
1745 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "uint32");
1746 } else if (n
== "mode_t") {
1747 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "uint");
1748 } else if (n
== "gint" || n
== "pid_t") {
1749 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "int");
1750 } else if (n
== "unsigned" || n
== "unsigned-int") {
1751 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "uint");
1752 } else if (n
== "FILE") {
1753 type
.unresolved_symbol
= new
UnresolvedSymbol (new
UnresolvedSymbol (null, "GLib"), "FileStream");
1754 } else if (n
== "struct") {
1755 return new
PointerType (new
VoidType ());
1756 } else if (n
== "iconv_t") {
1757 return new
PointerType (new
VoidType ());
1758 } else if (n
== "GType") {
1759 type
.unresolved_symbol
= new
UnresolvedSymbol (new
UnresolvedSymbol (null, "GLib"), "Type");
1760 if (type_node
.is_pointer
) {
1761 return new
ArrayType (type
, 1, type
.source_reference
);
1763 } else if (n
== "GStrv") {
1764 type
.unresolved_symbol
= new
UnresolvedSymbol (null, "string");
1765 return new
ArrayType (type
, 1, type
.source_reference
);
1767 var named_type
= parse_type_string (n
);
1768 type
= named_type as UnresolvedType
;
1772 if (is_simple_type (n
)) {
1773 if (type_node
.is_pointer
) {
1774 dir
= ParameterDirection
.OUT
;
1776 } else if (type_node
.unparsed
.has_suffix ("**")) {
1777 dir
= ParameterDirection
.OUT
;
1781 stdout
.printf ("%d\n", type_node
.tag
);
1783 if (&direction
!= null) {
1789 private bool is_simple_type (string type_name
) {
1790 var st
= cname_type_map
[type_name
] as Struct
;
1791 if (st
!= null && st
.is_simple_type ()) {
1798 private DataType
parse_type_string (string n
) {
1799 if (n
== "va_list") {
1801 return new
PointerType (new
VoidType ());
1804 var type
= new
UnresolvedType ();
1806 var dt
= cname_type_map
[n
];
1808 UnresolvedSymbol parent_symbol
= null;
1809 if (dt
.parent_symbol
.name
!= null) {
1810 parent_symbol
= new
UnresolvedSymbol (null, dt
.parent_symbol
.name
);
1812 type
.unresolved_symbol
= new
UnresolvedSymbol (parent_symbol
, dt
.name
);
1816 var type_attributes
= get_attributes (n
);
1818 string ns_name
= null;
1820 if (null != type_attributes
) {
1821 foreach (string attr
in type_attributes
) {
1822 var nv
= attr
.split ("=", 2);
1824 if (nv
[0] == "cprefix") {
1825 type
.unresolved_symbol
= new
UnresolvedSymbol (null, n
.substring (eval (nv
[1]).length
));
1826 } else if (nv
[0] == "name") {
1827 type
.unresolved_symbol
= new
UnresolvedSymbol (null, eval (nv
[1]));
1828 } else if (nv
[0] == "namespace") {
1829 ns_name
= eval (nv
[1]);
1830 } else if (nv
[0] == "rename_to") {
1831 type
.unresolved_symbol
= new
UnresolvedSymbol (null, eval (nv
[1]));
1836 if (type
.unresolved_symbol
!= null) {
1837 if (type
.unresolved_symbol
.name
== "pointer") {
1838 return new
PointerType (new
VoidType ());
1840 if (ns_name
!= null) {
1841 type
.unresolved_symbol
.inner
= new
UnresolvedSymbol (null, ns_name
);
1846 if (n
.has_prefix (current_namespace
.name
)) {
1847 type
.unresolved_symbol
= new
UnresolvedSymbol (new
UnresolvedSymbol (null, current_namespace
.name
), n
.substring (current_namespace
.name
.length
));
1848 } else if (n
.has_prefix ("G")) {
1849 type
.unresolved_symbol
= new
UnresolvedSymbol (new
UnresolvedSymbol (null, "GLib"), n
.substring (1));
1851 var name_parts
= n
.split (".", 2);
1852 if (name_parts
[1] == null) {
1853 type
.unresolved_symbol
= new
UnresolvedSymbol (null, name_parts
[0]);
1855 type
.unresolved_symbol
= new
UnresolvedSymbol (new
UnresolvedSymbol (null, name_parts
[0]), name_parts
[1]);
1862 private DataType?
parse_param (IdlNodeParam param
, out ParameterDirection direction
= null) {
1863 var type
= parse_type (param
.type
, out direction
);
1865 // disable for now as null_ok not yet correctly set
1866 // type.non_null = !param.null_ok;
1871 private UnresolvedSymbol?
parse_symbol_from_string (string symbol_string
, SourceReference? source_reference
= null) {
1872 UnresolvedSymbol? sym
= null;
1873 foreach (unowned
string s
in symbol_string
.split (".")) {
1874 sym
= new
UnresolvedSymbol (sym
, s
, source_reference
);
1877 Report
.error (source_reference
, "a symbol must be specified");
1882 private bool parse_type_arguments_from_string (DataType parent_type
, string type_arguments
, SourceReference? source_reference
= null) {
1883 int type_arguments_length
= (int) type_arguments
.length
;
1884 GLib
.StringBuilder current
= new GLib
.StringBuilder
.sized (type_arguments_length
);
1887 for (var c
= 0 ; c
< type_arguments_length
; c
++) {
1888 if (type_arguments
[c
] == '<' || type_arguments
[c
] == '[') {
1890 current
.append_unichar (type_arguments
[c
]);
1891 } else if (type_arguments
[c
] == '>' || type_arguments
[c
] == ']') {
1893 current
.append_unichar (type_arguments
[c
]);
1894 } else if (type_arguments
[c
] == ',') {
1896 var dt
= parse_type_from_string (current
.str
, true, source_reference
);
1900 parent_type
.add_type_argument (dt
);
1901 current
.truncate ();
1903 current
.append_unichar (type_arguments
[c
]);
1906 current
.append_unichar (type_arguments
[c
]);
1910 var dt
= parse_type_from_string (current
.str
, true, source_reference
);
1914 parent_type
.add_type_argument (dt
);
1919 private DataType?
parse_type_from_string (string type_string
, bool owned_by_default
, SourceReference? source_reference
= null) {
1920 if (type_from_string_regex
== null) {
1922 type_from_string_regex
= new GLib
.Regex ("^(?:(owned|unowned|weak) +)?([0-9a-zA-Z_\\.]+)(?:<(.+)>)?(\\*+)?(\\[(,*)?\\])?(\\?)?$", GLib
.RegexCompileFlags
.ANCHORED
| GLib
.RegexCompileFlags
.DOLLAR_ENDONLY
| GLib
.RegexCompileFlags
.OPTIMIZE
);
1923 } catch (GLib
.RegexError e
) {
1924 GLib
.error ("Unable to compile regex: %s", e
.message
);
1928 GLib
.MatchInfo match
;
1929 if (!type_from_string_regex
.match (type_string
, 0, out match
)) {
1930 Report
.error (source_reference
, "unable to parse type");
1934 DataType? type
= null;
1936 var ownership_data
= match
.fetch (1);
1937 var type_name
= match
.fetch (2);
1938 var type_arguments_data
= match
.fetch (3);
1939 var pointers_data
= match
.fetch (4);
1940 var array_data
= match
.fetch (5);
1941 var array_dimension_data
= match
.fetch (6);
1942 var nullable_data
= match
.fetch (7);
1944 var nullable
= nullable_data
!= null && nullable_data
.length
> 0;
1946 if (ownership_data
== null && type_name
== "void") {
1947 if (array_data
== null && !nullable
) {
1948 type
= new
VoidType (source_reference
);
1949 if (pointers_data
!= null) {
1950 for (int i
=0; i
< pointers_data
.length
; i
++) {
1951 type
= new
PointerType (type
);
1956 Report
.error (source_reference
, "invalid void type");
1961 bool value_owned
= owned_by_default
;
1963 if (ownership_data
== "owned") {
1965 } else if (ownership_data
== "unowned") {
1966 value_owned
= false;
1969 var sym
= parse_symbol_from_string (type_name
, source_reference
);
1973 type
= new UnresolvedType
.from_symbol (sym
, source_reference
);
1975 if (type_arguments_data
!= null && type_arguments_data
.length
> 0) {
1976 if (!parse_type_arguments_from_string (type
, type_arguments_data
, source_reference
)) {
1981 if (pointers_data
!= null) {
1982 for (int i
=0; i
< pointers_data
.length
; i
++) {
1983 type
= new
PointerType (type
);
1987 if (array_data
!= null && array_data
.length
> 0) {
1988 type
= new
ArrayType (type
, array_dimension_data
.length
+ 1, source_reference
);
1991 type
.nullable
= nullable
;
1992 type
.value_owned
= value_owned
;
1996 private Method?
create_method (string name
, string symbol
, IdlNodeParam? res
, GLib
.List
<IdlNodeParam
>? parameters
, bool is_constructor
, bool is_interface
) {
1997 DataType return_type
= null;
1999 return_type
= parse_param (res
);
2003 if (!is_interface
&& (is_constructor
|| name
.has_prefix ("new"))) {
2004 m
= new
CreationMethod (null, name
, current_source_reference
);
2005 m
.has_construct_function
= false;
2006 if (m
.name
== "new") {
2008 } else if (m
.name
.has_prefix ("new_")) {
2009 m
.name
= m
.name
.substring ("new_".length
);
2011 // For classes, check whether a creation method return type equals to the
2012 // type of the class created. If the types do not match (e.g. in most
2013 // gtk widgets) add an attribute to the creation method indicating the used
2015 if (current_data_type is Class
&& res
!= null) {
2016 if ("%s*".printf (current_data_type
.get_cname()) != res
.type
.unparsed
) {
2017 ((CreationMethod
)m
).custom_return_type_cname
= res
.type
.unparsed
;
2021 m
= new
Method (name
, return_type
, current_source_reference
);
2023 m
.access
= SymbolAccessibility
.PUBLIC
;
2025 if (current_type_symbol_set
!= null) {
2026 current_type_symbol_set
.add (name
);
2029 if (current_data_type
!= null) {
2030 var sig_attributes
= get_attributes ("%s::%s".printf (current_data_type
.get_cname (), name
));
2031 if (sig_attributes
!= null) {
2032 foreach (string attr
in sig_attributes
) {
2033 var nv
= attr
.split ("=", 2);
2034 if (nv
[0] == "has_emitter" && eval (nv
[1]) == "1") {
2041 bool add_ellipsis
= false;
2042 bool suppress_throws
= false;
2043 string? error_types
= null;
2045 var attributes
= get_attributes (symbol
);
2046 if (attributes
!= null) {
2047 foreach (string attr
in attributes
) {
2048 var nv
= attr
.split ("=", 2);
2049 if (nv
[0] == "name") {
2050 m
.set_cname (m
.name
);
2051 m
.name
= eval (nv
[1]);
2052 } else if (nv
[0] == "hidden") {
2053 if (eval (nv
[1]) == "1") {
2056 } else if (nv
[0] == "ellipsis") {
2057 if (eval (nv
[1]) == "1") {
2058 add_ellipsis
= true;
2060 } else if (nv
[0] == "printf_format") {
2061 if (eval (nv
[1]) == "1") {
2062 m
.printf_format
= true;
2064 } else if (nv
[0] == "transfer_ownership") {
2065 if (eval (nv
[1]) == "1") {
2066 return_type
.value_owned
= true;
2068 } else if (nv
[0] == "nullable") {
2069 if (eval (nv
[1]) == "1") {
2070 return_type
.nullable
= true;
2072 } else if (nv
[0] == "sentinel") {
2073 m
.sentinel
= eval (nv
[1]);
2074 } else if (nv
[0] == "is_array") {
2075 if (eval (nv
[1]) == "1") {
2076 return_type
= new
ArrayType (return_type
, 1, return_type
.source_reference
);
2077 m
.return_type
= return_type
;
2079 } else if (nv
[0] == "throws") {
2080 if (eval (nv
[1]) == "0") {
2081 suppress_throws
= true;
2083 } else if (nv
[0] == "error_types") {
2084 error_types
= eval (nv
[1]);
2085 } else if (nv
[0] == "no_array_length") {
2086 if (eval (nv
[1]) == "1") {
2087 m
.no_array_length
= true;
2089 } else if (nv
[0] == "array_null_terminated") {
2090 if (eval (nv
[1]) == "1") {
2091 m
.no_array_length
= true;
2092 m
.array_null_terminated
= true;
2094 } else if (nv
[0] == "array_length_type") {
2095 m
.array_length_type
= eval (nv
[1]);
2096 } else if (nv
[0] == "type_name") {
2097 m
.return_type
= return_type
= parse_type_from_string (eval (nv
[1]), return_type
.value_owned
);
2098 } else if (nv
[0] == "type_arguments") {
2099 parse_type_arguments_from_string (return_type
, eval (nv
[1]));
2100 } else if (nv
[0] == "deprecated") {
2101 if (eval (nv
[1]) == "1") {
2102 m
.deprecated
= true;
2104 } else if (nv
[0] == "replacement") {
2105 m
.replacement
= eval (nv
[1]);
2106 } else if (nv
[0] == "deprecated_since") {
2107 m
.deprecated_since
= eval (nv
[1]);
2108 } else if (nv
[0] == "cheader_filename") {
2109 m
.add_cheader_filename (eval (nv
[1]));
2110 } else if (nv
[0] == "abstract") {
2111 if (eval (nv
[1]) == "1") {
2112 m
.is_abstract
= true;
2114 } else if (nv
[0] == "virtual") {
2115 if (eval (nv
[1]) == "1") {
2116 m
.is_virtual
= true;
2118 } else if (nv
[0] == "vfunc_name") {
2119 m
.vfunc_name
= eval (nv
[1]);
2120 } else if (nv
[0] == "finish_name") {
2121 m
.set_finish_cname (eval (nv
[1]));
2122 } else if (nv
[0] == "async") {
2123 if (eval (nv
[1]) == "1") {
2124 // force async function, even if it doesn't end in _async
2127 } else if (nv
[0] == "parent") {
2128 Symbol container
= get_container_from_name (eval (nv
[1]));
2129 var prefix
= container
.get_lower_case_cprefix ();
2130 if (symbol
.has_prefix (prefix
)) {
2131 m
.set_cname (m
.name
);
2132 m
.name
= symbol
.substring (prefix
.length
);
2134 } else if (nv
[0] == "experimental") {
2135 if (eval (nv
[1]) == "1") {
2136 m
.experimental
= true;
2142 m
.set_cname (symbol
);
2145 Parameter last_param
= null;
2146 DataType last_param_type
= null;
2147 foreach (weak IdlNodeParam param
in parameters
) {
2148 weak IdlNode param_node
= (IdlNode
) param
;
2152 if (!(m is CreationMethod
) &&
2153 current_data_type
!= null &&
2154 param
.type
.is_interface
&&
2155 (param_node
.name
== "self" ||
2156 param
.type
.@
interface.has_suffix (current_data_type
.get_cname ()))) {
2159 } else if (!(m is CreationMethod
) &&
2160 current_data_type
!= null &&
2161 param
.type
.is_interface
&&
2162 (param_node
.name
== "klass" ||
2163 param
.type
.@
interface.has_suffix ("%sClass".printf(current_data_type
.get_cname ())))) {
2165 m
.binding
= MemberBinding
.CLASS
;
2166 if (m
.name
.has_prefix ("class_")) {
2167 m
.name
= m
.name
.substring ("class_".length
, m
.name
.length
- "class_".length
);
2172 m
.binding
= MemberBinding
.STATIC
;
2176 if (param
.type
.@
interface == "GAsyncReadyCallback" && (symbol
.has_suffix ("_async") || m
.coroutine
)) {
2182 // check for GError parameter
2183 if (suppress_throws
== false && param_is_exception (param
)) {
2184 if (error_types
== null)
2185 m
.add_error_type (parse_type (param
.type
));
2189 string param_name
= param_node
.name
;
2190 if (param_name
== "result") {
2191 // avoid conflict with generated result variable
2192 param_name
= "_result";
2193 } else if (param_name
== "string") {
2194 // avoid conflict with string type
2197 ParameterDirection direction
;
2198 var param_type
= parse_param (param
, out direction
);
2199 var p
= new
Parameter (param_name
, param_type
);
2200 p
.direction
= direction
;
2202 bool hide_param
= false;
2203 bool show_param
= false;
2204 bool set_array_length_pos
= false;
2205 double array_length_pos
= 0;
2206 bool set_delegate_target_pos
= false;
2207 double delegate_target_pos
= 0;
2208 bool array_requested
= false;
2209 bool out_requested
= false;
2210 attributes
= get_attributes ("%s.%s".printf (symbol
, param_node
.name
));
2211 if (attributes
!= null) {
2212 foreach (string attr
in attributes
) {
2213 var nv
= attr
.split ("=", 2);
2214 if (nv
[0] == "is_array") {
2215 if (eval (nv
[1]) == "1") {
2216 param_type
= new
ArrayType (param_type
, 1, param_type
.source_reference
);
2217 p
.variable_type
= param_type
;
2218 if (!out_requested
) {
2219 p
.direction
= ParameterDirection
.IN
;
2221 array_requested
= true;
2223 } else if (nv
[0] == "is_out") {
2224 if (eval (nv
[1]) == "1") {
2225 p
.direction
= ParameterDirection
.OUT
;
2226 out_requested
= true;
2227 if (!array_requested
&& param_type is ArrayType
) {
2228 var array_type
= (ArrayType
) param_type
;
2229 param_type
= array_type
.element_type
;
2230 p
.variable_type
= param_type
;
2233 } else if (nv
[0] == "is_ref") {
2234 if (eval (nv
[1]) == "1") {
2235 p
.direction
= ParameterDirection
.REF
;
2236 if (!array_requested
&& param_type is ArrayType
) {
2237 var array_type
= (ArrayType
) param_type
;
2238 param_type
= array_type
.element_type
;
2239 p
.variable_type
= param_type
;
2242 } else if (nv
[0] == "nullable") {
2243 if (eval (nv
[1]) == "1") {
2244 param_type
.nullable
= true;
2246 } else if (nv
[0] == "transfer_ownership") {
2247 if (eval (nv
[1]) == "1") {
2248 param_type
.value_owned
= true;
2250 } else if (nv
[0] == "takes_ownership") {
2251 if (eval (nv
[1]) == "1") {
2252 param_type
.value_owned
= true;
2254 } else if (nv
[0] == "value_owned") {
2255 if (eval (nv
[1]) == "0") {
2256 param_type
.value_owned
= false;
2257 } else if (eval (nv
[1]) == "1") {
2258 param_type
.value_owned
= true;
2260 } else if (nv
[0] == "hidden") {
2261 if (eval (nv
[1]) == "1") {
2263 } else if (eval (nv
[1]) == "0") {
2266 } else if (nv
[0] == "no_array_length") {
2267 if (eval (nv
[1]) == "1") {
2268 p
.no_array_length
= true;
2270 } else if (nv
[0] == "array_length_type") {
2271 p
.array_length_type
= eval (nv
[1]);
2272 } else if (nv
[0] == "array_null_terminated") {
2273 if (eval (nv
[1]) == "1") {
2274 p
.no_array_length
= true;
2275 p
.array_null_terminated
= true;
2277 } else if (nv
[0] == "array_length_pos") {
2278 set_array_length_pos
= true;
2279 array_length_pos
= double.parse (eval (nv
[1]));
2280 } else if (nv
[0] == "delegate_target_pos") {
2281 set_delegate_target_pos
= true;
2282 delegate_target_pos
= double.parse (eval (nv
[1]));
2283 } else if (nv
[0] == "type_name") {
2284 p
.variable_type
= param_type
= parse_type_from_string (eval (nv
[1]), false);
2285 } else if (nv
[0] == "ctype") {
2286 p
.ctype
= eval (nv
[1]);
2287 } else if (nv
[0] == "type_arguments") {
2288 parse_type_arguments_from_string (param_type
, eval (nv
[1]));
2289 } else if (nv
[0] == "default_value") {
2290 var val
= eval (nv
[1]);
2291 if (val
== "null") {
2292 p
.initializer
= new
NullLiteral (param_type
.source_reference
);
2293 } else if (val
== "true") {
2294 p
.initializer
= new
BooleanLiteral (true, param_type
.source_reference
);
2295 } else if (val
== "false") {
2296 p
.initializer
= new
BooleanLiteral (false, param_type
.source_reference
);
2297 } else if (val
== "") {
2298 p
.initializer
= new
StringLiteral ("\"\"", param_type
.source_reference
);
2300 if (int64.try_parse (val
)) {
2301 p
.initializer
= new
IntegerLiteral (val
, param_type
.source_reference
);
2303 if (double.try_parse (val
)) {
2304 p
.initializer
= new
RealLiteral (val
, param_type
.source_reference
);
2306 if (val
.has_prefix ("\"") && val
.has_suffix ("\"")) {
2307 p
.initializer
= new
StringLiteral (val
, param_type
.source_reference
);
2309 foreach (var member
in val
.split (".")) {
2310 p
.initializer
= new
MemberAccess (p
.initializer
, member
, param_type
.source_reference
);
2320 if (last_param
!= null && p
.name
== "n_" + last_param
.name
) {
2321 if (!(last_param_type is ArrayType
)) {
2322 // last_param is array, p is array length
2323 last_param_type
= new
ArrayType (last_param_type
, 1, last_param_type
.source_reference
);
2324 last_param
.variable_type
= last_param_type
;
2325 last_param
.direction
= ParameterDirection
.IN
;
2328 // hide array length param
2330 } else if (last_param
!= null && p
.name
== "user_data") {
2331 // last_param is delegate
2333 // hide deleate target param
2337 if (show_param
|| !hide_param
) {
2338 m
.add_parameter (p
);
2339 if (set_array_length_pos
) {
2340 p
.carray_length_parameter_position
= array_length_pos
;
2342 if (set_delegate_target_pos
) {
2343 p
.cdelegate_target_parameter_position
= delegate_target_pos
;
2348 last_param_type
= param_type
;
2351 if (suppress_throws
== false && error_types
!= null) {
2352 var type_args
= eval (error_types
).split (",");
2353 foreach (string type_arg
in type_args
) {
2354 m
.add_error_type (parse_type_from_string (type_arg
, true));
2359 // no parameters => static method
2360 m
.binding
= MemberBinding
.STATIC
;
2363 if (last_param
!= null && last_param
.name
.has_prefix ("first_")) {
2364 last_param
.ellipsis
= true;
2365 } else if (add_ellipsis
) {
2366 m
.add_parameter (new Parameter
.with_ellipsis ());
2372 private bool param_is_exception (IdlNodeParam param
) {
2373 if (!param
.type
.is_error
) {
2376 var s
= param
.type
.unparsed
.chomp ();
2377 if (s
.has_suffix ("**")) {
2383 private Method?
parse_function (IdlNodeFunction f
, bool is_interface
= false) {
2384 weak IdlNode node
= (IdlNode
) f
;
2390 return create_method (node
.name
, f
.symbol
, f
.result
, f
.parameters
, f
.is_constructor
, is_interface
);
2393 private Method
parse_virtual (IdlNodeVFunc v
, IdlNodeFunction? func
, bool is_interface
= false) {
2394 weak IdlNode node
= (IdlNode
) v
;
2395 string symbol
= "%s%s".printf (current_data_type
.get_lower_case_cprefix(), node
.name
);
2398 symbol
= func
.symbol
;
2401 Method m
= create_method (node
.name
, symbol
, v
.result
, func
!= null ? func
.parameters
: v
.parameters
, false, is_interface
);
2403 m
.binding
= MemberBinding
.INSTANCE
;
2404 m
.is_virtual
= !(m
.is_abstract
|| is_interface
);
2405 m
.is_abstract
= m
.is_abstract
|| is_interface
;
2407 var attributes
= get_attributes (symbol
);
2408 if (attributes
!= null) {
2409 foreach (string attr
in attributes
) {
2410 var nv
= attr
.split ("=", 2);
2411 if (nv
[0] == "virtual") {
2412 if (eval (nv
[1]) == "0") {
2413 m
.is_virtual
= false;
2414 m
.is_abstract
= false;
2416 m
.is_virtual
= true;
2417 m
.is_abstract
= false;
2424 m
.attributes
.append (new
Attribute ("NoWrapper", null));
2431 private string fix_prop_name (string name
) {
2432 var str
= new
StringBuilder ();
2436 while (i
.length
> 0) {
2437 unichar c
= i
.get_char ();
2441 str
.append_unichar (c
);
2450 private Property?
parse_property (IdlNodeProperty prop_node
) {
2451 weak IdlNode node
= (IdlNode
) prop_node
;
2453 if (prop_node
.deprecated
) {
2457 if (!prop_node
.readable
&& !prop_node
.writable
) {
2458 // buggy GIDL definition
2459 prop_node
.readable
= true;
2460 prop_node
.writable
= true;
2463 var prop
= new
Property (fix_prop_name (node
.name
), parse_type (prop_node
.type
), null, null, current_source_reference
);
2464 prop
.access
= SymbolAccessibility
.PUBLIC
;
2465 prop
.interface_only
= true;
2467 if (prop_node
.type
.is_interface
&& prop_node
.type
.interface == "GStrv") {
2468 prop
.no_array_length
= true;
2469 prop
.array_null_terminated
= true;
2472 if (prop_node
.readable
) {
2473 prop
.get_accessor
= new
PropertyAccessor (true, false, false, prop
.property_type
.copy (), null, null);
2475 if (prop_node
.writable
) {
2476 prop
.set_accessor
= new
PropertyAccessor (false, false, false, prop
.property_type
.copy (), null, null);
2477 if (prop_node
.construct_only
) {
2478 prop
.set_accessor
.construction
= true;
2480 prop
.set_accessor
.writable
= true;
2481 prop
.set_accessor
.construction
= prop_node
.@
construct;
2485 var attributes
= get_attributes ("%s:%s".printf (current_data_type
.get_cname (), node
.name
));
2486 if (attributes
!= null) {
2487 foreach (string attr
in attributes
) {
2488 var nv
= attr
.split ("=", 2);
2489 if (nv
[0] == "hidden") {
2490 if (eval (nv
[1]) == "1") {
2493 } else if (nv
[0] == "type_arguments") {
2494 parse_type_arguments_from_string (prop
.property_type
, eval (nv
[1]));
2495 } else if (nv
[0] == "deprecated") {
2496 if (eval (nv
[1]) == "1") {
2497 prop
.deprecated
= true;
2499 } else if (nv
[0] == "replacement") {
2500 prop
.replacement
= eval (nv
[1]);
2501 } else if (nv
[0] == "deprecated_since") {
2502 prop
.deprecated_since
= eval (nv
[1]);
2503 } else if (nv
[0] == "accessor_method") {
2504 if (eval (nv
[1]) == "0") {
2505 prop
.no_accessor_method
= true;
2507 } else if (nv
[0] == "owned_get") {
2508 if (eval (nv
[1]) == "1") {
2509 prop
.get_accessor
.value_type
.value_owned
= true;
2511 } else if (nv
[0] == "type_name") {
2512 prop
.property_type
= parse_type_from_string (eval (nv
[1]), false);
2513 } else if (nv
[0] == "experimental") {
2514 if (eval (nv
[1]) == "1") {
2515 prop
.experimental
= true;
2521 if (current_type_symbol_set
!= null) {
2522 current_type_symbol_set
.add (prop
.name
);
2528 private Constant?
parse_constant (IdlNodeConstant const_node
) {
2529 weak IdlNode node
= (IdlNode
) const_node
;
2531 var type
= parse_type (const_node
.type
);
2536 var c
= new
Constant (node
.name
, type
, null, current_source_reference
);
2539 string[] attributes
= get_attributes (node
.name
);
2540 if (attributes
!= null) {
2541 foreach (string attr
in attributes
) {
2542 var nv
= attr
.split ("=", 2);
2543 if (nv
[0] == "cheader_filename") {
2544 c
.add_cheader_filename (eval (nv
[1]));
2545 } else if (nv
[0] == "deprecated") {
2546 if (eval (nv
[1]) == "1") {
2547 c
.deprecated
= true;
2549 } else if (nv
[0] == "replacement") {
2550 c
.replacement
= eval (nv
[1]);
2551 } else if (nv
[0] == "deprecated_since") {
2552 c
.deprecated_since
= eval (nv
[1]);
2553 } else if (nv
[0] == "hidden") {
2554 if (eval (nv
[1]) == "1") {
2557 } else if (nv
[0] == "experimental") {
2558 if (eval (nv
[1]) == "1") {
2559 c
.experimental
= true;
2565 c
.access
= SymbolAccessibility
.PUBLIC
;
2570 private Field?
parse_field (IdlNodeField field_node
) {
2571 weak IdlNode node
= (IdlNode
) field_node
;
2572 bool unhidden
= false;
2574 var type
= parse_type (field_node
.type
);
2579 string cheader_filename
= null;
2580 string ctype
= null;
2581 string array_length_cname
= null;
2582 string array_length_type
= null;
2583 bool array_null_terminated
= false;
2584 bool deprecated
= false;
2585 string deprecated_since
= null;
2586 string replacement
= null;
2587 bool experimental
= false;
2589 var attributes
= get_attributes ("%s.%s".printf (current_data_type
.get_cname (), node
.name
));
2590 if (attributes
!= null) {
2591 foreach (string attr
in attributes
) {
2592 var nv
= attr
.split ("=", 2);
2593 if (nv
[0] == "hidden") {
2594 if (eval (nv
[1]) == "1") {
2599 } else if (nv
[0] == "is_array") {
2600 if (eval (nv
[1]) == "1") {
2601 type
= new
ArrayType (type
, 1, type
.source_reference
);
2603 } else if (nv
[0] == "weak") {
2604 if (eval (nv
[1]) == "0") {
2605 type
.value_owned
= true;
2607 } else if (nv
[0] == "value_owned") {
2608 if (eval (nv
[1]) == "0") {
2609 type
.value_owned
= false;
2610 } else if (eval (nv
[1]) == "1") {
2611 type
.value_owned
= true;
2613 } else if (nv
[0] == "type_name") {
2614 type
= parse_type_from_string (eval (nv
[1]), true);
2615 } else if (nv
[0] == "type_arguments") {
2616 parse_type_arguments_from_string (type
, eval (nv
[1]));
2617 } else if (nv
[0] == "deprecated") {
2618 if (eval (nv
[1]) == "1") {
2621 } else if (nv
[0] == "replacement") {
2622 replacement
= eval (nv
[1]);
2623 } else if (nv
[0] == "deprecated_since") {
2624 deprecated_since
= eval (nv
[1]);
2625 } else if (nv
[0] == "cheader_filename") {
2626 cheader_filename
= eval (nv
[1]);
2627 } else if (nv
[0] == "ctype") {
2628 ctype
= eval (nv
[1]);
2629 } else if (nv
[0] == "array_null_terminated") {
2630 if (eval (nv
[1]) == "1") {
2631 array_null_terminated
= true;
2633 } else if (nv
[0] == "array_length_cname") {
2634 array_length_cname
= eval (nv
[1]);
2635 } else if (nv
[0] == "array_length_type") {
2636 array_length_type
= eval (nv
[1]);
2637 } else if (nv
[0] == "experimental") {
2638 if (eval (nv
[1]) == "1") {
2639 experimental
= true;
2645 if (node
.name
.has_prefix("_") && !unhidden
) {
2649 if (current_type_symbol_set
!= null) {
2650 current_type_symbol_set
.add (node
.name
);
2653 string field_name
= node
.name
;
2654 if (field_name
== "string") {
2655 // avoid conflict with string type
2659 var field
= new
Field (field_name
, type
, null, current_source_reference
);
2660 field
.access
= SymbolAccessibility
.PUBLIC
;
2662 if (field_name
!= node
.name
) {
2663 field
.set_cname (node
.name
);
2667 field
.deprecated
= true;
2669 if (deprecated_since
!= null) {
2670 field
.deprecated_since
= deprecated_since
;
2673 if (replacement
!= null) {
2674 field
.replacement
= replacement
;
2679 field
.experimental
= true;
2682 if (ctype
!= null) {
2683 field
.set_ctype (ctype
);
2686 if (cheader_filename
!= null) {
2687 field
.add_cheader_filename (cheader_filename
);
2690 if (array_null_terminated
) {
2691 field
.array_null_terminated
= true;
2694 if (array_length_cname
!= null || array_length_type
!= null) {
2695 if (array_length_cname
!= null) {
2696 field
.set_array_length_cname (array_length_cname
);
2698 if (array_length_type
!= null) {
2699 field
.array_length_type
= array_length_type
;
2702 field
.no_array_length
= true;
2708 private string[]?
get_attributes (string codenode
) {
2709 var attributes
= codenode_attributes_map
.get (codenode
);
2711 if (attributes
== null) {
2712 var dot_required
= (-1 != codenode
.index_of_char ('.'));
2713 var colon_required
= (-1 != codenode
.index_of_char (':'));
2715 var pattern_specs
= codenode_attributes_patterns
.get_keys ();
2716 foreach (PatternSpec
* pattern
in pattern_specs
) {
2717 var pspec
= codenode_attributes_patterns
[pattern
];
2719 if ((dot_required
&& -1 == pspec
.index_of_char ('.')) ||
2720 (colon_required
&& -1 == pspec
.index_of_char (':'))) {
2724 if (pattern
->match_string (codenode
)) {
2725 return get_attributes (pspec
);
2730 if (attributes
== null) {
2734 GLib
.SList
<string> attr_list
= new GLib
.SList
<string> ();
2735 var attr
= new GLib
.StringBuilder
.sized (attributes
.length
);
2736 var attributes_len
= attributes
.length
;
2737 unowned
string remaining
= attributes
;
2738 bool quoted
= false, escaped
= false;
2739 for (int b
= 0 ; b
< attributes_len
; b
++) {
2740 unichar c
= remaining
.get_char ();
2744 attr
.append_unichar (c
);
2747 attr
.append_unichar (c
);
2749 } else if (c
== '\\') {
2751 } else if (!quoted
&& (c
== ' ')) {
2752 attr_list
.prepend (attr
.str
);
2755 attr
.append_unichar (c
);
2759 remaining
= (string) ((char*) remaining
+ remaining
.index_of_nth_char (1));
2763 attr_list
.prepend (attr
.str
);
2766 var attrs
= new
string[attr_list
.length ()];
2767 unowned GLib
.SList
<string>? attr_i
= attr_list
;
2768 for (int a
= 0 ; a
< attrs
.length
; a
++, attr_i
= attr_i
.next
) {
2769 attrs
[(attrs
.length
- 1) - a
] = attr_i
.data
;
2775 private string eval (string s
) {
2776 return ((s
.length
>= 2) && s
.has_prefix ("\"") && s
.has_suffix ("\"")) ? s
.substring (1, s
.length
- 2) : s
;
2779 private Signal?
parse_signal (IdlNodeSignal sig_node
) {
2780 weak IdlNode node
= (IdlNode
) sig_node
;
2782 if (sig_node
.deprecated
|| sig_node
.result
== null) {
2786 var sig
= new
Signal (fix_prop_name (node
.name
), parse_param (sig_node
.result
), current_source_reference
);
2787 sig
.access
= SymbolAccessibility
.PUBLIC
;
2789 var attributes
= get_attributes ("%s::%s".printf (current_data_type
.get_cname (), sig
.name
));
2790 if (attributes
!= null) {
2791 string ns_name
= null;
2792 foreach (string attr
in attributes
) {
2793 var nv
= attr
.split ("=", 2);
2794 if (nv
[0] == "name") {
2795 sig
.set_cname (sig
.name
);
2796 sig
.name
= eval (nv
[1]);
2797 } else if (nv
[0] == "has_emitter" && eval (nv
[1]) == "1") {
2798 sig
.has_emitter
= true;
2799 } else if (nv
[0] == "hidden") {
2800 if (eval (nv
[1]) == "1") {
2803 } else if (nv
[0] == "deprecated") {
2804 if (eval (nv
[1]) == "1") {
2805 sig
.deprecated
= true;
2807 } else if (nv
[0] == "replacement") {
2808 sig
.replacement
= eval (nv
[1]);
2809 } else if (nv
[0] == "deprecated_since") {
2810 sig
.deprecated_since
= eval (nv
[1]);
2811 } else if (nv
[0] == "transfer_ownership") {
2812 if (eval (nv
[1]) == "1") {
2813 sig
.return_type
.value_owned
= true;
2815 } else if (nv
[0] == "namespace_name") {
2816 ns_name
= eval (nv
[1]);
2817 } else if (nv
[0] == "type_name") {
2818 sig
.return_type
= parse_type_from_string (eval (nv
[1]), false);
2819 } else if (nv
[0] == "type_arguments") {
2820 parse_type_arguments_from_string (sig
.return_type
, eval (nv
[1]));
2821 } else if (nv
[0] == "experimental") {
2822 if (eval (nv
[1]) == "1") {
2823 sig
.experimental
= true;
2827 if (ns_name
!= null) {
2828 ((UnresolvedType
) sig
.return_type
).unresolved_symbol
.inner
= new
UnresolvedSymbol (null, ns_name
);
2832 sig
.is_virtual
= true;
2836 foreach (weak IdlNodeParam param
in sig_node
.parameters
) {
2838 // ignore implicit first signal parameter (sender)
2843 weak IdlNode param_node
= (IdlNode
) param
;
2845 ParameterDirection direction
;
2846 var param_type
= parse_param (param
, out direction
);
2847 var p
= new
Parameter (param_node
.name
, param_type
);
2848 p
.direction
= direction
;
2850 bool hide_param
= false;
2851 bool show_param
= false;
2852 attributes
= get_attributes ("%s::%s.%s".printf (current_data_type
.get_cname (), sig
.name
, param_node
.name
));
2853 if (attributes
!= null) {
2854 string ns_name
= null;
2855 foreach (string attr
in attributes
) {
2856 var nv
= attr
.split ("=", 2);
2857 if (nv
[0] == "hidden") {
2858 if (eval (nv
[1]) == "1") {
2860 } else if (eval (nv
[1]) == "0") {
2863 } else if (nv
[0] == "is_array") {
2864 if (eval (nv
[1]) == "1") {
2865 param_type
= new
ArrayType (param_type
, 1, param_type
.source_reference
);
2866 p
.variable_type
= param_type
;
2867 p
.direction
= ParameterDirection
.IN
;
2869 } else if (nv
[0] == "no_array_length") {
2870 if (eval (nv
[1]) == "1") {
2871 p
.no_array_length
= true;
2873 } else if (nv
[0] == "array_length_type") {
2874 p
.array_length_type
= eval (nv
[1]);
2875 } else if (nv
[0] == "array_null_terminated") {
2876 if (eval (nv
[1]) == "1") {
2877 p
.no_array_length
= true;
2878 p
.array_null_terminated
= true;
2880 } else if (nv
[0] == "is_out") {
2881 if (eval (nv
[1]) == "1") {
2882 p
.direction
= ParameterDirection
.OUT
;
2884 } else if (nv
[0] == "is_ref") {
2885 if (eval (nv
[1]) == "1") {
2886 p
.direction
= ParameterDirection
.REF
;
2888 } else if (nv
[0] == "nullable") {
2889 if (eval (nv
[1]) == "1") {
2890 param_type
.nullable
= true;
2892 } else if (nv
[0] == "transfer_ownership") {
2893 if (eval (nv
[1]) == "1") {
2894 param_type
.value_owned
= true;
2896 } else if (nv
[0] == "type_name") {
2897 p
.variable_type
= param_type
= parse_type_from_string (eval (nv
[1]), false);
2898 } else if (nv
[0] == "type_arguments") {
2899 parse_type_arguments_from_string (p
.variable_type
, eval (nv
[1]));
2900 } else if (nv
[0] == "namespace_name") {
2901 ns_name
= eval (nv
[1]);
2904 if (ns_name
!= null) {
2905 ((UnresolvedType
) param_type
).unresolved_symbol
.inner
= new
UnresolvedSymbol (null, ns_name
);
2909 if (show_param
|| !hide_param
) {
2910 sig
.add_parameter (p
);