Blame gobject/glib-genmarshal.in

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