Blame gobject/glib-genmarshal.in

Packit Service d3d246
#!/usr/bin/env @PYTHON@
Packit Service d3d246
Packit Service d3d246
# pylint: disable=too-many-lines, missing-docstring, invalid-name
Packit Service d3d246
Packit Service d3d246
# This file is part of GLib
Packit Service d3d246
#
Packit Service d3d246
# This library is free software; you can redistribute it and/or
Packit Service d3d246
# modify it under the terms of the GNU Lesser General Public
Packit Service d3d246
# License as published by the Free Software Foundation; either
Packit Service d3d246
# version 2.1 of the License, or (at your option) any later version.
Packit Service d3d246
#
Packit Service d3d246
# This library is distributed in the hope that it will be useful,
Packit Service d3d246
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service d3d246
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service d3d246
# Lesser General Public License for more details.
Packit Service d3d246
#
Packit Service d3d246
# You should have received a copy of the GNU Lesser General Public
Packit Service d3d246
# License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit Service d3d246
Packit Service d3d246
import argparse
Packit Service d3d246
import os
Packit Service d3d246
import re
Packit Service d3d246
import sys
Packit Service d3d246
Packit Service d3d246
VERSION_STR = '''glib-genmarshal version @VERSION@
Packit Service d3d246
glib-genmarshal comes with ABSOLUTELY NO WARRANTY.
Packit Service d3d246
You may redistribute copies of glib-genmarshal under the terms of
Packit Service d3d246
the GNU General Public License which can be found in the
Packit Service d3d246
GLib source package. Sources, examples and contact
Packit Service d3d246
information are available at http://www.gtk.org'''
Packit Service d3d246
Packit Service d3d246
GETTERS_STR = '''#ifdef G_ENABLE_DEBUG
Packit Service d3d246
#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
Packit Service d3d246
#define g_marshal_value_peek_char(v)     g_value_get_schar (v)
Packit Service d3d246
#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
Packit Service d3d246
#define g_marshal_value_peek_int(v)      g_value_get_int (v)
Packit Service d3d246
#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
Packit Service d3d246
#define g_marshal_value_peek_long(v)     g_value_get_long (v)
Packit Service d3d246
#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
Packit Service d3d246
#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
Packit Service d3d246
#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
Packit Service d3d246
#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
Packit Service d3d246
#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
Packit Service d3d246
#define g_marshal_value_peek_float(v)    g_value_get_float (v)
Packit Service d3d246
#define g_marshal_value_peek_double(v)   g_value_get_double (v)
Packit Service d3d246
#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
Packit Service d3d246
#define g_marshal_value_peek_param(v)    g_value_get_param (v)
Packit Service d3d246
#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
Packit Service d3d246
#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
Packit Service d3d246
#define g_marshal_value_peek_object(v)   g_value_get_object (v)
Packit Service d3d246
#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
Packit Service d3d246
#else /* !G_ENABLE_DEBUG */
Packit Service d3d246
/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
Packit Service d3d246
 *          Do not access GValues directly in your code. Instead, use the
Packit Service d3d246
 *          g_value_get_*() functions
Packit Service d3d246
 */
Packit Service d3d246
#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
Packit Service d3d246
#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
Packit Service d3d246
#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
Packit Service d3d246
#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
Packit Service d3d246
#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
Packit Service d3d246
#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
Packit Service d3d246
#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
Packit Service d3d246
#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
Packit Service d3d246
#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
Packit Service d3d246
#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
Packit Service d3d246
#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
Packit Service d3d246
#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
Packit Service d3d246
#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
Packit Service d3d246
#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
Packit Service d3d246
#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
Packit Service d3d246
#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
Packit Service d3d246
#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
Packit Service d3d246
#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
Packit Service d3d246
#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
Packit Service d3d246
#endif /* !G_ENABLE_DEBUG */'''
Packit Service d3d246
Packit Service d3d246
DEPRECATED_MSG_STR = 'The token "{}" is deprecated; use "{}" instead'
Packit Service d3d246
Packit Service d3d246
VA_ARG_STR = \
Packit Service d3d246
    '  arg{:d} = ({:s}) va_arg (args_copy, {:s});'
Packit Service d3d246
STATIC_CHECK_STR = \
Packit Service d3d246
    '(param_types[{:d}] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && '
Packit Service d3d246
BOX_TYPED_STR = \
Packit Service d3d246
    '    arg{idx:d} = {box_func} (param_types[{idx:d}] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg{idx:d});'
Packit Service d3d246
BOX_UNTYPED_STR = \
Packit Service d3d246
    '    arg{idx:d} = {box_func} (arg{idx:d});'
Packit Service d3d246
UNBOX_TYPED_STR = \
Packit Service d3d246
    '    {unbox_func} (param_types[{idx:d}] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg{idx:d});'
Packit Service d3d246
UNBOX_UNTYPED_STR = \
Packit Service d3d246
    '    {unbox_func} (arg{idx:d});'
Packit Service d3d246
Packit Service d3d246
STD_PREFIX = 'g_cclosure_marshal'
Packit Service d3d246
Packit Service d3d246
# These are part of our ABI; keep this in sync with gmarshal.h
Packit Service d3d246
GOBJECT_MARSHALLERS = {
Packit Service d3d246
    'g_cclosure_marshal_VOID__VOID',
Packit Service d3d246
    'g_cclosure_marshal_VOID__BOOLEAN',
Packit Service d3d246
    'g_cclosure_marshal_VOID__CHAR',
Packit Service d3d246
    'g_cclosure_marshal_VOID__UCHAR',
Packit Service d3d246
    'g_cclosure_marshal_VOID__INT',
Packit Service d3d246
    'g_cclosure_marshal_VOID__UINT',
Packit Service d3d246
    'g_cclosure_marshal_VOID__LONG',
Packit Service d3d246
    'g_cclosure_marshal_VOID__ULONG',
Packit Service d3d246
    'g_cclosure_marshal_VOID__ENUM',
Packit Service d3d246
    'g_cclosure_marshal_VOID__FLAGS',
Packit Service d3d246
    'g_cclosure_marshal_VOID__FLOAT',
Packit Service d3d246
    'g_cclosure_marshal_VOID__DOUBLE',
Packit Service d3d246
    'g_cclosure_marshal_VOID__STRING',
Packit Service d3d246
    'g_cclosure_marshal_VOID__PARAM',
Packit Service d3d246
    'g_cclosure_marshal_VOID__BOXED',
Packit Service d3d246
    'g_cclosure_marshal_VOID__POINTER',
Packit Service d3d246
    'g_cclosure_marshal_VOID__OBJECT',
Packit Service d3d246
    'g_cclosure_marshal_VOID__VARIANT',
Packit Service d3d246
    'g_cclosure_marshal_VOID__UINT_POINTER',
Packit Service d3d246
    'g_cclosure_marshal_BOOLEAN__FLAGS',
Packit Service d3d246
    'g_cclosure_marshal_STRING__OBJECT_POINTER',
Packit Service d3d246
    'g_cclosure_marshal_BOOLEAN__BOXED_BOXED',
Packit Service d3d246
}
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
# pylint: disable=too-few-public-methods
Packit Service d3d246
class Color:
Packit Service d3d246
    '''ANSI Terminal colors'''
Packit Service d3d246
    GREEN = '\033[1;32m'
Packit Service d3d246
    BLUE = '\033[1;34m'
Packit Service d3d246
    YELLOW = '\033[1;33m'
Packit Service d3d246
    RED = '\033[1;31m'
Packit Service d3d246
    END = '\033[0m'
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def print_color(msg, color=Color.END, prefix='MESSAGE'):
Packit Service d3d246
    '''Print a string with a color prefix'''
Packit Service d3d246
    if os.isatty(sys.stderr.fileno()):
Packit Service d3d246
        real_prefix = '{start}{prefix}{end}'.format(start=color, prefix=prefix, end=Color.END)
Packit Service d3d246
    else:
Packit Service d3d246
        real_prefix = prefix
Packit Service d3d246
    sys.stderr.write('{prefix}: {msg}\n'.format(prefix=real_prefix, msg=msg))
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def print_error(msg):
Packit Service d3d246
    '''Print an error, and terminate'''
Packit Service d3d246
    print_color(msg, color=Color.RED, prefix='ERROR')
Packit Service d3d246
    sys.exit(1)
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def print_warning(msg, fatal=False):
Packit Service d3d246
    '''Print a warning, and optionally terminate'''
Packit Service d3d246
    if fatal:
Packit Service d3d246
        color = Color.RED
Packit Service d3d246
        prefix = 'ERROR'
Packit Service d3d246
    else:
Packit Service d3d246
        color = Color.YELLOW
Packit Service d3d246
        prefix = 'WARNING'
Packit Service d3d246
    print_color(msg, color, prefix)
Packit Service d3d246
    if fatal:
Packit Service d3d246
        sys.exit(1)
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def print_info(msg):
Packit Service d3d246
    '''Print a message'''
Packit Service d3d246
    print_color(msg, color=Color.GREEN, prefix='INFO')
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def generate_licensing_comment(outfile):
Packit Service d3d246
    outfile.write('/* This file is generated by glib-genmarshal, do not '
Packit Service d3d246
                  'modify it. This code is licensed under the same license as '
Packit Service d3d246
                  'the containing project. Note that it links to GLib, so '
Packit Service d3d246
                  'must comply with the LGPL linking clauses. */\n')
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def generate_header_preamble(outfile, prefix='', std_includes=True, use_pragma=False):
Packit Service d3d246
    '''Generate the preamble for the marshallers header file'''
Packit Service d3d246
    generate_licensing_comment(outfile)
Packit Service d3d246
Packit Service d3d246
    if use_pragma:
Packit Service d3d246
        outfile.write('#pragma once\n')
Packit Service d3d246
        outfile.write('\n')
Packit Service d3d246
    else:
Packit Service d3d246
        outfile.write('#ifndef __{}_MARSHAL_H__\n'.format(prefix.upper()))
Packit Service d3d246
        outfile.write('#define __{}_MARSHAL_H__\n'.format(prefix.upper()))
Packit Service d3d246
        outfile.write('\n')
Packit Service d3d246
    # Maintain compatibility with the old C-based tool
Packit Service d3d246
    if std_includes:
Packit Service d3d246
        outfile.write('#include <glib-object.h>\n')
Packit Service d3d246
        outfile.write('\n')
Packit Service d3d246
Packit Service d3d246
    outfile.write('G_BEGIN_DECLS\n')
Packit Service d3d246
    outfile.write('\n')
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def generate_header_postamble(outfile, prefix='', use_pragma=False):
Packit Service d3d246
    '''Generate the postamble for the marshallers header file'''
Packit Service d3d246
    outfile.write('\n')
Packit Service d3d246
    outfile.write('G_END_DECLS\n')
Packit Service d3d246
Packit Service d3d246
    if not use_pragma:
Packit Service d3d246
        outfile.write('\n')
Packit Service d3d246
        outfile.write('#endif /* __{}_MARSHAL_H__ */\n'.format(prefix.upper()))
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def generate_body_preamble(outfile, std_includes=True, include_headers=None, cpp_defines=None, cpp_undefines=None):
Packit Service d3d246
    '''Generate the preamble for the marshallers source file'''
Packit Service d3d246
    generate_licensing_comment(outfile)
Packit Service d3d246
Packit Service d3d246
    for header in (include_headers or []):
Packit Service d3d246
        outfile.write('#include "{}"\n'.format(header))
Packit Service d3d246
    if include_headers:
Packit Service d3d246
        outfile.write('\n')
Packit Service d3d246
Packit Service d3d246
    for define in (cpp_defines or []):
Packit Service d3d246
        s = define.split('=')
Packit Service d3d246
        symbol = s[0]
Packit Service d3d246
        value = s[1] if len(s) > 1 else '1'
Packit Service d3d246
        outfile.write('#define {} {}\n'.format(symbol, value))
Packit Service d3d246
    if cpp_defines:
Packit Service d3d246
        outfile.write('\n')
Packit Service d3d246
Packit Service d3d246
    for undefine in (cpp_undefines or []):
Packit Service d3d246
        outfile.write('#undef {}\n'.format(undefine))
Packit Service d3d246
    if cpp_undefines:
Packit Service d3d246
        outfile.write('\n')
Packit Service d3d246
Packit Service d3d246
    if std_includes:
Packit Service d3d246
        outfile.write('#include <glib-object.h>\n')
Packit Service d3d246
        outfile.write('\n')
Packit Service d3d246
Packit Service d3d246
    outfile.write(GETTERS_STR)
Packit Service d3d246
    outfile.write('\n\n')
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
# Marshaller arguments, as a dictionary where the key is the token used in
Packit Service d3d246
# the source file, and the value is another dictionary with the following
Packit Service d3d246
# keys:
Packit Service d3d246
#
Packit Service d3d246
#   - signal: the token used in the marshaller prototype (mandatory)
Packit Service d3d246
#   - ctype: the C type for the marshaller argument (mandatory)
Packit Service d3d246
#   - getter: the function used to retrieve the argument from the GValue
Packit Service d3d246
#       array when invoking the callback (optional)
Packit Service d3d246
#   - promoted: the C type used by va_arg() to retrieve the argument from
Packit Service d3d246
#       the va_list when invoking the callback (optional, only used when
Packit Service d3d246
#       generating va_list marshallers)
Packit Service d3d246
#   - box: an array of two elements, containing the boxing and unboxing
Packit Service d3d246
#       functions for the given type (optional, only used when generating
Packit Service d3d246
#       va_list marshallers)
Packit Service d3d246
#   - static-check: a boolean value, if the given type should perform
Packit Service d3d246
#       a static type check before boxing or unboxing the argument (optional,
Packit Service d3d246
#       only used when generating va_list marshallers)
Packit Service d3d246
#   - takes-type: a boolean value, if the boxing and unboxing functions
Packit Service d3d246
#       for the given type require the type (optional, only used when
Packit Service d3d246
#       generating va_list marshallers)
Packit Service d3d246
#   - deprecated: whether the token has been deprecated (optional)
Packit Service d3d246
#   - replaced-by: the token used to replace a deprecated token (optional,
Packit Service d3d246
#       only used if deprecated is True)
Packit Service d3d246
IN_ARGS = {
Packit Service d3d246
    'VOID': {
Packit Service d3d246
        'signal': 'VOID',
Packit Service d3d246
        'ctype': 'void',
Packit Service d3d246
    },
Packit Service d3d246
    'BOOLEAN': {
Packit Service d3d246
        'signal': 'BOOLEAN',
Packit Service d3d246
        'ctype': 'gboolean',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_boolean',
Packit Service d3d246
    },
Packit Service d3d246
    'CHAR': {
Packit Service d3d246
        'signal': 'CHAR',
Packit Service d3d246
        'ctype': 'gchar',
Packit Service d3d246
        'promoted': 'gint',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_char',
Packit Service d3d246
    },
Packit Service d3d246
    'UCHAR': {
Packit Service d3d246
        'signal': 'UCHAR',
Packit Service d3d246
        'ctype': 'guchar',
Packit Service d3d246
        'promoted': 'guint',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_uchar',
Packit Service d3d246
    },
Packit Service d3d246
    'INT': {
Packit Service d3d246
        'signal': 'INT',
Packit Service d3d246
        'ctype': 'gint',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_int',
Packit Service d3d246
    },
Packit Service d3d246
    'UINT': {
Packit Service d3d246
        'signal': 'UINT',
Packit Service d3d246
        'ctype': 'guint',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_uint',
Packit Service d3d246
    },
Packit Service d3d246
    'LONG': {
Packit Service d3d246
        'signal': 'LONG',
Packit Service d3d246
        'ctype': 'glong',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_long',
Packit Service d3d246
    },
Packit Service d3d246
    'ULONG': {
Packit Service d3d246
        'signal': 'ULONG',
Packit Service d3d246
        'ctype': 'gulong',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_ulong',
Packit Service d3d246
    },
Packit Service d3d246
    'INT64': {
Packit Service d3d246
        'signal': 'INT64',
Packit Service d3d246
        'ctype': 'gint64',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_int64',
Packit Service d3d246
    },
Packit Service d3d246
    'UINT64': {
Packit Service d3d246
        'signal': 'UINT64',
Packit Service d3d246
        'ctype': 'guint64',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_uint64',
Packit Service d3d246
    },
Packit Service d3d246
    'ENUM': {
Packit Service d3d246
        'signal': 'ENUM',
Packit Service d3d246
        'ctype': 'gint',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_enum',
Packit Service d3d246
    },
Packit Service d3d246
    'FLAGS': {
Packit Service d3d246
        'signal': 'FLAGS',
Packit Service d3d246
        'ctype': 'guint',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_flags',
Packit Service d3d246
    },
Packit Service d3d246
    'FLOAT': {
Packit Service d3d246
        'signal': 'FLOAT',
Packit Service d3d246
        'ctype': 'gfloat',
Packit Service d3d246
        'promoted': 'gdouble',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_float',
Packit Service d3d246
    },
Packit Service d3d246
    'DOUBLE': {
Packit Service d3d246
        'signal': 'DOUBLE',
Packit Service d3d246
        'ctype': 'gdouble',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_double',
Packit Service d3d246
    },
Packit Service d3d246
    'STRING': {
Packit Service d3d246
        'signal': 'STRING',
Packit Service d3d246
        'ctype': 'gpointer',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_string',
Packit Service d3d246
        'box': ['g_strdup', 'g_free'],
Packit Service d3d246
    },
Packit Service d3d246
    'PARAM': {
Packit Service d3d246
        'signal': 'PARAM',
Packit Service d3d246
        'ctype': 'gpointer',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_param',
Packit Service d3d246
        'box': ['g_param_spec_ref', 'g_param_spec_unref'],
Packit Service d3d246
    },
Packit Service d3d246
    'BOXED': {
Packit Service d3d246
        'signal': 'BOXED',
Packit Service d3d246
        'ctype': 'gpointer',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_boxed',
Packit Service d3d246
        'box': ['g_boxed_copy', 'g_boxed_free'],
Packit Service d3d246
        'static-check': True,
Packit Service d3d246
        'takes-type': True,
Packit Service d3d246
    },
Packit Service d3d246
    'POINTER': {
Packit Service d3d246
        'signal': 'POINTER',
Packit Service d3d246
        'ctype': 'gpointer',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_pointer',
Packit Service d3d246
    },
Packit Service d3d246
    'OBJECT': {
Packit Service d3d246
        'signal': 'OBJECT',
Packit Service d3d246
        'ctype': 'gpointer',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_object',
Packit Service d3d246
        'box': ['g_object_ref', 'g_object_unref'],
Packit Service d3d246
    },
Packit Service d3d246
    'VARIANT': {
Packit Service d3d246
        'signal': 'VARIANT',
Packit Service d3d246
        'ctype': 'gpointer',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_variant',
Packit Service d3d246
        'box': ['g_variant_ref', 'g_variant_unref'],
Packit Service d3d246
        'static-check': True,
Packit Service d3d246
        'takes-type': False,
Packit Service d3d246
    },
Packit Service d3d246
Packit Service d3d246
    # Deprecated tokens
Packit Service d3d246
    'NONE': {
Packit Service d3d246
        'signal': 'VOID',
Packit Service d3d246
        'ctype': 'void',
Packit Service d3d246
        'deprecated': True,
Packit Service d3d246
        'replaced_by': 'VOID'
Packit Service d3d246
    },
Packit Service d3d246
    'BOOL': {
Packit Service d3d246
        'signal': 'BOOLEAN',
Packit Service d3d246
        'ctype': 'gboolean',
Packit Service d3d246
        'getter': 'g_marshal_value_peek_boolean',
Packit Service d3d246
        'deprecated': True,
Packit Service d3d246
        'replaced_by': 'BOOLEAN'
Packit Service d3d246
    }
Packit Service d3d246
}
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
# Marshaller return values, as a dictionary where the key is the token used
Packit Service d3d246
# in the source file, and the value is another dictionary with the following
Packit Service d3d246
# keys:
Packit Service d3d246
#
Packit Service d3d246
#   - signal: the token used in the marshaller prototype (mandatory)
Packit Service d3d246
#   - ctype: the C type for the marshaller argument (mandatory)
Packit Service d3d246
#   - setter: the function used to set the return value of the callback
Packit Service d3d246
#       into a GValue (optional)
Packit Service d3d246
#   - deprecated: whether the token has been deprecated (optional)
Packit Service d3d246
#   - replaced-by: the token used to replace a deprecated token (optional,
Packit Service d3d246
#       only used if deprecated is True)
Packit Service d3d246
OUT_ARGS = {
Packit Service d3d246
    'VOID': {
Packit Service d3d246
        'signal': 'VOID',
Packit Service d3d246
        'ctype': 'void',
Packit Service d3d246
    },
Packit Service d3d246
    'BOOLEAN': {
Packit Service d3d246
        'signal': 'BOOLEAN',
Packit Service d3d246
        'ctype': 'gboolean',
Packit Service d3d246
        'setter': 'g_value_set_boolean',
Packit Service d3d246
    },
Packit Service d3d246
    'CHAR': {
Packit Service d3d246
        'signal': 'CHAR',
Packit Service d3d246
        'ctype': 'gchar',
Packit Service d3d246
        'setter': 'g_value_set_char',
Packit Service d3d246
    },
Packit Service d3d246
    'UCHAR': {
Packit Service d3d246
        'signal': 'UCHAR',
Packit Service d3d246
        'ctype': 'guchar',
Packit Service d3d246
        'setter': 'g_value_set_uchar',
Packit Service d3d246
    },
Packit Service d3d246
    'INT': {
Packit Service d3d246
        'signal': 'INT',
Packit Service d3d246
        'ctype': 'gint',
Packit Service d3d246
        'setter': 'g_value_set_int',
Packit Service d3d246
    },
Packit Service d3d246
    'UINT': {
Packit Service d3d246
        'signal': 'UINT',
Packit Service d3d246
        'ctype': 'guint',
Packit Service d3d246
        'setter': 'g_value_set_uint',
Packit Service d3d246
    },
Packit Service d3d246
    'LONG': {
Packit Service d3d246
        'signal': 'LONG',
Packit Service d3d246
        'ctype': 'glong',
Packit Service d3d246
        'setter': 'g_value_set_long',
Packit Service d3d246
    },
Packit Service d3d246
    'ULONG': {
Packit Service d3d246
        'signal': 'ULONG',
Packit Service d3d246
        'ctype': 'gulong',
Packit Service d3d246
        'setter': 'g_value_set_ulong',
Packit Service d3d246
    },
Packit Service d3d246
    'INT64': {
Packit Service d3d246
        'signal': 'INT64',
Packit Service d3d246
        'ctype': 'gint64',
Packit Service d3d246
        'setter': 'g_value_set_int64',
Packit Service d3d246
    },
Packit Service d3d246
    'UINT64': {
Packit Service d3d246
        'signal': 'UINT64',
Packit Service d3d246
        'ctype': 'guint64',
Packit Service d3d246
        'setter': 'g_value_set_uint64',
Packit Service d3d246
    },
Packit Service d3d246
    'ENUM': {
Packit Service d3d246
        'signal': 'ENUM',
Packit Service d3d246
        'ctype': 'gint',
Packit Service d3d246
        'setter': 'g_value_set_enum',
Packit Service d3d246
    },
Packit Service d3d246
    'FLAGS': {
Packit Service d3d246
        'signal': 'FLAGS',
Packit Service d3d246
        'ctype': 'guint',
Packit Service d3d246
        'setter': 'g_value_set_flags',
Packit Service d3d246
    },
Packit Service d3d246
    'FLOAT': {
Packit Service d3d246
        'signal': 'FLOAT',
Packit Service d3d246
        'ctype': 'gfloat',
Packit Service d3d246
        'setter': 'g_value_set_float',
Packit Service d3d246
    },
Packit Service d3d246
    'DOUBLE': {
Packit Service d3d246
        'signal': 'DOUBLE',
Packit Service d3d246
        'ctype': 'gdouble',
Packit Service d3d246
        'setter': 'g_value_set_double',
Packit Service d3d246
    },
Packit Service d3d246
    'STRING': {
Packit Service d3d246
        'signal': 'STRING',
Packit Service d3d246
        'ctype': 'gchar*',
Packit Service d3d246
        'setter': 'g_value_take_string',
Packit Service d3d246
    },
Packit Service d3d246
    'PARAM': {
Packit Service d3d246
        'signal': 'PARAM',
Packit Service d3d246
        'ctype': 'GParamSpec*',
Packit Service d3d246
        'setter': 'g_value_take_param',
Packit Service d3d246
    },
Packit Service d3d246
    'BOXED': {
Packit Service d3d246
        'signal': 'BOXED',
Packit Service d3d246
        'ctype': 'gpointer',
Packit Service d3d246
        'setter': 'g_value_take_boxed',
Packit Service d3d246
    },
Packit Service d3d246
    'POINTER': {
Packit Service d3d246
        'signal': 'POINTER',
Packit Service d3d246
        'ctype': 'gpointer',
Packit Service d3d246
        'setter': 'g_value_set_pointer',
Packit Service d3d246
    },
Packit Service d3d246
    'OBJECT': {
Packit Service d3d246
        'signal': 'OBJECT',
Packit Service d3d246
        'ctype': 'GObject*',
Packit Service d3d246
        'setter': 'g_value_take_object',
Packit Service d3d246
    },
Packit Service d3d246
    'VARIANT': {
Packit Service d3d246
        'signal': 'VARIANT',
Packit Service d3d246
        'ctype': 'GVariant*',
Packit Service d3d246
        'setter': 'g_value_take_variant',
Packit Service d3d246
    },
Packit Service d3d246
Packit Service d3d246
    # Deprecated tokens
Packit Service d3d246
    'NONE': {
Packit Service d3d246
        'signal': 'VOID',
Packit Service d3d246
        'ctype': 'void',
Packit Service d3d246
        'setter': None,
Packit Service d3d246
        'deprecated': True,
Packit Service d3d246
        'replaced_by': 'VOID',
Packit Service d3d246
    },
Packit Service d3d246
    'BOOL': {
Packit Service d3d246
        'signal': 'BOOLEAN',
Packit Service d3d246
        'ctype': 'gboolean',
Packit Service d3d246
        'setter': 'g_value_set_boolean',
Packit Service d3d246
        'deprecated': True,
Packit Service d3d246
        'replaced_by': 'BOOLEAN',
Packit Service d3d246
    },
Packit Service d3d246
}
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def check_args(retval, params, fatal_warnings=False):
Packit Service d3d246
    '''Check the @retval and @params tokens for invalid and deprecated symbols.'''
Packit Service d3d246
    if retval not in OUT_ARGS:
Packit Service d3d246
        print_error('Unknown return value type "{}"'.format(retval))
Packit Service d3d246
Packit Service d3d246
    if OUT_ARGS[retval].get('deprecated', False):
Packit Service d3d246
        replaced_by = OUT_ARGS[retval]['replaced_by']
Packit Service d3d246
        print_warning(DEPRECATED_MSG_STR.format(retval, replaced_by), fatal_warnings)
Packit Service d3d246
Packit Service d3d246
    for param in params:
Packit Service d3d246
        if param not in IN_ARGS:
Packit Service d3d246
            print_error('Unknown parameter type "{}"'.format(param))
Packit Service d3d246
        else:
Packit Service d3d246
            if IN_ARGS[param].get('deprecated', False):
Packit Service d3d246
                replaced_by = IN_ARGS[param]['replaced_by']
Packit Service d3d246
                print_warning(DEPRECATED_MSG_STR.format(param, replaced_by), fatal_warnings)
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def indent(text, level=0, fill=' '):
Packit Service d3d246
    '''Indent @text by @level columns, using the @fill character'''
Packit Service d3d246
    return ''.join([fill for x in range(level)]) + text
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
# pylint: disable=too-few-public-methods
Packit Service d3d246
class Visibility:
Packit Service d3d246
    '''Symbol visibility options'''
Packit Service d3d246
    NONE = 0
Packit Service d3d246
    INTERNAL = 1
Packit Service d3d246
    EXTERN = 2
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def generate_marshaller_name(prefix, retval, params, replace_deprecated=True):
Packit Service d3d246
    '''Generate a marshaller name for the given @prefix, @retval, and @params.
Packit Service d3d246
    If @replace_deprecated is True, the generated name will replace deprecated
Packit Service d3d246
    tokens.'''
Packit Service d3d246
    if replace_deprecated:
Packit Service d3d246
        real_retval = OUT_ARGS[retval]['signal']
Packit Service d3d246
        real_params = []
Packit Service d3d246
        for param in params:
Packit Service d3d246
            real_params.append(IN_ARGS[param]['signal'])
Packit Service d3d246
    else:
Packit Service d3d246
        real_retval = retval
Packit Service d3d246
        real_params = params
Packit Service d3d246
    return '{prefix}_{retval}__{args}'.format(prefix=prefix,
Packit Service d3d246
                                              retval=real_retval,
Packit Service d3d246
                                              args='_'.join(real_params))
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def generate_prototype(retval, params,
Packit Service d3d246
                       prefix='g_cclosure_user_marshal',
Packit Service d3d246
                       visibility=Visibility.NONE,
Packit Service d3d246
                       va_marshal=False):
Packit Service d3d246
    '''Generate a marshaller declaration with the given @visibility. If @va_marshal
Packit Service d3d246
    is True, the marshaller will use variadic arguments in place of a GValue array.'''
Packit Service d3d246
    signature = []
Packit Service d3d246
Packit Service d3d246
    if visibility == Visibility.INTERNAL:
Packit Service d3d246
        signature += ['G_GNUC_INTERNAL']
Packit Service d3d246
    elif visibility == Visibility.EXTERN:
Packit Service d3d246
        signature += ['extern']
Packit Service d3d246
Packit Service d3d246
    function_name = generate_marshaller_name(prefix, retval, params)
Packit Service d3d246
Packit Service d3d246
    if not va_marshal:
Packit Service d3d246
        signature += ['void ' + function_name + ' (GClosure     *closure,']
Packit Service d3d246
        width = len('void ') + len(function_name) + 2
Packit Service d3d246
Packit Service d3d246
        signature += [indent('GValue       *return_value,', level=width, fill=' ')]
Packit Service d3d246
        signature += [indent('guint         n_param_values,', level=width, fill=' ')]
Packit Service d3d246
        signature += [indent('const GValue *param_values,', level=width, fill=' ')]
Packit Service d3d246
        signature += [indent('gpointer      invocation_hint,', level=width, fill=' ')]
Packit Service d3d246
        signature += [indent('gpointer      marshal_data);', level=width, fill=' ')]
Packit Service d3d246
    else:
Packit Service d3d246
        signature += ['void ' + function_name + 'v (GClosure *closure,']
Packit Service d3d246
        width = len('void ') + len(function_name) + 3
Packit Service d3d246
Packit Service d3d246
        signature += [indent('GValue   *return_value,', level=width, fill=' ')]
Packit Service d3d246
        signature += [indent('gpointer  instance,', level=width, fill=' ')]
Packit Service d3d246
        signature += [indent('va_list   args,', level=width, fill=' ')]
Packit Service d3d246
        signature += [indent('gpointer  marshal_data,', level=width, fill=' ')]
Packit Service d3d246
        signature += [indent('int       n_params,', level=width, fill=' ')]
Packit Service d3d246
        signature += [indent('GType    *param_types);', level=width, fill=' ')]
Packit Service d3d246
Packit Service d3d246
    return signature
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
# pylint: disable=too-many-statements, too-many-locals, too-many-branches
Packit Service d3d246
def generate_body(retval, params, prefix, va_marshal=False):
Packit Service d3d246
    '''Generate a marshaller definition. If @va_marshal is True, the marshaller
Packit Service d3d246
    will use va_list and variadic arguments in place of a GValue array.'''
Packit Service d3d246
    retval_setter = OUT_ARGS[retval].get('setter', None)
Packit Service d3d246
    # If there's no return value then we can mark the retval argument as unused
Packit Service d3d246
    # and get a minor optimisation, as well as avoid a compiler warning
Packit Service d3d246
    if not retval_setter:
Packit Service d3d246
        unused = ' G_GNUC_UNUSED'
Packit Service d3d246
    else:
Packit Service d3d246
        unused = ''
Packit Service d3d246
Packit Service d3d246
    body = ['void']
Packit Service d3d246
Packit Service d3d246
    function_name = generate_marshaller_name(prefix, retval, params)
Packit Service d3d246
Packit Service d3d246
    if not va_marshal:
Packit Service d3d246
        body += [function_name + ' (GClosure     *closure,']
Packit Service d3d246
        width = len(function_name) + 2
Packit Service d3d246
Packit Service d3d246
        body += [indent('GValue       *return_value{},'.format(unused), level=width, fill=' ')]
Packit Service d3d246
        body += [indent('guint         n_param_values,', level=width, fill=' ')]
Packit Service d3d246
        body += [indent('const GValue *param_values,', level=width, fill=' ')]
Packit Service d3d246
        body += [indent('gpointer      invocation_hint G_GNUC_UNUSED,', level=width, fill=' ')]
Packit Service d3d246
        body += [indent('gpointer      marshal_data)', level=width, fill=' ')]
Packit Service d3d246
    else:
Packit Service d3d246
        body += [function_name + 'v (GClosure *closure,']
Packit Service d3d246
        width = len(function_name) + 3
Packit Service d3d246
Packit Service d3d246
        body += [indent('GValue   *return_value{},'.format(unused), level=width, fill=' ')]
Packit Service d3d246
        body += [indent('gpointer  instance,', level=width, fill=' ')]
Packit Service d3d246
        body += [indent('va_list   args,', level=width, fill=' ')]
Packit Service d3d246
        body += [indent('gpointer  marshal_data,', level=width, fill=' ')]
Packit Service d3d246
        body += [indent('int       n_params,', level=width, fill=' ')]
Packit Service d3d246
        body += [indent('GType    *param_types)', level=width, fill=' ')]
Packit Service d3d246
Packit Service d3d246
    # Filter the arguments that have a getter
Packit Service d3d246
    get_args = [x for x in params if IN_ARGS[x].get('getter', None) is not None]
Packit Service d3d246
Packit Service d3d246
    body += ['{']
Packit Service d3d246
Packit Service d3d246
    # Generate the type of the marshaller function
Packit Service d3d246
    typedef_marshal = generate_marshaller_name('GMarshalFunc', retval, params)
Packit Service d3d246
Packit Service d3d246
    typedef = '  typedef {ctype} (*{func_name}) ('.format(ctype=OUT_ARGS[retval]['ctype'],
Packit Service d3d246
                                                          func_name=typedef_marshal)
Packit Service d3d246
    pad = len(typedef)
Packit Service d3d246
    typedef += 'gpointer data1,'
Packit Service d3d246
    body += [typedef]
Packit Service d3d246
Packit Service d3d246
    for idx, in_arg in enumerate(get_args):
Packit Service d3d246
        body += [indent('{} arg{:d},'.format(IN_ARGS[in_arg]['ctype'], idx + 1), level=pad)]
Packit Service d3d246
Packit Service d3d246
    body += [indent('gpointer data2);', level=pad)]
Packit Service d3d246
Packit Service d3d246
    # Variable declarations
Packit Service d3d246
    body += ['  GCClosure *cc = (GCClosure *) closure;']
Packit Service d3d246
    body += ['  gpointer data1, data2;']
Packit Service d3d246
    body += ['  {} callback;'.format(typedef_marshal)]
Packit Service d3d246
Packit Service d3d246
    if retval_setter:
Packit Service d3d246
        body += ['  {} v_return;'.format(OUT_ARGS[retval]['ctype'])]
Packit Service d3d246
Packit Service d3d246
    if va_marshal:
Packit Service d3d246
        for idx, arg in enumerate(get_args):
Packit Service d3d246
            body += ['  {} arg{:d};'.format(IN_ARGS[arg]['ctype'], idx)]
Packit Service d3d246
Packit Service d3d246
        if get_args:
Packit Service d3d246
            body += ['  va_list args_copy;']
Packit Service d3d246
            body += ['']
Packit Service d3d246
Packit Service d3d246
            body += ['  G_VA_COPY (args_copy, args);']
Packit Service d3d246
Packit Service d3d246
            for idx, arg in enumerate(get_args):
Packit Service d3d246
                ctype = IN_ARGS[arg]['ctype']
Packit Service d3d246
                promoted_ctype = IN_ARGS[arg].get('promoted', ctype)
Packit Service d3d246
                body += [VA_ARG_STR.format(idx, ctype, promoted_ctype)]
Packit Service d3d246
                if IN_ARGS[arg].get('box', None):
Packit Service d3d246
                    box_func = IN_ARGS[arg]['box'][0]
Packit Service d3d246
                    if IN_ARGS[arg].get('static-check', False):
Packit Service d3d246
                        static_check = STATIC_CHECK_STR.format(idx)
Packit Service d3d246
                    else:
Packit Service d3d246
                        static_check = ''
Packit Service d3d246
                    arg_check = 'arg{:d} != NULL'.format(idx)
Packit Service d3d246
                    body += ['  if ({}{})'.format(static_check, arg_check)]
Packit Service d3d246
                    if IN_ARGS[arg].get('takes-type', False):
Packit Service d3d246
                        body += [BOX_TYPED_STR.format(idx=idx, box_func=box_func)]
Packit Service d3d246
                    else:
Packit Service d3d246
                        body += [BOX_UNTYPED_STR.format(idx=idx, box_func=box_func)]
Packit Service d3d246
Packit Service d3d246
            body += ['  va_end (args_copy);']
Packit Service d3d246
Packit Service d3d246
    body += ['']
Packit Service d3d246
Packit Service d3d246
    # Preconditions check
Packit Service d3d246
    if retval_setter:
Packit Service d3d246
        body += ['  g_return_if_fail (return_value != NULL);']
Packit Service d3d246
Packit Service d3d246
    if not va_marshal:
Packit Service d3d246
        body += ['  g_return_if_fail (n_param_values == {:d});'.format(len(get_args) + 1)]
Packit Service d3d246
Packit Service d3d246
    body += ['']
Packit Service d3d246
Packit Service d3d246
    # Marshal instance, data, and callback set up
Packit Service d3d246
    body += ['  if (G_CCLOSURE_SWAP_DATA (closure))']
Packit Service d3d246
    body += ['    {']
Packit Service d3d246
    body += ['      data1 = closure->data;']
Packit Service d3d246
    if va_marshal:
Packit Service d3d246
        body += ['      data2 = instance;']
Packit Service d3d246
    else:
Packit Service d3d246
        body += ['      data2 = g_value_peek_pointer (param_values + 0);']
Packit Service d3d246
    body += ['    }']
Packit Service d3d246
    body += ['  else']
Packit Service d3d246
    body += ['    {']
Packit Service d3d246
    if va_marshal:
Packit Service d3d246
        body += ['      data1 = instance;']
Packit Service d3d246
    else:
Packit Service d3d246
        body += ['      data1 = g_value_peek_pointer (param_values + 0);']
Packit Service d3d246
    body += ['      data2 = closure->data;']
Packit Service d3d246
    body += ['    }']
Packit Service d3d246
    # pylint: disable=line-too-long
Packit Service d3d246
    body += ['  callback = ({}) (marshal_data ? marshal_data : cc->callback);'.format(typedef_marshal)]
Packit Service d3d246
    body += ['']
Packit Service d3d246
Packit Service d3d246
    # Marshal callback action
Packit Service d3d246
    if retval_setter:
Packit Service d3d246
        callback = ' {} callback ('.format(' v_return =')
Packit Service d3d246
    else:
Packit Service d3d246
        callback = '  callback ('
Packit Service d3d246
Packit Service d3d246
    pad = len(callback)
Packit Service d3d246
    body += [callback + 'data1,']
Packit Service d3d246
Packit Service d3d246
    if va_marshal:
Packit Service d3d246
        for idx, arg in enumerate(get_args):
Packit Service d3d246
            body += [indent('arg{:d},'.format(idx), level=pad)]
Packit Service d3d246
    else:
Packit Service d3d246
        for idx, arg in enumerate(get_args):
Packit Service d3d246
            arg_getter = IN_ARGS[arg]['getter']
Packit Service d3d246
            body += [indent('{} (param_values + {:d}),'.format(arg_getter, idx + 1), level=pad)]
Packit Service d3d246
Packit Service d3d246
    body += [indent('data2);', level=pad)]
Packit Service d3d246
Packit Service d3d246
    if va_marshal:
Packit Service d3d246
        boxed_args = [x for x in get_args if IN_ARGS[x].get('box', None) is not None]
Packit Service d3d246
        if not boxed_args:
Packit Service d3d246
            body += ['']
Packit Service d3d246
        else:
Packit Service d3d246
            for idx, arg in enumerate(get_args):
Packit Service d3d246
                if not IN_ARGS[arg].get('box', None):
Packit Service d3d246
                    continue
Packit Service d3d246
                unbox_func = IN_ARGS[arg]['box'][1]
Packit Service d3d246
                if IN_ARGS[arg].get('static-check', False):
Packit Service d3d246
                    static_check = STATIC_CHECK_STR.format(idx)
Packit Service d3d246
                else:
Packit Service d3d246
                    static_check = ''
Packit Service d3d246
                arg_check = 'arg{:d} != NULL'.format(idx)
Packit Service d3d246
                body += ['  if ({}{})'.format(static_check, arg_check)]
Packit Service d3d246
                if IN_ARGS[arg].get('takes-type', False):
Packit Service d3d246
                    body += [UNBOX_TYPED_STR.format(idx=idx, unbox_func=unbox_func)]
Packit Service d3d246
                else:
Packit Service d3d246
                    body += [UNBOX_UNTYPED_STR.format(idx=idx, unbox_func=unbox_func)]
Packit Service d3d246
Packit Service d3d246
    if retval_setter:
Packit Service d3d246
        body += ['']
Packit Service d3d246
        body += ['  {} (return_value, v_return);'.format(retval_setter)]
Packit Service d3d246
Packit Service d3d246
    body += ['}']
Packit Service d3d246
Packit Service d3d246
    return body
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def generate_marshaller_alias(outfile, marshaller, real_marshaller,
Packit Service d3d246
                              include_va=False,
Packit Service d3d246
                              source_location=None):
Packit Service d3d246
    '''Generate an alias between @marshaller and @real_marshaller, including
Packit Service d3d246
    an optional alias for va_list marshallers'''
Packit Service d3d246
    if source_location:
Packit Service d3d246
        outfile.write('/* {} */\n'.format(source_location))
Packit Service d3d246
Packit Service d3d246
    outfile.write('#define {}\t{}\n'.format(marshaller, real_marshaller))
Packit Service d3d246
Packit Service d3d246
    if include_va:
Packit Service d3d246
        outfile.write('#define {}v\t{}v\n'.format(marshaller, real_marshaller))
Packit Service d3d246
Packit Service d3d246
    outfile.write('\n')
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def generate_marshallers_header(outfile, retval, params,
Packit Service d3d246
                                prefix='g_cclosure_user_marshal',
Packit Service d3d246
                                internal=False,
Packit Service d3d246
                                include_va=False, source_location=None):
Packit Service d3d246
    '''Generate a declaration for a marshaller function, to be used in the header,
Packit Service d3d246
    with the given @retval, @params, and @prefix. An optional va_list marshaller
Packit Service d3d246
    for the same arguments is also generated. The generated buffer is written to
Packit Service d3d246
    the @outfile stream object.'''
Packit Service d3d246
    if source_location:
Packit Service d3d246
        outfile.write('/* {} */\n'.format(source_location))
Packit Service d3d246
Packit Service d3d246
    if internal:
Packit Service d3d246
        visibility = Visibility.INTERNAL
Packit Service d3d246
    else:
Packit Service d3d246
        visibility = Visibility.EXTERN
Packit Service d3d246
Packit Service d3d246
    signature = generate_prototype(retval, params, prefix, visibility, False)
Packit Service d3d246
    if include_va:
Packit Service d3d246
        signature += generate_prototype(retval, params, prefix, visibility, True)
Packit Service d3d246
    signature += ['']
Packit Service d3d246
Packit Service d3d246
    outfile.write('\n'.join(signature))
Packit Service d3d246
    outfile.write('\n')
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
def generate_marshallers_body(outfile, retval, params,
Packit Service d3d246
                              prefix='g_cclosure_user_marshal',
Packit Service d3d246
                              include_prototype=True,
Packit Service d3d246
                              internal=False,
Packit Service d3d246
                              include_va=False, source_location=None):
Packit Service d3d246
    '''Generate a definition for a marshaller function, to be used in the source,
Packit Service d3d246
    with the given @retval, @params, and @prefix. An optional va_list marshaller
Packit Service d3d246
    for the same arguments is also generated. The generated buffer is written to
Packit Service d3d246
    the @outfile stream object.'''
Packit Service d3d246
    if source_location:
Packit Service d3d246
        outfile.write('/* {} */\n'.format(source_location))
Packit Service d3d246
Packit Service d3d246
    if include_prototype:
Packit Service d3d246
        # Declaration visibility
Packit Service d3d246
        if internal:
Packit Service d3d246
            decl_visibility = Visibility.INTERNAL
Packit Service d3d246
        else:
Packit Service d3d246
            decl_visibility = Visibility.EXTERN
Packit Service d3d246
        proto = ['/* Prototype for -Wmissing-prototypes */']
Packit Service d3d246
        # Add C++ guards in case somebody compiles the generated code
Packit Service d3d246
        # with a C++ compiler
Packit Service d3d246
        proto += ['G_BEGIN_DECLS']
Packit Service d3d246
        proto += generate_prototype(retval, params, prefix, decl_visibility, False)
Packit Service d3d246
        proto += ['G_END_DECLS']
Packit Service d3d246
        outfile.write('\n'.join(proto))
Packit Service d3d246
        outfile.write('\n')
Packit Service d3d246
Packit Service d3d246
    body = generate_body(retval, params, prefix, False)
Packit Service d3d246
    outfile.write('\n'.join(body))
Packit Service d3d246
    outfile.write('\n\n')
Packit Service d3d246
Packit Service d3d246
    if include_va:
Packit Service d3d246
        if include_prototype:
Packit Service d3d246
            # Declaration visibility
Packit Service d3d246
            if internal:
Packit Service d3d246
                decl_visibility = Visibility.INTERNAL
Packit Service d3d246
            else:
Packit Service d3d246
                decl_visibility = Visibility.EXTERN
Packit Service d3d246
            proto = ['/* Prototype for -Wmissing-prototypes */']
Packit Service d3d246
            # Add C++ guards here as well
Packit Service d3d246
            proto += ['G_BEGIN_DECLS']
Packit Service d3d246
            proto += generate_prototype(retval, params, prefix, decl_visibility, True)
Packit Service d3d246
            proto += ['G_END_DECLS']
Packit Service d3d246
            outfile.write('\n'.join(proto))
Packit Service d3d246
            outfile.write('\n')
Packit Service d3d246
Packit Service d3d246
        body = generate_body(retval, params, prefix, True)
Packit Service d3d246
        outfile.write('\n'.join(body))
Packit Service d3d246
        outfile.write('\n\n')
Packit Service d3d246
Packit Service d3d246
Packit Service d3d246
if __name__ == '__main__':
Packit Service d3d246
    arg_parser = argparse.ArgumentParser(description='Generate signal marshallers for GObject')
Packit Service d3d246
    arg_parser.add_argument('--prefix', metavar='STRING',
Packit Service d3d246
                            default='g_cclosure_user_marshal',
Packit Service d3d246
                            help='Specify marshaller prefix')
Packit Service d3d246
    arg_parser.add_argument('--output', metavar='FILE',
Packit Service d3d246
                            type=argparse.FileType('w'),
Packit Service d3d246
                            default=sys.stdout,
Packit Service d3d246
                            help='Write output into the specified file')
Packit Service d3d246
    arg_parser.add_argument('--skip-source',
Packit Service d3d246
                            action='store_true',
Packit Service d3d246
                            help='Skip source location comments')
Packit Service d3d246
    arg_parser.add_argument('--internal',
Packit Service d3d246
                            action='store_true',
Packit Service d3d246
                            help='Mark generated functions as internal')
Packit Service d3d246
    arg_parser.add_argument('--valist-marshallers',
Packit Service d3d246
                            action='store_true',
Packit Service d3d246
                            help='Generate va_list marshallers')
Packit Service d3d246
    arg_parser.add_argument('-v', '--version',
Packit Service d3d246
                            action='store_true',
Packit Service d3d246
                            dest='show_version',
Packit Service d3d246
                            help='Print version information, and exit')
Packit Service d3d246
    arg_parser.add_argument('--g-fatal-warnings',
Packit Service d3d246
                            action='store_true',
Packit Service d3d246
                            dest='fatal_warnings',
Packit Service d3d246
                            help='Make warnings fatal')
Packit Service d3d246
    arg_parser.add_argument('--include-header', metavar='HEADER', nargs='?',
Packit Service d3d246
                            action='append',
Packit Service d3d246
                            dest='include_headers',
Packit Service d3d246
                            help='Include the specified header in the body')
Packit Service d3d246
    arg_parser.add_argument('--pragma-once',
Packit Service d3d246
                            action='store_true',
Packit Service d3d246
                            help='Use "pragma once" as the inclusion guard')
Packit Service d3d246
    arg_parser.add_argument('-D',
Packit Service d3d246
                            action='append',
Packit Service d3d246
                            dest='cpp_defines',
Packit Service d3d246
                            default=[],
Packit Service d3d246
                            help='Pre-processor define')
Packit Service d3d246
    arg_parser.add_argument('-U',
Packit Service d3d246
                            action='append',
Packit Service d3d246
                            dest='cpp_undefines',
Packit Service d3d246
                            default=[],
Packit Service d3d246
                            help='Pre-processor undefine')
Packit Service d3d246
    arg_parser.add_argument('files', metavar='FILE', nargs='*',
Packit Service d3d246
                            type=argparse.FileType('r'),
Packit Service d3d246
                            help='Files with lists of marshallers to generate, ' +
Packit Service d3d246
                            'or "-" for standard input')
Packit Service d3d246
    arg_parser.add_argument('--prototypes',
Packit Service d3d246
                            action='store_true',
Packit Service d3d246
                            help='Generate the marshallers prototype in the C code')
Packit Service d3d246
    arg_parser.add_argument('--header',
Packit Service d3d246
                            action='store_true',
Packit Service d3d246
                            help='Generate C headers')
Packit Service d3d246
    arg_parser.add_argument('--body',
Packit Service d3d246
                            action='store_true',
Packit Service d3d246
                            help='Generate C code')
Packit Service d3d246
Packit Service d3d246
    group = arg_parser.add_mutually_exclusive_group()
Packit Service d3d246
    group.add_argument('--stdinc',
Packit Service d3d246
                       action='store_true',
Packit Service d3d246
                       dest='stdinc', default=True,
Packit Service d3d246
                       help='Include standard marshallers')
Packit Service d3d246
    group.add_argument('--nostdinc',
Packit Service d3d246
                       action='store_false',
Packit Service d3d246
                       dest='stdinc', default=True,
Packit Service d3d246
                       help='Use standard marshallers')
Packit Service d3d246
Packit Service d3d246
    group = arg_parser.add_mutually_exclusive_group()
Packit Service d3d246
    group.add_argument('--quiet',
Packit Service d3d246
                       action='store_true',
Packit Service d3d246
                       help='Only print warnings and errors')
Packit Service d3d246
    group.add_argument('--verbose',
Packit Service d3d246
                       action='store_true',
Packit Service d3d246
                       help='Be verbose, and include debugging information')
Packit Service d3d246
Packit Service d3d246
    args = arg_parser.parse_args()
Packit Service d3d246
Packit Service d3d246
    if args.show_version:
Packit Service d3d246
        print(VERSION_STR)
Packit Service d3d246
        sys.exit(0)
Packit Service d3d246
Packit Service d3d246
    # Backward compatibility hack; some projects use both arguments to
Packit Service d3d246
    # generate the marshallers prototype in the C source, even though
Packit Service d3d246
    # it's not really a supported use case. We keep this behaviour by
Packit Service d3d246
    # forcing the --prototypes and --body arguments instead. We make this
Packit Service d3d246
    # warning non-fatal even with --g-fatal-warnings, as it's a deprecation
Packit Service d3d246
    compatibility_mode = False
Packit Service d3d246
    if args.header and args.body:
Packit Service d3d246
        print_warning('Using --header and --body at the same time is deprecated; ' +
Packit Service d3d246
                      'use --body --prototypes instead', False)
Packit Service d3d246
        args.prototypes = True
Packit Service d3d246
        args.header = False
Packit Service d3d246
        compatibility_mode = True
Packit Service d3d246
Packit Service d3d246
    if args.header:
Packit Service d3d246
        generate_header_preamble(args.output,
Packit Service d3d246
                                 prefix=args.prefix,
Packit Service d3d246
                                 std_includes=args.stdinc,
Packit Service d3d246
                                 use_pragma=args.pragma_once)
Packit Service d3d246
    elif args.body:
Packit Service d3d246
        generate_body_preamble(args.output,
Packit Service d3d246
                               std_includes=args.stdinc,
Packit Service d3d246
                               include_headers=args.include_headers,
Packit Service d3d246
                               cpp_defines=args.cpp_defines,
Packit Service d3d246
                               cpp_undefines=args.cpp_undefines)
Packit Service d3d246
Packit Service d3d246
    seen_marshallers = set()
Packit Service d3d246
Packit Service d3d246
    for infile in args.files:
Packit Service d3d246
        if not args.quiet:
Packit Service d3d246
            print_info('Reading {}...'.format(infile.name))
Packit Service d3d246
Packit Service d3d246
        line_count = 0
Packit Service d3d246
        for line in infile:
Packit Service d3d246
            line_count += 1
Packit Service d3d246
Packit Service d3d246
            if line == '\n' or line.startswith('#'):
Packit Service d3d246
                continue
Packit Service d3d246
Packit Service d3d246
            matches = re.match(r'^([A-Z0-9]+)\s?:\s?([A-Z0-9,\s]+)$', line.strip())
Packit Service d3d246
            if not matches or len(matches.groups()) != 2:
Packit Service d3d246
                print_warning('Invalid entry: "{}"'.format(line.strip()), args.fatal_warnings)
Packit Service d3d246
                continue
Packit Service d3d246
Packit Service d3d246
            if not args.skip_source:
Packit Service d3d246
                location = '{} ({}:{:d})'.format(line.strip(), infile.name, line_count)
Packit Service d3d246
            else:
Packit Service d3d246
                location = None
Packit Service d3d246
Packit Service d3d246
            retval = matches.group(1).strip()
Packit Service d3d246
            params = [x.strip() for x in matches.group(2).split(',')]
Packit Service d3d246
            check_args(retval, params, args.fatal_warnings)
Packit Service d3d246
Packit Service d3d246
            raw_marshaller = generate_marshaller_name(args.prefix, retval, params, False)
Packit Service d3d246
            if raw_marshaller in seen_marshallers:
Packit Service d3d246
                if args.verbose:
Packit Service d3d246
                    print_info('Skipping repeated marshaller {}'.format(line.strip()))
Packit Service d3d246
                continue
Packit Service d3d246
Packit Service d3d246
            if args.header:
Packit Service d3d246
                if args.verbose:
Packit Service d3d246
                    print_info('Generating declaration for {}'.format(line.strip()))
Packit Service d3d246
                generate_std_alias = False
Packit Service d3d246
                if args.stdinc:
Packit Service d3d246
                    std_marshaller = generate_marshaller_name(STD_PREFIX, retval, params)
Packit Service d3d246
                    if std_marshaller in GOBJECT_MARSHALLERS:
Packit Service d3d246
                        if args.verbose:
Packit Service d3d246
                            print_info('Skipping default marshaller {}'.format(line.strip()))
Packit Service d3d246
                        generate_std_alias = True
Packit Service d3d246
Packit Service d3d246
                marshaller = generate_marshaller_name(args.prefix, retval, params)
Packit Service d3d246
                if generate_std_alias:
Packit Service d3d246
                    generate_marshaller_alias(args.output, marshaller, std_marshaller,
Packit Service d3d246
                                              source_location=location,
Packit Service d3d246
                                              include_va=args.valist_marshallers)
Packit Service d3d246
                else:
Packit Service d3d246
                    generate_marshallers_header(args.output, retval, params,
Packit Service d3d246
                                                prefix=args.prefix,
Packit Service d3d246
                                                internal=args.internal,
Packit Service d3d246
                                                include_va=args.valist_marshallers,
Packit Service d3d246
                                                source_location=location)
Packit Service d3d246
                # If the marshaller is defined using a deprecated token, we want to maintain
Packit Service d3d246
                # compatibility and generate an alias for the old name pointing to the new
Packit Service d3d246
                # one
Packit Service d3d246
                if marshaller != raw_marshaller:
Packit Service d3d246
                    if args.verbose:
Packit Service d3d246
                        print_info('Generating alias for deprecated tokens')
Packit Service d3d246
                    generate_marshaller_alias(args.output, raw_marshaller, marshaller,
Packit Service d3d246
                                              include_va=args.valist_marshallers)
Packit Service d3d246
            elif args.body:
Packit Service d3d246
                if args.verbose:
Packit Service d3d246
                    print_info('Generating definition for {}'.format(line.strip()))
Packit Service d3d246
                generate_std_alias = False
Packit Service d3d246
                if args.stdinc:
Packit Service d3d246
                    std_marshaller = generate_marshaller_name(STD_PREFIX, retval, params)
Packit Service d3d246
                    if std_marshaller in GOBJECT_MARSHALLERS:
Packit Service d3d246
                        if args.verbose:
Packit Service d3d246
                            print_info('Skipping default marshaller {}'.format(line.strip()))
Packit Service d3d246
                        generate_std_alias = True
Packit Service d3d246
                marshaller = generate_marshaller_name(args.prefix, retval, params)
Packit Service d3d246
                if generate_std_alias:
Packit Service d3d246
                    # We need to generate the alias if we are in compatibility mode
Packit Service d3d246
                    if compatibility_mode:
Packit Service d3d246
                        generate_marshaller_alias(args.output, marshaller, std_marshaller,
Packit Service d3d246
                                                  source_location=location,
Packit Service d3d246
                                                  include_va=args.valist_marshallers)
Packit Service d3d246
                else:
Packit Service d3d246
                    generate_marshallers_body(args.output, retval, params,
Packit Service d3d246
                                              prefix=args.prefix,
Packit Service d3d246
                                              internal=args.internal,
Packit Service d3d246
                                              include_prototype=args.prototypes,
Packit Service d3d246
                                              include_va=args.valist_marshallers,
Packit Service d3d246
                                              source_location=location)
Packit Service d3d246
                if compatibility_mode and marshaller != raw_marshaller:
Packit Service d3d246
                    if args.verbose:
Packit Service d3d246
                        print_info('Generating alias for deprecated tokens')
Packit Service d3d246
                    generate_marshaller_alias(args.output, raw_marshaller, marshaller,
Packit Service d3d246
                                              include_va=args.valist_marshallers)
Packit Service d3d246
Packit Service d3d246
            seen_marshallers.add(raw_marshaller)
Packit Service d3d246
Packit Service d3d246
        if args.header:
Packit Service d3d246
            generate_header_postamble(args.output, prefix=args.prefix, use_pragma=args.pragma_once)