1 #!/usr/bin/env @PYTHON@
3 # pylint: disable=too-many-lines, missing-docstring, invalid-name
5 # This file is part of GLib
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 VERSION_STR = '''glib-genmarshal version @VERSION@
26 glib-genmarshal comes with ABSOLUTELY NO WARRANTY.
27 You may redistribute copies of glib-genmarshal under the terms of
28 the GNU General Public License which can be found in the
29 GLib source package. Sources, examples and contact
30 information are available at http://www.gtk.org'''
32 GETTERS_STR = '''#ifdef G_ENABLE_DEBUG
33 #define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
34 #define g_marshal_value_peek_char(v) g_value_get_schar (v)
35 #define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
36 #define g_marshal_value_peek_int(v) g_value_get_int (v)
37 #define g_marshal_value_peek_uint(v) g_value_get_uint (v)
38 #define g_marshal_value_peek_long(v) g_value_get_long (v)
39 #define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
40 #define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
41 #define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
42 #define g_marshal_value_peek_enum(v) g_value_get_enum (v)
43 #define g_marshal_value_peek_flags(v) g_value_get_flags (v)
44 #define g_marshal_value_peek_float(v) g_value_get_float (v)
45 #define g_marshal_value_peek_double(v) g_value_get_double (v)
46 #define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
47 #define g_marshal_value_peek_param(v) g_value_get_param (v)
48 #define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
49 #define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
50 #define g_marshal_value_peek_object(v) g_value_get_object (v)
51 #define g_marshal_value_peek_variant(v) g_value_get_variant (v)
52 #else /* !G_ENABLE_DEBUG */
53 /* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
54 * Do not access GValues directly in your code. Instead, use the
55 * g_value_get_*() functions
57 #define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
58 #define g_marshal_value_peek_char(v) (v)->data[0].v_int
59 #define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
60 #define g_marshal_value_peek_int(v) (v)->data[0].v_int
61 #define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
62 #define g_marshal_value_peek_long(v) (v)->data[0].v_long
63 #define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
64 #define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
65 #define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
66 #define g_marshal_value_peek_enum(v) (v)->data[0].v_long
67 #define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
68 #define g_marshal_value_peek_float(v) (v)->data[0].v_float
69 #define g_marshal_value_peek_double(v) (v)->data[0].v_double
70 #define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
71 #define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
72 #define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
73 #define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
74 #define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
75 #define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
76 #endif /* !G_ENABLE_DEBUG */'''
78 DEPRECATED_MSG_STR = 'The token "{}" is deprecated; use "{}" instead'
81 ' arg{:d} = ({:s}) va_arg (args_copy, {:s});'
83 '(param_types[{:d}] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && '
85 ' arg{idx:d} = {box_func} (param_types[{idx:d}] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg{idx:d});'
87 ' arg{idx:d} = {box_func} (arg{idx:d});'
89 ' {unbox_func} (param_types[{idx:d}] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg{idx:d});'
91 ' {unbox_func} (arg{idx:d});'
93 STD_PREFIX = 'g_cclosure_marshal'
95 # These are part of our ABI; keep this in sync with gmarshal.h
96 GOBJECT_MARSHALLERS = {
97 'g_cclosure_marshal_VOID__VOID',
98 'g_cclosure_marshal_VOID__BOOLEAN',
99 'g_cclosure_marshal_VOID__CHAR',
100 'g_cclosure_marshal_VOID__UCHAR',
101 'g_cclosure_marshal_VOID__INT',
102 'g_cclosure_marshal_VOID__UINT',
103 'g_cclosure_marshal_VOID__LONG',
104 'g_cclosure_marshal_VOID__ULONG',
105 'g_cclosure_marshal_VOID__ENUM',
106 'g_cclosure_marshal_VOID__FLAGS',
107 'g_cclosure_marshal_VOID__FLOAT',
108 'g_cclosure_marshal_VOID__DOUBLE',
109 'g_cclosure_marshal_VOID__STRING',
110 'g_cclosure_marshal_VOID__PARAM',
111 'g_cclosure_marshal_VOID__BOXED',
112 'g_cclosure_marshal_VOID__POINTER',
113 'g_cclosure_marshal_VOID__OBJECT',
114 'g_cclosure_marshal_VOID__VARIANT',
115 'g_cclosure_marshal_VOID__UINT_POINTER',
116 'g_cclosure_marshal_BOOLEAN__FLAGS',
117 'g_cclosure_marshal_STRING__OBJECT_POINTER',
118 'g_cclosure_marshal_BOOLEAN__BOXED_BOXED',
122 # pylint: disable=too-few-public-methods
124 '''ANSI Terminal colors'''
127 YELLOW = '\033[1;33m'
132 def print_color(msg, color=Color.END, prefix='MESSAGE'):
133 '''Print a string with a color prefix'''
134 if os.isatty(sys.stderr.fileno()):
135 real_prefix = '{start}{prefix}{end}'.format(start=color, prefix=prefix, end=Color.END)
138 sys.stderr.write('{prefix}: {msg}\n'.format(prefix=real_prefix, msg=msg))
141 def print_error(msg):
142 '''Print an error, and terminate'''
143 print_color(msg, color=Color.RED, prefix='ERROR')
147 def print_warning(msg, fatal=False):
148 '''Print a warning, and optionally terminate'''
155 print_color(msg, color, prefix)
161 '''Print a message'''
162 print_color(msg, color=Color.GREEN, prefix='INFO')
165 def generate_header_preamble(outfile, prefix='', std_includes=True, use_pragma=False):
166 '''Generate the preamble for the marshallers header file'''
167 outfile.write('/* This file is generated, all changes will be lost */\n')
169 outfile.write('#pragma once\n')
172 outfile.write('#ifndef __{}_MARSHAL_H__\n'.format(prefix.upper()))
173 outfile.write('#define __{}_MARSHAL_H__\n'.format(prefix.upper()))
175 # Maintain compatibility with the old C-based tool
177 outfile.write('#include <glib-object.h>\n')
180 outfile.write('G_BEGIN_DECLS\n')
184 def generate_header_postamble(outfile, prefix='', use_pragma=False):
185 '''Generate the postamble for the marshallers header file'''
187 outfile.write('G_END_DECLS\n')
191 outfile.write('#endif /* __{}_MARSHAL_H__ */\n'.format(prefix.upper()))
194 def generate_body_preamble(outfile, std_includes=True, include_headers=None, cpp_defines=None, cpp_undefines=None):
195 '''Generate the preamble for the marshallers source file'''
196 for header in (include_headers or []):
197 outfile.write('#include "{}"\n'.format(header))
201 for define in (cpp_defines or []):
202 s = define.split('=')
204 value = s[1] if len(s) > 1 else '1'
205 outfile.write('#define {} {}\n'.format(symbol, value))
209 for undefine in (cpp_undefines or []):
210 outfile.write('#undef {}\n'.format(undefine))
215 outfile.write('#include <glib-object.h>\n')
218 outfile.write(GETTERS_STR)
219 outfile.write('\n\n')
222 # Marshaller arguments, as a dictionary where the key is the token used in
223 # the source file, and the value is another dictionary with the following
226 # - signal: the token used in the marshaller prototype (mandatory)
227 # - ctype: the C type for the marshaller argument (mandatory)
228 # - getter: the function used to retrieve the argument from the GValue
229 # array when invoking the callback (optional)
230 # - promoted: the C type used by va_arg() to retrieve the argument from
231 # the va_list when invoking the callback (optional, only used when
232 # generating va_list marshallers)
233 # - box: an array of two elements, containing the boxing and unboxing
234 # functions for the given type (optional, only used when generating
235 # va_list marshallers)
236 # - static-check: a boolean value, if the given type should perform
237 # a static type check before boxing or unboxing the argument (optional,
238 # only used when generating va_list marshallers)
239 # - takes-type: a boolean value, if the boxing and unboxing functions
240 # for the given type require the type (optional, only used when
241 # generating va_list marshallers)
242 # - deprecated: whether the token has been deprecated (optional)
243 # - replaced-by: the token used to replace a deprecated token (optional,
244 # only used if deprecated is True)
253 'getter': 'g_marshal_value_peek_boolean',
259 'getter': 'g_marshal_value_peek_char',
265 'getter': 'g_marshal_value_peek_uchar',
270 'getter': 'g_marshal_value_peek_int',
275 'getter': 'g_marshal_value_peek_uint',
280 'getter': 'g_marshal_value_peek_long',
285 'getter': 'g_marshal_value_peek_ulong',
290 'getter': 'g_marshal_value_peek_int64',
295 'getter': 'g_marshal_value_peek_uint64',
300 'getter': 'g_marshal_value_peek_enum',
305 'getter': 'g_marshal_value_peek_flags',
310 'promoted': 'gdouble',
311 'getter': 'g_marshal_value_peek_float',
316 'getter': 'g_marshal_value_peek_double',
321 'getter': 'g_marshal_value_peek_string',
322 'box': ['g_strdup', 'g_free'],
327 'getter': 'g_marshal_value_peek_param',
328 'box': ['g_param_spec_ref', 'g_param_spec_unref'],
333 'getter': 'g_marshal_value_peek_boxed',
334 'box': ['g_boxed_copy', 'g_boxed_free'],
335 'static-check': True,
341 'getter': 'g_marshal_value_peek_pointer',
346 'getter': 'g_marshal_value_peek_object',
347 'box': ['g_object_ref', 'g_object_unref'],
352 'getter': 'g_marshal_value_peek_variant',
353 'box': ['g_variant_ref', 'g_variant_unref'],
354 'static-check': True,
363 'replaced_by': 'VOID'
368 'getter': 'g_marshal_value_peek_boolean',
370 'replaced_by': 'BOOLEAN'
375 # Marshaller return values, as a dictionary where the key is the token used
376 # in the source file, and the value is another dictionary with the following
379 # - signal: the token used in the marshaller prototype (mandatory)
380 # - ctype: the C type for the marshaller argument (mandatory)
381 # - setter: the function used to set the return value of the callback
382 # into a GValue (optional)
383 # - deprecated: whether the token has been deprecated (optional)
384 # - replaced-by: the token used to replace a deprecated token (optional,
385 # only used if deprecated is True)
394 'setter': 'g_value_set_boolean',
399 'setter': 'g_value_set_char',
404 'setter': 'g_value_set_uchar',
409 'setter': 'g_value_set_int',
414 'setter': 'g_value_set_uint',
419 'setter': 'g_value_set_long',
424 'setter': 'g_value_set_ulong',
429 'setter': 'g_value_set_int64',
434 'setter': 'g_value_set_uint64',
439 'setter': 'g_value_set_enum',
444 'setter': 'g_value_set_flags',
449 'setter': 'g_value_set_float',
454 'setter': 'g_value_set_double',
459 'setter': 'g_value_take_string',
463 'ctype': 'GParamSpec*',
464 'setter': 'g_value_take_param',
469 'setter': 'g_value_take_boxed',
474 'setter': 'g_value_set_pointer',
479 'setter': 'g_value_take_object',
483 'ctype': 'GVariant*',
484 'setter': 'g_value_take_variant',
493 'replaced_by': 'VOID',
498 'setter': 'g_value_set_boolean',
500 'replaced_by': 'BOOLEAN',
505 def check_args(retval, params, fatal_warnings=False):
506 '''Check the @retval and @params tokens for invalid and deprecated symbols.'''
507 if retval not in OUT_ARGS:
508 print_error('Unknown return value type "{}"'.format(retval))
510 if OUT_ARGS[retval].get('deprecated', False):
511 replaced_by = OUT_ARGS[retval]['replaced_by']
512 print_warning(DEPRECATED_MSG_STR.format(retval, replaced_by), fatal_warnings)
515 if param not in IN_ARGS:
516 print_error('Unknown parameter type "{}"'.format(param))
518 if IN_ARGS[param].get('deprecated', False):
519 replaced_by = IN_ARGS[param]['replaced_by']
520 print_warning(DEPRECATED_MSG_STR.format(param, replaced_by), fatal_warnings)
523 def indent(text, level=0, fill=' '):
524 '''Indent @text by @level columns, using the @fill character'''
525 return ''.join([fill for x in range(level)]) + text
528 # pylint: disable=too-few-public-methods
530 '''Symbol visibility options'''
536 def generate_marshaller_name(prefix, retval, params, replace_deprecated=True):
537 '''Generate a marshaller name for the given @prefix, @retval, and @params.
538 If @replace_deprecated is True, the generated name will replace deprecated
540 if replace_deprecated:
541 real_retval = OUT_ARGS[retval]['signal']
544 real_params.append(IN_ARGS[param]['signal'])
548 return '{prefix}_{retval}__{args}'.format(prefix=prefix,
550 args='_'.join(real_params))
553 def generate_prototype(retval, params,
554 prefix='g_cclosure_user_marshal',
555 visibility=Visibility.NONE,
557 '''Generate a marshaller declaration with the given @visibility. If @va_marshal
558 is True, the marshaller will use variadic arguments in place of a GValue array.'''
559 signature = ['G_BEGIN_DECLS']
561 if visibility == Visibility.INTERNAL:
562 signature += ['G_GNUC_INTERNAL']
563 elif visibility == Visibility.EXTERN:
564 signature += ['extern']
566 function_name = generate_marshaller_name(prefix, retval, params)
569 signature += ['void ' + function_name + ' (GClosure *closure,']
570 width = len('void ') + len(function_name) + 2
572 signature += [indent('GValue *return_value,', level=width, fill=' ')]
573 signature += [indent('guint n_param_values,', level=width, fill=' ')]
574 signature += [indent('const GValue *param_values,', level=width, fill=' ')]
575 signature += [indent('gpointer invocation_hint,', level=width, fill=' ')]
576 signature += [indent('gpointer marshal_data);', level=width, fill=' ')]
578 signature += ['void ' + function_name + 'v (GClosure *closure,']
579 width = len('void ') + len(function_name) + 3
581 signature += [indent('GValue *return_value,', level=width, fill=' ')]
582 signature += [indent('gpointer instance,', level=width, fill=' ')]
583 signature += [indent('va_list args,', level=width, fill=' ')]
584 signature += [indent('gpointer marshal_data,', level=width, fill=' ')]
585 signature += [indent('int n_params,', level=width, fill=' ')]
586 signature += [indent('GType *param_types);', level=width, fill=' ')]
588 signature += ['G_END_DECLS']
593 # pylint: disable=too-many-statements, too-many-locals, too-many-branches
594 def generate_body(retval, params, prefix, va_marshal=False):
595 '''Generate a marshaller definition. If @va_marshal is True, the marshaller
596 will use va_list and variadic arguments in place of a GValue array.'''
597 retval_setter = OUT_ARGS[retval].get('setter', None)
598 # If there's no return value then we can mark the retval argument as unused
599 # and get a minor optimisation, as well as avoid a compiler warning
600 if not retval_setter:
601 unused = ' G_GNUC_UNUSED'
607 function_name = generate_marshaller_name(prefix, retval, params)
610 body += [function_name + ' (GClosure *closure,']
611 width = len(function_name) + 2
613 body += [indent('GValue *return_value{},'.format(unused), level=width, fill=' ')]
614 body += [indent('guint n_param_values,', level=width, fill=' ')]
615 body += [indent('const GValue *param_values,', level=width, fill=' ')]
616 body += [indent('gpointer invocation_hint G_GNUC_UNUSED,', level=width, fill=' ')]
617 body += [indent('gpointer marshal_data)', level=width, fill=' ')]
619 body += [function_name + 'v (GClosure *closure,']
620 width = len(function_name) + 3
622 body += [indent('GValue *return_value{},'.format(unused), level=width, fill=' ')]
623 body += [indent('gpointer instance,', level=width, fill=' ')]
624 body += [indent('va_list args,', level=width, fill=' ')]
625 body += [indent('gpointer marshal_data,', level=width, fill=' ')]
626 body += [indent('int n_params,', level=width, fill=' ')]
627 body += [indent('GType *param_types)', level=width, fill=' ')]
629 # Filter the arguments that have a getter
630 get_args = [x for x in params if IN_ARGS[x].get('getter', None) is not None]
634 # Generate the type of the marshaller function
635 typedef_marshal = generate_marshaller_name('GMarshalFunc', retval, params)
637 typedef = ' typedef {ctype} (*{func_name}) ('.format(ctype=OUT_ARGS[retval]['ctype'],
638 func_name=typedef_marshal)
640 typedef += 'gpointer data1,'
643 for idx, in_arg in enumerate(get_args):
644 body += [indent('{} arg{:d},'.format(IN_ARGS[in_arg]['ctype'], idx + 1), level=pad)]
646 body += [indent('gpointer data2);', level=pad)]
648 # Variable declarations
649 body += [' GCClosure *cc = (GCClosure *) closure;']
650 body += [' gpointer data1, data2;']
651 body += [' {} callback;'.format(typedef_marshal)]
654 body += [' {} v_return;'.format(OUT_ARGS[retval]['ctype'])]
657 for idx, arg in enumerate(get_args):
658 body += [' {} arg{:d};'.format(IN_ARGS[arg]['ctype'], idx)]
661 body += [' va_list args_copy;']
664 body += [' G_VA_COPY (args_copy, args);']
666 for idx, arg in enumerate(get_args):
667 ctype = IN_ARGS[arg]['ctype']
668 promoted_ctype = IN_ARGS[arg].get('promoted', ctype)
669 body += [VA_ARG_STR.format(idx, ctype, promoted_ctype)]
670 if IN_ARGS[arg].get('box', None):
671 box_func = IN_ARGS[arg]['box'][0]
672 if IN_ARGS[arg].get('static-check', False):
673 static_check = STATIC_CHECK_STR.format(idx)
676 arg_check = 'arg{:d} != NULL'.format(idx)
677 body += [' if ({}{})'.format(static_check, arg_check)]
678 if IN_ARGS[arg].get('takes-type', False):
679 body += [BOX_TYPED_STR.format(idx=idx, box_func=box_func)]
681 body += [BOX_UNTYPED_STR.format(idx=idx, box_func=box_func)]
683 body += [' va_end (args_copy);']
687 # Preconditions check
689 body += [' g_return_if_fail (return_value != NULL);']
692 body += [' g_return_if_fail (n_param_values == {:d});'.format(len(get_args) + 1)]
696 # Marshal instance, data, and callback set up
697 body += [' if (G_CCLOSURE_SWAP_DATA (closure))']
699 body += [' data1 = closure->data;']
701 body += [' data2 = instance;']
703 body += [' data2 = g_value_peek_pointer (param_values + 0);']
708 body += [' data1 = instance;']
710 body += [' data1 = g_value_peek_pointer (param_values + 0);']
711 body += [' data2 = closure->data;']
713 # pylint: disable=line-too-long
714 body += [' callback = ({}) (marshal_data ? marshal_data : cc->callback);'.format(typedef_marshal)]
717 # Marshal callback action
719 callback = ' {} callback ('.format(' v_return =')
721 callback = ' callback ('
724 body += [callback + 'data1,']
727 for idx, arg in enumerate(get_args):
728 body += [indent('arg{:d},'.format(idx), level=pad)]
730 for idx, arg in enumerate(get_args):
731 arg_getter = IN_ARGS[arg]['getter']
732 body += [indent('{} (param_values + {:d}),'.format(arg_getter, idx + 1), level=pad)]
734 body += [indent('data2);', level=pad)]
737 boxed_args = [x for x in get_args if IN_ARGS[x].get('box', None) is not None]
741 for idx, arg in enumerate(get_args):
742 if not IN_ARGS[arg].get('box', None):
744 unbox_func = IN_ARGS[arg]['box'][1]
745 if IN_ARGS[arg].get('static-check', False):
746 static_check = STATIC_CHECK_STR.format(idx)
749 arg_check = 'arg{:d} != NULL'.format(idx)
750 body += [' if ({}{})'.format(static_check, arg_check)]
751 if IN_ARGS[arg].get('takes-type', False):
752 body += [UNBOX_TYPED_STR.format(idx=idx, unbox_func=unbox_func)]
754 body += [UNBOX_UNTYPED_STR.format(idx=idx, unbox_func=unbox_func)]
758 body += [' {} (return_value, v_return);'.format(retval_setter)]
765 def generate_marshaller_alias(outfile, marshaller, real_marshaller,
767 source_location=None):
768 '''Generate an alias between @marshaller and @real_marshaller, including
769 an optional alias for va_list marshallers'''
771 outfile.write('/* {} */\n'.format(source_location))
773 outfile.write('#define {}\t{}\n'.format(marshaller, real_marshaller))
776 outfile.write('#define {}v\t{}v\n'.format(marshaller, real_marshaller))
781 def generate_marshallers_header(outfile, retval, params,
782 prefix='g_cclosure_user_marshal',
784 include_va=False, source_location=None):
785 '''Generate a declaration for a marshaller function, to be used in the header,
786 with the given @retval, @params, and @prefix. An optional va_list marshaller
787 for the same arguments is also generated. The generated buffer is written to
788 the @outfile stream object.'''
790 outfile.write('/* {} */\n'.format(source_location))
793 visibility = Visibility.INTERNAL
795 visibility = Visibility.EXTERN
797 signature = generate_prototype(retval, params, prefix, visibility, False)
799 signature += generate_prototype(retval, params, prefix, visibility, True)
802 outfile.write('\n'.join(signature))
806 def generate_marshallers_body(outfile, retval, params,
807 prefix='g_cclosure_user_marshal',
808 include_prototype=True,
810 include_va=False, source_location=None):
811 '''Generate a definition for a marshaller function, to be used in the source,
812 with the given @retval, @params, and @prefix. An optional va_list marshaller
813 for the same arguments is also generated. The generated buffer is written to
814 the @outfile stream object.'''
816 outfile.write('/* {} */\n'.format(source_location))
818 if include_prototype:
819 # Declaration visibility
821 decl_visibility = Visibility.INTERNAL
823 decl_visibility = Visibility.EXTERN
824 proto = ['/* Prototype for -Wmissing-prototypes */']
825 proto += generate_prototype(retval, params, prefix, decl_visibility, False)
826 outfile.write('\n'.join(proto))
829 body = generate_body(retval, params, prefix, False)
830 outfile.write('\n'.join(body))
831 outfile.write('\n\n')
834 if include_prototype:
835 # Declaration visibility
837 decl_visibility = Visibility.INTERNAL
839 decl_visibility = Visibility.EXTERN
840 proto = ['/* Prototype for -Wmissing-prototypes */']
841 proto += generate_prototype(retval, params, prefix, decl_visibility, True)
842 outfile.write('\n'.join(proto))
845 body = generate_body(retval, params, prefix, True)
846 outfile.write('\n'.join(body))
847 outfile.write('\n\n')
850 if __name__ == '__main__':
851 arg_parser = argparse.ArgumentParser(description='Generate signal marshallers for GObject')
852 arg_parser.add_argument('--prefix', metavar='STRING',
853 default='g_cclosure_user_marshal',
854 help='Specify marshaller prefix')
855 arg_parser.add_argument('--output', metavar='FILE',
856 type=argparse.FileType('w'),
858 help='Write output into the specified file')
859 arg_parser.add_argument('--skip-source',
861 help='Skip source location comments')
862 arg_parser.add_argument('--internal',
864 help='Mark generated functions as internal')
865 arg_parser.add_argument('--valist-marshallers',
867 help='Generate va_list marshallers')
868 arg_parser.add_argument('-v', '--version',
871 help='Print version information, and exit')
872 arg_parser.add_argument('--g-fatal-warnings',
874 dest='fatal_warnings',
875 help='Make warnings fatal')
876 arg_parser.add_argument('--include-header', metavar='HEADER', nargs='?',
878 dest='include_headers',
879 help='Include the specified header in the body')
880 arg_parser.add_argument('--pragma-once',
882 help='Use "pragma once" as the inclusion guard')
883 arg_parser.add_argument('-D',
887 help='Pre-processor define')
888 arg_parser.add_argument('-U',
890 dest='cpp_undefines',
892 help='Pre-processor undefine')
893 arg_parser.add_argument('files', metavar='FILE', nargs='*',
894 type=argparse.FileType('r'),
895 help='Files with lists of marshallers to generate, ' +
896 'or "-" for standard input')
897 arg_parser.add_argument('--prototypes',
899 help='Generate the marshallers prototype in the C code')
900 arg_parser.add_argument('--header',
902 help='Generate C headers')
903 arg_parser.add_argument('--body',
905 help='Generate C code')
907 group = arg_parser.add_mutually_exclusive_group()
908 group.add_argument('--stdinc',
910 dest='stdinc', default=True,
911 help='Include standard marshallers')
912 group.add_argument('--nostdinc',
913 action='store_false',
914 dest='stdinc', default=True,
915 help='Use standard marshallers')
917 group = arg_parser.add_mutually_exclusive_group()
918 group.add_argument('--quiet',
920 help='Only print warnings and errors')
921 group.add_argument('--verbose',
923 help='Be verbose, and include debugging information')
925 args = arg_parser.parse_args()
927 if args.show_version:
931 # Backward compatibility hack; some projects use both arguments to
932 # generate the marshallers prototype in the C source, even though
933 # it's not really a supported use case. We keep this behaviour by
934 # forcing the --prototypes and --body arguments instead. We make this
935 # warning non-fatal even with --g-fatal-warnings, as it's a deprecation
936 compatibility_mode = False
937 if args.header and args.body:
938 print_warning('Using --header and --body at the same time time is deprecated; ' +
939 'use --body --prototypes instead', False)
940 args.prototypes = True
942 compatibility_mode = True
945 generate_header_preamble(args.output,
947 std_includes=args.stdinc,
948 use_pragma=args.pragma_once)
950 generate_body_preamble(args.output,
951 std_includes=args.stdinc,
952 include_headers=args.include_headers,
953 cpp_defines=args.cpp_defines,
954 cpp_undefines=args.cpp_undefines)
956 seen_marshallers = set()
958 for infile in args.files:
960 print_info('Reading {}...'.format(infile.name))
966 if line == '\n' or line.startswith('#'):
969 matches = re.match(r'^([A-Z0-9]+)\s?:\s?([A-Z0-9,\s]+)$', line.strip())
970 if not matches or len(matches.groups()) != 2:
971 print_warning('Invalid entry: "{}"'.format(line.strip()), args.fatal_warnings)
974 if not args.skip_source:
975 location = '{} ({}:{:d})'.format(line.strip(), infile.name, line_count)
979 retval = matches.group(1).strip()
980 params = [x.strip() for x in matches.group(2).split(',')]
981 check_args(retval, params, args.fatal_warnings)
983 raw_marshaller = generate_marshaller_name(args.prefix, retval, params, False)
984 if raw_marshaller in seen_marshallers:
986 print_info('Skipping repeated marshaller {}'.format(line.strip()))
991 print_info('Generating declaration for {}'.format(line.strip()))
992 generate_std_alias = False
994 std_marshaller = generate_marshaller_name(STD_PREFIX, retval, params)
995 if std_marshaller in GOBJECT_MARSHALLERS:
997 print_info('Skipping default marshaller {}'.format(line.strip()))
998 generate_std_alias = True
1000 marshaller = generate_marshaller_name(args.prefix, retval, params)
1001 if generate_std_alias:
1002 generate_marshaller_alias(args.output, marshaller, std_marshaller,
1003 source_location=location,
1004 include_va=args.valist_marshallers)
1006 generate_marshallers_header(args.output, retval, params,
1008 internal=args.internal,
1009 include_va=args.valist_marshallers,
1010 source_location=location)
1011 # If the marshaller is defined using a deprecated token, we want to maintain
1012 # compatibility and generate an alias for the old name pointing to the new
1014 if marshaller != raw_marshaller:
1016 print_info('Generating alias for deprecated tokens')
1017 generate_marshaller_alias(args.output, raw_marshaller, marshaller,
1018 include_va=args.valist_marshallers)
1021 print_info('Generating definition for {}'.format(line.strip()))
1022 if compatibility_mode:
1023 generate_std_alias = False
1025 std_marshaller = generate_marshaller_name(STD_PREFIX, retval, params)
1026 if std_marshaller in GOBJECT_MARSHALLERS:
1028 print_info('Skipping default marshaller {}'.format(line.strip()))
1029 generate_std_alias = True
1030 marshaller = generate_marshaller_name(args.prefix, retval, params)
1031 if compatibility_mode and generate_std_alias:
1032 generate_marshaller_alias(args.output, marshaller, std_marshaller,
1033 source_location=location,
1034 include_va=args.valist_marshallers)
1036 generate_marshallers_body(args.output, retval, params,
1038 internal=args.internal,
1039 include_prototype=args.prototypes,
1040 include_va=args.valist_marshallers,
1041 source_location=location)
1042 if compatibility_mode and marshaller != raw_marshaller:
1044 print_info('Generating alias for deprecated tokens')
1045 generate_marshaller_alias(args.output, raw_marshaller, marshaller,
1046 include_va=args.valist_marshallers)
1048 seen_marshallers.add(raw_marshaller)
1051 generate_header_postamble(args.output, prefix=args.prefix, use_pragma=args.pragma_once)