3 * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <rasa@gmx.ch>
27 * Code visitor parsing all GIDL files.
29 public class Vala
.GIdlParser
: CodeVisitor
{
30 private SourceReference current_source_reference
;
32 private DataType current_data_type
;
33 private HashTable
<string,string> codenode_attributes_map
;
34 private HashTable
<string,string> current_type_symbol_map
;
37 * Parse all source files in the specified code context and build a
40 * @param context a code context
42 public void parse (CodeContext
! context
) {
43 context
.accept (this
);
46 public override void visit_source_file (SourceFile
! source_file
) {
47 if (source_file
.filename
.has_suffix (".gidl")) {
48 parse_file (source_file
);
52 private void parse_file (SourceFile
! source_file
) {
55 string metadata_filename
= "%s.metadata".printf (source_file
.filename
.ndup (source_file
.filename
.size () - ".gidl".size ()));
57 codenode_attributes_map
= new HashTable
.full (str_hash
, str_equal
, g_free
, g_free
);
59 if (FileUtils
.test (metadata_filename
, FileTest
.EXISTS
)) {
62 FileUtils
.get_contents (metadata_filename
, out metadata
, out metadata_len
, out error
);
64 foreach (string line
in metadata
.split ("\n")) {
65 var line_parts
= line
.split (" ", 2);
66 if (line_parts
[0] == null) {
70 codenode_attributes_map
.insert (line_parts
[0], line_parts
[1]);
74 var modules
= Idl
.parse_file (source_file
.filename
, out error
);
77 stdout
.printf ("error parsing GIDL file: %s\n", error
.message
);
80 current_source_reference
= new
SourceReference (source_file
);
82 foreach (IdlModule module
in modules
) {
83 var ns
= parse_module (module
);
84 source_file
.add_namespace (ns
);
88 private string! fix_type_name (string! type_name
, IdlModule
! module
) {
89 if (type_name
.has_prefix (module
.name
)) {
90 return type_name
.offset (module
.name
.len ());
91 } else if (module
.name
== "GLib" && type_name
.has_prefix ("G")) {
92 return type_name
.offset (1);
97 private string! fix_const_name (string! const_name
, IdlModule
! module
) {
98 if (const_name
.has_prefix (module
.name
.up () + "_")) {
99 return const_name
.offset (module
.name
.len () + 1);
100 } else if (module
.name
== "GLib" && const_name
.has_prefix ("G_")) {
101 return const_name
.offset (2);
106 private Namespace
parse_module (IdlModule
! module
) {
107 var ns
= new
Namespace (module
.name
, current_source_reference
);
109 var attributes
= get_attributes (ns
.name
);
110 if (attributes
!= null) {
111 foreach (string attr
in attributes
) {
112 var nv
= attr
.split ("=", 2);
113 if (nv
[0] == "cheader_filename") {
114 ns
.set_cheader_filename (eval (nv
[1]));
115 } else if (nv
[0] == "cprefix") {
116 ns
.set_cprefix (eval (nv
[1]));
117 } else if (nv
[0] == "lower_case_cprefix") {
118 ns
.set_lower_case_cprefix (eval (nv
[1]));
123 foreach (IdlNode node
in module
.entries
) {
124 if (node
.type
== IdlNodeTypeId
.CALLBACK
) {
125 var cb
= parse_callback ((IdlNodeFunction
) node
);
129 cb
.name
= fix_type_name (cb
.name
, module
);
130 ns
.add_callback (cb
);
131 } else if (node
.type
== IdlNodeTypeId
.STRUCT
) {
132 var st
= parse_struct ((IdlNodeStruct
) node
);
136 st
.name
= fix_type_name (st
.name
, module
);
138 } else if (node
.type
== IdlNodeTypeId
.BOXED
) {
139 var st
= parse_boxed ((IdlNodeBoxed
) node
);
140 st
.name
= fix_type_name (st
.name
, module
);
142 st
.set_type_id (st
.get_upper_case_cname ("TYPE_"));
143 } else if (node
.type
== IdlNodeTypeId
.ENUM
) {
144 var en
= parse_enum ((IdlNodeEnum
) node
);
145 en
.name
= fix_type_name (en
.name
, module
);
147 } else if (node
.type
== IdlNodeTypeId
.OBJECT
) {
148 var cl
= parse_object ((IdlNodeInterface
) node
);
149 cl
.name
= fix_type_name (cl
.name
, module
);
151 } else if (node
.type
== IdlNodeTypeId
.INTERFACE
) {
152 var iface
= parse_interface ((IdlNodeInterface
) node
);
153 iface
.name
= fix_type_name (iface
.name
, module
);
154 ns
.add_interface (iface
);
155 } else if (node
.type
== IdlNodeTypeId
.CONSTANT
) {
156 var c
= parse_constant ((IdlNodeConstant
) node
);
157 c
.name
= fix_const_name (c
.name
, module
);
159 } else if (node
.type
== IdlNodeTypeId
.FUNCTION
) {
160 var m
= parse_function ((IdlNodeFunction
) node
);
171 private Callback
parse_callback (IdlNodeFunction
! f_node
) {
172 weak IdlNode node
= (IdlNode
) f_node
;
174 var attributes
= get_attributes (node
.name
);
175 if (attributes
!= null) {
176 foreach (string attr
in attributes
) {
177 var nv
= attr
.split ("=", 2);
178 if (nv
[0] == "hidden") {
179 if (eval (nv
[1]) == "1") {
186 var cb
= new
Callback (node
.name
, parse_param (f_node
.result
), current_source_reference
);
187 cb
.access
= MemberAccessibility
.PUBLIC
;
189 foreach (IdlNodeParam param
in f_node
.parameters
) {
190 weak IdlNode param_node
= (IdlNode
) param
;
192 var p
= new
FormalParameter (param_node
.name
, parse_param (param
));
193 cb
.add_parameter (p
);
199 private Struct
parse_struct (IdlNodeStruct
! st_node
) {
200 weak IdlNode node
= (IdlNode
) st_node
;
202 if (st_node
.deprecated
) {
206 var st
= new
Struct (node
.name
, current_source_reference
);
207 st
.access
= MemberAccessibility
.PUBLIC
;
209 st
.set_is_reference_type (true);
211 var st_attributes
= get_attributes (node
.name
);
212 if (st_attributes
!= null) {
213 foreach (string attr
in st_attributes
) {
214 var nv
= attr
.split ("=", 2);
215 if (nv
[0] == "is_value_type" && eval (nv
[1]) == "1") {
216 st
.set_is_reference_type (false);
221 current_data_type
= st
;
223 foreach (IdlNode member
in st_node
.members
) {
224 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
225 var m
= parse_function ((IdlNodeFunction
) member
);
229 } else if (member
.type
== IdlNodeTypeId
.FIELD
) {
230 var f
= parse_field ((IdlNodeField
) member
);
237 current_data_type
= null;
242 private Struct
parse_boxed (IdlNodeBoxed
! boxed_node
) {
243 weak IdlNode node
= (IdlNode
) boxed_node
;
245 var st
= new
Struct (node
.name
, current_source_reference
);
246 st
.access
= MemberAccessibility
.PUBLIC
;
248 st
.set_is_reference_type (true);
250 var st_attributes
= get_attributes (node
.name
);
251 if (st_attributes
!= null) {
252 foreach (string attr
in st_attributes
) {
253 var nv
= attr
.split ("=", 2);
254 if (nv
[0] == "is_value_type" && eval (nv
[1]) == "1") {
255 st
.set_is_reference_type (false);
260 current_data_type
= st
;
262 foreach (IdlNode member
in boxed_node
.members
) {
263 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
264 var m
= parse_function ((IdlNodeFunction
) member
);
268 } else if (member
.type
== IdlNodeTypeId
.FIELD
) {
269 var f
= parse_field ((IdlNodeField
) member
);
276 current_data_type
= null;
281 private Enum
parse_enum (IdlNodeEnum
! en_node
) {
282 weak IdlNode node
= (IdlNode
) en_node
;
284 var en
= new
Enum (node
.name
, current_source_reference
);
285 en
.access
= MemberAccessibility
.PUBLIC
;
287 string common_prefix
= null;
289 foreach (IdlNode value
in en_node
.values
) {
290 if (common_prefix
== null) {
291 common_prefix
= value
.name
;
292 while (common_prefix
.len () > 0 && !common_prefix
.has_suffix ("_")) {
293 // FIXME: could easily be made faster
294 common_prefix
= common_prefix
.ndup (common_prefix
.size () - 1);
297 while (!value
.name
.has_prefix (common_prefix
)) {
298 common_prefix
= common_prefix
.ndup (common_prefix
.size () - 1);
303 en
.set_cprefix (common_prefix
);
305 foreach (IdlNode value2
in en_node
.values
) {
306 var ev
= new
EnumValue (value2
.name
.offset (common_prefix
.len ()));
313 private Class
parse_object (IdlNodeInterface
! node
) {
314 var cl
= new
Class (node
.gtype_name
, current_source_reference
);
315 cl
.access
= MemberAccessibility
.PUBLIC
;
317 var attributes
= get_attributes (cl
.name
);
318 if (attributes
!= null) {
319 foreach (string attr
in attributes
) {
320 var nv
= attr
.split ("=", 2);
321 if (nv
[0] == "cheader_filename") {
322 cl
.add_cheader_filename (eval (nv
[1]));
327 if (node
.parent
!= null) {
328 var parent
= new
TypeReference ();
329 parse_type_string (parent
, node
.parent
);
330 cl
.add_base_type (parent
);
333 foreach (string iface_name
in node
.interfaces
) {
334 var iface
= new
TypeReference ();
335 parse_type_string (iface
, iface_name
);
336 cl
.add_base_type (iface
);
339 current_data_type
= cl
;
341 current_type_symbol_map
= new HashTable
<string,string>.full (str_hash
, str_equal
, g_free
, g_free
);
342 var current_type_vfunc_map
= new HashTable
<string,string>.full (str_hash
, str_equal
, g_free
, g_free
);
344 foreach (IdlNode member
in node
.members
) {
345 if (member
.type
== IdlNodeTypeId
.VFUNC
) {
346 current_type_vfunc_map
.insert (member
.name
, "1");
350 foreach (IdlNode member
in node
.members
) {
351 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
352 bool is_virtual
= current_type_vfunc_map
.lookup (member
.name
) != null;
354 var m
= parse_function ((IdlNodeFunction
) member
, is_virtual
);
358 } else if (member
.type
== IdlNodeTypeId
.PROPERTY
) {
359 var prop
= parse_property ((IdlNodeProperty
) member
);
361 cl
.add_property (prop
);
363 } else if (member
.type
== IdlNodeTypeId
.SIGNAL
) {
364 var sig
= parse_signal ((IdlNodeSignal
) member
);
371 foreach (IdlNode member
in node
.members
) {
372 if (member
.type
== IdlNodeTypeId
.FIELD
) {
373 if (current_type_symbol_map
.lookup (member
.name
) == null) {
374 var f
= parse_field ((IdlNodeField
) member
);
382 foreach (Property prop
in cl
.get_properties ()) {
383 var getter
= "get_%s".printf (prop
.name
);
385 if (prop
.get_accessor
!= null && current_type_symbol_map
.lookup (getter
) == null) {
386 prop
.no_accessor_method
= true;
389 var setter
= "set_%s".printf (prop
.name
);
391 if (prop
.set_accessor
!= null && current_type_symbol_map
.lookup (setter
) == null) {
392 prop
.no_accessor_method
= true;
396 current_data_type
= null;
397 current_type_symbol_map
= null;
402 private Interface
parse_interface (IdlNodeInterface
! node
) {
403 var iface
= new
Interface (node
.gtype_name
, current_source_reference
);
404 iface
.access
= MemberAccessibility
.PUBLIC
;
406 var attributes
= get_attributes (iface
.name
);
407 if (attributes
!= null) {
408 foreach (string attr
in attributes
) {
409 var nv
= attr
.split ("=", 2);
410 if (nv
[0] == "cheader_filename") {
411 iface
.add_cheader_filename (eval (nv
[1]));
416 foreach (string prereq_name
in node
.prerequisites
) {
417 var prereq
= new
TypeReference ();
418 parse_type_string (prereq
, prereq_name
);
419 iface
.add_prerequisite (prereq
);
422 current_data_type
= iface
;
424 var current_type_vfunc_map
= new HashTable
<string,string>.full (str_hash
, str_equal
, g_free
, g_free
);
425 foreach (IdlNode member
in node
.members
) {
426 if (member
.type
== IdlNodeTypeId
.VFUNC
) {
427 current_type_vfunc_map
.insert (member
.name
, "1");
431 foreach (IdlNode member
in node
.members
) {
432 if (member
.type
== IdlNodeTypeId
.FUNCTION
) {
433 bool is_virtual
= current_type_vfunc_map
.lookup (member
.name
) != null;
435 var m
= parse_function ((IdlNodeFunction
) member
, is_virtual
);
437 iface
.add_method (m
);
439 } else if (member
.type
== IdlNodeTypeId
.SIGNAL
) {
440 var sig
= parse_signal ((IdlNodeSignal
) member
);
442 iface
.add_signal (sig
);
447 current_data_type
= null;
452 private TypeReference
parse_type (IdlNodeType
! type_node
) {
453 var type
= new
TypeReference ();
454 if (type_node
.tag
== TypeTag
.VOID
) {
455 if (type_node
.is_pointer
) {
456 type
.type_name
= "pointer";
458 type
.type_name
= "void";
460 } else if (type_node
.tag
== TypeTag
.BOOLEAN
) {
461 type
.type_name
= "bool";
462 } else if (type_node
.tag
== TypeTag
.INT8
) {
463 type
.type_name
= "char";
464 } else if (type_node
.tag
== TypeTag
.UINT8
) {
465 type
.type_name
= "uchar";
466 } else if (type_node
.tag
== TypeTag
.INT16
) {
467 type
.type_name
= "short";
468 } else if (type_node
.tag
== TypeTag
.UINT16
) {
469 type
.type_name
= "ushort";
470 } else if (type_node
.tag
== TypeTag
.INT32
) {
471 type
.type_name
= "int";
472 } else if (type_node
.tag
== TypeTag
.UINT32
) {
473 type
.type_name
= "uint";
474 } else if (type_node
.tag
== TypeTag
.INT64
) {
475 type
.type_name
= "int64";
476 } else if (type_node
.tag
== TypeTag
.UINT64
) {
477 type
.type_name
= "uint64";
478 } else if (type_node
.tag
== TypeTag
.INT
) {
479 type
.type_name
= "int";
480 } else if (type_node
.tag
== TypeTag
.UINT
) {
481 type
.type_name
= "uint";
482 } else if (type_node
.tag
== TypeTag
.LONG
) {
483 type
.type_name
= "long";
484 } else if (type_node
.tag
== TypeTag
.ULONG
) {
485 type
.type_name
= "ulong";
486 } else if (type_node
.tag
== TypeTag
.SSIZE
) {
487 type
.type_name
= "long";
488 } else if (type_node
.tag
== TypeTag
.SIZE
) {
489 type
.type_name
= "ulong";
490 } else if (type_node
.tag
== TypeTag
.FLOAT
) {
491 type
.type_name
= "float";
492 } else if (type_node
.tag
== TypeTag
.DOUBLE
) {
493 type
.type_name
= "double";
494 } else if (type_node
.tag
== TypeTag
.UTF8
) {
495 type
.type_name
= "string";
496 } else if (type_node
.tag
== TypeTag
.FILENAME
) {
497 type
.type_name
= "string";
498 } else if (type_node
.tag
== TypeTag
.ARRAY
) {
499 type
= parse_type (type_node
.parameter_type1
);
501 } else if (type_node
.tag
== TypeTag
.LIST
) {
502 type
.namespace_name
= "GLib";
503 type
.type_name
= "List";
504 } else if (type_node
.tag
== TypeTag
.SLIST
) {
505 type
.namespace_name
= "GLib";
506 type
.type_name
= "SList";
507 } else if (type_node
.tag
== TypeTag
.HASH
) {
508 type
.namespace_name
= "GLib";
509 type
.type_name
= "HashTable";
510 } else if (type_node
.tag
== TypeTag
.ERROR
) {
511 type
.namespace_name
= "GLib";
512 type
.type_name
= "Error";
513 } else if (type_node
.is_interface
) {
514 var n
= type_node
.@
interface;
520 if (n
.has_prefix ("const-")) {
521 n
= n
.offset ("const-".len ());
524 if (type_node
.is_pointer
&&
525 (n
== "gchar" || n
== "char")) {
526 type
.type_name
= "string";
527 } else if (n
== "gunichar") {
528 type
.type_name
= "unichar";
529 } else if (n
== "gchar") {
530 type
.type_name
= "char";
531 } else if (n
== "guchar" || n
== "guint8") {
532 type
.type_name
= "uchar";
533 if (type_node
.is_pointer
) {
536 } else if (n
== "gushort") {
537 type
.type_name
= "ushort";
538 } else if (n
== "gshort") {
539 type
.type_name
= "short";
540 } else if (n
== "gconstpointer" || n
== "void") {
541 type
.type_name
= "pointer";
542 } else if (n
== "goffset") {
543 type
.type_name
= "int64";
544 } else if (n
== "value_array") {
545 type
.namespace_name
= "GLib";
546 type
.type_name
= "ValueArray";
547 } else if (n
== "time_t") {
548 type
.type_name
= "ulong";
549 } else if (n
== "pid_t") {
550 type
.type_name
= "int";
551 } else if (n
== "FILE") {
552 type
.namespace_name
= "GLib";
553 type
.type_name
= "FileStream";
555 parse_type_string (type
, n
);
556 if (type_node
.is_pointer
&& is_value_type (n
)) {
561 stdout
.printf ("%d\n", type_node
.tag
);
566 private bool is_value_type (string! type_name
) {
567 // FIXME only works if both types are in current package, e.g. doesn't work when Gtk uses GdkRectangle
568 var type_attributes
= get_attributes (type_name
);
569 if (type_attributes
!= null) {
570 foreach (string attr
in type_attributes
) {
571 var nv
= attr
.split ("=", 2);
572 if (nv
[0] == "is_value_type" && eval (nv
[1]) == "1") {
581 private void parse_type_string (TypeReference
! type
, string! n
) {
582 // Generated GIDL misses explicit namespace specifier,
583 // so try to guess namespace
584 if (n
.has_prefix ("H") || n
.has_suffix ("Class") || n
== "va_list" || n
.has_prefix ("LOGFONT")) {
586 type
.type_name
= "pointer";
587 } else if (n
.has_prefix ("cairo")) {
588 type
.namespace_name
= "Cairo";
589 if (n
== "cairo_t") {
590 type
.type_name
= "Context";
591 } else if (n
== "cairo_surface_t") {
592 type
.type_name
= "Surface";
594 type
.namespace_name
= null;
595 type
.type_name
= "pointer";
597 } else if (n
.has_prefix ("Atk")) {
598 type
.namespace_name
= "Atk";
599 type
.type_name
= n
.offset ("Atk".len ());
600 if (type
.type_name
== "AttributeSet") {
601 type
.namespace_name
= "GLib";
602 type
.type_name
= "SList";
604 } else if (n
.has_prefix ("Gtk")) {
605 type
.namespace_name
= "Gtk";
606 type
.type_name
= n
.offset ("Gtk".len ());
607 if (type
.type_name
== "TextLayout") {
608 type
.namespace_name
= null;
609 type
.type_name
= "pointer";
611 } else if (n
.has_prefix ("Gdk")) {
612 type
.namespace_name
= "Gdk";
613 type
.type_name
= n
.offset ("Gdk".len ());
614 if (type
.type_name
== "NativeWindow" || type
.type_name
== "XEvent") {
615 type
.namespace_name
= null;
616 type
.type_name
= "pointer";
618 } else if (n
.has_prefix ("Pango")) {
619 type
.namespace_name
= "Pango";
620 type
.type_name
= n
.offset ("Pango".len ());
621 if (type
.type_name
== "Glyph") {
622 type
.namespace_name
= null;
623 type
.type_name
= "uint";
624 } else if (type
.type_name
== "GlyphUnit") {
625 type
.namespace_name
= null;
626 type
.type_name
= "int";
628 } else if (n
.has_prefix ("Vte")) {
629 type
.namespace_name
= "Vte";
630 type
.type_name
= n
.offset ("Vte".len ());
631 } else if (n
.has_prefix ("Goo")) {
632 type
.namespace_name
= "Goo";
633 type
.type_name
= n
.offset ("Goo".len ());
634 } else if (n
.has_prefix ("G")) {
635 type
.namespace_name
= "GLib";
636 type
.type_name
= n
.offset ("G".len ());
637 if (type
.type_name
== "Strv") {
638 type
.namespace_name
= null;
639 type
.type_name
= "string";
643 var name_parts
= n
.split (".", 2);
644 if (name_parts
[1] == null) {
645 type
.type_name
= name_parts
[0];
647 type
.namespace_name
= name_parts
[0];
648 type
.type_name
= name_parts
[1];
653 private TypeReference
parse_param (IdlNodeParam
! param
) {
654 var type
= parse_type (param
.type
);
656 // disable for now as null_ok not yet correctly set
657 // type.non_null = !param.null_ok;
662 private Method
parse_function (IdlNodeFunction
! f
, bool is_virtual
= false) {
663 weak IdlNode node
= (IdlNode
) f
;
669 TypeReference return_type
= null;
670 if (f
.result
!= null) {
671 return_type
= parse_param (f
.result
);
675 if (f
.is_constructor
|| node
.name
.has_prefix ("new")) {
676 m
= new
CreationMethod (node
.name
, current_source_reference
);
677 if (m
.name
== "new") {
679 } else if (m
.name
.has_prefix ("new_")) {
680 m
.name
= m
.name
.offset ("new_".len ());
683 m
= new
Method (node
.name
, return_type
, current_source_reference
);
685 m
.access
= MemberAccessibility
.PUBLIC
;
687 m
.is_virtual
= is_virtual
;
689 // GIDL generator can't provide array parameter information yet
690 m
.no_array_length
= true;
692 if (current_type_symbol_map
!= null) {
693 current_type_symbol_map
.insert (node
.name
, "1");
696 if (current_data_type
!= null) {
697 var sig_attributes
= get_attributes ("%s::%s".printf (current_data_type
.name
, node
.name
));
698 if (sig_attributes
!= null) {
699 foreach (string attr
in sig_attributes
) {
700 var nv
= attr
.split ("=", 2);
701 if (nv
[0] == "has_emitter" && eval (nv
[1]) == "1") {
708 bool add_ellipsis
= false;
710 var attributes
= get_attributes (f
.symbol
);
711 if (attributes
!= null) {
712 foreach (string attr
in attributes
) {
713 var nv
= attr
.split ("=", 2);
714 if (nv
[0] == "hidden") {
715 if (eval (nv
[1]) == "1") {
718 } else if (nv
[0] == "ellipsis") {
719 if (eval (nv
[1]) == "1") {
726 m
.set_cname (f
.symbol
);
729 FormalParameter last_param
= null;
730 foreach (IdlNodeParam param
in f
.parameters
) {
731 weak IdlNode param_node
= (IdlNode
) param
;
735 if (current_data_type
!= null &&
736 param
.type
.is_interface
&&
737 (param_node
.name
== "self" ||
738 param
.type
.@
interface.has_suffix (current_data_type
.name
))) {
741 if (!current_data_type
.is_reference_type () &&
742 param
.type
.is_pointer
) {
743 m
.instance_by_reference
= true;
753 var p
= new
FormalParameter (param_node
.name
, parse_param (param
));
756 if (last_param
!= null && p
.name
== "n_" + last_param
.name
) {
757 // last_param is array, p is array length
758 last_param
.type_reference
.array_rank
= 1;
759 last_param
.type_reference
.is_out
= false;
766 // no parameters => static method
771 m
.add_parameter (new FormalParameter
.with_ellipsis ());
777 private string! fix_prop_name (string name
) {
778 var str
= new
String ();
782 while (i
.len () > 0) {
783 unichar c
= i
.get_char ();
787 str
.append_unichar (c
);
796 private Property
parse_property (IdlNodeProperty
! prop_node
) {
797 weak IdlNode node
= (IdlNode
) prop_node
;
799 if (prop_node
.deprecated
) {
803 if (!prop_node
.readable
&& !prop_node
.writable
) {
804 // buggy GIDL definition
805 prop_node
.readable
= true;
806 prop_node
.writable
= true;
809 PropertyAccessor get_acc
= null;
810 PropertyAccessor set_acc
= null;
811 if (prop_node
.readable
) {
812 get_acc
= new
PropertyAccessor (true, false, false, null, null);
814 if (prop_node
.writable
) {
815 set_acc
= new
PropertyAccessor (false, false, false, null, null);
816 if (prop_node
.construct_only
) {
817 set_acc
.construction
= true;
819 set_acc
.writable
= true;
820 set_acc
.construction
= prop_node
.@
construct;
824 var prop
= new
Property (fix_prop_name (node
.name
), parse_type (prop_node
.type
), get_acc
, set_acc
, current_source_reference
);
825 prop
.access
= MemberAccessibility
.PUBLIC
;
826 prop
.interface_only
= true;
828 if (current_type_symbol_map
!= null) {
829 current_type_symbol_map
.insert (prop
.name
, "1");
835 private Constant
parse_constant (IdlNodeConstant
! const_node
) {
836 weak IdlNode node
= (IdlNode
) const_node
;
838 var type
= parse_type (const_node
.type
);
843 var c
= new
Constant (node
.name
, type
, null, current_source_reference
);
848 private Field
parse_field (IdlNodeField
! field_node
) {
849 weak IdlNode node
= (IdlNode
) field_node
;
851 var type
= parse_type (field_node
.type
);
856 if (!field_node
.readable
) {
860 if (current_type_symbol_map
!= null) {
861 current_type_symbol_map
.insert (node
.name
, "1");
864 var field
= new
Field (node
.name
, type
, null, current_source_reference
);
865 field
.access
= MemberAccessibility
.PUBLIC
;
871 private string[] get_attributes (string! codenode
) {
872 string attributes
= codenode_attributes_map
.lookup (codenode
);
873 if (attributes
== null) {
877 return attributes
.split (" ");
880 private string eval (string! s
) {
881 return s
.offset (1).ndup (s
.size () - 2);
884 private Signal
parse_signal (IdlNodeSignal
! sig_node
) {
885 weak IdlNode node
= (IdlNode
) sig_node
;
887 if (sig_node
.deprecated
|| sig_node
.result
== null) {
891 var sig
= new
Signal (fix_prop_name (node
.name
), parse_param (sig_node
.result
), current_source_reference
);
892 sig
.access
= MemberAccessibility
.PUBLIC
;
894 var attributes
= get_attributes ("%s::%s".printf (current_data_type
.name
, sig
.name
));
895 if (attributes
!= null) {
896 foreach (string attr
in attributes
) {
897 var nv
= attr
.split ("=", 2);
898 if (nv
[0] == "name") {
899 sig
.set_cname (sig
.name
);
900 sig
.name
= eval (nv
[1]);
901 } else if (nv
[0] == "has_emitter" && eval (nv
[1]) == "1") {
902 sig
.has_emitter
= true;
903 } else if (nv
[0] == "hidden") {
904 if (eval (nv
[1]) == "1") {
913 foreach (IdlNodeParam param
in sig_node
.parameters
) {
915 // ignore implicit first signal parameter (sender)
920 weak IdlNode param_node
= (IdlNode
) param
;
922 var p
= new
FormalParameter (param_node
.name
, parse_param (param
));
923 sig
.add_parameter (p
);