1 /* valaccodeattribute.vala
3 * Copyright (C) 2011 Luca Bruno
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.1 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 * Luca Bruno <lucabru@src.gnome.org>
25 * Cache for the CCode attribute
27 public class Vala.CCodeAttribute : AttributeCache {
28 private weak CodeNode node;
29 private weak Symbol? sym;
30 private Attribute ccode;
36 _name = ccode.get_string ("cname");
39 _name = get_default_name ();
46 public string const_name {
48 if (_const_name == null) {
50 _const_name = ccode.get_string ("const_cname");
52 if (_const_name == null) {
53 _const_name = get_default_const_name ();
60 public string type_name {
62 if (_type_name == null) {
64 _type_name = ccode.get_string ("type_cname");
66 if (_type_name == null) {
68 _type_name = "%sClass".printf (get_ccode_name (sym));
69 } else if (sym is Interface) {
70 _type_name = "%sIface".printf (get_ccode_name (sym));
72 Report.error (sym.source_reference, "`CCode.type_cname' not supported");
81 public string feature_test_macros {
83 if (_feature_test_macros == null) {
85 _feature_test_macros = ccode.get_string ("feature_test_macro");
87 if (_feature_test_macros == null) {
88 _feature_test_macros = "";
91 return _feature_test_macros;
95 public string header_filenames {
97 if (_header_filenames == null) {
99 _header_filenames = ccode.get_string ("cheader_filename");
101 if (_header_filenames == null) {
102 _header_filenames = get_default_header_filenames ();
105 return _header_filenames;
109 public string prefix {
111 if (_prefix == null) {
113 _prefix = ccode.get_string ("cprefix");
115 if (_prefix == null) {
116 _prefix = get_default_prefix ();
123 public string lower_case_prefix {
125 if (_lower_case_prefix == null) {
127 _lower_case_prefix = ccode.get_string ("lower_case_cprefix");
128 if (_lower_case_prefix == null && (sym is ObjectTypeSymbol || sym is Struct)) {
129 _lower_case_prefix = ccode.get_string ("cprefix");
132 if (_lower_case_prefix == null) {
133 _lower_case_prefix = get_default_lower_case_prefix ();
136 return _lower_case_prefix;
140 public string lower_case_suffix {
142 if (_lower_case_suffix == null) {
144 _lower_case_suffix = ccode.get_string ("lower_case_csuffix");
146 if (_lower_case_suffix == null) {
147 _lower_case_suffix = get_default_lower_case_suffix ();
150 return _lower_case_suffix;
154 public string ref_function {
156 if (!ref_function_set) {
158 _ref_function = ccode.get_string ("ref_function");
160 if (_ref_function == null) {
161 _ref_function = get_default_ref_function ();
163 ref_function_set = true;
165 return _ref_function;
169 public bool ref_function_void {
171 if (_ref_function_void == null) {
172 if (ccode != null && ccode.has_argument ("ref_function_void")) {
173 _ref_function_void = ccode.get_bool ("ref_function_void");
175 var cl = (Class) sym;
176 if (cl.base_class != null) {
177 _ref_function_void = get_ccode_ref_function_void (cl.base_class);
179 _ref_function_void = false;
183 return _ref_function_void;
187 public string unref_function {
189 if (!unref_function_set) {
191 _unref_function = ccode.get_string ("unref_function");
193 if (_unref_function == null) {
194 _unref_function = get_default_unref_function ();
196 unref_function_set = true;
198 return _unref_function;
202 public string ref_sink_function {
204 if (_ref_sink_function == null) {
206 _ref_sink_function = ccode.get_string ("ref_sink_function");
208 if (_ref_sink_function == null) {
209 _ref_sink_function = get_default_ref_sink_function ();
212 return _ref_sink_function;
216 public string copy_function {
218 if (!copy_function_set) {
220 _copy_function = ccode.get_string ("copy_function");
222 if (_copy_function == null && sym is Struct) {
223 _copy_function = "%scopy".printf (lower_case_prefix);
225 if (_copy_function == null && sym is TypeParameter) {
226 _copy_function = "%s_dup_func".printf (sym.name.ascii_down ());
228 copy_function_set = true;
230 return _copy_function;
234 public string destroy_function {
236 if (!destroy_function_set) {
238 _destroy_function = ccode.get_string ("destroy_function");
240 if (_destroy_function == null && sym is Struct) {
241 _destroy_function = "%sdestroy".printf (lower_case_prefix);
243 if (_destroy_function == null && sym is TypeParameter) {
244 _destroy_function = "%s_destroy_func".printf (sym.name.ascii_down ());
246 destroy_function_set = true;
248 return _destroy_function;
252 public string dup_function {
254 if (!dup_function_set) {
256 _dup_function = ccode.get_string ("dup_function");
258 if (_dup_function == null && !sym.external_package
259 && sym is Struct && !((Struct) sym).is_simple_type ()) {
260 _dup_function = "%sdup".printf (lower_case_prefix);
262 dup_function_set = true;
264 return _dup_function;
268 public string free_function {
270 if (!free_function_set) {
272 _free_function = ccode.get_string ("free_function");
274 if (_free_function == null) {
275 _free_function = get_default_free_function ();
277 free_function_set = true;
279 return _free_function;
283 public bool free_function_address_of {
285 if (_free_function_address_of == null) {
286 if (ccode != null && ccode.has_argument ("free_function_address_of")) {
287 _free_function_address_of = ccode.get_bool ("free_function_address_of");
289 unowned Class cl = (Class) sym;
290 if (cl.base_class != null) {
291 _free_function_address_of = get_ccode_free_function_address_of (cl.base_class);
293 _free_function_address_of = false;
297 return _free_function_address_of;
301 public string ctype {
305 _ctype = ccode.get_string ("type");
306 if (_ctype == null) {
307 _ctype = ccode.get_string ("ctype");
308 if (_ctype != null) {
309 Report.deprecated (node.source_reference, "[CCode (ctype = \"...\")] is deprecated, use [CCode (type = \"...\")] instead.");
319 public string type_id {
321 if (_type_id == null) {
323 _type_id = ccode.get_string ("type_id");
325 if (_type_id == null && sym is TypeParameter) {
326 _type_id = "%s_type".printf (sym.name.ascii_down ());
328 if (_type_id == null) {
329 _type_id = get_default_type_id ();
336 public string marshaller_type_name {
338 if (_marshaller_type_name == null) {
340 _marshaller_type_name = ccode.get_string ("marshaller_type_name");
342 if (_marshaller_type_name == null) {
343 _marshaller_type_name = get_default_marshaller_type_name ();
346 return _marshaller_type_name;
350 public string get_value_function {
352 if (_get_value_function == null) {
354 _get_value_function = ccode.get_string ("get_value_function");
356 if (_get_value_function == null) {
357 _get_value_function = get_default_get_value_function ();
360 return _get_value_function;
364 public string set_value_function {
366 if (_set_value_function == null) {
368 _set_value_function = ccode.get_string ("set_value_function");
370 if (_set_value_function == null) {
371 _set_value_function = get_default_set_value_function ();
374 return _set_value_function;
378 public string take_value_function {
380 if (_take_value_function == null) {
382 _take_value_function = ccode.get_string ("take_value_function");
384 if (_take_value_function == null) {
385 _take_value_function = get_default_take_value_function ();
388 return _take_value_function;
392 public string param_spec_function {
394 if (_param_spec_function == null) {
396 _param_spec_function = ccode.get_string ("param_spec_function");
398 if (_param_spec_function == null) {
399 _param_spec_function = get_default_param_spec_function ();
402 return _param_spec_function;
406 public string default_value {
408 if (_default_value == null) {
410 _default_value = ccode.get_string ("default_value");
412 if (_default_value == null) {
413 _default_value = get_default_default_value ();
416 return _default_value;
420 public string default_value_on_error {
422 if (_default_value_on_error == null) {
424 _default_value_on_error = ccode.get_string ("default_value_on_error");
426 if (_default_value_on_error == null) {
427 _default_value_on_error = default_value;
430 return _default_value_on_error;
437 if (ccode != null && ccode.has_argument ("pos")) {
438 _pos = ccode.get_double ("pos");
440 unowned Parameter param = (Parameter) node;
441 unowned Callable? callable = param.parent_symbol as Callable;
442 unowned Method? method = param.parent_symbol as Method;
443 if (method != null && method.coroutine) {
444 int index = method.get_async_begin_parameters ().index_of (param);
446 index = method.get_async_end_parameters ().index_of (param);
449 Report.error (param.source_reference, "internal: Parameter `%s' not found in `%s'", param.name, method.get_full_name ());
452 } else if (callable != null) {
453 _pos = callable.get_parameters ().index_of (param) + 1.0;
463 public string real_name {
465 if (_real_name == null) {
466 if (ccode != null && sym is CreationMethod) {
467 _real_name = ccode.get_string ("construct_function");
469 if (_real_name == null) {
470 _real_name = get_default_real_name ();
477 public string vfunc_name {
479 if (_vfunc_name == null) {
481 _vfunc_name = ccode.get_string ("vfunc_name");
483 if (_vfunc_name == null) {
484 unowned Method? m = node as Method;
485 if (m != null && m.signal_reference != null) {
486 _vfunc_name = get_ccode_lower_case_name (m.signal_reference);
488 _vfunc_name = sym.name;
496 public string finish_name {
498 if (_finish_name == null) {
500 _finish_name = ccode.get_string ("finish_name");
501 if (_finish_name == null) {
502 _finish_name = ccode.get_string ("finish_function");
503 if (_finish_name != null) {
504 Report.deprecated (node.source_reference, "[CCode (finish_function = \"...\")] is deprecated, use [CCode (finish_name = \"...\")] instead.");
508 if (_finish_name == null) {
509 _finish_name = get_finish_name_for_basename (name);
516 public string finish_vfunc_name {
518 if (_finish_vfunc_name == null) {
520 _finish_vfunc_name = ccode.get_string ("finish_vfunc_name");
522 if (_finish_vfunc_name == null) {
523 _finish_vfunc_name = get_finish_name_for_basename (vfunc_name);
526 return _finish_vfunc_name;
530 public string finish_real_name {
532 if (_finish_real_name == null) {
533 unowned Method? m = node as Method;
534 if (m != null && !(m is CreationMethod) && !(m.is_abstract || m.is_virtual)) {
535 _finish_real_name = finish_name;
537 _finish_real_name = get_finish_name_for_basename (real_name);
540 return _finish_real_name;
544 public bool finish_instance {
546 if (_finish_instance == null) {
547 unowned Method? m = node as Method;
548 bool is_creation_method = m is CreationMethod;
549 if (ccode == null || m == null || m.is_abstract || m.is_virtual) {
550 _finish_instance = !is_creation_method;
552 _finish_instance = ccode.get_bool ("finish_instance", !is_creation_method);
555 return _finish_instance;
559 public bool delegate_target {
561 if (_delegate_target == null) {
563 _delegate_target = ccode.get_bool ("delegate_target", get_default_delegate_target ());
565 _delegate_target = get_default_delegate_target ();
568 return _delegate_target;
572 public string delegate_target_name {
574 if (_delegate_target_name == null) {
576 _delegate_target_name = ccode.get_string ("delegate_target_cname");
578 if (_delegate_target_name == null) {
579 _delegate_target_name = "%s_target".printf (name);
582 return _delegate_target_name;
586 public string delegate_target_destroy_notify_name {
588 if (_delegate_target_destroy_notify_name == null) {
590 _delegate_target_destroy_notify_name = ccode.get_string ("destroy_notify_cname");
592 if (_delegate_target_destroy_notify_name == null) {
593 _delegate_target_destroy_notify_name = "%s_destroy_notify".printf (delegate_target_name);
596 return _delegate_target_destroy_notify_name;
600 public bool array_length {
602 if (_array_length == null) {
603 if (node.get_attribute ("NoArrayLength") != null) {
604 Report.deprecated (node.source_reference, "[NoArrayLength] is deprecated, use [CCode (array_length = false)] instead.");
605 _array_length = false;
606 } else if (ccode != null && ccode.has_argument ("array_length")) {
607 _array_length = ccode.get_bool ("array_length");
609 _array_length = get_default_array_length ();
612 return _array_length;
616 public bool array_null_terminated {
618 if (_array_null_terminated == null) {
619 // If arrays claim to have an array-length and also are null-terminated then rely on the given length
620 if (ccode != null && ccode.has_argument ("array_length") && ccode.get_bool ("array_length")) {
621 _array_null_terminated = false;
622 } else if (ccode != null && ccode.has_argument ("array_null_terminated")) {
623 _array_null_terminated = ccode.get_bool ("array_null_terminated");
625 _array_null_terminated = get_default_array_null_terminated ();
628 return _array_null_terminated;
632 public string array_length_type {
634 if (_array_length_type == null) {
635 if (ccode != null && ccode.has_argument ("array_length_type")) {
636 _array_length_type = ccode.get_string ("array_length_type");
638 _array_length_type = get_default_array_length_type ();
641 return _array_length_type;
645 public string sentinel {
647 if (_sentinel == null) {
649 _sentinel = ccode.get_string ("sentinel", "NULL");
658 public string? array_length_name { get; private set; }
659 public string? array_length_expr { get; private set; }
661 private string _name;
662 private string _const_name;
663 private string _type_name;
664 private string _feature_test_macros;
665 private string _header_filenames;
666 private string _prefix;
667 private string _lower_case_prefix;
668 private string _lower_case_suffix;
669 private string? _ref_function;
670 private bool ref_function_set;
671 private bool? _ref_function_void;
672 private string? _unref_function;
673 private bool unref_function_set;
674 private string _ref_sink_function;
675 private string? _copy_function;
676 private bool copy_function_set;
677 private string? _destroy_function;
678 private bool destroy_function_set;
679 private string? _dup_function;
680 private bool dup_function_set;
681 private string? _free_function;
682 private bool free_function_set;
683 private bool? _free_function_address_of;
684 private string _type_id;
685 private string _marshaller_type_name;
686 private string _get_value_function;
687 private string _set_value_function;
688 private string _take_value_function;
689 private string _param_spec_function;
690 private string _default_value;
691 private string _default_value_on_error;
692 private double? _pos;
693 private string _vfunc_name;
694 private string _finish_name;
695 private string _finish_vfunc_name;
696 private string _finish_real_name;
697 private bool? _finish_instance;
698 private string _real_name;
699 private bool? _delegate_target;
700 private string _delegate_target_name;
701 private string _delegate_target_destroy_notify_name;
702 private string _ctype;
703 private bool ctype_set = false;
704 private bool? _array_length;
705 private string _array_length_type;
706 private bool? _array_null_terminated;
707 private string _sentinel;
709 private static int dynamic_method_id;
711 public CCodeAttribute (CodeNode node) {
713 this.sym = node as Symbol;
715 ccode = node.get_attribute ("CCode");
717 array_length_name = ccode.get_string ("array_length_cname");
718 array_length_expr = ccode.get_string ("array_length_cexpr");
722 private string get_default_name () {
724 if (sym is Constant && !(sym is EnumValue)) {
725 if (sym.parent_symbol is Block) {
729 return "%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol).ascii_up (), sym.name);
730 } else if (sym is Field) {
731 var cname = sym.name;
732 if (((Field) sym).binding == MemberBinding.STATIC) {
733 cname = "%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), sym.name);
735 if (cname[0].isdigit ()) {
736 Report.error (node.source_reference, "Field name starts with a digit. Use the `cname' attribute to provide a valid C name if intended");
740 } else if (sym is CreationMethod) {
741 unowned CreationMethod m = (CreationMethod) sym;
743 if (m.parent_symbol is Struct) {
748 if (m.name == ".new") {
749 return "%s%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), infix);
751 return "%s%s_%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), infix, m.name);
753 } else if (sym is DynamicMethod) {
754 return "_dynamic_%s%d".printf (sym.name, dynamic_method_id++);
755 } else if (sym is Method) {
756 unowned Method m = (Method) sym;
757 if (m.is_async_callback) {
758 return "%s_co".printf (get_ccode_real_name ((Method) m.parent_symbol));
760 if (m.signal_reference != null) {
761 return "%s%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), get_ccode_lower_case_name (m.signal_reference));
763 if (sym.name == "main" && sym.parent_symbol.name == null) {
764 // avoid conflict with generated main function
766 return "_vala_main_async";
770 } else if (sym.name.has_prefix ("_")) {
771 return "_%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), sym.name.substring (1));
773 return "%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), sym.name);
775 } else if (sym is Property) {
776 return sym.name.replace ("_", "-");
777 } else if (sym is PropertyAccessor) {
778 unowned PropertyAccessor acc = (PropertyAccessor) sym;
779 var t = (TypeSymbol) acc.prop.parent_symbol;
782 return "%sget_%s".printf (get_ccode_lower_case_prefix (t), acc.prop.name);
784 return "%sset_%s".printf (get_ccode_lower_case_prefix (t), acc.prop.name);
786 } else if (sym is Signal) {
787 return Symbol.camel_case_to_lower_case (sym.name).replace ("_", "-");;
788 } else if (sym is LocalVariable) {
789 unowned string name = sym.name;
790 if (CCodeBaseModule.reserved_identifiers.contains (name)) {
791 return "_%s_".printf (name);
795 } else if (sym is Parameter) {
796 unowned Parameter param = (Parameter) sym;
797 if (param.ellipsis) {
800 unowned string name = sym.name;
801 if (CCodeBaseModule.reserved_identifiers.contains (name)) {
802 return "_%s_".printf (name);
806 } else if (sym is TypeParameter) {
807 assert (node is GenericType);
808 var type = (GenericType) node;
809 if (type.value_owned) {
810 if (CodeContext.get ().profile == Profile.GOBJECT) {
816 if (CodeContext.get ().profile == Profile.GOBJECT) {
817 return "gconstpointer";
819 return "const void *";
823 return "%s%s".printf (get_ccode_prefix (sym.parent_symbol), sym.name);
825 } else if (node is ObjectType) {
826 var type = (ObjectType) node;
829 if (!type.value_owned) {
830 cname = get_ccode_const_name (type.type_symbol);
832 cname = get_ccode_name (type.type_symbol);
834 return "%s*".printf (cname);
835 } else if (node is ArrayType) {
836 var type = (ArrayType) node;
837 var cname = get_ccode_name (type.element_type);
838 if (type.inline_allocated) {
841 return "%s*".printf (cname);
843 } else if (node is DelegateType) {
844 var type = (DelegateType) node;
845 return get_ccode_name (type.delegate_symbol);
846 } else if (node is ErrorType) {
848 } else if (node is GenericType) {
849 var type = (GenericType) node;
850 if (type.value_owned) {
851 if (CodeContext.get ().profile == Profile.GOBJECT) {
857 if (CodeContext.get ().profile == Profile.GOBJECT) {
858 return "gconstpointer";
860 return "const void *";
863 } else if (node is MethodType) {
864 if (CodeContext.get ().profile == Profile.GOBJECT) {
869 } else if (node is NullType) {
870 if (CodeContext.get ().profile == Profile.GOBJECT) {
875 } else if (node is PointerType) {
876 var type = (PointerType) node;
877 if (type.base_type.type_symbol != null && type.base_type.type_symbol.is_reference_type ()) {
878 return get_ccode_name (type.base_type);
880 return "%s*".printf (get_ccode_name (type.base_type));
882 } else if (node is VoidType) {
884 } else if (node is ClassType) {
885 var type = (ClassType) node;
886 return "%s*".printf (get_ccode_type_name (type.class_symbol));
887 } else if (node is InterfaceType) {
888 var type = (InterfaceType) node;
889 return "%s*".printf (get_ccode_type_name (type.interface_symbol));
890 } else if (node is ValueType) {
891 var type = (ValueType) node;
892 var cname = get_ccode_name (type.type_symbol);
894 return "%s*".printf (cname);
898 } else if (node is CType) {
899 return ((CType) node).ctype_name;
901 Report.error (node.source_reference, "Unresolved type reference");
906 private string get_default_header_filenames () {
907 if (sym is DynamicProperty || sym is DynamicMethod) {
910 if (sym.parent_symbol != null && !sym.is_extern) {
911 var parent_headers = get_ccode_header_filenames (sym.parent_symbol);
912 if (parent_headers.length > 0) {
913 return parent_headers;
916 if (sym.source_reference != null && !sym.external_package && !sym.is_extern) {
917 // don't add default include directives for VAPI files
918 return sym.source_reference.file.get_cinclude_filename ();
923 private string get_default_prefix () {
924 if (sym is ObjectTypeSymbol) {
926 } else if (sym is Enum || sym is ErrorDomain) {
927 return "%s_".printf (get_ccode_upper_case_name (sym));
928 } else if (sym is Namespace) {
929 if (sym.name != null) {
930 var parent_prefix = "";
931 if (sym.parent_symbol != null) {
932 parent_prefix = get_ccode_prefix (sym.parent_symbol);
934 return "%s%s".printf (parent_prefix, sym.name);
938 } else if (sym.name != null) {
944 private string get_default_lower_case_prefix () {
945 if (sym is Namespace) {
946 if (sym.name == null) {
949 return "%s%s_".printf (get_ccode_lower_case_prefix (sym.parent_symbol), Symbol.camel_case_to_lower_case (sym.name));
951 } else if (sym is Method) {
952 // for lambda expressions
955 return "%s_".printf (get_ccode_lower_case_name (sym));
959 private string get_default_lower_case_suffix () {
960 if (sym is ObjectTypeSymbol) {
961 var csuffix = Symbol.camel_case_to_lower_case (sym.name);
963 // FIXME Code duplication with GirParser.Node.get_default_lower_case_suffix()
964 // remove underscores in some cases to avoid conflicts of type macros
965 if (csuffix.has_prefix ("type_")) {
966 csuffix = "type" + csuffix.substring ("type_".length);
967 } else if (csuffix.has_prefix ("is_")) {
968 csuffix = "is" + csuffix.substring ("is_".length);
970 if (csuffix.has_suffix ("_class")) {
971 csuffix = csuffix.substring (0, csuffix.length - "_class".length) + "class";
974 } else if (sym is Signal) {
975 return get_ccode_attribute (sym).name.replace ("-", "_");
976 } else if (sym.name != null) {
977 return Symbol.camel_case_to_lower_case (sym.name);
982 private string? get_default_ref_function () {
984 unowned Class cl = (Class) sym;
985 if (cl.is_fundamental ()) {
986 return "%sref".printf (lower_case_prefix);
987 } else if (cl.base_class != null) {
988 return get_ccode_ref_function (cl.base_class);
990 } else if (sym is Interface) {
991 foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
992 string ref_func = get_ccode_ref_function ((ObjectTypeSymbol) prereq.type_symbol);
993 if (ref_func != null) {
1001 private string? get_default_unref_function () {
1003 unowned Class cl = (Class) sym;
1004 if (cl.is_fundamental ()) {
1005 return "%sunref".printf (lower_case_prefix);
1006 } else if (cl.base_class != null) {
1007 return get_ccode_unref_function (cl.base_class);
1009 } else if (sym is Interface) {
1010 foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1011 string unref_func = get_ccode_unref_function ((ObjectTypeSymbol) prereq.type_symbol);
1012 if (unref_func != null) {
1020 private string get_default_ref_sink_function () {
1022 unowned Class? base_class = ((Class) sym).base_class;
1023 if (base_class != null) {
1024 return get_ccode_ref_sink_function (base_class);
1026 } else if (sym is Interface) {
1027 foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1028 string ref_sink_func = get_ccode_ref_sink_function ((ObjectTypeSymbol) prereq.type_symbol);
1029 if (ref_sink_func != "") {
1030 return ref_sink_func;
1037 private string? get_default_free_function () {
1039 unowned Class cl = (Class) sym;
1040 if (cl.base_class != null) {
1041 return get_ccode_free_function (cl.base_class);
1043 return "%sfree".printf (lower_case_prefix);
1044 } else if (sym is Struct) {
1045 if (!sym.external_package && !((Struct) sym).is_simple_type ()) {
1046 return "%sfree".printf (lower_case_prefix);
1052 private string get_default_type_id () {
1054 if (sym is Class && !((Class) sym).is_compact || sym is Interface) {
1055 return get_ccode_upper_case_name (sym, "TYPE_");
1056 } else if (sym is Struct) {
1057 unowned Struct st = (Struct) sym;
1058 unowned Struct? base_struct = st.base_struct;
1059 if (!get_ccode_has_type_id (st) || (base_struct != null && base_struct.is_simple_type ())) {
1060 if (base_struct != null) {
1061 return get_ccode_type_id (base_struct);
1063 if (!st.is_simple_type ()) {
1064 return "G_TYPE_POINTER";
1067 return get_ccode_upper_case_name (st, "TYPE_");
1069 } else if (sym is Enum) {
1070 unowned Enum en = (Enum) sym;
1071 if (get_ccode_has_type_id (en)) {
1072 return get_ccode_upper_case_name (en, "TYPE_");
1074 return en.is_flags ? "G_TYPE_UINT" : "G_TYPE_INT";
1077 return "G_TYPE_POINTER";
1079 } else if (node is ArrayType && ((ArrayType) node).element_type.type_symbol == CodeContext.get ().analyzer.string_type.type_symbol) {
1080 return "G_TYPE_STRV";
1081 } else if (node is PointerType || node is DelegateType) {
1082 return "G_TYPE_POINTER";
1083 } else if (node is ErrorType) {
1084 return "G_TYPE_ERROR";
1085 } else if (node is VoidType) {
1086 return "G_TYPE_NONE";
1088 var type = (DataType) node;
1089 if (type.type_symbol != null) {
1090 return get_ccode_type_id (type.type_symbol);
1096 private string get_default_marshaller_type_name () {
1099 unowned Class cl = (Class) sym;
1100 if (cl.base_class != null) {
1101 return get_ccode_marshaller_type_name (cl.base_class);
1102 } else if (!cl.is_compact) {
1103 return get_ccode_upper_case_name (cl);
1104 } else if (type_id == "G_TYPE_POINTER") {
1109 } else if (sym is Enum) {
1110 unowned Enum en = (Enum) sym;
1111 if (get_ccode_has_type_id (en)) {
1124 } else if (sym is Interface) {
1125 foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1126 var type_name = get_ccode_marshaller_type_name (prereq.type_symbol);
1127 if (type_name != "") {
1132 } else if (sym is Struct) {
1133 unowned Struct st = (Struct) sym;
1134 unowned Struct? base_st = st.base_struct;
1135 while (base_st != null) {
1136 if (get_ccode_has_type_id (base_st)) {
1137 return get_ccode_marshaller_type_name (base_st);
1139 base_st = base_st.base_struct;
1142 if (st.is_simple_type ()) {
1143 Report.error (st.source_reference, "The type `%s' doesn't declare a marshaller type name", st.get_full_name ());
1144 } else if (get_ccode_has_type_id (st)) {
1149 } else if (sym is Parameter) {
1150 unowned Parameter param = (Parameter) sym;
1151 if (param.direction != ParameterDirection.IN) {
1154 return get_ccode_marshaller_type_name (param.variable_type);
1159 } else if (node is ValueType && ((ValueType) node).nullable) {
1161 } else if (node is PointerType || node is GenericType) {
1163 } else if (node is ErrorType) {
1165 } else if (node is ArrayType) {
1166 unowned ArrayType array_type = (ArrayType) node;
1167 if (array_type.element_type.type_symbol == CodeContext.get ().analyzer.string_type.type_symbol) {
1168 return "BOXED,%s".printf (get_ccode_marshaller_type_name (array_type.length_type.type_symbol));
1170 var ret = "POINTER";
1171 var length_marshaller_type_name = get_ccode_marshaller_type_name (array_type.length_type.type_symbol);
1172 for (var i = 0; i < array_type.rank; i++) {
1173 ret = "%s,%s".printf (ret, length_marshaller_type_name);
1177 } else if (node is DelegateType) {
1178 unowned DelegateType delegate_type = (DelegateType) node;
1179 var ret = "POINTER";
1180 if (delegate_type.delegate_symbol.has_target) {
1181 ret = "%s,POINTER".printf (ret);
1182 if (delegate_type.is_disposable ()) {
1183 ret = "%s,POINTER".printf (ret);
1187 } else if (node is VoidType) {
1190 return get_ccode_marshaller_type_name (((DataType) node).type_symbol);
1195 private string get_default_get_value_function () {
1197 unowned Class cl = (Class) sym;
1198 if (cl.is_fundamental ()) {
1199 return get_ccode_lower_case_name (cl, "value_get_");
1200 } else if (cl.base_class != null) {
1201 return get_ccode_get_value_function (cl.base_class);
1202 } else if (type_id == "G_TYPE_POINTER") {
1203 return "g_value_get_pointer";
1205 return "g_value_get_boxed";
1207 } else if (sym is Enum) {
1208 unowned Enum en = (Enum) sym;
1209 if (get_ccode_has_type_id (en)) {
1211 return "g_value_get_flags";
1213 return "g_value_get_enum";
1217 return "g_value_get_uint";
1219 return "g_value_get_int";
1222 } else if (sym is Interface) {
1223 foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1224 var type_name = get_ccode_get_value_function (prereq.type_symbol);
1225 if (type_name != "") {
1229 return "g_value_get_pointer";
1230 } else if (sym is Struct) {
1231 unowned Struct st = (Struct) sym;
1232 unowned Struct? base_st = st.base_struct;
1233 while (base_st != null) {
1234 if (get_ccode_has_type_id (base_st)) {
1235 return get_ccode_get_value_function (base_st);
1237 base_st = base_st.base_struct;
1240 if (st.is_simple_type ()) {
1241 Report.error (st.source_reference, "The type `%s' doesn't declare a GValue get function", st.get_full_name ());
1242 } else if (get_ccode_has_type_id (st)) {
1243 return "g_value_get_boxed";
1245 return "g_value_get_pointer";
1248 return "g_value_get_pointer";
1253 private string get_default_set_value_function () {
1255 unowned Class cl = (Class) sym;
1256 if (cl.is_fundamental ()) {
1257 return get_ccode_lower_case_name (cl, "value_set_");
1258 } else if (cl.base_class != null) {
1259 return get_ccode_set_value_function (cl.base_class);
1260 } else if (type_id == "G_TYPE_POINTER") {
1261 return "g_value_set_pointer";
1263 return "g_value_set_boxed";
1265 } else if (sym is Enum) {
1266 unowned Enum en = (Enum) sym;
1267 if (get_ccode_has_type_id (en)) {
1269 return "g_value_set_flags";
1271 return "g_value_set_enum";
1275 return "g_value_set_uint";
1277 return "g_value_set_int";
1280 } else if (sym is Interface) {
1281 foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1282 var type_name = get_ccode_set_value_function (prereq.type_symbol);
1283 if (type_name != "") {
1287 return "g_value_set_pointer";
1288 } else if (sym is Struct) {
1289 unowned Struct st = (Struct) sym;
1290 unowned Struct? base_st = st.base_struct;
1291 while (base_st != null) {
1292 if (get_ccode_has_type_id (base_st)) {
1293 return get_ccode_set_value_function (base_st);
1295 base_st = base_st.base_struct;
1298 if (st.is_simple_type ()) {
1299 Report.error (st.source_reference, "The type `%s' doesn't declare a GValue set function", st.get_full_name ());
1300 } else if (get_ccode_has_type_id (st)) {
1301 return "g_value_set_boxed";
1303 return "g_value_set_pointer";
1306 return "g_value_set_pointer";
1311 private string get_default_take_value_function () {
1313 unowned Class cl = (Class) sym;
1314 if (cl.is_fundamental ()) {
1315 return get_ccode_lower_case_name (cl, "value_take_");
1316 } else if (cl.base_class != null) {
1317 return get_ccode_take_value_function (cl.base_class);
1318 } else if (type_id == "G_TYPE_POINTER") {
1319 return "g_value_set_pointer";
1321 return "g_value_take_boxed";
1323 } else if (sym is Enum) {
1324 unowned Enum en = (Enum) sym;
1325 if (get_ccode_has_type_id (en)) {
1327 return "g_value_take_flags";
1329 return "g_value_take_enum";
1333 return "g_value_take_uint";
1335 return "g_value_take_int";
1338 } else if (sym is Interface) {
1339 foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1340 var func = get_ccode_take_value_function (prereq.type_symbol);
1345 return "g_value_set_pointer";
1346 } else if (sym is Struct) {
1347 unowned Struct st = (Struct) sym;
1348 unowned Struct? base_st = st.base_struct;
1349 while (base_st != null) {
1350 if (get_ccode_has_type_id (base_st)) {
1351 return get_ccode_take_value_function (base_st);
1353 base_st = base_st.base_struct;
1356 if (st.is_simple_type ()) {
1357 Report.error (st.source_reference, "The type `%s' doesn't declare a GValue take function", st.get_full_name ());
1358 } else if (get_ccode_has_type_id (st)) {
1359 return "g_value_take_boxed";
1361 return "g_value_set_pointer";
1364 return "g_value_set_pointer";
1369 private string get_default_param_spec_function () {
1370 if (node is Symbol) {
1372 unowned Class cl = (Class) sym;
1373 if (cl.is_fundamental ()) {
1374 return get_ccode_lower_case_name (cl, "param_spec_");
1375 } else if (cl.base_class != null) {
1376 return get_ccode_param_spec_function (cl.base_class);
1377 } else if (type_id == "G_TYPE_POINTER") {
1378 return "g_param_spec_pointer";
1380 return "g_param_spec_boxed";
1382 } else if (sym is Interface) {
1383 foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
1384 var func = get_ccode_param_spec_function (prereq.type_symbol);
1389 return "g_param_spec_pointer";
1390 } else if (sym is Enum) {
1391 unowned Enum e = (Enum) sym;
1392 if (get_ccode_has_type_id (e)) {
1394 return "g_param_spec_flags";
1396 return "g_param_spec_enum";
1400 return "g_param_spec_uint";
1402 return "g_param_spec_int";
1405 } else if (sym is Struct) {
1406 var type_id = get_ccode_type_id (sym);
1407 if (type_id == "G_TYPE_INT") {
1408 return "g_param_spec_int";
1409 } else if (type_id == "G_TYPE_UINT") {
1410 return "g_param_spec_uint";
1411 } else if (type_id == "G_TYPE_INT64") {
1412 return "g_param_spec_int64";
1413 } else if (type_id == "G_TYPE_UINT64") {
1414 return "g_param_spec_uint64";
1415 } else if (type_id == "G_TYPE_LONG") {
1416 return "g_param_spec_long";
1417 } else if (type_id == "G_TYPE_ULONG") {
1418 return "g_param_spec_ulong";
1419 } else if (type_id == "G_TYPE_BOOLEAN") {
1420 return "g_param_spec_boolean";
1421 } else if (type_id == "G_TYPE_CHAR") {
1422 return "g_param_spec_char";
1423 } else if (type_id == "G_TYPE_UCHAR") {
1424 return "g_param_spec_uchar";
1425 }else if (type_id == "G_TYPE_FLOAT") {
1426 return "g_param_spec_float";
1427 } else if (type_id == "G_TYPE_DOUBLE") {
1428 return "g_param_spec_double";
1429 } else if (type_id == "G_TYPE_GTYPE") {
1430 return "g_param_spec_gtype";
1432 return "g_param_spec_boxed";
1435 } else if (node is ArrayType && ((ArrayType) node).element_type.type_symbol == CodeContext.get ().analyzer.string_type.type_symbol) {
1436 return "g_param_spec_boxed";
1437 } else if (node is DataType && ((DataType) node).type_symbol != null) {
1438 return get_ccode_param_spec_function (((DataType) node).type_symbol);
1441 return "g_param_spec_pointer";
1444 private string get_default_default_value () {
1446 unowned Enum en = (Enum) sym;
1452 } else if (sym is Struct) {
1453 unowned Struct st = (Struct) sym;
1454 unowned Struct? base_st = st.base_struct;
1455 if (base_st != null) {
1456 return get_ccode_default_value (base_st);
1462 private string get_finish_name_for_basename (string basename) {
1463 string result = basename;
1464 if (result.has_suffix ("_async")) {
1465 result = result.substring (0, result.length - "_async".length);
1467 return "%s_finish".printf (result);
1470 private string get_default_real_name () {
1471 if (sym is CreationMethod) {
1472 unowned CreationMethod m = (CreationMethod) sym;
1473 unowned Class? parent = m.parent_symbol as Class;
1475 if (parent == null || parent.is_compact) {
1479 string infix = "construct";
1481 if (m.name == ".new") {
1482 return "%s%s".printf (get_ccode_lower_case_prefix (parent), infix);
1484 return "%s%s_%s".printf (get_ccode_lower_case_prefix (parent), infix, m.name);
1486 } else if (sym is Method) {
1487 unowned Method m = (Method) sym;
1488 if (m.base_method != null || m.base_interface_method != null || m.signal_reference != null) {
1490 if (m.signal_reference != null) {
1491 m_name = get_ccode_lower_case_name (m.signal_reference);
1495 if (m.base_interface_type != null) {
1496 return "%sreal_%s%s".printf (get_ccode_lower_case_prefix (m.parent_symbol),
1497 get_ccode_lower_case_prefix (m.base_interface_type.type_symbol),
1500 return "%sreal_%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), m_name);
1505 } else if (sym is PropertyAccessor) {
1506 unowned PropertyAccessor acc = (PropertyAccessor) sym;
1507 unowned Property prop = (Property) acc.prop;
1508 if (prop.base_property != null || prop.base_interface_property != null) {
1510 return "%sreal_get_%s".printf (get_ccode_lower_case_prefix (prop.parent_symbol), prop.name);
1512 return "%sreal_set_%s".printf (get_ccode_lower_case_prefix (prop.parent_symbol), prop.name);
1518 assert_not_reached ();
1521 private string get_default_const_name () {
1522 if (node is DataType) {
1523 unowned DataType type = (DataType) node;
1526 // FIXME: workaround to make constant arrays possible
1527 if (type is ArrayType) {
1528 t = ((ArrayType) type).element_type.type_symbol;
1530 t = type.type_symbol;
1532 if (!t.is_reference_type ()) {
1538 return "const %s%s".printf (get_ccode_name (t), ptr);
1540 if (node is Class && ((Class) node).is_immutable) {
1541 return "const %s".printf (name);
1548 private bool get_default_delegate_target () {
1549 if (node is Field || node is Parameter || node is LocalVariable) {
1550 if (node is Parameter) {
1551 unowned Parameter param = (Parameter) node;
1552 if (param.base_parameter != null) {
1553 return get_ccode_delegate_target (param.base_parameter);
1556 unowned DelegateType? delegate_type = ((Variable) node).variable_type as DelegateType;
1557 return delegate_type != null && delegate_type.delegate_symbol.has_target;
1558 } else if (node is Callable) {
1559 if (node is Method) {
1560 unowned Method method = (Method) node;
1561 if (method.base_method != null && method.base_method != method) {
1562 return get_ccode_delegate_target (method.base_method);
1563 } else if (method.base_interface_method != null && method.base_interface_method != method) {
1564 return get_ccode_delegate_target (method.base_interface_method);
1567 unowned DelegateType? delegate_type = ((Callable) node).return_type as DelegateType;
1568 return delegate_type != null && delegate_type.delegate_symbol.has_target;
1569 } else if (node is Property) {
1570 unowned Property prop = (Property) node;
1571 if (prop.base_property != null && prop.base_property != prop) {
1572 return get_ccode_delegate_target (prop.base_property);
1573 } else if (prop.base_interface_property != null && prop.base_interface_property != prop) {
1574 return get_ccode_delegate_target (prop.base_interface_property);
1576 unowned DelegateType? delegate_type = prop.property_type as DelegateType;
1577 return delegate_type != null && delegate_type.delegate_symbol.has_target;
1578 } else if (node is PropertyAccessor) {
1579 return get_ccode_delegate_target (((PropertyAccessor) node).prop);
1580 } else if (node is Expression) {
1581 unowned Symbol? symbol = ((Expression) node).symbol_reference;
1582 if (symbol != null) {
1583 return get_ccode_delegate_target (symbol);
1589 private bool get_default_array_length () {
1590 if (node is Parameter) {
1591 unowned Parameter param = (Parameter) node;
1592 if (param.base_parameter != null) {
1593 return get_ccode_array_length (param.base_parameter);
1595 } else if (node is Method) {
1596 unowned Method method = (Method) node;
1597 if (method.base_method != null && method.base_method != method) {
1598 return get_ccode_array_length (method.base_method);
1599 } else if (method.base_interface_method != null && method.base_interface_method != method) {
1600 return get_ccode_array_length (method.base_interface_method);
1602 } else if (node is Property) {
1603 unowned Property prop = (Property) node;
1604 if (prop.base_property != null && prop.base_property != prop) {
1605 return get_ccode_array_length (prop.base_property);
1606 } else if (prop.base_interface_property != null && prop.base_interface_property != prop) {
1607 return get_ccode_array_length (prop.base_interface_property);
1609 } else if (node is PropertyAccessor) {
1610 return get_ccode_array_length (((PropertyAccessor) node).prop);
1615 private bool get_default_array_null_terminated () {
1616 if (node is Parameter) {
1617 unowned Parameter param = (Parameter) node;
1618 if (param.base_parameter != null) {
1619 return get_ccode_array_null_terminated (param.base_parameter);
1621 } else if (node is Method) {
1622 unowned Method method = (Method) node;
1623 if (method.base_method != null && method.base_method != method) {
1624 return get_ccode_array_null_terminated (method.base_method);
1625 } else if (method.base_interface_method != null && method.base_interface_method != method) {
1626 return get_ccode_array_null_terminated (method.base_interface_method);
1628 } else if (node is Property) {
1629 unowned Property prop = (Property) node;
1630 if (prop.base_property != null && prop.base_property != prop) {
1631 return get_ccode_array_null_terminated (prop.base_property);
1632 } else if (prop.base_interface_property != null && prop.base_interface_property != prop) {
1633 return get_ccode_array_null_terminated (prop.base_interface_property);
1635 } else if (node is PropertyAccessor) {
1636 return get_ccode_array_null_terminated (((PropertyAccessor) node).prop);
1641 private string get_default_array_length_type () {
1642 if (node is Field || node is Parameter) {
1643 if (node is Parameter) {
1644 unowned Parameter param = (Parameter) node;
1645 if (param.base_parameter != null) {
1646 return get_ccode_array_length_type (param.base_parameter);
1649 return get_ccode_array_length_type (((Variable) node).variable_type);
1650 } else if (node is Method || node is Delegate) {
1651 if (node is Method) {
1652 unowned Method method = (Method) node;
1653 if (method.base_method != null && method.base_method != method) {
1654 return get_ccode_array_length_type (method.base_method);
1655 } else if (method.base_interface_method != null && method.base_interface_method != method) {
1656 return get_ccode_array_length_type (method.base_interface_method);
1659 return get_ccode_array_length_type (((Callable) node).return_type);
1660 } else if (node is Property) {
1661 unowned Property prop = (Property) node;
1662 if (prop.base_property != null && prop.base_property != prop) {
1663 return get_ccode_array_length_type (prop.base_property);
1664 } else if (prop.base_interface_property != null && prop.base_interface_property != prop) {
1665 return get_ccode_array_length_type (prop.base_interface_property);
1667 return get_ccode_array_length_type (prop.property_type);
1669 } else if (node is PropertyAccessor) {
1670 return get_ccode_array_length_type (((PropertyAccessor) node).prop);
1672 Report.error (node.source_reference, "`CCode.array_length_type' not supported");