2012-02-03 19:42:56 +01:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
|
|
|
* GObject introspection: A parser for the XML GIR format
|
2008-08-09 14:46:48 +02:00
|
|
|
*
|
2010-06-08 16:25:12 +02:00
|
|
|
* Copyright (C) 2005 Matthias Clasen
|
2008-08-09 14:46:48 +02:00
|
|
|
* Copyright (C) 2008 Philip Van Hoof
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2014-07-04 12:27:41 +02:00
|
|
|
#include "config.h"
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <glib.h>
|
2008-10-22 16:31:58 +02:00
|
|
|
#include "girparser.h"
|
2008-08-09 14:46:48 +02:00
|
|
|
#include "girmodule.h"
|
|
|
|
#include "girnode.h"
|
2010-05-31 22:44:46 +02:00
|
|
|
#include "gitypelib-internal.h"
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 16:38:39 +02:00
|
|
|
/* This is a "major" version in the sense that it's only bumped
|
|
|
|
* for incompatible changes.
|
|
|
|
*/
|
2010-07-27 12:16:37 +02:00
|
|
|
#define SUPPORTED_GIR_VERSION "1.2"
|
2010-06-17 16:38:39 +02:00
|
|
|
|
2012-07-24 10:09:38 +02:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
|
|
#ifdef GIR_DIR
|
|
|
|
#undef GIR_DIR
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* GIR_DIR is used only in code called just once,
|
|
|
|
* so no problem leaking this
|
|
|
|
*/
|
|
|
|
#define GIR_DIR \
|
|
|
|
g_build_filename (g_win32_get_package_installation_directory_of_module(NULL), \
|
|
|
|
"share", \
|
|
|
|
GIR_SUFFIX, \
|
|
|
|
NULL)
|
|
|
|
#endif
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
struct _GIrParser
|
|
|
|
{
|
|
|
|
gchar **includes;
|
2008-11-12 18:17:15 +01:00
|
|
|
GList *parsed_modules; /* All previously parsed modules */
|
2008-11-12 18:16:42 +01:00
|
|
|
};
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
typedef enum
|
|
|
|
{
|
2014-02-27 11:05:54 +01:00
|
|
|
STATE_NONE = 0,
|
2009-02-05 23:36:35 +01:00
|
|
|
STATE_START,
|
|
|
|
STATE_END,
|
|
|
|
STATE_REPOSITORY,
|
|
|
|
STATE_INCLUDE,
|
2014-02-27 11:05:54 +01:00
|
|
|
STATE_C_INCLUDE, /* 5 */
|
|
|
|
STATE_PACKAGE,
|
2010-07-27 12:16:37 +02:00
|
|
|
STATE_NAMESPACE,
|
2009-02-05 23:36:35 +01:00
|
|
|
STATE_ENUM,
|
|
|
|
STATE_BITFIELD,
|
2014-02-27 11:05:54 +01:00
|
|
|
STATE_FUNCTION, /* 10 */
|
|
|
|
STATE_FUNCTION_RETURN,
|
2010-07-27 12:16:37 +02:00
|
|
|
STATE_FUNCTION_PARAMETERS,
|
2009-02-05 23:36:35 +01:00
|
|
|
STATE_FUNCTION_PARAMETER,
|
|
|
|
STATE_CLASS,
|
2014-02-27 11:05:54 +01:00
|
|
|
STATE_CLASS_FIELD, /* 15 */
|
|
|
|
STATE_CLASS_PROPERTY,
|
2010-07-27 12:16:37 +02:00
|
|
|
STATE_INTERFACE,
|
2009-02-05 23:36:35 +01:00
|
|
|
STATE_INTERFACE_PROPERTY,
|
2008-08-23 18:11:01 +02:00
|
|
|
STATE_INTERFACE_FIELD,
|
2014-02-27 11:05:54 +01:00
|
|
|
STATE_IMPLEMENTS, /* 20 */
|
|
|
|
STATE_PREREQUISITE,
|
2010-07-27 12:16:37 +02:00
|
|
|
STATE_BOXED,
|
2009-02-05 23:36:35 +01:00
|
|
|
STATE_BOXED_FIELD,
|
|
|
|
STATE_STRUCT,
|
2014-02-27 11:05:54 +01:00
|
|
|
STATE_STRUCT_FIELD, /* 25 */
|
|
|
|
STATE_UNION,
|
2009-02-05 23:36:35 +01:00
|
|
|
STATE_UNION_FIELD,
|
|
|
|
STATE_NAMESPACE_CONSTANT,
|
|
|
|
STATE_CLASS_CONSTANT,
|
2014-02-27 11:05:54 +01:00
|
|
|
STATE_INTERFACE_CONSTANT, /* 30 */
|
|
|
|
STATE_ALIAS,
|
2009-02-11 01:08:49 +01:00
|
|
|
STATE_TYPE,
|
2009-02-20 03:48:51 +01:00
|
|
|
STATE_ATTRIBUTE,
|
2010-06-17 02:34:18 +02:00
|
|
|
STATE_PASSTHROUGH
|
2008-08-09 14:46:48 +02:00
|
|
|
} ParseState;
|
|
|
|
|
|
|
|
typedef struct _ParseContext ParseContext;
|
|
|
|
struct _ParseContext
|
|
|
|
{
|
2008-11-12 18:16:42 +01:00
|
|
|
GIrParser *parser;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
ParseState state;
|
2009-02-11 01:08:49 +01:00
|
|
|
int unknown_depth;
|
2008-08-09 14:46:48 +02:00
|
|
|
ParseState prev_state;
|
|
|
|
|
|
|
|
GList *modules;
|
2008-11-11 01:48:17 +01:00
|
|
|
GList *include_modules;
|
2008-08-30 22:31:07 +02:00
|
|
|
GList *dependencies;
|
2008-08-13 18:10:09 +02:00
|
|
|
GHashTable *aliases;
|
2008-11-11 00:58:49 +01:00
|
|
|
GHashTable *disguised_structures;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
const char *file_path;
|
2008-08-28 23:19:22 +02:00
|
|
|
const char *namespace;
|
2009-02-13 00:42:47 +01:00
|
|
|
const char *c_prefix;
|
2008-08-09 14:46:48 +02:00
|
|
|
GIrModule *current_module;
|
2009-02-04 01:48:17 +01:00
|
|
|
GSList *node_stack;
|
2010-08-03 19:01:35 +02:00
|
|
|
char *current_alias;
|
2008-08-09 14:46:48 +02:00
|
|
|
GIrNode *current_typed;
|
2008-09-29 21:03:44 +02:00
|
|
|
GList *type_stack;
|
|
|
|
GList *type_parameters;
|
2008-08-22 22:05:23 +02:00
|
|
|
int type_depth;
|
2014-02-27 11:05:54 +01:00
|
|
|
ParseState in_embedded_state;
|
2008-08-09 14:46:48 +02:00
|
|
|
};
|
2009-02-04 01:48:17 +01:00
|
|
|
#define CURRENT_NODE(ctx) ((GIrNode *)((ctx)->node_stack->data))
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-11-11 01:48:17 +01:00
|
|
|
static void start_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error);
|
|
|
|
static void end_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error);
|
|
|
|
static void text_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *text,
|
|
|
|
gsize text_len,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error);
|
|
|
|
static void cleanup (GMarkupParseContext *context,
|
|
|
|
GError *error,
|
|
|
|
gpointer user_data);
|
2010-08-03 19:01:35 +02:00
|
|
|
static void state_switch (ParseContext *ctx, ParseState newstate);
|
|
|
|
|
2008-11-11 01:48:17 +01:00
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
static GMarkupParser markup_parser =
|
2008-11-11 01:48:17 +01:00
|
|
|
{
|
|
|
|
start_element_handler,
|
|
|
|
end_element_handler,
|
|
|
|
text_handler,
|
|
|
|
NULL,
|
|
|
|
cleanup
|
|
|
|
};
|
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
static gboolean
|
|
|
|
start_alias (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error);
|
2010-08-03 19:01:35 +02:00
|
|
|
static gboolean
|
|
|
|
start_type (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error);
|
2008-08-28 23:19:22 +02:00
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
static const gchar *find_attribute (const gchar *name,
|
2008-11-11 00:58:49 +01:00
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values);
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
|
|
|
|
GIrParser *
|
2010-11-16 21:08:33 +01:00
|
|
|
_g_ir_parser_new (void)
|
2008-11-12 18:16:42 +01:00
|
|
|
{
|
|
|
|
GIrParser *parser = g_slice_new0 (GIrParser);
|
|
|
|
|
|
|
|
return parser;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-11-16 21:08:33 +01:00
|
|
|
_g_ir_parser_free (GIrParser *parser)
|
2008-11-12 18:16:42 +01:00
|
|
|
{
|
2008-11-12 18:17:15 +01:00
|
|
|
GList *l;
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
if (parser->includes)
|
|
|
|
g_strfreev (parser->includes);
|
|
|
|
|
2008-11-12 18:17:15 +01:00
|
|
|
for (l = parser->parsed_modules; l; l = l->next)
|
2010-11-16 21:08:33 +01:00
|
|
|
_g_ir_module_free (l->data);
|
2008-11-12 18:17:15 +01:00
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
g_slice_free (GIrParser, parser);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-11-16 21:08:33 +01:00
|
|
|
_g_ir_parser_set_includes (GIrParser *parser,
|
|
|
|
const gchar *const *includes)
|
2008-11-12 18:16:42 +01:00
|
|
|
{
|
|
|
|
if (parser->includes)
|
|
|
|
g_strfreev (parser->includes);
|
|
|
|
|
|
|
|
parser->includes = g_strdupv ((char **)includes);
|
|
|
|
}
|
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
static void
|
|
|
|
firstpass_start_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
ParseContext *ctx = user_data;
|
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
if (strcmp (element_name, "alias") == 0)
|
2008-08-28 23:19:22 +02:00
|
|
|
{
|
|
|
|
start_alias (context, element_name, attribute_names, attribute_values,
|
|
|
|
ctx, error);
|
|
|
|
}
|
2010-08-03 19:01:35 +02:00
|
|
|
else if (ctx->state == STATE_ALIAS && strcmp (element_name, "type") == 0)
|
|
|
|
{
|
|
|
|
start_type (context, element_name, attribute_names, attribute_values,
|
|
|
|
ctx, error);
|
|
|
|
}
|
2008-11-11 00:58:49 +01:00
|
|
|
else if (strcmp (element_name, "record") == 0)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *disguised;
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
disguised = find_attribute ("disguised", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (disguised && strcmp (disguised, "1") == 0)
|
|
|
|
{
|
|
|
|
char *key;
|
|
|
|
|
2008-11-12 18:17:01 +01:00
|
|
|
key = g_strdup_printf ("%s.%s", ctx->namespace, name);
|
2008-11-11 00:58:49 +01:00
|
|
|
g_hash_table_replace (ctx->disguised_structures, key, GINT_TO_POINTER (1));
|
|
|
|
}
|
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
firstpass_end_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-08-03 19:01:35 +02:00
|
|
|
ParseContext *ctx = user_data;
|
|
|
|
if (strcmp (element_name, "alias") == 0)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
g_free (ctx->current_alias);
|
|
|
|
ctx->current_alias = NULL;
|
|
|
|
}
|
|
|
|
else if (strcmp (element_name, "type") == 0 && ctx->state == STATE_TYPE)
|
|
|
|
state_switch (ctx, ctx->prev_state);
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
static GMarkupParser firstpass_parser =
|
2008-08-28 23:19:22 +02:00
|
|
|
{
|
|
|
|
firstpass_start_element_handler,
|
|
|
|
firstpass_end_element_handler,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
static char *
|
2008-11-12 18:16:42 +01:00
|
|
|
locate_gir (GIrParser *parser,
|
2009-03-28 13:34:36 +01:00
|
|
|
const char *girname)
|
2008-08-28 23:19:22 +02:00
|
|
|
{
|
|
|
|
const gchar *const *datadirs;
|
|
|
|
const gchar *const *dir;
|
|
|
|
char *path = NULL;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
datadirs = g_get_system_data_dirs ();
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
if (parser->includes != NULL)
|
2008-08-29 00:13:00 +02:00
|
|
|
{
|
2010-03-24 19:00:06 +01:00
|
|
|
for (dir = (const gchar *const *)parser->includes; *dir; dir++)
|
2008-08-31 18:01:02 +02:00
|
|
|
{
|
|
|
|
path = g_build_filename (*dir, girname, NULL);
|
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
|
|
|
return path;
|
|
|
|
g_free (path);
|
|
|
|
path = NULL;
|
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
for (dir = datadirs; *dir; dir++)
|
2008-11-11 16:25:59 +01:00
|
|
|
{
|
2009-06-01 09:18:43 +02:00
|
|
|
path = g_build_filename (*dir, GIR_SUFFIX, girname, NULL);
|
2008-11-11 16:25:59 +01:00
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
|
|
|
return path;
|
|
|
|
g_free (path);
|
|
|
|
path = NULL;
|
|
|
|
}
|
2009-06-01 09:18:43 +02:00
|
|
|
|
|
|
|
path = g_build_filename (GIR_DIR, girname, NULL);
|
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
|
|
|
return path;
|
|
|
|
g_free (path);
|
|
|
|
return NULL;
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
|
|
|
|
2011-02-17 18:01:31 +01:00
|
|
|
#define MISSING_ATTRIBUTE(context,error,element,attribute) \
|
2008-08-09 14:46:48 +02:00
|
|
|
do { \
|
|
|
|
int line_number, char_number; \
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number); \
|
|
|
|
g_set_error (error, \
|
|
|
|
G_MARKUP_ERROR, \
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT, \
|
|
|
|
"Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
|
|
|
|
line_number, char_number, attribute, element); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
static const gchar *
|
2010-03-24 19:00:06 +01:00
|
|
|
find_attribute (const gchar *name,
|
2008-08-09 14:46:48 +02:00
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values)
|
|
|
|
{
|
|
|
|
gint i;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
for (i = 0; attribute_names[i] != NULL; i++)
|
|
|
|
if (strcmp (attribute_names[i], name) == 0)
|
|
|
|
return attribute_values[i];
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
state_switch (ParseContext *ctx, ParseState newstate)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
g_assert (ctx->state != newstate);
|
2008-08-09 14:46:48 +02:00
|
|
|
ctx->prev_state = ctx->state;
|
|
|
|
ctx->state = newstate;
|
2013-02-01 05:02:02 +01:00
|
|
|
|
|
|
|
if (ctx->state == STATE_PASSTHROUGH)
|
|
|
|
ctx->unknown_depth = 1;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
static GIrNode *
|
|
|
|
pop_node (ParseContext *ctx)
|
|
|
|
{
|
2012-07-24 10:09:38 +02:00
|
|
|
GSList *top;
|
|
|
|
GIrNode *node;
|
2009-02-04 01:48:17 +01:00
|
|
|
g_assert (ctx->node_stack != 0);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2012-07-24 10:09:38 +02:00
|
|
|
top = ctx->node_stack;
|
|
|
|
node = top->data;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
g_debug ("popping node %d %s", node->type, node->name);
|
|
|
|
ctx->node_stack = top->next;
|
|
|
|
g_slist_free_1 (top);
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
push_node (ParseContext *ctx, GIrNode *node)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
g_assert (node != NULL);
|
2009-02-04 01:48:17 +01:00
|
|
|
g_debug ("pushing node %d %s", node->type, node->name);
|
|
|
|
ctx->node_stack = g_slist_prepend (ctx->node_stack, node);
|
|
|
|
}
|
|
|
|
|
2010-07-26 22:26:46 +02:00
|
|
|
static GIrNodeType * parse_type_internal (GIrModule *module,
|
|
|
|
const gchar *str, gchar **next, gboolean in_glib,
|
2008-10-02 15:25:46 +02:00
|
|
|
gboolean in_gobject);
|
2008-08-13 18:10:09 +02:00
|
|
|
|
2010-07-07 20:07:17 +02:00
|
|
|
typedef struct {
|
|
|
|
const gchar *str;
|
|
|
|
guint size;
|
|
|
|
guint is_signed : 1;
|
|
|
|
} IntegerAliasInfo;
|
|
|
|
|
|
|
|
static IntegerAliasInfo integer_aliases[] = {
|
2013-01-11 08:42:27 +01:00
|
|
|
{ "gchar", SIZEOF_CHAR, 1 },
|
|
|
|
{ "guchar", SIZEOF_CHAR, 0 },
|
2010-07-22 03:06:17 +02:00
|
|
|
{ "gshort", SIZEOF_SHORT, 1 },
|
|
|
|
{ "gushort", SIZEOF_SHORT, 0 },
|
|
|
|
{ "gint", SIZEOF_INT, 1 },
|
|
|
|
{ "guint", SIZEOF_INT, 0 },
|
|
|
|
{ "glong", SIZEOF_LONG, 1 },
|
|
|
|
{ "gulong", SIZEOF_LONG, 0 },
|
2010-07-07 20:07:17 +02:00
|
|
|
{ "gssize", GLIB_SIZEOF_SIZE_T, 1 },
|
2010-12-14 16:28:01 +01:00
|
|
|
{ "gsize", GLIB_SIZEOF_SIZE_T, 0 },
|
|
|
|
{ "gintptr", GLIB_SIZEOF_SIZE_T, 1 },
|
|
|
|
{ "guintptr", GLIB_SIZEOF_SIZE_T, 0 },
|
2010-07-07 20:07:17 +02:00
|
|
|
};
|
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
typedef struct {
|
|
|
|
const gchar *str;
|
|
|
|
gint tag;
|
|
|
|
gboolean pointer;
|
|
|
|
} BasicTypeInfo;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-07-07 20:07:17 +02:00
|
|
|
#define BASIC_TYPE_FIXED_OFFSET 3
|
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
static BasicTypeInfo basic_types[] = {
|
2010-07-22 03:06:17 +02:00
|
|
|
{ "none", GI_TYPE_TAG_VOID, 0 },
|
|
|
|
{ "gpointer", GI_TYPE_TAG_VOID, 1 },
|
|
|
|
|
|
|
|
{ "gboolean", GI_TYPE_TAG_BOOLEAN, 0 },
|
|
|
|
{ "gint8", GI_TYPE_TAG_INT8, 0 }, /* Start of BASIC_TYPE_FIXED_OFFSET */
|
|
|
|
{ "guint8", GI_TYPE_TAG_UINT8, 0 },
|
|
|
|
{ "gint16", GI_TYPE_TAG_INT16, 0 },
|
|
|
|
{ "guint16", GI_TYPE_TAG_UINT16, 0 },
|
|
|
|
{ "gint32", GI_TYPE_TAG_INT32, 0 },
|
|
|
|
{ "guint32", GI_TYPE_TAG_UINT32, 0 },
|
|
|
|
{ "gint64", GI_TYPE_TAG_INT64, 0 },
|
|
|
|
{ "guint64", GI_TYPE_TAG_UINT64, 0 },
|
|
|
|
{ "gfloat", GI_TYPE_TAG_FLOAT, 0 },
|
|
|
|
{ "gdouble", GI_TYPE_TAG_DOUBLE, 0 },
|
|
|
|
{ "GType", GI_TYPE_TAG_GTYPE, 0 },
|
|
|
|
{ "utf8", GI_TYPE_TAG_UTF8, 1 },
|
|
|
|
{ "filename", GI_TYPE_TAG_FILENAME,1 },
|
2010-10-26 17:12:26 +02:00
|
|
|
{ "gunichar", GI_TYPE_TAG_UNICHAR, 0 },
|
2010-03-24 19:00:06 +01:00
|
|
|
};
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
static const BasicTypeInfo *
|
|
|
|
parse_basic (const char *str)
|
|
|
|
{
|
2010-07-22 03:06:17 +02:00
|
|
|
guint i;
|
|
|
|
guint n_basic = G_N_ELEMENTS (basic_types);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
for (i = 0; i < n_basic; i++)
|
|
|
|
{
|
2010-12-14 16:28:01 +01:00
|
|
|
if (strcmp (str, basic_types[i].str) == 0)
|
2008-08-29 22:06:10 +02:00
|
|
|
return &(basic_types[i]);
|
2010-03-24 19:00:06 +01:00
|
|
|
}
|
2010-07-07 20:07:17 +02:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (integer_aliases); i++)
|
|
|
|
{
|
2010-12-14 16:28:01 +01:00
|
|
|
if (strcmp (str, integer_aliases[i].str) == 0)
|
2010-07-07 20:07:17 +02:00
|
|
|
{
|
|
|
|
switch (integer_aliases[i].size)
|
|
|
|
{
|
|
|
|
case sizeof(guint8):
|
|
|
|
if (integer_aliases[i].is_signed)
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET];
|
|
|
|
else
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+1];
|
|
|
|
break;
|
|
|
|
case sizeof(guint16):
|
|
|
|
if (integer_aliases[i].is_signed)
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+2];
|
|
|
|
else
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+3];
|
|
|
|
break;
|
|
|
|
case sizeof(guint32):
|
|
|
|
if (integer_aliases[i].is_signed)
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+4];
|
|
|
|
else
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+5];
|
|
|
|
break;
|
|
|
|
case sizeof(guint64):
|
|
|
|
if (integer_aliases[i].is_signed)
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+6];
|
|
|
|
else
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+7];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-08-29 22:06:10 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GIrNodeType *
|
2010-07-26 22:26:46 +02:00
|
|
|
parse_type_internal (GIrModule *module,
|
|
|
|
const gchar *str, char **next, gboolean in_glib,
|
2008-10-02 15:25:46 +02:00
|
|
|
gboolean in_gobject)
|
2008-08-29 22:06:10 +02:00
|
|
|
{
|
2010-03-24 19:00:06 +01:00
|
|
|
const BasicTypeInfo *basic;
|
2008-08-09 14:46:48 +02:00
|
|
|
GIrNodeType *type;
|
2008-08-29 22:06:10 +02:00
|
|
|
char *temporary_type = NULL;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
type = (GIrNodeType *)_g_ir_node_new (G_IR_NODE_TYPE, module);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
type->unparsed = g_strdup (str);
|
2008-08-29 21:33:09 +02:00
|
|
|
|
2008-10-02 15:25:46 +02:00
|
|
|
/* See comment below on GLib.List handling */
|
2010-03-24 19:00:06 +01:00
|
|
|
if (in_gobject && strcmp (str, "Type") == 0)
|
2008-10-02 15:25:46 +02:00
|
|
|
{
|
|
|
|
temporary_type = g_strdup ("GLib.Type");
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
basic = parse_basic (str);
|
|
|
|
if (basic != NULL)
|
|
|
|
{
|
|
|
|
type->is_basic = TRUE;
|
|
|
|
type->tag = basic->tag;
|
|
|
|
type->is_pointer = basic->pointer;
|
|
|
|
|
|
|
|
str += strlen(basic->str);
|
|
|
|
}
|
|
|
|
else if (in_glib)
|
2008-08-29 21:33:09 +02:00
|
|
|
{
|
2008-10-02 15:25:46 +02:00
|
|
|
/* If we're inside GLib, handle "List" etc. by prefixing with
|
2008-08-29 22:06:10 +02:00
|
|
|
* "GLib." so the parsing code below doesn't have to get more
|
2010-03-24 19:00:06 +01:00
|
|
|
* special.
|
2008-08-29 22:06:10 +02:00
|
|
|
*/
|
2008-08-29 21:33:09 +02:00
|
|
|
if (g_str_has_prefix (str, "List<") ||
|
|
|
|
strcmp (str, "List") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
|
|
|
else if (g_str_has_prefix (str, "SList<") ||
|
|
|
|
strcmp (str, "SList") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
|
|
|
else if (g_str_has_prefix (str, "HashTable<") ||
|
|
|
|
strcmp (str, "HashTable") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
|
|
|
else if (g_str_has_prefix (str, "Error<") ||
|
|
|
|
strcmp (str, "Error") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
if (basic != NULL)
|
2008-08-09 14:46:48 +02:00
|
|
|
/* found a basic type */;
|
2008-08-29 21:33:09 +02:00
|
|
|
else if (g_str_has_prefix (str, "GLib.List") ||
|
|
|
|
g_str_has_prefix (str, "GLib.SList"))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("GLib.");
|
|
|
|
if (g_str_has_prefix (str, "List"))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-12 17:34:27 +02:00
|
|
|
type->tag = GI_TYPE_TAG_GLIST;
|
2008-08-09 14:46:48 +02:00
|
|
|
type->is_glist = TRUE;
|
|
|
|
type->is_pointer = TRUE;
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("List");
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-08-12 17:34:27 +02:00
|
|
|
type->tag = GI_TYPE_TAG_GSLIST;
|
2008-08-09 14:46:48 +02:00
|
|
|
type->is_gslist = TRUE;
|
|
|
|
type->is_pointer = TRUE;
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("SList");
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
}
|
2008-08-29 21:33:09 +02:00
|
|
|
else if (g_str_has_prefix (str, "GLib.HashTable"))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("GLib.");
|
2008-08-29 20:19:26 +02:00
|
|
|
|
2008-08-12 17:34:27 +02:00
|
|
|
type->tag = GI_TYPE_TAG_GHASH;
|
2008-08-09 14:46:48 +02:00
|
|
|
type->is_ghashtable = TRUE;
|
|
|
|
type->is_pointer = TRUE;
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("HashTable");
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
2008-08-29 21:33:09 +02:00
|
|
|
else if (g_str_has_prefix (str, "GLib.Error"))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("GLib.");
|
2008-08-29 20:19:26 +02:00
|
|
|
|
2008-08-12 17:34:27 +02:00
|
|
|
type->tag = GI_TYPE_TAG_ERROR;
|
2008-08-09 14:46:48 +02:00
|
|
|
type->is_error = TRUE;
|
|
|
|
type->is_pointer = TRUE;
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("Error");
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-29 21:33:09 +02:00
|
|
|
if (*str == '<')
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-29 22:06:10 +02:00
|
|
|
char *tmp, *end;
|
2012-07-24 10:09:38 +02:00
|
|
|
(str)++;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-29 21:33:09 +02:00
|
|
|
end = strchr (str, '>');
|
|
|
|
tmp = g_strndup (str, end - str);
|
|
|
|
type->errors = g_strsplit (tmp, ",", 0);
|
|
|
|
g_free (tmp);
|
|
|
|
|
|
|
|
str = end;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
else
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2012-07-24 10:09:38 +02:00
|
|
|
const char *start;
|
2008-08-12 17:34:27 +02:00
|
|
|
type->tag = GI_TYPE_TAG_INTERFACE;
|
2010-03-24 19:00:06 +01:00
|
|
|
type->is_interface = TRUE;
|
2012-07-24 10:09:38 +02:00
|
|
|
start = str;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
/* must be an interface type */
|
2010-03-24 19:00:06 +01:00
|
|
|
while (g_ascii_isalnum (*str) ||
|
|
|
|
*str == '.' ||
|
|
|
|
*str == '-' ||
|
2008-08-29 21:33:09 +02:00
|
|
|
*str == '_' ||
|
|
|
|
*str == ':')
|
|
|
|
(str)++;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2012-07-24 10:09:38 +02:00
|
|
|
type->giinterface = g_strndup (start, str - start);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-29 21:33:09 +02:00
|
|
|
if (next)
|
|
|
|
*next = (char*)str;
|
2010-10-26 17:12:26 +02:00
|
|
|
g_assert (type->tag >= 0 && type->tag < GI_TYPE_TAG_N_TYPES);
|
2008-08-29 21:33:09 +02:00
|
|
|
g_free (temporary_type);
|
2008-08-09 14:46:48 +02:00
|
|
|
return type;
|
|
|
|
|
Bug 556543 – reduce compiler warnings
2008-10-16 Tommi Komulainen <tommi.komulainen@iki.fi>
Bug 556543 – reduce compiler warnings
* girepository/ginfo.c:
* girepository/girepository.c (register_internal,
count_interfaces, find_interface, find_namespace_version,
parse_version, g_irepository_require):
* girepository/girmodule.c (g_ir_module_build_typelib):
* girepository/girnode.c (init_stats, dump_stats,
_g_irnode_init_stats, _g_irnode_dump_stats,
g_ir_node_can_have_member):
* girepository/girparser.c (firstpass_end_element_handler,
locate_gir, parse_basic, parse_type_internal, resolve_aliases,
start_alias, start_type, end_type_top, parse_include, cleanup,
post_filter):
* girepository/gtypelib.c (validate_function_blob, validate_enum_blob):
* giscanner/giscannermodule.c (directive_get_options,
type_get_child_list):
* giscanner/scannerlexer.l (parse_gtkdoc):
* giscanner/scannerparser.y (ctype_free):
* giscanner/sourcescanner.c:
* giscanner/sourcescanner.h (gi_source_scanner_parse_macros):
* tests/types/gitesttypes.c:
* tools/compiler.c (main):
* tools/generate.c (write_repository): Remove unused variables
and code, add missing includes, declarations and case
statements.
svn path=/trunk/; revision=730
2008-10-16 19:07:05 +02:00
|
|
|
/* error: */
|
2010-11-16 21:08:33 +01:00
|
|
|
_g_ir_node_free ((GIrNode *)type);
|
2010-03-24 19:00:06 +01:00
|
|
|
g_free (temporary_type);
|
2008-08-09 14:46:48 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-08-13 18:10:09 +02:00
|
|
|
static const char *
|
|
|
|
resolve_aliases (ParseContext *ctx, const gchar *type)
|
|
|
|
{
|
|
|
|
gpointer orig;
|
|
|
|
gpointer value;
|
2008-08-20 21:01:20 +02:00
|
|
|
GSList *seen_values = NULL;
|
2008-11-12 18:17:01 +01:00
|
|
|
const gchar *lookup;
|
|
|
|
gchar *prefixed;
|
2008-11-11 23:02:37 +01:00
|
|
|
|
2008-11-12 18:17:01 +01:00
|
|
|
if (strchr (type, '.') == NULL)
|
2008-11-11 23:02:37 +01:00
|
|
|
{
|
|
|
|
prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
|
|
|
|
lookup = prefixed;
|
|
|
|
}
|
|
|
|
else
|
2008-11-12 18:17:01 +01:00
|
|
|
{
|
|
|
|
lookup = type;
|
|
|
|
prefixed = NULL;
|
|
|
|
}
|
2008-08-13 18:10:09 +02:00
|
|
|
|
2008-11-11 23:02:37 +01:00
|
|
|
seen_values = g_slist_prepend (seen_values, (char*)lookup);
|
2008-11-12 18:17:01 +01:00
|
|
|
while (g_hash_table_lookup_extended (ctx->current_module->aliases, lookup, &orig, &value))
|
2008-08-13 18:10:09 +02:00
|
|
|
{
|
2008-11-11 23:02:37 +01:00
|
|
|
g_debug ("Resolved: %s => %s\n", lookup, (char*)value);
|
|
|
|
lookup = value;
|
|
|
|
if (g_slist_find_custom (seen_values, lookup,
|
2008-08-21 10:20:07 +02:00
|
|
|
(GCompareFunc)strcmp) != NULL)
|
2008-08-20 21:01:20 +02:00
|
|
|
break;
|
2008-11-11 23:02:37 +01:00
|
|
|
seen_values = g_slist_prepend (seen_values, (gchar*)lookup);
|
2008-08-13 18:10:09 +02:00
|
|
|
}
|
2008-08-21 10:20:07 +02:00
|
|
|
g_slist_free (seen_values);
|
2008-11-11 23:02:37 +01:00
|
|
|
|
|
|
|
if (lookup == prefixed)
|
|
|
|
lookup = type;
|
2008-11-12 18:17:01 +01:00
|
|
|
|
2008-11-11 23:02:37 +01:00
|
|
|
g_free (prefixed);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-11-11 23:02:37 +01:00
|
|
|
return lookup;
|
2008-08-13 18:10:09 +02:00
|
|
|
}
|
|
|
|
|
2008-11-12 18:17:01 +01:00
|
|
|
static gboolean
|
|
|
|
is_disguised_structure (ParseContext *ctx, const gchar *type)
|
|
|
|
{
|
|
|
|
const gchar *lookup;
|
|
|
|
gchar *prefixed;
|
|
|
|
gboolean result;
|
|
|
|
|
|
|
|
if (strchr (type, '.') == NULL)
|
|
|
|
{
|
|
|
|
prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
|
|
|
|
lookup = prefixed;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lookup = type;
|
|
|
|
prefixed = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = g_hash_table_lookup (ctx->current_module->disguised_structures,
|
|
|
|
lookup) != NULL;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-11-12 18:17:01 +01:00
|
|
|
g_free (prefixed);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-11-12 18:17:01 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static GIrNodeType *
|
2008-08-13 18:10:09 +02:00
|
|
|
parse_type (ParseContext *ctx, const gchar *type)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
GIrNodeType *node;
|
2008-08-29 22:06:10 +02:00
|
|
|
const BasicTypeInfo *basic;
|
2008-10-02 15:25:46 +02:00
|
|
|
gboolean in_glib, in_gobject;
|
2008-08-29 21:33:09 +02:00
|
|
|
|
|
|
|
in_glib = strcmp (ctx->namespace, "GLib") == 0;
|
2008-10-02 15:25:46 +02:00
|
|
|
in_gobject = strcmp (ctx->namespace, "GObject") == 0;
|
2008-08-29 21:33:09 +02:00
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
/* Do not search aliases for basic types */
|
|
|
|
basic = parse_basic (type);
|
|
|
|
if (basic == NULL)
|
|
|
|
type = resolve_aliases (ctx, type);
|
|
|
|
|
2010-07-26 22:26:46 +02:00
|
|
|
node = parse_type_internal (ctx->current_module, type, NULL, in_glib, in_gobject);
|
2008-08-29 21:33:09 +02:00
|
|
|
if (node)
|
|
|
|
g_debug ("Parsed type: %s => %d", type, node->tag);
|
|
|
|
else
|
|
|
|
g_critical ("Failed to parse type: '%s'", type);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
static gboolean
|
|
|
|
introspectable_prelude (GMarkupParseContext *context,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
ParseState new_state)
|
|
|
|
{
|
|
|
|
const gchar *introspectable_arg;
|
2010-12-07 00:07:08 +01:00
|
|
|
const gchar *shadowed_by;
|
2010-06-17 02:34:18 +02:00
|
|
|
gboolean introspectable;
|
|
|
|
|
|
|
|
g_assert (ctx->state != STATE_PASSTHROUGH);
|
|
|
|
|
|
|
|
introspectable_arg = find_attribute ("introspectable", attribute_names, attribute_values);
|
2010-12-07 00:07:08 +01:00
|
|
|
shadowed_by = find_attribute ("shadowed-by", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
introspectable = !(introspectable_arg && atoi (introspectable_arg) == 0) && shadowed_by == NULL;
|
2010-06-17 02:34:18 +02:00
|
|
|
|
|
|
|
if (introspectable)
|
|
|
|
state_switch (ctx, new_state);
|
|
|
|
else
|
2013-02-01 05:02:02 +01:00
|
|
|
state_switch (ctx, STATE_PASSTHROUGH);
|
2010-06-17 02:34:18 +02:00
|
|
|
|
|
|
|
return introspectable;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
|
|
|
start_glib_boxed (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *typename;
|
|
|
|
const gchar *typeinit;
|
|
|
|
const gchar *deprecated;
|
|
|
|
GIrNodeBoxed *boxed;
|
|
|
|
|
|
|
|
if (!(strcmp (element_name, "glib:boxed") == 0 &&
|
|
|
|
ctx->state == STATE_NAMESPACE))
|
|
|
|
return FALSE;
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_BOXED))
|
|
|
|
return TRUE;
|
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
name = find_attribute ("glib:name", attribute_names, attribute_values);
|
|
|
|
typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
|
|
|
|
typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
if (name == NULL)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (typename == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (typeinit == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
boxed = (GIrNodeBoxed *) _g_ir_node_new (G_IR_NODE_BOXED,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
((GIrNode *)boxed)->name = g_strdup (name);
|
|
|
|
boxed->gtype_name = g_strdup (typename);
|
|
|
|
boxed->gtype_init = g_strdup (typeinit);
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-08-24 13:01:44 +02:00
|
|
|
boxed->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
boxed->deprecated = FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
push_node (ctx, (GIrNode *)boxed);
|
2010-03-24 19:00:06 +01:00
|
|
|
ctx->current_module->entries =
|
2008-08-24 13:01:44 +02:00
|
|
|
g_list_append (ctx->current_module->entries, boxed);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_function (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
const gchar *name;
|
2010-09-04 00:07:16 +02:00
|
|
|
const gchar *shadows;
|
2008-08-24 13:01:44 +02:00
|
|
|
const gchar *symbol;
|
|
|
|
const gchar *deprecated;
|
2008-10-21 19:04:11 +02:00
|
|
|
const gchar *throws;
|
2008-08-24 13:01:44 +02:00
|
|
|
GIrNodeFunction *function;
|
|
|
|
gboolean found = FALSE;
|
2014-02-27 11:05:54 +01:00
|
|
|
ParseState in_embedded_state = STATE_NONE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
switch (ctx->state)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
case STATE_NAMESPACE:
|
|
|
|
found = (strcmp (element_name, "function") == 0 ||
|
|
|
|
strcmp (element_name, "callback") == 0);
|
|
|
|
break;
|
|
|
|
case STATE_CLASS:
|
|
|
|
case STATE_BOXED:
|
|
|
|
case STATE_STRUCT:
|
|
|
|
case STATE_UNION:
|
2010-07-27 12:16:37 +02:00
|
|
|
found = strcmp (element_name, "constructor") == 0;
|
2008-08-24 13:01:44 +02:00
|
|
|
/* fallthrough */
|
|
|
|
case STATE_INTERFACE:
|
|
|
|
found = (found ||
|
2010-07-27 12:16:37 +02:00
|
|
|
strcmp (element_name, "function") == 0 ||
|
2008-08-24 13:01:44 +02:00
|
|
|
strcmp (element_name, "method") == 0 ||
|
|
|
|
strcmp (element_name, "callback") == 0);
|
|
|
|
break;
|
2011-08-13 17:28:30 +02:00
|
|
|
case STATE_ENUM:
|
|
|
|
found = strcmp (element_name, "function") == 0;
|
|
|
|
break;
|
2014-02-27 11:05:54 +01:00
|
|
|
case STATE_CLASS_FIELD:
|
2009-11-09 19:17:23 +01:00
|
|
|
case STATE_STRUCT_FIELD:
|
|
|
|
found = (found || strcmp (element_name, "callback") == 0);
|
2014-02-27 11:05:54 +01:00
|
|
|
in_embedded_state = ctx->state;
|
2009-11-09 19:17:23 +01:00
|
|
|
break;
|
2008-08-24 13:01:44 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
return FALSE;
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_FUNCTION))
|
|
|
|
return TRUE;
|
|
|
|
|
2014-02-27 11:05:54 +01:00
|
|
|
ctx->in_embedded_state = in_embedded_state;
|
2010-07-27 12:16:37 +02:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
2010-09-04 00:09:35 +02:00
|
|
|
shadows = find_attribute ("shadows", attribute_names, attribute_values);
|
2008-08-24 13:01:44 +02:00
|
|
|
symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
2008-10-21 19:04:11 +02:00
|
|
|
throws = find_attribute ("throws", attribute_names, attribute_values);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2010-09-04 00:07:16 +02:00
|
|
|
if (shadows)
|
|
|
|
name = shadows;
|
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
function = (GIrNodeFunction *) _g_ir_node_new (G_IR_NODE_FUNCTION,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
((GIrNode *)function)->name = g_strdup (name);
|
|
|
|
function->symbol = g_strdup (symbol);
|
|
|
|
function->parameters = NULL;
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-08-24 13:01:44 +02:00
|
|
|
function->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
function->deprecated = FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
if (strcmp (element_name, "method") == 0 ||
|
|
|
|
strcmp (element_name, "constructor") == 0)
|
|
|
|
{
|
|
|
|
function->is_method = TRUE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
if (strcmp (element_name, "constructor") == 0)
|
|
|
|
function->is_constructor = TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
else
|
2008-08-24 13:01:44 +02:00
|
|
|
function->is_constructor = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
function->is_method = FALSE;
|
|
|
|
function->is_setter = FALSE;
|
|
|
|
function->is_getter = FALSE;
|
|
|
|
function->is_constructor = FALSE;
|
|
|
|
if (strcmp (element_name, "callback") == 0)
|
|
|
|
((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
|
|
|
|
}
|
2008-10-21 19:04:11 +02:00
|
|
|
|
|
|
|
if (throws && strcmp (throws, "1") == 0)
|
|
|
|
function->throws = TRUE;
|
|
|
|
else
|
|
|
|
function->throws = FALSE;
|
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
if (ctx->node_stack == NULL)
|
2008-08-24 13:01:44 +02:00
|
|
|
{
|
2010-03-24 19:00:06 +01:00
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, function);
|
2008-08-24 13:01:44 +02:00
|
|
|
}
|
2009-11-09 19:17:23 +01:00
|
|
|
else if (ctx->current_typed)
|
|
|
|
{
|
|
|
|
GIrNodeField *field;
|
|
|
|
|
|
|
|
field = (GIrNodeField *)ctx->current_typed;
|
|
|
|
field->callback = function;
|
|
|
|
}
|
2008-08-24 13:01:44 +02:00
|
|
|
else
|
2009-02-04 01:48:17 +01:00
|
|
|
switch (CURRENT_NODE (ctx)->type)
|
2008-08-24 13:01:44 +02:00
|
|
|
{
|
|
|
|
case G_IR_NODE_INTERFACE:
|
|
|
|
case G_IR_NODE_OBJECT:
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
GIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
2008-08-24 13:01:44 +02:00
|
|
|
iface->members = g_list_append (iface->members, function);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_BOXED:
|
|
|
|
{
|
|
|
|
GIrNodeBoxed *boxed;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
boxed = (GIrNodeBoxed *)CURRENT_NODE (ctx);
|
2008-08-24 13:01:44 +02:00
|
|
|
boxed->members = g_list_append (boxed->members, function);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_STRUCT:
|
|
|
|
{
|
|
|
|
GIrNodeStruct *struct_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
struct_ = (GIrNodeStruct *)CURRENT_NODE (ctx);
|
2008-08-24 13:01:44 +02:00
|
|
|
struct_->members = g_list_append (struct_->members, function); }
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_UNION:
|
|
|
|
{
|
|
|
|
GIrNodeUnion *union_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
union_ = (GIrNodeUnion *)CURRENT_NODE (ctx);
|
2008-08-24 13:01:44 +02:00
|
|
|
union_->members = g_list_append (union_->members, function);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
2008-08-24 13:01:44 +02:00
|
|
|
break;
|
2011-08-13 17:28:30 +02:00
|
|
|
case G_IR_NODE_ENUM:
|
|
|
|
case G_IR_NODE_FLAGS:
|
|
|
|
{
|
|
|
|
GIrNodeEnum *enum_;
|
|
|
|
|
|
|
|
enum_ = (GIrNodeEnum *)CURRENT_NODE (ctx);
|
|
|
|
enum_->methods = g_list_append (enum_->methods, function);
|
|
|
|
}
|
|
|
|
break;
|
2008-08-24 13:01:44 +02:00
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
push_node(ctx, (GIrNode *)function);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2010-06-08 16:40:35 +02:00
|
|
|
static void
|
|
|
|
parse_property_transfer (GIrNodeProperty *property,
|
|
|
|
const gchar *transfer,
|
|
|
|
ParseContext *ctx)
|
|
|
|
{
|
|
|
|
if (transfer == NULL)
|
|
|
|
{
|
2010-06-08 19:20:06 +02:00
|
|
|
#if 0
|
2010-06-08 16:40:35 +02:00
|
|
|
GIrNodeInterface *iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
|
|
|
|
2010-06-08 19:20:06 +02:00
|
|
|
g_debug ("required attribute 'transfer-ownership' is missing from "
|
|
|
|
"property '%s' in type '%s.%s'. Assuming 'none'\n",
|
|
|
|
property->node.name, ctx->namespace, iface->node.name);
|
|
|
|
#endif
|
|
|
|
transfer = "none";
|
2010-06-08 16:40:35 +02:00
|
|
|
}
|
2010-06-08 19:20:06 +02:00
|
|
|
if (strcmp (transfer, "none") == 0)
|
2010-06-08 16:40:35 +02:00
|
|
|
{
|
|
|
|
property->transfer = FALSE;
|
|
|
|
property->shallow_transfer = FALSE;
|
|
|
|
}
|
|
|
|
else if (strcmp (transfer, "container") == 0)
|
|
|
|
{
|
|
|
|
property->transfer = FALSE;
|
|
|
|
property->shallow_transfer = TRUE;
|
|
|
|
}
|
|
|
|
else if (strcmp (transfer, "full") == 0)
|
|
|
|
{
|
|
|
|
property->transfer = TRUE;
|
|
|
|
property->shallow_transfer = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
|
|
|
|
|
|
|
g_warning ("Unknown transfer-ownership value: '%s' for property '%s' in "
|
|
|
|
"type '%s.%s'", transfer, property->node.name, ctx->namespace,
|
|
|
|
iface->node.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-27 12:16:37 +02:00
|
|
|
static gboolean
|
|
|
|
parse_param_transfer (GIrNodeParam *param, const gchar *transfer, const gchar *name,
|
|
|
|
GError **error)
|
2008-10-12 23:07:22 +02:00
|
|
|
{
|
2008-10-23 19:42:25 +02:00
|
|
|
if (transfer == NULL)
|
|
|
|
{
|
2010-07-27 12:16:37 +02:00
|
|
|
g_set_error (error, G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"required attribute 'transfer-ownership' missing");
|
|
|
|
return FALSE;
|
2008-10-23 19:42:25 +02:00
|
|
|
}
|
|
|
|
else if (strcmp (transfer, "none") == 0)
|
2008-10-12 23:07:22 +02:00
|
|
|
{
|
|
|
|
param->transfer = FALSE;
|
|
|
|
param->shallow_transfer = FALSE;
|
|
|
|
}
|
2008-10-23 19:42:25 +02:00
|
|
|
else if (strcmp (transfer, "container") == 0)
|
2008-10-12 23:07:22 +02:00
|
|
|
{
|
|
|
|
param->transfer = FALSE;
|
|
|
|
param->shallow_transfer = TRUE;
|
|
|
|
}
|
2008-10-23 19:42:25 +02:00
|
|
|
else if (strcmp (transfer, "full") == 0)
|
2008-10-12 23:07:22 +02:00
|
|
|
{
|
2008-10-23 19:42:25 +02:00
|
|
|
param->transfer = TRUE;
|
2008-10-12 23:07:22 +02:00
|
|
|
param->shallow_transfer = FALSE;
|
|
|
|
}
|
2008-10-23 19:42:25 +02:00
|
|
|
else
|
|
|
|
{
|
2010-07-27 12:16:37 +02:00
|
|
|
g_set_error (error, G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"invalid value for 'transfer-ownership': %s", transfer);
|
|
|
|
return FALSE;
|
2008-10-23 19:42:25 +02:00
|
|
|
}
|
2010-07-27 12:16:37 +02:00
|
|
|
return TRUE;
|
2008-10-12 23:07:22 +02:00
|
|
|
}
|
|
|
|
|
2014-05-06 18:53:21 +02:00
|
|
|
static gboolean
|
|
|
|
start_instance_parameter (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
const gchar *transfer;
|
|
|
|
gboolean transfer_full;
|
|
|
|
|
|
|
|
if (!(strcmp (element_name, "instance-parameter") == 0 &&
|
|
|
|
ctx->state == STATE_FUNCTION_PARAMETERS))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_PASSTHROUGH);
|
|
|
|
|
|
|
|
if (strcmp (transfer, "full") == 0)
|
|
|
|
transfer_full = TRUE;
|
|
|
|
else if (strcmp (transfer, "none") == 0)
|
|
|
|
transfer_full = FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_set_error (error, G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"invalid value for 'transfer-ownership' for instance parameter: %s", transfer);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (CURRENT_NODE (ctx)->type)
|
|
|
|
{
|
|
|
|
case G_IR_NODE_FUNCTION:
|
|
|
|
case G_IR_NODE_CALLBACK:
|
|
|
|
{
|
|
|
|
GIrNodeFunction *func;
|
|
|
|
|
|
|
|
func = (GIrNodeFunction *)CURRENT_NODE (ctx);
|
|
|
|
func->instance_transfer_full = transfer_full;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_SIGNAL:
|
|
|
|
{
|
|
|
|
GIrNodeSignal *signal;
|
|
|
|
|
|
|
|
signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
|
|
|
|
signal->instance_transfer_full = transfer_full;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_VFUNC:
|
|
|
|
{
|
|
|
|
GIrNodeVFunc *vfunc;
|
|
|
|
|
|
|
|
vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
|
|
|
|
vfunc->instance_transfer_full = transfer_full;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
|
|
|
start_parameter (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *direction;
|
|
|
|
const gchar *retval;
|
|
|
|
const gchar *optional;
|
2009-12-16 17:47:19 +01:00
|
|
|
const gchar *caller_allocates;
|
2008-10-22 16:02:02 +02:00
|
|
|
const gchar *allow_none;
|
2008-08-09 14:46:48 +02:00
|
|
|
const gchar *transfer;
|
Bug 556489 – callback annotations
2008-01-03 Andreas Rottmann <a.rottmann@gmx.at>
Bug 556489 – callback annotations
* giscanner/transformer.py
* tools/generate.c (write_callable_info): Write out the new scope,
closure and destroy attributes.
* giscanner/transformer.py (Transformer._type_is_callback): New
method, checking if a given type is a callback.
(Transformer._augment_callback_params): New method; adds
information (closure, destroy) to callback parameters.
(Transformer._handle_closure, Transformer._handle_destroy): New methods,
auxiliary to _augment_callback_params.
(Transformer._create_function): Call _augment_callback_params().
(Transformer._create_parameter): Handle scope option.
(Transformer._create_typedef_callback): New method, creates a
callback, and registers it in the typedef namespace
(Transformer._create_typedef): Use _create_typedef_callback()
instead of the plain _create_callback().
* giscanner/ast.py (Parameter): Added callback-related fields.
* giscanner/girwriter.py: Write out new Parameter fields.
* girepository/girnode.h (GIrNodeParam): Added fields scope,
closure and destroy.
* girepository/gtypelib.h (ArgBlob): Ditto.
* girepository/girparser.c (start_parameter): Handle new fields.
* girepository/girmodule.c (g_ir_module_build_typelib): Adjust
arg_blob_size, bump major version due to this change.
* girepository/girnode.c (g_ir_node_get_full_size_internal)
(g_ir_node_build_typelib)
* girepository/gtypelib.c (g_typelib_check_sanity): ArgBlob size
adjustments.
(g_ir_node_build_typelib): Fill in new ArgBlob flags from param.
* girepository/girepository.h (GIScope): New enumeration, listing
the different possible scopes for callbacks.
* girepository/ginfo.c (g_arg_info_get_scope)
(g_arg_info_get_closure, g_arg_info_get_destroy): Accessors for
callback-related argument indices (callback scope, closure for a
callback, destroy notification for a callback).
* tests/scanner/: Added testcases for new features.
svn path=/trunk/; revision=998
2009-01-03 14:44:42 +01:00
|
|
|
const gchar *scope;
|
|
|
|
const gchar *closure;
|
|
|
|
const gchar *destroy;
|
2011-05-13 18:20:05 +02:00
|
|
|
const gchar *skip;
|
2014-04-16 17:39:09 +02:00
|
|
|
const gchar *nullable;
|
2008-08-09 14:46:48 +02:00
|
|
|
GIrNodeParam *param;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
if (!(strcmp (element_name, "parameter") == 0 &&
|
|
|
|
ctx->state == STATE_FUNCTION_PARAMETERS))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
direction = find_attribute ("direction", attribute_names, attribute_values);
|
|
|
|
retval = find_attribute ("retval", attribute_names, attribute_values);
|
|
|
|
optional = find_attribute ("optional", attribute_names, attribute_values);
|
2008-10-22 16:02:02 +02:00
|
|
|
allow_none = find_attribute ("allow-none", attribute_names, attribute_values);
|
2009-12-16 17:47:19 +01:00
|
|
|
caller_allocates = find_attribute ("caller-allocates", attribute_names, attribute_values);
|
2008-10-17 16:59:23 +02:00
|
|
|
transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
|
Bug 556489 – callback annotations
2008-01-03 Andreas Rottmann <a.rottmann@gmx.at>
Bug 556489 – callback annotations
* giscanner/transformer.py
* tools/generate.c (write_callable_info): Write out the new scope,
closure and destroy attributes.
* giscanner/transformer.py (Transformer._type_is_callback): New
method, checking if a given type is a callback.
(Transformer._augment_callback_params): New method; adds
information (closure, destroy) to callback parameters.
(Transformer._handle_closure, Transformer._handle_destroy): New methods,
auxiliary to _augment_callback_params.
(Transformer._create_function): Call _augment_callback_params().
(Transformer._create_parameter): Handle scope option.
(Transformer._create_typedef_callback): New method, creates a
callback, and registers it in the typedef namespace
(Transformer._create_typedef): Use _create_typedef_callback()
instead of the plain _create_callback().
* giscanner/ast.py (Parameter): Added callback-related fields.
* giscanner/girwriter.py: Write out new Parameter fields.
* girepository/girnode.h (GIrNodeParam): Added fields scope,
closure and destroy.
* girepository/gtypelib.h (ArgBlob): Ditto.
* girepository/girparser.c (start_parameter): Handle new fields.
* girepository/girmodule.c (g_ir_module_build_typelib): Adjust
arg_blob_size, bump major version due to this change.
* girepository/girnode.c (g_ir_node_get_full_size_internal)
(g_ir_node_build_typelib)
* girepository/gtypelib.c (g_typelib_check_sanity): ArgBlob size
adjustments.
(g_ir_node_build_typelib): Fill in new ArgBlob flags from param.
* girepository/girepository.h (GIScope): New enumeration, listing
the different possible scopes for callbacks.
* girepository/ginfo.c (g_arg_info_get_scope)
(g_arg_info_get_closure, g_arg_info_get_destroy): Accessors for
callback-related argument indices (callback scope, closure for a
callback, destroy notification for a callback).
* tests/scanner/: Added testcases for new features.
svn path=/trunk/; revision=998
2009-01-03 14:44:42 +01:00
|
|
|
scope = find_attribute ("scope", attribute_names, attribute_values);
|
|
|
|
closure = find_attribute ("closure", attribute_names, attribute_values);
|
|
|
|
destroy = find_attribute ("destroy", attribute_names, attribute_values);
|
2011-05-13 18:20:05 +02:00
|
|
|
skip = find_attribute ("skip", attribute_names, attribute_values);
|
2014-04-16 17:39:09 +02:00
|
|
|
nullable = find_attribute ("nullable", attribute_names, attribute_values);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
if (name == NULL)
|
|
|
|
name = "unknown";
|
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
param = (GIrNodeParam *)_g_ir_node_new (G_IR_NODE_PARAM,
|
|
|
|
ctx->current_module);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
ctx->current_typed = (GIrNode*) param;
|
2008-08-12 17:34:27 +02:00
|
|
|
ctx->current_typed->name = g_strdup (name);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
state_switch (ctx, STATE_FUNCTION_PARAMETER);
|
|
|
|
|
|
|
|
if (direction && strcmp (direction, "out") == 0)
|
|
|
|
{
|
|
|
|
param->in = FALSE;
|
|
|
|
param->out = TRUE;
|
2009-12-16 17:47:19 +01:00
|
|
|
if (caller_allocates == NULL)
|
2010-05-26 19:52:36 +02:00
|
|
|
param->caller_allocates = FALSE;
|
|
|
|
else
|
|
|
|
param->caller_allocates = strcmp (caller_allocates, "1") == 0;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
else if (direction && strcmp (direction, "inout") == 0)
|
|
|
|
{
|
|
|
|
param->in = TRUE;
|
|
|
|
param->out = TRUE;
|
2009-12-16 17:47:19 +01:00
|
|
|
param->caller_allocates = FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
param->in = TRUE;
|
|
|
|
param->out = FALSE;
|
2009-12-16 17:47:19 +01:00
|
|
|
param->caller_allocates = FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (retval && strcmp (retval, "1") == 0)
|
|
|
|
param->retval = TRUE;
|
|
|
|
else
|
|
|
|
param->retval = FALSE;
|
|
|
|
|
|
|
|
if (optional && strcmp (optional, "1") == 0)
|
|
|
|
param->optional = TRUE;
|
|
|
|
else
|
|
|
|
param->optional = FALSE;
|
|
|
|
|
2014-04-16 17:39:09 +02:00
|
|
|
if (nullable && strcmp (nullable, "1") == 0)
|
2014-04-16 17:33:36 +02:00
|
|
|
param->nullable = TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
else
|
2014-04-16 17:33:36 +02:00
|
|
|
param->nullable = FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2014-04-16 17:39:09 +02:00
|
|
|
if (allow_none && strcmp (allow_none, "1") == 0)
|
|
|
|
{
|
|
|
|
if (param->out)
|
|
|
|
param->optional = TRUE;
|
|
|
|
else
|
|
|
|
param->nullable = TRUE;
|
|
|
|
}
|
|
|
|
|
2011-05-13 18:20:05 +02:00
|
|
|
if (skip && strcmp (skip, "1") == 0)
|
|
|
|
param->skip = TRUE;
|
|
|
|
else
|
|
|
|
param->skip = FALSE;
|
|
|
|
|
2010-07-27 12:16:37 +02:00
|
|
|
if (!parse_param_transfer (param, transfer, name, error))
|
|
|
|
return FALSE;
|
2008-10-12 23:07:22 +02:00
|
|
|
|
Bug 556489 – callback annotations
2008-01-03 Andreas Rottmann <a.rottmann@gmx.at>
Bug 556489 – callback annotations
* giscanner/transformer.py
* tools/generate.c (write_callable_info): Write out the new scope,
closure and destroy attributes.
* giscanner/transformer.py (Transformer._type_is_callback): New
method, checking if a given type is a callback.
(Transformer._augment_callback_params): New method; adds
information (closure, destroy) to callback parameters.
(Transformer._handle_closure, Transformer._handle_destroy): New methods,
auxiliary to _augment_callback_params.
(Transformer._create_function): Call _augment_callback_params().
(Transformer._create_parameter): Handle scope option.
(Transformer._create_typedef_callback): New method, creates a
callback, and registers it in the typedef namespace
(Transformer._create_typedef): Use _create_typedef_callback()
instead of the plain _create_callback().
* giscanner/ast.py (Parameter): Added callback-related fields.
* giscanner/girwriter.py: Write out new Parameter fields.
* girepository/girnode.h (GIrNodeParam): Added fields scope,
closure and destroy.
* girepository/gtypelib.h (ArgBlob): Ditto.
* girepository/girparser.c (start_parameter): Handle new fields.
* girepository/girmodule.c (g_ir_module_build_typelib): Adjust
arg_blob_size, bump major version due to this change.
* girepository/girnode.c (g_ir_node_get_full_size_internal)
(g_ir_node_build_typelib)
* girepository/gtypelib.c (g_typelib_check_sanity): ArgBlob size
adjustments.
(g_ir_node_build_typelib): Fill in new ArgBlob flags from param.
* girepository/girepository.h (GIScope): New enumeration, listing
the different possible scopes for callbacks.
* girepository/ginfo.c (g_arg_info_get_scope)
(g_arg_info_get_closure, g_arg_info_get_destroy): Accessors for
callback-related argument indices (callback scope, closure for a
callback, destroy notification for a callback).
* tests/scanner/: Added testcases for new features.
svn path=/trunk/; revision=998
2009-01-03 14:44:42 +01:00
|
|
|
if (scope && strcmp (scope, "call") == 0)
|
|
|
|
param->scope = GI_SCOPE_TYPE_CALL;
|
|
|
|
else if (scope && strcmp (scope, "async") == 0)
|
|
|
|
param->scope = GI_SCOPE_TYPE_ASYNC;
|
|
|
|
else if (scope && strcmp (scope, "notified") == 0)
|
|
|
|
param->scope = GI_SCOPE_TYPE_NOTIFIED;
|
|
|
|
else
|
|
|
|
param->scope = GI_SCOPE_TYPE_INVALID;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
Bug 556489 – callback annotations
2008-01-03 Andreas Rottmann <a.rottmann@gmx.at>
Bug 556489 – callback annotations
* giscanner/transformer.py
* tools/generate.c (write_callable_info): Write out the new scope,
closure and destroy attributes.
* giscanner/transformer.py (Transformer._type_is_callback): New
method, checking if a given type is a callback.
(Transformer._augment_callback_params): New method; adds
information (closure, destroy) to callback parameters.
(Transformer._handle_closure, Transformer._handle_destroy): New methods,
auxiliary to _augment_callback_params.
(Transformer._create_function): Call _augment_callback_params().
(Transformer._create_parameter): Handle scope option.
(Transformer._create_typedef_callback): New method, creates a
callback, and registers it in the typedef namespace
(Transformer._create_typedef): Use _create_typedef_callback()
instead of the plain _create_callback().
* giscanner/ast.py (Parameter): Added callback-related fields.
* giscanner/girwriter.py: Write out new Parameter fields.
* girepository/girnode.h (GIrNodeParam): Added fields scope,
closure and destroy.
* girepository/gtypelib.h (ArgBlob): Ditto.
* girepository/girparser.c (start_parameter): Handle new fields.
* girepository/girmodule.c (g_ir_module_build_typelib): Adjust
arg_blob_size, bump major version due to this change.
* girepository/girnode.c (g_ir_node_get_full_size_internal)
(g_ir_node_build_typelib)
* girepository/gtypelib.c (g_typelib_check_sanity): ArgBlob size
adjustments.
(g_ir_node_build_typelib): Fill in new ArgBlob flags from param.
* girepository/girepository.h (GIScope): New enumeration, listing
the different possible scopes for callbacks.
* girepository/ginfo.c (g_arg_info_get_scope)
(g_arg_info_get_closure, g_arg_info_get_destroy): Accessors for
callback-related argument indices (callback scope, closure for a
callback, destroy notification for a callback).
* tests/scanner/: Added testcases for new features.
svn path=/trunk/; revision=998
2009-01-03 14:44:42 +01:00
|
|
|
param->closure = closure ? atoi (closure) : -1;
|
|
|
|
param->destroy = destroy ? atoi (destroy) : -1;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
((GIrNode *)param)->name = g_strdup (name);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
switch (CURRENT_NODE (ctx)->type)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
case G_IR_NODE_FUNCTION:
|
|
|
|
case G_IR_NODE_CALLBACK:
|
|
|
|
{
|
|
|
|
GIrNodeFunction *func;
|
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
func = (GIrNodeFunction *)CURRENT_NODE (ctx);
|
2008-08-09 14:46:48 +02:00
|
|
|
func->parameters = g_list_append (func->parameters, param);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_SIGNAL:
|
|
|
|
{
|
|
|
|
GIrNodeSignal *signal;
|
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
|
2008-08-09 14:46:48 +02:00
|
|
|
signal->parameters = g_list_append (signal->parameters, param);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_VFUNC:
|
|
|
|
{
|
|
|
|
GIrNodeVFunc *vfunc;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
|
2008-08-09 14:46:48 +02:00
|
|
|
vfunc->parameters = g_list_append (vfunc->parameters, param);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_field (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *readable;
|
|
|
|
const gchar *writable;
|
|
|
|
const gchar *bits;
|
|
|
|
const gchar *branch;
|
|
|
|
GIrNodeField *field;
|
2010-07-27 12:16:37 +02:00
|
|
|
ParseState target_state;
|
|
|
|
gboolean introspectable;
|
2008-08-24 13:01:44 +02:00
|
|
|
|
|
|
|
switch (ctx->state)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
case STATE_CLASS:
|
2010-07-27 12:16:37 +02:00
|
|
|
target_state = STATE_CLASS_FIELD;
|
|
|
|
break;
|
2008-08-24 13:01:44 +02:00
|
|
|
case STATE_BOXED:
|
2010-07-27 12:16:37 +02:00
|
|
|
target_state = STATE_BOXED_FIELD;
|
|
|
|
break;
|
2008-08-24 13:01:44 +02:00
|
|
|
case STATE_STRUCT:
|
2010-07-27 12:16:37 +02:00
|
|
|
target_state = STATE_STRUCT_FIELD;
|
|
|
|
break;
|
2008-08-24 13:01:44 +02:00
|
|
|
case STATE_UNION:
|
2010-07-27 12:16:37 +02:00
|
|
|
target_state = STATE_UNION_FIELD;
|
|
|
|
break;
|
2008-08-24 13:01:44 +02:00
|
|
|
case STATE_INTERFACE:
|
2010-07-27 12:16:37 +02:00
|
|
|
target_state = STATE_INTERFACE_FIELD;
|
2008-08-24 13:01:44 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
if (strcmp (element_name, "field") != 0)
|
|
|
|
return FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-07-27 12:16:37 +02:00
|
|
|
g_assert (ctx->state != STATE_PASSTHROUGH);
|
|
|
|
|
|
|
|
/* We handle introspectability specially here; we replace with just gpointer
|
|
|
|
* for the type.
|
|
|
|
*/
|
|
|
|
introspectable = introspectable_prelude (context, attribute_names, attribute_values, ctx, target_state);
|
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
readable = find_attribute ("readable", attribute_names, attribute_values);
|
|
|
|
writable = find_attribute ("writable", attribute_names, attribute_values);
|
|
|
|
bits = find_attribute ("bits", attribute_names, attribute_values);
|
|
|
|
branch = find_attribute ("branch", attribute_names, attribute_values);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
field = (GIrNodeField *)_g_ir_node_new (G_IR_NODE_FIELD,
|
|
|
|
ctx->current_module);
|
2010-07-27 12:16:37 +02:00
|
|
|
if (introspectable)
|
|
|
|
{
|
|
|
|
ctx->current_typed = (GIrNode*) field;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
field->type = parse_type (ctx, "gpointer");
|
|
|
|
}
|
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
((GIrNode *)field)->name = g_strdup (name);
|
2008-10-17 16:58:37 +02:00
|
|
|
/* Fields are assumed to be read-only.
|
|
|
|
* (see also girwriter.py and generate.c)
|
|
|
|
*/
|
|
|
|
field->readable = readable == NULL || strcmp (readable, "0") == 0;
|
|
|
|
field->writable = writable != NULL && strcmp (writable, "1") == 0;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
if (bits)
|
|
|
|
field->bits = atoi (bits);
|
|
|
|
else
|
|
|
|
field->bits = 0;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
switch (CURRENT_NODE (ctx)->type)
|
2008-08-24 13:01:44 +02:00
|
|
|
{
|
|
|
|
case G_IR_NODE_OBJECT:
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
2008-08-24 13:01:44 +02:00
|
|
|
iface->members = g_list_append (iface->members, field);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_INTERFACE:
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
2008-08-24 13:01:44 +02:00
|
|
|
iface->members = g_list_append (iface->members, field);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_BOXED:
|
|
|
|
{
|
|
|
|
GIrNodeBoxed *boxed;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
boxed = (GIrNodeBoxed *)CURRENT_NODE (ctx);
|
2008-08-09 14:46:48 +02:00
|
|
|
boxed->members = g_list_append (boxed->members, field);
|
2008-08-24 13:01:44 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_STRUCT:
|
|
|
|
{
|
|
|
|
GIrNodeStruct *struct_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
struct_ = (GIrNodeStruct *)CURRENT_NODE (ctx);
|
2008-08-24 13:01:44 +02:00
|
|
|
struct_->members = g_list_append (struct_->members, field);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_UNION:
|
|
|
|
{
|
|
|
|
GIrNodeUnion *union_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
union_ = (GIrNodeUnion *)CURRENT_NODE (ctx);
|
2008-08-24 13:01:44 +02:00
|
|
|
union_->members = g_list_append (union_->members, field);
|
|
|
|
if (branch)
|
|
|
|
{
|
|
|
|
GIrNodeConstant *constant;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
constant = (GIrNodeConstant *) _g_ir_node_new (G_IR_NODE_CONSTANT,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2008-08-24 13:01:44 +02:00
|
|
|
((GIrNode *)constant)->name = g_strdup (name);
|
2010-03-24 19:00:06 +01:00
|
|
|
constant->value = g_strdup (branch);
|
2008-08-24 13:01:44 +02:00
|
|
|
constant->type = union_->discriminator_type;
|
|
|
|
constant->deprecated = FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
union_->discriminators = g_list_append (union_->discriminators, constant);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2008-08-13 18:10:09 +02:00
|
|
|
static gboolean
|
|
|
|
start_alias (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
2008-08-24 13:01:44 +02:00
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-08-13 18:10:09 +02:00
|
|
|
|
2010-08-03 19:01:35 +02:00
|
|
|
ctx->current_alias = g_strdup (name);
|
|
|
|
state_switch (ctx, STATE_ALIAS);
|
2008-08-24 13:01:44 +02:00
|
|
|
|
2008-08-13 18:10:09 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
|
|
|
start_enum (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *typename;
|
|
|
|
const gchar *typeinit;
|
|
|
|
const gchar *deprecated;
|
2011-05-19 22:21:13 +02:00
|
|
|
const gchar *error_domain;
|
2010-06-17 02:34:18 +02:00
|
|
|
GIrNodeEnum *enum_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
|
|
|
|
(strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE)))
|
|
|
|
return FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_ENUM))
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
|
|
|
|
typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
|
2011-05-19 22:21:13 +02:00
|
|
|
error_domain = find_attribute ("glib:error-domain", attribute_names, attribute_values);
|
2010-06-17 02:34:18 +02:00
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (strcmp (element_name, "enumeration") == 0)
|
2010-11-16 21:08:33 +01:00
|
|
|
enum_ = (GIrNodeEnum *) _g_ir_node_new (G_IR_NODE_ENUM,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2010-06-17 02:34:18 +02:00
|
|
|
else
|
2010-11-16 21:08:33 +01:00
|
|
|
enum_ = (GIrNodeEnum *) _g_ir_node_new (G_IR_NODE_FLAGS,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2010-06-17 02:34:18 +02:00
|
|
|
((GIrNode *)enum_)->name = g_strdup (name);
|
|
|
|
enum_->gtype_name = g_strdup (typename);
|
|
|
|
enum_->gtype_init = g_strdup (typeinit);
|
2011-05-19 22:21:13 +02:00
|
|
|
enum_->error_domain = g_strdup (error_domain);
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (deprecated)
|
|
|
|
enum_->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
enum_->deprecated = FALSE;
|
2010-06-17 02:34:18 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
push_node (ctx, (GIrNode *) enum_);
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, enum_);
|
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_property (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
ParseState target_state;
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *readable;
|
|
|
|
const gchar *writable;
|
|
|
|
const gchar *construct;
|
|
|
|
const gchar *construct_only;
|
|
|
|
const gchar *transfer;
|
|
|
|
GIrNodeProperty *property;
|
|
|
|
GIrNodeInterface *iface;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "property") == 0 &&
|
|
|
|
(ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE)))
|
|
|
|
return FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (ctx->state == STATE_CLASS)
|
|
|
|
target_state = STATE_CLASS_PROPERTY;
|
|
|
|
else if (ctx->state == STATE_INTERFACE)
|
|
|
|
target_state = STATE_INTERFACE_PROPERTY;
|
|
|
|
else
|
|
|
|
g_assert_not_reached ();
|
2010-06-17 02:34:18 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, target_state))
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-08 16:40:35 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
readable = find_attribute ("readable", attribute_names, attribute_values);
|
|
|
|
writable = find_attribute ("writable", attribute_names, attribute_values);
|
|
|
|
construct = find_attribute ("construct", attribute_names, attribute_values);
|
|
|
|
construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
|
|
|
|
transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
property = (GIrNodeProperty *) _g_ir_node_new (G_IR_NODE_PROPERTY,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2010-06-17 02:34:18 +02:00
|
|
|
ctx->current_typed = (GIrNode*) property;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
((GIrNode *)property)->name = g_strdup (name);
|
2010-06-17 02:34:18 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
/* Assume properties are readable */
|
|
|
|
if (readable == NULL || strcmp (readable, "1") == 0)
|
|
|
|
property->readable = TRUE;
|
|
|
|
else
|
|
|
|
property->readable = FALSE;
|
|
|
|
if (writable && strcmp (writable, "1") == 0)
|
|
|
|
property->writable = TRUE;
|
|
|
|
else
|
|
|
|
property->writable = FALSE;
|
|
|
|
if (construct && strcmp (construct, "1") == 0)
|
|
|
|
property->construct = TRUE;
|
|
|
|
else
|
|
|
|
property->construct = FALSE;
|
|
|
|
if (construct_only && strcmp (construct_only, "1") == 0)
|
|
|
|
property->construct_only = TRUE;
|
|
|
|
else
|
|
|
|
property->construct_only = FALSE;
|
2010-06-17 02:34:18 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
parse_property_transfer (property, transfer, ctx);
|
|
|
|
|
|
|
|
iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
|
|
|
iface->members = g_list_append (iface->members, property);
|
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2010-09-14 17:59:03 +02:00
|
|
|
static gint64
|
2008-08-09 14:46:48 +02:00
|
|
|
parse_value (const gchar *str)
|
|
|
|
{
|
|
|
|
gchar *shift_op;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
/* FIXME just a quick hack */
|
|
|
|
shift_op = strstr (str, "<<");
|
|
|
|
|
|
|
|
if (shift_op)
|
|
|
|
{
|
2010-09-14 17:59:03 +02:00
|
|
|
gint64 base, shift;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-09-14 17:59:03 +02:00
|
|
|
base = g_ascii_strtoll (str, NULL, 10);
|
|
|
|
shift = g_ascii_strtoll (shift_op + 3, NULL, 10);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
return base << shift;
|
|
|
|
}
|
|
|
|
else
|
2010-09-14 17:59:03 +02:00
|
|
|
return g_ascii_strtoll (str, NULL, 10);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_member (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *value;
|
|
|
|
const gchar *deprecated;
|
2011-02-22 16:02:12 +01:00
|
|
|
const gchar *c_identifier;
|
2010-06-17 02:34:18 +02:00
|
|
|
GIrNodeEnum *enum_;
|
|
|
|
GIrNodeValue *value_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "member") == 0 &&
|
|
|
|
ctx->state == STATE_ENUM))
|
|
|
|
return FALSE;
|
2010-06-17 02:34:18 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
value = find_attribute ("value", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
2011-02-22 16:02:12 +01:00
|
|
|
c_identifier = find_attribute ("c:identifier", attribute_names, attribute_values);
|
2010-06-17 02:34:18 +02:00
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
value_ = (GIrNodeValue *) _g_ir_node_new (G_IR_NODE_VALUE,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
((GIrNode *)value_)->name = g_strdup (name);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
value_->value = parse_value (value);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (deprecated)
|
|
|
|
value_->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
value_->deprecated = FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2011-02-22 16:02:12 +01:00
|
|
|
g_hash_table_insert (((GIrNode *)value_)->attributes,
|
|
|
|
g_strdup ("c:identifier"),
|
|
|
|
g_strdup (c_identifier));
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
enum_ = (GIrNodeEnum *)CURRENT_NODE (ctx);
|
|
|
|
enum_->values = g_list_append (enum_->values, value_);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_constant (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
ParseState prev_state;
|
|
|
|
ParseState target_state;
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *value;
|
|
|
|
const gchar *deprecated;
|
|
|
|
GIrNodeConstant *constant;
|
|
|
|
|
|
|
|
if (!(strcmp (element_name, "constant") == 0 &&
|
|
|
|
(ctx->state == STATE_NAMESPACE ||
|
|
|
|
ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
switch (ctx->state)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
case STATE_NAMESPACE:
|
|
|
|
target_state = STATE_NAMESPACE_CONSTANT;
|
|
|
|
break;
|
|
|
|
case STATE_CLASS:
|
|
|
|
target_state = STATE_CLASS_CONSTANT;
|
|
|
|
break;
|
|
|
|
case STATE_INTERFACE:
|
|
|
|
target_state = STATE_INTERFACE_CONSTANT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
prev_state = ctx->state;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, target_state))
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
value = find_attribute ("value", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (value == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "value");
|
|
|
|
return FALSE;
|
|
|
|
}
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
constant = (GIrNodeConstant *) _g_ir_node_new (G_IR_NODE_CONSTANT,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
((GIrNode *)constant)->name = g_strdup (name);
|
|
|
|
constant->value = g_strdup (value);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
ctx->current_typed = (GIrNode*) constant;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (deprecated)
|
|
|
|
constant->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
constant->deprecated = FALSE;
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (prev_state == STATE_NAMESPACE)
|
|
|
|
{
|
|
|
|
push_node (ctx, (GIrNode *) constant);
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, constant);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
|
|
|
iface->members = g_list_append (iface->members, constant);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
2010-06-17 02:34:18 +02:00
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_interface (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *typename;
|
|
|
|
const gchar *typeinit;
|
|
|
|
const gchar *deprecated;
|
|
|
|
const gchar *glib_type_struct;
|
|
|
|
GIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "interface") == 0 &&
|
|
|
|
ctx->state == STATE_NAMESPACE))
|
|
|
|
return FALSE;
|
2010-06-17 14:14:04 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_INTERFACE))
|
|
|
|
return TRUE;
|
2010-06-17 14:14:04 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
|
|
|
|
typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
|
|
|
|
glib_type_struct = find_attribute ("glib:type-struct", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
2010-06-17 14:14:04 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
2010-06-17 02:34:18 +02:00
|
|
|
else if (typename == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (typeinit == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
iface = (GIrNodeInterface *) _g_ir_node_new (G_IR_NODE_INTERFACE,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2010-06-17 02:34:18 +02:00
|
|
|
((GIrNode *)iface)->name = g_strdup (name);
|
|
|
|
iface->gtype_name = g_strdup (typename);
|
|
|
|
iface->gtype_init = g_strdup (typeinit);
|
|
|
|
iface->glib_type_struct = g_strdup (glib_type_struct);
|
|
|
|
if (deprecated)
|
|
|
|
iface->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
iface->deprecated = FALSE;
|
|
|
|
|
|
|
|
push_node (ctx, (GIrNode *) iface);
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, iface);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
static gboolean
|
2008-08-09 14:46:48 +02:00
|
|
|
start_class (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *parent;
|
|
|
|
const gchar *glib_type_struct;
|
|
|
|
const gchar *typename;
|
|
|
|
const gchar *typeinit;
|
|
|
|
const gchar *deprecated;
|
|
|
|
const gchar *abstract;
|
2010-06-12 23:08:56 +02:00
|
|
|
const gchar *fundamental;
|
|
|
|
const gchar *ref_func;
|
|
|
|
const gchar *unref_func;
|
|
|
|
const gchar *set_value_func;
|
|
|
|
const gchar *get_value_func;
|
2010-06-17 02:34:18 +02:00
|
|
|
GIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "class") == 0 &&
|
|
|
|
ctx->state == STATE_NAMESPACE))
|
|
|
|
return FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_CLASS))
|
|
|
|
return TRUE;
|
2008-10-20 19:04:17 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
parent = find_attribute ("parent", attribute_names, attribute_values);
|
|
|
|
glib_type_struct = find_attribute ("glib:type-struct", attribute_names, attribute_values);
|
|
|
|
typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
|
|
|
|
typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
|
|
|
abstract = find_attribute ("abstract", attribute_names, attribute_values);
|
2010-06-12 23:08:56 +02:00
|
|
|
fundamental = find_attribute ("glib:fundamental", attribute_names, attribute_values);
|
|
|
|
ref_func = find_attribute ("glib:ref-func", attribute_names, attribute_values);
|
|
|
|
unref_func = find_attribute ("glib:unref-func", attribute_names, attribute_values);
|
|
|
|
set_value_func = find_attribute ("glib:set-value-func", attribute_names, attribute_values);
|
|
|
|
get_value_func = find_attribute ("glib:get-value-func", attribute_names, attribute_values);
|
2008-10-20 19:04:17 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (typename == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (typeinit == NULL && strcmp (typename, "GObject"))
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
iface = (GIrNodeInterface *) _g_ir_node_new (G_IR_NODE_OBJECT,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2010-06-17 02:34:18 +02:00
|
|
|
((GIrNode *)iface)->name = g_strdup (name);
|
|
|
|
iface->gtype_name = g_strdup (typename);
|
|
|
|
iface->gtype_init = g_strdup (typeinit);
|
|
|
|
iface->parent = g_strdup (parent);
|
|
|
|
iface->glib_type_struct = g_strdup (glib_type_struct);
|
|
|
|
if (deprecated)
|
|
|
|
iface->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
iface->deprecated = FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
iface->abstract = abstract && strcmp (abstract, "1") == 0;
|
2010-06-17 02:34:18 +02:00
|
|
|
|
2010-09-27 11:52:55 +02:00
|
|
|
if (fundamental)
|
|
|
|
iface->fundamental = TRUE;
|
2010-06-12 23:08:56 +02:00
|
|
|
if (ref_func)
|
|
|
|
iface->ref_func = g_strdup (ref_func);
|
|
|
|
if (unref_func)
|
|
|
|
iface->unref_func = g_strdup (unref_func);
|
|
|
|
if (set_value_func)
|
|
|
|
iface->set_value_func = g_strdup (set_value_func);
|
|
|
|
if (get_value_func)
|
|
|
|
iface->get_value_func = g_strdup (get_value_func);
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
push_node (ctx, (GIrNode *) iface);
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, iface);
|
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_type (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
2008-09-01 20:52:34 +02:00
|
|
|
const gchar *ctype;
|
2010-08-03 19:01:35 +02:00
|
|
|
gboolean in_alias = FALSE;
|
2008-09-29 21:03:44 +02:00
|
|
|
gboolean is_array;
|
2008-10-02 16:07:38 +02:00
|
|
|
gboolean is_varargs;
|
2008-09-01 20:52:34 +02:00
|
|
|
GIrNodeType *typenode;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
is_array = strcmp (element_name, "array") == 0;
|
2008-10-02 16:07:38 +02:00
|
|
|
is_varargs = strcmp (element_name, "varargs") == 0;
|
2008-09-29 21:03:44 +02:00
|
|
|
|
2008-10-02 16:07:38 +02:00
|
|
|
if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
|
2008-08-09 14:46:48 +02:00
|
|
|
return FALSE;
|
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
if (ctx->state == STATE_TYPE)
|
2008-09-29 21:03:44 +02:00
|
|
|
{
|
|
|
|
ctx->type_depth++;
|
|
|
|
ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
|
|
|
|
ctx->type_parameters = NULL;
|
2010-03-24 19:00:06 +01:00
|
|
|
}
|
2008-08-22 22:05:23 +02:00
|
|
|
else if (ctx->state == STATE_FUNCTION_PARAMETER ||
|
2010-03-24 19:00:06 +01:00
|
|
|
ctx->state == STATE_FUNCTION_RETURN ||
|
2008-08-22 22:05:23 +02:00
|
|
|
ctx->state == STATE_STRUCT_FIELD ||
|
|
|
|
ctx->state == STATE_UNION_FIELD ||
|
|
|
|
ctx->state == STATE_CLASS_PROPERTY ||
|
|
|
|
ctx->state == STATE_CLASS_FIELD ||
|
|
|
|
ctx->state == STATE_INTERFACE_FIELD ||
|
|
|
|
ctx->state == STATE_INTERFACE_PROPERTY ||
|
|
|
|
ctx->state == STATE_BOXED_FIELD ||
|
|
|
|
ctx->state == STATE_NAMESPACE_CONSTANT ||
|
|
|
|
ctx->state == STATE_CLASS_CONSTANT ||
|
2010-08-03 19:01:35 +02:00
|
|
|
ctx->state == STATE_INTERFACE_CONSTANT ||
|
|
|
|
ctx->state == STATE_ALIAS
|
2008-08-22 22:05:23 +02:00
|
|
|
)
|
|
|
|
{
|
2010-08-03 19:01:35 +02:00
|
|
|
if (ctx->state == STATE_ALIAS)
|
|
|
|
in_alias = TRUE;
|
2008-08-22 22:05:23 +02:00
|
|
|
state_switch (ctx, STATE_TYPE);
|
|
|
|
ctx->type_depth = 1;
|
2008-09-29 21:03:44 +02:00
|
|
|
ctx->type_stack = NULL;
|
|
|
|
ctx->type_parameters = NULL;
|
2008-08-22 22:05:23 +02:00
|
|
|
}
|
|
|
|
|
2010-08-03 19:01:35 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (in_alias && ctx->current_alias)
|
|
|
|
{
|
|
|
|
char *key;
|
|
|
|
char *value;
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
key = g_strdup_printf ("%s.%s", ctx->namespace, ctx->current_alias);
|
|
|
|
if (!strchr (name, '.'))
|
|
|
|
{
|
|
|
|
const BasicTypeInfo *basic = parse_basic (name);
|
|
|
|
if (!basic)
|
|
|
|
{
|
|
|
|
/* For non-basic types, re-qualify the interface */
|
|
|
|
value = g_strdup_printf ("%s.%s", ctx->namespace, name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
value = g_strdup (name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
value = g_strdup (name);
|
|
|
|
|
|
|
|
g_hash_table_replace (ctx->aliases, key, value);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if (!ctx->current_module || in_alias)
|
|
|
|
return TRUE;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
if (!ctx->current_typed)
|
|
|
|
{
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"The element <type> is invalid here");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-10-02 16:07:38 +02:00
|
|
|
if (is_varargs)
|
|
|
|
return TRUE;
|
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
if (is_array)
|
2008-09-29 21:03:44 +02:00
|
|
|
{
|
|
|
|
const char *zero;
|
|
|
|
const char *len;
|
2008-10-25 17:20:54 +02:00
|
|
|
const char *size;
|
2008-09-29 21:03:44 +02:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
typenode = (GIrNodeType *)_g_ir_node_new (G_IR_NODE_TYPE,
|
|
|
|
ctx->current_module);
|
2008-09-01 20:52:34 +02:00
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
typenode->tag = GI_TYPE_TAG_ARRAY;
|
|
|
|
typenode->is_pointer = TRUE;
|
|
|
|
typenode->is_array = TRUE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-05-04 16:57:51 +02:00
|
|
|
if (name && strcmp (name, "GLib.Array") == 0) {
|
|
|
|
typenode->array_type = GI_ARRAY_TYPE_ARRAY;
|
|
|
|
} else if (name && strcmp (name, "GLib.ByteArray") == 0) {
|
|
|
|
typenode->array_type = GI_ARRAY_TYPE_BYTE_ARRAY;
|
|
|
|
} else if (name && strcmp (name, "GLib.PtrArray") == 0) {
|
|
|
|
typenode->array_type = GI_ARRAY_TYPE_PTR_ARRAY;
|
|
|
|
} else {
|
|
|
|
typenode->array_type = GI_ARRAY_TYPE_C;
|
|
|
|
}
|
2010-05-03 19:17:00 +02:00
|
|
|
|
2010-05-04 16:57:51 +02:00
|
|
|
if (typenode->array_type == GI_ARRAY_TYPE_C) {
|
|
|
|
zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
|
|
|
|
len = find_attribute ("length", attribute_names, attribute_values);
|
|
|
|
size = find_attribute ("fixed-size", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
typenode->has_length = len != NULL;
|
|
|
|
typenode->length = typenode->has_length ? atoi (len) : -1;
|
|
|
|
|
|
|
|
typenode->has_size = size != NULL;
|
|
|
|
typenode->size = typenode->has_size ? atoi (size) : -1;
|
|
|
|
|
|
|
|
if (zero)
|
|
|
|
typenode->zero_terminated = strcmp(zero, "1") == 0;
|
|
|
|
else
|
|
|
|
/* If neither zero-terminated nor length nor fixed-size is given, assume zero-terminated. */
|
|
|
|
typenode->zero_terminated = !(typenode->has_length || typenode->has_size);
|
2010-06-02 19:36:59 +02:00
|
|
|
|
|
|
|
if (typenode->has_size && ctx->current_typed->type == G_IR_NODE_FIELD)
|
|
|
|
typenode->is_pointer = FALSE;
|
2010-05-04 16:57:51 +02:00
|
|
|
} else {
|
|
|
|
typenode->zero_terminated = FALSE;
|
|
|
|
typenode->has_length = FALSE;
|
|
|
|
typenode->length = -1;
|
|
|
|
typenode->has_size = FALSE;
|
|
|
|
typenode->size = -1;
|
|
|
|
}
|
2008-09-29 21:03:44 +02:00
|
|
|
}
|
2008-09-01 20:52:34 +02:00
|
|
|
else
|
2008-09-29 21:03:44 +02:00
|
|
|
{
|
2008-11-16 21:58:35 +01:00
|
|
|
int pointer_depth;
|
2008-09-29 21:03:44 +02:00
|
|
|
|
|
|
|
if (name == NULL)
|
2010-07-26 22:26:46 +02:00
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-11-16 21:58:35 +01:00
|
|
|
pointer_depth = 0;
|
2008-09-29 21:03:44 +02:00
|
|
|
ctype = find_attribute ("c:type", attribute_names, attribute_values);
|
2008-11-16 21:58:35 +01:00
|
|
|
if (ctype != NULL)
|
|
|
|
{
|
|
|
|
const char *cp = ctype + strlen(ctype) - 1;
|
|
|
|
while (cp > ctype && *cp-- == '*')
|
|
|
|
pointer_depth++;
|
2011-09-12 19:54:39 +02:00
|
|
|
|
|
|
|
if (g_str_has_prefix (ctype, "gpointer")
|
|
|
|
|| g_str_has_prefix (ctype, "gconstpointer"))
|
|
|
|
pointer_depth++;
|
2008-11-16 21:58:35 +01:00
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-11-16 21:58:35 +01:00
|
|
|
if (ctx->current_typed->type == G_IR_NODE_PARAM &&
|
|
|
|
((GIrNodeParam *)ctx->current_typed)->out &&
|
|
|
|
pointer_depth > 0)
|
|
|
|
pointer_depth--;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
typenode = parse_type (ctx, name);
|
|
|
|
|
2008-11-11 00:58:49 +01:00
|
|
|
/* A 'disguised' structure is one where the c:type is a typedef that
|
|
|
|
* doesn't look like a pointer, but is internally.
|
|
|
|
*/
|
|
|
|
if (typenode->tag == GI_TYPE_TAG_INTERFACE &&
|
2012-07-24 10:09:38 +02:00
|
|
|
is_disguised_structure (ctx, typenode->giinterface))
|
2008-11-16 21:58:35 +01:00
|
|
|
pointer_depth++;
|
2008-11-11 00:58:49 +01:00
|
|
|
|
2008-11-16 21:58:35 +01:00
|
|
|
if (pointer_depth > 0)
|
|
|
|
typenode->is_pointer = TRUE;
|
2008-09-29 21:03:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
end_type_top (ParseContext *ctx)
|
|
|
|
{
|
2008-10-02 16:07:38 +02:00
|
|
|
GIrNodeType *typenode;
|
|
|
|
|
|
|
|
if (!ctx->type_parameters)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
typenode = (GIrNodeType*)ctx->type_parameters->data;
|
2008-09-29 21:03:44 +02:00
|
|
|
|
|
|
|
/* Default to pointer for unspecified containers */
|
|
|
|
if (typenode->tag == GI_TYPE_TAG_ARRAY ||
|
|
|
|
typenode->tag == GI_TYPE_TAG_GLIST ||
|
|
|
|
typenode->tag == GI_TYPE_TAG_GSLIST)
|
|
|
|
{
|
2008-09-29 21:03:46 +02:00
|
|
|
if (typenode->parameter_type1 == NULL)
|
2010-07-22 03:06:17 +02:00
|
|
|
typenode->parameter_type1 = parse_type (ctx, "gpointer");
|
2008-09-29 21:03:44 +02:00
|
|
|
}
|
|
|
|
else if (typenode->tag == GI_TYPE_TAG_GHASH)
|
|
|
|
{
|
2008-09-29 21:03:46 +02:00
|
|
|
if (typenode->parameter_type1 == NULL)
|
|
|
|
{
|
2010-07-22 03:06:17 +02:00
|
|
|
typenode->parameter_type1 = parse_type (ctx, "gpointer");
|
|
|
|
typenode->parameter_type2 = parse_type (ctx, "gpointer");
|
2008-09-29 21:03:46 +02:00
|
|
|
}
|
2008-09-29 21:03:44 +02:00
|
|
|
}
|
2008-09-01 20:52:34 +02:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
switch (ctx->current_typed->type)
|
|
|
|
{
|
|
|
|
case G_IR_NODE_PARAM:
|
|
|
|
{
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
|
2008-09-01 20:52:34 +02:00
|
|
|
param->type = typenode;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_FIELD:
|
|
|
|
{
|
|
|
|
GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
|
2008-09-01 20:52:34 +02:00
|
|
|
field->type = typenode;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_PROPERTY:
|
|
|
|
{
|
|
|
|
GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
|
2008-09-01 20:52:34 +02:00
|
|
|
property->type = typenode;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
case G_IR_NODE_CONSTANT:
|
|
|
|
{
|
|
|
|
GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
|
2008-09-01 20:52:34 +02:00
|
|
|
constant->type = typenode;
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
}
|
|
|
|
break;
|
2008-08-09 14:46:48 +02:00
|
|
|
default:
|
2009-02-04 01:48:17 +01:00
|
|
|
g_printerr("current node is %d\n", CURRENT_NODE (ctx)->type);
|
2008-08-09 14:46:48 +02:00
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
2008-09-29 21:03:44 +02:00
|
|
|
g_list_free (ctx->type_parameters);
|
2008-10-02 16:07:38 +02:00
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
out:
|
2008-09-29 21:03:44 +02:00
|
|
|
ctx->type_depth = 0;
|
|
|
|
ctx->type_parameters = NULL;
|
|
|
|
ctx->current_typed = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
end_type_recurse (ParseContext *ctx)
|
|
|
|
{
|
|
|
|
GIrNodeType *parent;
|
2008-10-16 00:08:26 +02:00
|
|
|
GIrNodeType *param = NULL;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
|
2008-10-16 00:08:26 +02:00
|
|
|
if (ctx->type_parameters)
|
|
|
|
param = (GIrNodeType *) ctx->type_parameters->data;
|
2008-09-01 20:52:34 +02:00
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
if (parent->tag == GI_TYPE_TAG_ARRAY ||
|
|
|
|
parent->tag == GI_TYPE_TAG_GLIST ||
|
|
|
|
parent->tag == GI_TYPE_TAG_GSLIST)
|
|
|
|
{
|
2008-10-16 00:08:26 +02:00
|
|
|
g_assert (param != NULL);
|
|
|
|
|
|
|
|
if (parent->parameter_type1 == NULL)
|
|
|
|
parent->parameter_type1 = param;
|
2008-09-29 21:03:44 +02:00
|
|
|
else
|
2008-10-16 00:08:26 +02:00
|
|
|
g_assert_not_reached ();
|
2008-09-29 21:03:44 +02:00
|
|
|
}
|
|
|
|
else if (parent->tag == GI_TYPE_TAG_GHASH)
|
|
|
|
{
|
2008-10-16 00:08:26 +02:00
|
|
|
g_assert (param != NULL);
|
|
|
|
|
|
|
|
if (parent->parameter_type1 == NULL)
|
|
|
|
parent->parameter_type1 = param;
|
|
|
|
else if (parent->parameter_type2 == NULL)
|
|
|
|
parent->parameter_type2 = param;
|
2008-09-29 21:03:44 +02:00
|
|
|
else
|
2008-10-16 00:08:26 +02:00
|
|
|
g_assert_not_reached ();
|
2008-09-29 21:03:44 +02:00
|
|
|
}
|
|
|
|
g_list_free (ctx->type_parameters);
|
|
|
|
ctx->type_parameters = (GList *)ctx->type_stack->data;
|
|
|
|
ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
end_type (ParseContext *ctx)
|
|
|
|
{
|
|
|
|
if (ctx->type_depth == 1)
|
|
|
|
{
|
|
|
|
end_type_top (ctx);
|
|
|
|
state_switch (ctx, ctx->prev_state);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
end_type_recurse (ctx);
|
|
|
|
ctx->type_depth--;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2009-02-20 03:48:51 +01:00
|
|
|
static gboolean
|
|
|
|
start_attribute (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *value;
|
|
|
|
GIrNode *curnode;
|
|
|
|
|
|
|
|
if (strcmp (element_name, "attribute") != 0 || ctx->node_stack == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
value = find_attribute ("value", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (value == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "value");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_ATTRIBUTE);
|
|
|
|
|
|
|
|
curnode = CURRENT_NODE (ctx);
|
|
|
|
|
2010-06-15 17:01:37 +02:00
|
|
|
if (ctx->current_typed && ctx->current_typed->type == G_IR_NODE_PARAM)
|
|
|
|
{
|
|
|
|
g_hash_table_insert (ctx->current_typed->attributes, g_strdup (name), g_strdup (value));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_hash_table_insert (curnode->attributes, g_strdup (name), g_strdup (value));
|
|
|
|
}
|
2009-02-20 03:48:51 +01:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
|
|
|
start_return_value (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
GIrNodeParam *param;
|
|
|
|
const gchar *transfer;
|
2011-05-13 18:20:05 +02:00
|
|
|
const gchar *skip;
|
2014-04-16 17:39:09 +02:00
|
|
|
const gchar *nullable;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "return-value") == 0 &&
|
|
|
|
ctx->state == STATE_FUNCTION))
|
|
|
|
return FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
param = (GIrNodeParam *)_g_ir_node_new (G_IR_NODE_PARAM,
|
|
|
|
ctx->current_module);
|
2010-06-17 02:34:18 +02:00
|
|
|
param->in = FALSE;
|
|
|
|
param->out = FALSE;
|
|
|
|
param->retval = TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
ctx->current_typed = (GIrNode*) param;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
state_switch (ctx, STATE_FUNCTION_RETURN);
|
2008-10-12 23:07:33 +02:00
|
|
|
|
2011-05-13 18:20:05 +02:00
|
|
|
skip = find_attribute ("skip", attribute_names, attribute_values);
|
|
|
|
if (skip && strcmp (skip, "1") == 0)
|
|
|
|
param->skip = TRUE;
|
|
|
|
else
|
|
|
|
param->skip = FALSE;
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
|
2010-07-27 12:16:37 +02:00
|
|
|
if (!parse_param_transfer (param, transfer, NULL, error))
|
|
|
|
return FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2014-04-16 17:39:09 +02:00
|
|
|
nullable = find_attribute ("nullable", attribute_names, attribute_values);
|
|
|
|
if (nullable && g_str_equal (nullable, "1"))
|
|
|
|
param->nullable = TRUE;
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
switch (CURRENT_NODE (ctx)->type)
|
|
|
|
{
|
|
|
|
case G_IR_NODE_FUNCTION:
|
|
|
|
case G_IR_NODE_CALLBACK:
|
|
|
|
{
|
|
|
|
GIrNodeFunction *func = (GIrNodeFunction *)CURRENT_NODE (ctx);
|
|
|
|
func->result = param;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_SIGNAL:
|
|
|
|
{
|
|
|
|
GIrNodeSignal *signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
|
|
|
|
signal->result = param;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_VFUNC:
|
|
|
|
{
|
|
|
|
GIrNodeVFunc *vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
|
|
|
|
vfunc->result = param;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2008-08-25 17:22:39 +02:00
|
|
|
static gboolean
|
|
|
|
start_implements (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
if (strcmp (element_name, "implements") != 0 ||
|
|
|
|
!(ctx->state == STATE_CLASS))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_IMPLEMENTS);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-25 17:22:39 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
2008-08-25 17:22:39 +02:00
|
|
|
iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
|
|
|
start_glib_signal (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *when;
|
|
|
|
const gchar *no_recurse;
|
|
|
|
const gchar *detailed;
|
|
|
|
const gchar *action;
|
|
|
|
const gchar *no_hooks;
|
|
|
|
const gchar *has_class_closure;
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
GIrNodeSignal *signal;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "glib:signal") == 0 &&
|
|
|
|
(ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE)))
|
|
|
|
return FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_FUNCTION))
|
|
|
|
return TRUE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
when = find_attribute ("when", attribute_names, attribute_values);
|
|
|
|
no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
|
|
|
|
detailed = find_attribute ("detailed", attribute_names, attribute_values);
|
|
|
|
action = find_attribute ("action", attribute_names, attribute_values);
|
|
|
|
no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
|
|
|
|
has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-11-16 21:08:33 +01:00
|
|
|
signal = (GIrNodeSignal *)_g_ir_node_new (G_IR_NODE_SIGNAL,
|
|
|
|
ctx->current_module);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
((GIrNode *)signal)->name = g_strdup (name);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
signal->run_first = FALSE;
|
|
|
|
signal->run_last = FALSE;
|
|
|
|
signal->run_cleanup = FALSE;
|
2013-10-05 10:40:20 +02:00
|
|
|
if (when == NULL || g_ascii_strcasecmp (when, "LAST") == 0)
|
2010-06-17 02:34:18 +02:00
|
|
|
signal->run_last = TRUE;
|
2013-10-05 10:40:20 +02:00
|
|
|
else if (g_ascii_strcasecmp (when, "FIRST") == 0)
|
2010-06-17 02:34:18 +02:00
|
|
|
signal->run_first = TRUE;
|
|
|
|
else
|
|
|
|
signal->run_cleanup = TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (no_recurse && strcmp (no_recurse, "1") == 0)
|
|
|
|
signal->no_recurse = TRUE;
|
|
|
|
else
|
|
|
|
signal->no_recurse = FALSE;
|
|
|
|
if (detailed && strcmp (detailed, "1") == 0)
|
|
|
|
signal->detailed = TRUE;
|
|
|
|
else
|
|
|
|
signal->detailed = FALSE;
|
|
|
|
if (action && strcmp (action, "1") == 0)
|
|
|
|
signal->action = TRUE;
|
|
|
|
else
|
|
|
|
signal->action = FALSE;
|
|
|
|
if (no_hooks && strcmp (no_hooks, "1") == 0)
|
|
|
|
signal->no_hooks = TRUE;
|
|
|
|
else
|
|
|
|
signal->no_hooks = FALSE;
|
|
|
|
if (has_class_closure && strcmp (has_class_closure, "1") == 0)
|
|
|
|
signal->has_class_closure = TRUE;
|
|
|
|
else
|
|
|
|
signal->has_class_closure = FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
|
|
|
iface->members = g_list_append (iface->members, signal);
|
2010-06-17 02:34:18 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
push_node (ctx, (GIrNode *)signal);
|
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_vfunc (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *must_chain_up;
|
|
|
|
const gchar *override;
|
|
|
|
const gchar *is_class_closure;
|
|
|
|
const gchar *offset;
|
|
|
|
const gchar *invoker;
|
2012-02-03 19:20:00 +01:00
|
|
|
const gchar *throws;
|
2010-06-17 02:34:18 +02:00
|
|
|
GIrNodeInterface *iface;
|
|
|
|
GIrNodeVFunc *vfunc;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "virtual-method") == 0 &&
|
|
|
|
(ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE)))
|
|
|
|
return FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_FUNCTION))
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
|
|
|
|
override = find_attribute ("override", attribute_names, attribute_values);
|
|
|
|
is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
|
|
|
|
offset = find_attribute ("offset", attribute_names, attribute_values);
|
|
|
|
invoker = find_attribute ("invoker", attribute_names, attribute_values);
|
2012-02-03 19:20:00 +01:00
|
|
|
throws = find_attribute ("throws", attribute_names, attribute_values);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
vfunc = (GIrNodeVFunc *)_g_ir_node_new (G_IR_NODE_VFUNC,
|
|
|
|
ctx->current_module);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
((GIrNode *)vfunc)->name = g_strdup (name);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (must_chain_up && strcmp (must_chain_up, "1") == 0)
|
|
|
|
vfunc->must_chain_up = TRUE;
|
|
|
|
else
|
|
|
|
vfunc->must_chain_up = FALSE;
|
2009-02-28 01:02:48 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (override && strcmp (override, "always") == 0)
|
|
|
|
{
|
|
|
|
vfunc->must_be_implemented = TRUE;
|
|
|
|
vfunc->must_not_be_implemented = FALSE;
|
|
|
|
}
|
|
|
|
else if (override && strcmp (override, "never") == 0)
|
|
|
|
{
|
|
|
|
vfunc->must_be_implemented = FALSE;
|
|
|
|
vfunc->must_not_be_implemented = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vfunc->must_be_implemented = FALSE;
|
|
|
|
vfunc->must_not_be_implemented = FALSE;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (is_class_closure && strcmp (is_class_closure, "1") == 0)
|
|
|
|
vfunc->is_class_closure = TRUE;
|
|
|
|
else
|
|
|
|
vfunc->is_class_closure = FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2012-02-03 19:20:00 +01:00
|
|
|
if (throws && strcmp (throws, "1") == 0)
|
|
|
|
vfunc->throws = TRUE;
|
|
|
|
else
|
|
|
|
vfunc->throws = FALSE;
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (offset)
|
|
|
|
vfunc->offset = atoi (offset);
|
|
|
|
else
|
2010-08-29 22:48:54 +02:00
|
|
|
vfunc->offset = 0xFFFF;
|
2010-06-17 02:34:18 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
vfunc->invoker = g_strdup (invoker);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
|
|
|
iface->members = g_list_append (iface->members, vfunc);
|
|
|
|
|
|
|
|
push_node (ctx, (GIrNode *)vfunc);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
2010-06-17 14:14:04 +02:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
|
|
|
start_struct (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *deprecated;
|
|
|
|
const gchar *disguised;
|
|
|
|
const gchar *gtype_name;
|
|
|
|
const gchar *gtype_init;
|
|
|
|
const gchar *gtype_struct;
|
|
|
|
const gchar *foreign;
|
|
|
|
GIrNodeStruct *struct_;
|
|
|
|
|
|
|
|
if (!(strcmp (element_name, "record") == 0 &&
|
|
|
|
(ctx->state == STATE_NAMESPACE ||
|
|
|
|
ctx->state == STATE_UNION ||
|
|
|
|
ctx->state == STATE_STRUCT ||
|
|
|
|
ctx->state == STATE_CLASS)))
|
|
|
|
return FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_STRUCT))
|
|
|
|
return TRUE;
|
2008-09-06 22:33:51 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
|
|
|
disguised = find_attribute ("disguised", attribute_names, attribute_values);
|
|
|
|
gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
|
|
|
|
gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
|
|
|
|
gtype_struct = find_attribute ("glib:is-gtype-struct-for", attribute_names, attribute_values);
|
|
|
|
foreign = find_attribute ("foreign", attribute_names, attribute_values);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (name == NULL && ctx->node_stack == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if ((gtype_name == NULL && gtype_init != NULL))
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if ((gtype_name != NULL && gtype_init == NULL))
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
struct_ = (GIrNodeStruct *) _g_ir_node_new (G_IR_NODE_STRUCT,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
((GIrNode *)struct_)->name = g_strdup (name ? name : "");
|
|
|
|
if (deprecated)
|
|
|
|
struct_->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
struct_->deprecated = FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (disguised && strcmp (disguised, "1") == 0)
|
|
|
|
struct_->disguised = TRUE;
|
2008-11-11 00:58:49 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
struct_->is_gtype_struct = gtype_struct != NULL;
|
2009-02-04 01:48:24 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
struct_->gtype_name = g_strdup (gtype_name);
|
|
|
|
struct_->gtype_init = g_strdup (gtype_init);
|
2010-03-26 03:12:12 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
struct_->foreign = (g_strcmp0 (foreign, "1") == 0);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (ctx->node_stack == NULL)
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, struct_);
|
|
|
|
push_node (ctx, (GIrNode *)struct_);
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
|
|
|
start_union (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *deprecated;
|
|
|
|
const gchar *typename;
|
|
|
|
const gchar *typeinit;
|
|
|
|
GIrNodeUnion *union_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "union") == 0 &&
|
|
|
|
(ctx->state == STATE_NAMESPACE ||
|
|
|
|
ctx->state == STATE_UNION ||
|
|
|
|
ctx->state == STATE_STRUCT ||
|
|
|
|
ctx->state == STATE_CLASS)))
|
|
|
|
return FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_UNION))
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
|
|
|
typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
|
|
|
|
typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (name == NULL && ctx->node_stack == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
union_ = (GIrNodeUnion *) _g_ir_node_new (G_IR_NODE_UNION,
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->current_module);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
((GIrNode *)union_)->name = g_strdup (name ? name : "");
|
|
|
|
union_->gtype_name = g_strdup (typename);
|
|
|
|
union_->gtype_init = g_strdup (typeinit);
|
|
|
|
if (deprecated)
|
|
|
|
union_->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
union_->deprecated = FALSE;
|
|
|
|
|
|
|
|
if (ctx->node_stack == NULL)
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, union_);
|
|
|
|
push_node (ctx, (GIrNode *)union_);
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_discriminator (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
const gchar *type;
|
|
|
|
const gchar *offset;
|
|
|
|
if (!(strcmp (element_name, "discriminator") == 0 &&
|
|
|
|
ctx->state == STATE_UNION))
|
|
|
|
return FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
type = find_attribute ("type", attribute_names, attribute_values);
|
|
|
|
offset = find_attribute ("offset", attribute_names, attribute_values);
|
|
|
|
if (type == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "type");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (offset == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "offset");
|
|
|
|
return FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
((GIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_type
|
|
|
|
= parse_type (ctx, type);
|
|
|
|
((GIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_offset
|
|
|
|
= atoi (offset);
|
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
|
|
|
|
static gboolean
|
|
|
|
parse_include (GMarkupParseContext *context,
|
|
|
|
ParseContext *ctx,
|
|
|
|
const char *name,
|
2010-06-17 02:34:18 +02:00
|
|
|
const char *version)
|
2008-08-28 23:19:22 +02:00
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
GError *error = NULL;
|
2008-08-28 23:19:22 +02:00
|
|
|
gchar *buffer;
|
|
|
|
gsize length;
|
2009-03-28 13:34:36 +01:00
|
|
|
gchar *girpath, *girname;
|
2010-07-26 22:26:46 +02:00
|
|
|
GIrModule *module;
|
2008-11-11 01:48:17 +01:00
|
|
|
GList *l;
|
|
|
|
|
2008-11-12 18:17:15 +01:00
|
|
|
for (l = ctx->parser->parsed_modules; l; l = l->next)
|
2008-11-11 01:48:17 +01:00
|
|
|
{
|
|
|
|
GIrModule *m = l->data;
|
|
|
|
|
|
|
|
if (strcmp (m->name, name) == 0)
|
|
|
|
{
|
|
|
|
if (strcmp (m->version, version) == 0)
|
|
|
|
{
|
2008-11-12 18:17:15 +01:00
|
|
|
ctx->include_modules = g_list_prepend (ctx->include_modules, m);
|
|
|
|
|
2008-11-11 01:48:17 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
g_printerr ("Module '%s' imported with conflicting versions '%s' and '%s'\n",
|
|
|
|
name, m->version, version);
|
2008-11-11 01:48:17 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-28 13:34:36 +01:00
|
|
|
girname = g_strdup_printf ("%s-%s.gir", name, version);
|
|
|
|
girpath = locate_gir (ctx->parser, girname);
|
2008-08-28 23:19:22 +02:00
|
|
|
|
|
|
|
if (girpath == NULL)
|
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
g_printerr ("Could not find GIR file '%s'; check XDG_DATA_DIRS or use --includedir\n",
|
2009-03-28 13:34:36 +01:00
|
|
|
girname);
|
|
|
|
g_free (girname);
|
2008-08-28 23:19:22 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
2009-03-28 13:34:36 +01:00
|
|
|
g_free (girname);
|
2008-08-28 23:19:22 +02:00
|
|
|
|
2010-07-26 22:26:46 +02:00
|
|
|
g_debug ("Parsing include %s\n", girpath);
|
2008-08-28 23:19:22 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!g_file_get_contents (girpath, &buffer, &length, &error))
|
2008-08-28 23:19:22 +02:00
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
g_printerr ("%s: %s\n", girpath, error->message);
|
|
|
|
g_clear_error (&error);
|
2010-06-17 02:34:18 +02:00
|
|
|
g_free (girpath);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-11-11 01:48:17 +01:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
module = _g_ir_parser_parse_string (ctx->parser, name, girpath, buffer, length, &error);
|
2010-06-17 02:34:18 +02:00
|
|
|
g_free (buffer);
|
|
|
|
if (error != NULL)
|
|
|
|
{
|
|
|
|
int line_number, char_number;
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
|
|
g_printerr ("%s:%d:%d: error: %s\n", girpath, line_number, char_number, error->message);
|
|
|
|
g_clear_error (&error);
|
|
|
|
g_free (girpath);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
g_free (girpath);
|
2010-06-17 14:14:04 +02:00
|
|
|
|
2010-07-26 22:26:46 +02:00
|
|
|
ctx->include_modules = g_list_append (ctx->include_modules,
|
|
|
|
module);
|
2008-11-11 01:48:17 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
return TRUE;
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
extern GLogLevelFlags logged_levels;
|
|
|
|
|
|
|
|
static void
|
|
|
|
start_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
ParseContext *ctx = user_data;
|
|
|
|
gint line_number, char_number;
|
|
|
|
|
|
|
|
if (logged_levels & G_LOG_LEVEL_DEBUG)
|
|
|
|
{
|
|
|
|
GString *tags = g_string_new ("");
|
|
|
|
int i;
|
|
|
|
for (i = 0; attribute_names[i]; i++)
|
|
|
|
g_string_append_printf (tags, "%s=\"%s\" ",
|
|
|
|
attribute_names[i],
|
|
|
|
attribute_values[i]);
|
|
|
|
|
|
|
|
if (i)
|
|
|
|
{
|
|
|
|
g_string_insert_c (tags, 0, ' ');
|
|
|
|
g_string_truncate (tags, tags->len - 1);
|
|
|
|
}
|
|
|
|
g_debug ("<%s%s>", element_name, tags->str);
|
|
|
|
g_string_free (tags, TRUE);
|
|
|
|
}
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (ctx->state == STATE_PASSTHROUGH)
|
|
|
|
{
|
|
|
|
ctx->unknown_depth += 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
switch (element_name[0])
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-13 18:10:09 +02:00
|
|
|
case 'a':
|
2010-03-24 19:00:06 +01:00
|
|
|
if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
|
2008-08-13 18:10:09 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_ALIAS);
|
|
|
|
goto out;
|
|
|
|
}
|
2008-09-29 21:03:44 +02:00
|
|
|
if (start_type (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2009-02-20 03:48:51 +01:00
|
|
|
else if (start_attribute (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-13 18:10:09 +02:00
|
|
|
break;
|
2008-08-09 14:46:48 +02:00
|
|
|
case 'b':
|
2010-03-24 19:00:06 +01:00
|
|
|
if (start_enum (context, element_name,
|
2008-08-09 14:46:48 +02:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case 'c':
|
2010-03-24 19:00:06 +01:00
|
|
|
if (start_function (context, element_name,
|
2008-08-09 14:46:48 +02:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
else if (start_constant (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2010-03-24 19:00:06 +01:00
|
|
|
else if (start_class (context, element_name,
|
2008-08-09 14:46:48 +02:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'd':
|
2010-03-24 19:00:06 +01:00
|
|
|
if (start_discriminator (context, element_name,
|
2008-08-09 14:46:48 +02:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2013-05-21 10:47:11 +02:00
|
|
|
if (strcmp ("doc", element_name) == 0 || strcmp ("doc-deprecated", element_name) == 0 ||
|
|
|
|
strcmp ("doc-stability", element_name) == 0 || strcmp ("doc-version", element_name) == 0)
|
2013-02-01 04:59:23 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_PASSTHROUGH);
|
|
|
|
goto out;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'e':
|
2010-03-24 19:00:06 +01:00
|
|
|
if (start_enum (context, element_name,
|
2008-08-09 14:46:48 +02:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'f':
|
2010-03-24 19:00:06 +01:00
|
|
|
if (start_function (context, element_name,
|
2008-08-09 14:46:48 +02:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2010-03-24 19:00:06 +01:00
|
|
|
else if (start_field (context, element_name,
|
2008-08-09 14:46:48 +02:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'g':
|
|
|
|
if (start_glib_boxed (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
else if (start_glib_signal (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'i':
|
2008-08-23 18:11:01 +02:00
|
|
|
if (strcmp (element_name, "include") == 0 &&
|
|
|
|
ctx->state == STATE_REPOSITORY)
|
|
|
|
{
|
2008-08-28 23:19:22 +02:00
|
|
|
const gchar *name;
|
2008-10-16 03:40:29 +02:00
|
|
|
const gchar *version;
|
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
2008-10-16 03:40:29 +02:00
|
|
|
version = find_attribute ("version", attribute_names, attribute_values);
|
2008-08-28 23:19:22 +02:00
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
break;
|
|
|
|
}
|
2008-10-16 03:40:29 +02:00
|
|
|
if (version == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "version");
|
|
|
|
break;
|
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!parse_include (context, ctx, name, version))
|
|
|
|
{
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Failed to parse included gir %s-%s",
|
|
|
|
name,
|
|
|
|
version);
|
|
|
|
return;
|
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
|
2008-10-16 03:40:29 +02:00
|
|
|
ctx->dependencies = g_list_prepend (ctx->dependencies,
|
|
|
|
g_strdup_printf ("%s-%s", name, version));
|
2008-08-30 22:31:07 +02:00
|
|
|
|
|
|
|
|
2008-08-23 18:11:01 +02:00
|
|
|
state_switch (ctx, STATE_INCLUDE);
|
|
|
|
goto out;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
if (start_interface (context, element_name,
|
2008-08-09 14:46:48 +02:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-25 17:22:39 +02:00
|
|
|
else if (start_implements (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2014-05-06 18:53:21 +02:00
|
|
|
else if (start_instance_parameter (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2010-07-22 00:55:24 +02:00
|
|
|
else if (strcmp (element_name, "c:include") == 0)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_C_INCLUDE);
|
|
|
|
goto out;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'm':
|
2010-03-24 19:00:06 +01:00
|
|
|
if (start_function (context, element_name,
|
2008-08-09 14:46:48 +02:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2010-03-24 19:00:06 +01:00
|
|
|
else if (start_member (context, element_name,
|
2008-08-09 14:46:48 +02:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
|
|
|
|
{
|
2009-02-13 00:42:47 +01:00
|
|
|
const gchar *name, *version, *shared_library, *cprefix;
|
2008-11-12 18:16:49 +01:00
|
|
|
|
|
|
|
if (ctx->current_module != NULL)
|
|
|
|
{
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Only one <namespace/> element is currently allowed per <repository/>");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
2008-10-12 06:51:48 +02:00
|
|
|
version = find_attribute ("version", attribute_names, attribute_values);
|
2008-08-09 14:46:48 +02:00
|
|
|
shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
|
2011-03-20 02:00:22 +01:00
|
|
|
cprefix = find_attribute ("c:identifier-prefixes", attribute_names, attribute_values);
|
2013-04-12 19:31:53 +02:00
|
|
|
/* Backwards compatibility; vala currently still generates this */
|
|
|
|
if (cprefix == NULL)
|
|
|
|
cprefix = find_attribute ("c:prefix", attribute_names, attribute_values);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
2008-10-12 06:51:48 +02:00
|
|
|
else if (version == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "version");
|
2008-08-09 14:46:48 +02:00
|
|
|
else
|
|
|
|
{
|
2008-11-12 18:17:01 +01:00
|
|
|
GList *l;
|
|
|
|
|
2008-11-12 18:16:49 +01:00
|
|
|
if (strcmp (name, ctx->namespace) != 0)
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"<namespace/> name element '%s' doesn't match file name '%s'",
|
|
|
|
name, ctx->namespace);
|
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
ctx->current_module = _g_ir_module_new (name, version, shared_library, cprefix);
|
2008-11-12 18:17:01 +01:00
|
|
|
|
|
|
|
ctx->current_module->aliases = ctx->aliases;
|
|
|
|
ctx->aliases = NULL;
|
|
|
|
ctx->current_module->disguised_structures = ctx->disguised_structures;
|
|
|
|
ctx->disguised_structures = NULL;
|
|
|
|
|
|
|
|
for (l = ctx->include_modules; l; l = l->next)
|
2010-11-16 21:08:33 +01:00
|
|
|
_g_ir_module_add_include_module (ctx->current_module, l->data);
|
2008-11-12 18:17:01 +01:00
|
|
|
|
2008-11-12 18:17:08 +01:00
|
|
|
g_list_free (ctx->include_modules);
|
|
|
|
ctx->include_modules = NULL;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
ctx->modules = g_list_append (ctx->modules, ctx->current_module);
|
2008-08-30 22:31:07 +02:00
|
|
|
ctx->current_module->dependencies = ctx->dependencies;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
2008-08-29 22:41:26 +02:00
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'p':
|
|
|
|
if (start_property (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
else if (strcmp (element_name, "parameters") == 0 &&
|
|
|
|
ctx->state == STATE_FUNCTION)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION_PARAMETERS);
|
|
|
|
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
else if (start_parameter (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-11-17 01:27:37 +01:00
|
|
|
else if (strcmp (element_name, "prerequisite") == 0 &&
|
|
|
|
ctx->state == STATE_INTERFACE)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-11-17 01:27:37 +01:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_PREREQUISITE);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else
|
2010-03-24 19:00:06 +01:00
|
|
|
{
|
2008-11-17 01:27:37 +01:00
|
|
|
GIrNodeInterface *iface;
|
|
|
|
|
2009-02-04 01:48:17 +01:00
|
|
|
iface = (GIrNodeInterface *)CURRENT_NODE(ctx);
|
2008-11-17 01:27:44 +01:00
|
|
|
iface->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
|
2008-11-17 01:27:37 +01:00
|
|
|
}
|
|
|
|
goto out;
|
|
|
|
}
|
2009-02-05 23:36:35 +01:00
|
|
|
else if (strcmp (element_name, "package") == 0 &&
|
|
|
|
ctx->state == STATE_REPOSITORY)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_PACKAGE);
|
|
|
|
goto out;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'r':
|
|
|
|
if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
|
|
|
|
{
|
|
|
|
const gchar *version;
|
|
|
|
|
|
|
|
version = find_attribute ("version", attribute_names, attribute_values);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
if (version == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "version");
|
2010-06-17 16:38:39 +02:00
|
|
|
else if (strcmp (version, SUPPORTED_GIR_VERSION) != 0)
|
2008-08-09 14:46:48 +02:00
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Unsupported version '%s'",
|
|
|
|
version);
|
|
|
|
else
|
|
|
|
state_switch (ctx, STATE_REPOSITORY);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
else if (start_return_value (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
2010-03-24 19:00:06 +01:00
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
else if (start_struct (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
2010-03-24 19:00:06 +01:00
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'u':
|
|
|
|
if (start_union (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 't':
|
|
|
|
if (start_type (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'v':
|
|
|
|
if (start_vfunc (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
2008-10-02 16:07:38 +02:00
|
|
|
goto out;
|
|
|
|
if (start_type (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-08-03 19:01:35 +02:00
|
|
|
if (*error == NULL && ctx->state != STATE_PASSTHROUGH)
|
2009-02-11 01:08:49 +01:00
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
|
|
if (!g_str_has_prefix (element_name, "c:"))
|
2010-07-27 12:16:37 +02:00
|
|
|
g_printerr ("%s:%d:%d: warning: element %s from state %d is unknown, ignoring\n",
|
|
|
|
ctx->file_path, line_number, char_number, element_name,
|
|
|
|
ctx->state);
|
2010-06-17 02:34:18 +02:00
|
|
|
state_switch (ctx, STATE_PASSTHROUGH);
|
2009-02-11 01:08:49 +01:00
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2009-02-20 03:48:51 +01:00
|
|
|
out:
|
2010-03-24 19:00:06 +01:00
|
|
|
if (*error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
g_printerr ("%s:%d:%d: error: %s\n", ctx->file_path, line_number, char_number, (*error)->message);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
require_one_of_end_elements (GMarkupParseContext *context,
|
2008-08-14 18:09:06 +02:00
|
|
|
ParseContext *ctx,
|
2008-08-09 14:46:48 +02:00
|
|
|
const char *actual_name,
|
2010-03-24 19:00:06 +01:00
|
|
|
GError **error,
|
2008-08-09 14:46:48 +02:00
|
|
|
...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
int line_number, char_number;
|
|
|
|
const char *expected;
|
|
|
|
gboolean matched = FALSE;
|
|
|
|
|
|
|
|
va_start (args, error);
|
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
while ((expected = va_arg (args, const char*)) != NULL)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
if (strcmp (expected, actual_name) == 0)
|
|
|
|
{
|
|
|
|
matched = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
va_end (args);
|
|
|
|
|
|
|
|
if (matched)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
2010-07-27 12:16:37 +02:00
|
|
|
"Unexpected end tag '%s' on line %d char %d; current state=%d (prev=%d)",
|
2010-03-24 19:00:06 +01:00
|
|
|
actual_name,
|
2010-07-27 12:16:37 +02:00
|
|
|
line_number, char_number, ctx->state, ctx->prev_state);
|
2008-08-09 14:46:48 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2009-02-04 01:48:24 +01:00
|
|
|
static gboolean
|
|
|
|
state_switch_end_struct_or_union (GMarkupParseContext *context,
|
|
|
|
ParseContext *ctx,
|
|
|
|
const gchar *element_name,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
pop_node (ctx);
|
|
|
|
if (ctx->node_stack == NULL)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
else
|
2009-02-04 01:48:24 +01:00
|
|
|
{
|
|
|
|
if (CURRENT_NODE (ctx)->type == G_IR_NODE_STRUCT)
|
|
|
|
state_switch (ctx, STATE_STRUCT);
|
|
|
|
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION)
|
|
|
|
state_switch (ctx, STATE_UNION);
|
|
|
|
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT)
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int line_number, char_number;
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Unexpected end tag '%s' on line %d char %d",
|
|
|
|
element_name,
|
|
|
|
line_number, char_number);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
|
|
|
require_end_element (GMarkupParseContext *context,
|
2008-08-14 18:09:06 +02:00
|
|
|
ParseContext *ctx,
|
2008-08-09 14:46:48 +02:00
|
|
|
const char *expected_name,
|
|
|
|
const char *actual_name,
|
|
|
|
GError **error)
|
|
|
|
{
|
2008-08-14 18:09:06 +02:00
|
|
|
return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
end_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
ParseContext *ctx = user_data;
|
|
|
|
|
|
|
|
g_debug ("</%s>", element_name);
|
|
|
|
|
|
|
|
switch (ctx->state)
|
|
|
|
{
|
|
|
|
case STATE_START:
|
|
|
|
case STATE_END:
|
|
|
|
/* no need to GError here, GMarkup already catches this */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_REPOSITORY:
|
|
|
|
state_switch (ctx, STATE_END);
|
|
|
|
break;
|
|
|
|
|
2008-08-23 18:11:01 +02:00
|
|
|
case STATE_INCLUDE:
|
|
|
|
if (require_end_element (context, ctx, "include", element_name, error))
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_REPOSITORY);
|
|
|
|
}
|
|
|
|
break;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-07-22 00:55:24 +02:00
|
|
|
case STATE_C_INCLUDE:
|
|
|
|
if (require_end_element (context, ctx, "c:include", element_name, error))
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_REPOSITORY);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2009-02-05 23:36:35 +01:00
|
|
|
case STATE_PACKAGE:
|
|
|
|
if (require_end_element (context, ctx, "package", element_name, error))
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_REPOSITORY);
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
break;
|
2008-08-23 18:11:01 +02:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
case STATE_NAMESPACE:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "namespace", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ctx->current_module = NULL;
|
|
|
|
state_switch (ctx, STATE_REPOSITORY);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-08-13 18:10:09 +02:00
|
|
|
case STATE_ALIAS:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "alias", element_name, error))
|
2008-08-13 18:10:09 +02:00
|
|
|
{
|
2010-08-03 19:01:35 +02:00
|
|
|
g_free (ctx->current_alias);
|
|
|
|
ctx->current_alias = NULL;
|
2008-08-13 18:10:09 +02:00
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
case STATE_FUNCTION_RETURN:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "return-value", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_FUNCTION_PARAMETERS:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "parameters", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_FUNCTION_PARAMETER:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "parameter", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION_PARAMETERS);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_FUNCTION:
|
2008-10-02 16:07:38 +02:00
|
|
|
{
|
2009-02-04 01:48:17 +01:00
|
|
|
pop_node (ctx);
|
|
|
|
if (ctx->node_stack == NULL)
|
2008-10-02 16:07:38 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
else
|
2009-02-04 01:48:17 +01:00
|
|
|
{
|
2009-11-09 19:17:23 +01:00
|
|
|
g_debug("case STATE_FUNCTION %d", CURRENT_NODE (ctx)->type);
|
2014-02-27 11:05:54 +01:00
|
|
|
if (ctx->in_embedded_state != STATE_NONE)
|
2009-11-09 19:17:23 +01:00
|
|
|
{
|
2014-02-27 11:05:54 +01:00
|
|
|
state_switch (ctx, ctx->in_embedded_state);
|
|
|
|
ctx->in_embedded_state = STATE_NONE;
|
2009-11-09 19:17:23 +01:00
|
|
|
}
|
|
|
|
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_INTERFACE)
|
2008-10-02 16:07:38 +02:00
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
2010-03-24 19:00:06 +01:00
|
|
|
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT)
|
2008-10-02 16:07:38 +02:00
|
|
|
state_switch (ctx, STATE_CLASS);
|
2009-02-04 01:48:17 +01:00
|
|
|
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_BOXED)
|
2008-10-02 16:07:38 +02:00
|
|
|
state_switch (ctx, STATE_BOXED);
|
2009-02-04 01:48:17 +01:00
|
|
|
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_STRUCT)
|
2008-10-02 16:07:38 +02:00
|
|
|
state_switch (ctx, STATE_STRUCT);
|
2009-02-04 01:48:17 +01:00
|
|
|
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION)
|
2008-10-02 16:07:38 +02:00
|
|
|
state_switch (ctx, STATE_UNION);
|
2011-08-13 17:28:30 +02:00
|
|
|
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_ENUM ||
|
|
|
|
CURRENT_NODE (ctx)->type == G_IR_NODE_FLAGS)
|
|
|
|
state_switch (ctx, STATE_ENUM);
|
2008-10-02 16:07:38 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
int line_number, char_number;
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Unexpected end tag '%s' on line %d char %d",
|
|
|
|
element_name,
|
|
|
|
line_number, char_number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_CLASS_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_CLASS_PROPERTY:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "property", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_CLASS:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "class", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2009-02-04 01:48:17 +01:00
|
|
|
pop_node (ctx);
|
2008-08-09 14:46:48 +02:00
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_INTERFACE_PROPERTY:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
|
|
|
if (require_end_element (context, ctx, "property", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_INTERFACE_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_INTERFACE:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "interface", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2009-02-04 01:48:17 +01:00
|
|
|
pop_node (ctx);
|
2008-08-09 14:46:48 +02:00
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_ENUM:
|
|
|
|
if (strcmp ("member", element_name) == 0)
|
|
|
|
break;
|
2011-08-13 17:28:30 +02:00
|
|
|
else if (strcmp ("function", element_name) == 0)
|
|
|
|
break;
|
2010-03-24 19:00:06 +01:00
|
|
|
else if (require_one_of_end_elements (context, ctx,
|
|
|
|
element_name, error, "enumeration",
|
2008-08-14 18:09:06 +02:00
|
|
|
"bitfield", NULL))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2009-02-04 01:48:17 +01:00
|
|
|
pop_node (ctx);
|
2008-08-09 14:46:48 +02:00
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_BOXED:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "glib:boxed", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2009-02-04 01:48:17 +01:00
|
|
|
pop_node (ctx);
|
2008-08-09 14:46:48 +02:00
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_BOXED_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_BOXED);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_STRUCT_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_STRUCT);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_STRUCT:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "record", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2009-02-04 01:48:24 +01:00
|
|
|
state_switch_end_struct_or_union (context, ctx, element_name, error);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2008-08-20 17:05:46 +02:00
|
|
|
|
|
|
|
case STATE_UNION_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_UNION);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
case STATE_UNION:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "union", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2009-02-04 01:48:24 +01:00
|
|
|
state_switch_end_struct_or_union (context, ctx, element_name, error);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_IMPLEMENTS:
|
|
|
|
if (strcmp ("interface", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "implements", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
break;
|
2008-11-17 01:27:37 +01:00
|
|
|
case STATE_PREREQUISITE:
|
|
|
|
if (require_end_element (context, ctx, "prerequisite", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
break;
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
case STATE_NAMESPACE_CONSTANT:
|
|
|
|
case STATE_CLASS_CONSTANT:
|
|
|
|
case STATE_INTERFACE_CONSTANT:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "constant", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
switch (ctx->state)
|
|
|
|
{
|
|
|
|
case STATE_NAMESPACE_CONSTANT:
|
2009-03-22 21:50:40 +01:00
|
|
|
pop_node (ctx);
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
break;
|
|
|
|
case STATE_CLASS_CONSTANT:
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
break;
|
|
|
|
case STATE_INTERFACE_CONSTANT:
|
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2008-08-22 22:05:23 +02:00
|
|
|
case STATE_TYPE:
|
2008-10-02 16:07:38 +02:00
|
|
|
if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
|
|
|
|
(strcmp ("varargs", element_name) == 0))
|
2008-08-22 22:05:23 +02:00
|
|
|
{
|
2008-09-29 21:03:44 +02:00
|
|
|
end_type (ctx);
|
2008-08-22 22:05:23 +02:00
|
|
|
break;
|
|
|
|
}
|
2009-02-20 03:48:51 +01:00
|
|
|
case STATE_ATTRIBUTE:
|
|
|
|
if (strcmp ("attribute", element_name) == 0)
|
|
|
|
{
|
|
|
|
state_switch (ctx, ctx->prev_state);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
case STATE_PASSTHROUGH:
|
2009-02-11 01:08:49 +01:00
|
|
|
ctx->unknown_depth -= 1;
|
2010-07-27 12:16:37 +02:00
|
|
|
g_assert (ctx->unknown_depth >= 0);
|
2009-02-11 01:08:49 +01:00
|
|
|
if (ctx->unknown_depth == 0)
|
|
|
|
state_switch (ctx, ctx->prev_state);
|
|
|
|
break;
|
2008-08-09 14:46:48 +02:00
|
|
|
default:
|
|
|
|
g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
static void
|
2008-08-09 14:46:48 +02:00
|
|
|
text_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *text,
|
2010-03-24 19:00:06 +01:00
|
|
|
gsize text_len,
|
2008-08-09 14:46:48 +02:00
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
/* FIXME warn about non-whitespace text */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cleanup (GMarkupParseContext *context,
|
|
|
|
GError *error,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
ParseContext *ctx = user_data;
|
|
|
|
GList *m;
|
|
|
|
|
|
|
|
for (m = ctx->modules; m; m = m->next)
|
2010-11-16 21:08:33 +01:00
|
|
|
_g_ir_module_free (m->data);
|
2008-08-09 14:46:48 +02:00
|
|
|
g_list_free (ctx->modules);
|
|
|
|
ctx->modules = NULL;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
ctx->current_module = NULL;
|
|
|
|
}
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
/**
|
2010-11-16 21:08:33 +01:00
|
|
|
* _g_ir_parser_parse_string:
|
2008-11-12 18:16:42 +01:00
|
|
|
* @parser: a #GIrParser
|
2009-02-12 04:32:25 +01:00
|
|
|
* @namespace: the namespace of the string
|
2010-06-17 02:34:18 +02:00
|
|
|
* @filename: (allow-none): Path to parsed file, or %NULL
|
2009-02-12 04:32:25 +01:00
|
|
|
* @buffer: the data containing the XML
|
|
|
|
* @length: length of the data
|
2008-11-12 18:16:42 +01:00
|
|
|
* @error: return location for a #GError, or %NULL
|
|
|
|
*
|
|
|
|
* Parse a string that holds a complete GIR XML file, and return a list of a
|
|
|
|
* a #GirModule for each <namespace/> element within the file.
|
|
|
|
*
|
2010-07-26 22:26:46 +02:00
|
|
|
* Returns: (transfer none): a new #GirModule
|
2008-11-12 18:16:42 +01:00
|
|
|
*/
|
2010-07-26 22:26:46 +02:00
|
|
|
GIrModule *
|
2010-11-16 21:08:33 +01:00
|
|
|
_g_ir_parser_parse_string (GIrParser *parser,
|
|
|
|
const gchar *namespace,
|
|
|
|
const gchar *filename,
|
|
|
|
const gchar *buffer,
|
|
|
|
gssize length,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ParseContext ctx = { 0 };
|
|
|
|
GMarkupParseContext *context;
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
ctx.parser = parser;
|
2008-08-09 14:46:48 +02:00
|
|
|
ctx.state = STATE_START;
|
2010-06-17 02:34:18 +02:00
|
|
|
ctx.file_path = filename;
|
2008-08-28 23:19:22 +02:00
|
|
|
ctx.namespace = namespace;
|
2008-11-12 18:17:08 +01:00
|
|
|
ctx.include_modules = NULL;
|
2008-08-13 18:10:09 +02:00
|
|
|
ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
2008-11-11 00:58:49 +01:00
|
|
|
ctx.disguised_structures = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
2008-08-22 22:05:23 +02:00
|
|
|
ctx.type_depth = 0;
|
2008-08-30 22:31:07 +02:00
|
|
|
ctx.dependencies = NULL;
|
2008-08-29 22:41:26 +02:00
|
|
|
ctx.current_module = NULL;
|
2008-08-13 18:10:09 +02:00
|
|
|
|
|
|
|
context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
|
|
|
|
|
|
|
|
if (!g_markup_parse_context_parse (context, buffer, length, error))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (!g_markup_parse_context_end_parse (context, error))
|
|
|
|
goto out;
|
2008-08-28 23:19:22 +02:00
|
|
|
|
|
|
|
g_markup_parse_context_free (context);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-08-03 19:01:35 +02:00
|
|
|
ctx.state = STATE_START;
|
2008-11-12 18:16:42 +01:00
|
|
|
context = g_markup_parse_context_new (&markup_parser, 0, &ctx, NULL);
|
2008-08-09 14:46:48 +02:00
|
|
|
if (!g_markup_parse_context_parse (context, buffer, length, error))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (!g_markup_parse_context_end_parse (context, error))
|
|
|
|
goto out;
|
|
|
|
|
2008-11-12 18:17:15 +01:00
|
|
|
parser->parsed_modules = g_list_concat (g_list_copy (ctx.modules),
|
|
|
|
parser->parsed_modules);
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
out:
|
2008-08-13 18:10:09 +02:00
|
|
|
|
2008-11-12 18:17:01 +01:00
|
|
|
if (ctx.modules == NULL)
|
|
|
|
{
|
2008-11-12 18:17:08 +01:00
|
|
|
/* An error occurred before we created a module, so we haven't
|
|
|
|
* transferred ownership of these hash tables to the module.
|
|
|
|
*/
|
2008-11-12 18:17:01 +01:00
|
|
|
if (ctx.aliases != NULL)
|
|
|
|
g_hash_table_destroy (ctx.aliases);
|
|
|
|
if (ctx.disguised_structures != NULL)
|
|
|
|
g_hash_table_destroy (ctx.disguised_structures);
|
2008-11-12 18:17:08 +01:00
|
|
|
g_list_free (ctx.include_modules);
|
2008-11-12 18:17:01 +01:00
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
g_markup_parse_context_free (context);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-07-27 12:16:37 +02:00
|
|
|
if (ctx.modules)
|
|
|
|
return ctx.modules->data;
|
2011-10-18 17:45:38 +02:00
|
|
|
|
2012-02-17 17:48:35 +01:00
|
|
|
if (error && *error == NULL)
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Expected namespace element in the gir file");
|
2010-07-27 12:16:37 +02:00
|
|
|
return NULL;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
/**
|
2010-11-16 21:08:33 +01:00
|
|
|
* _g_ir_parser_parse_file:
|
2008-11-12 18:16:42 +01:00
|
|
|
* @parser: a #GIrParser
|
2009-02-12 04:32:25 +01:00
|
|
|
* @filename: filename to parse
|
2008-11-12 18:16:42 +01:00
|
|
|
* @error: return location for a #GError, or %NULL
|
|
|
|
*
|
|
|
|
* Parse GIR XML file, and return a list of a a #GirModule for each
|
|
|
|
* <namespace/> element within the file.
|
|
|
|
*
|
2010-06-12 16:31:06 +02:00
|
|
|
* Returns: (transfer container): a newly allocated list of #GIrModule. The modules themselves
|
2008-11-12 18:16:42 +01:00
|
|
|
* are owned by the #GIrParser and will be freed along with the parser.
|
|
|
|
*/
|
2010-07-26 22:26:46 +02:00
|
|
|
GIrModule *
|
2010-11-16 21:08:33 +01:00
|
|
|
_g_ir_parser_parse_file (GIrParser *parser,
|
|
|
|
const gchar *filename,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
gchar *buffer;
|
|
|
|
gsize length;
|
2010-07-26 22:26:46 +02:00
|
|
|
GIrModule *module;
|
2008-08-28 23:19:22 +02:00
|
|
|
const char *slash;
|
2008-11-12 18:16:49 +01:00
|
|
|
char *dash;
|
2008-08-28 23:19:22 +02:00
|
|
|
char *namespace;
|
|
|
|
|
|
|
|
if (!g_str_has_suffix (filename, ".gir"))
|
|
|
|
{
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Expected filename to end with '.gir'");
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
g_debug ("[parsing] filename %s", filename);
|
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
slash = g_strrstr (filename, "/");
|
|
|
|
if (!slash)
|
|
|
|
namespace = g_strdup (filename);
|
|
|
|
else
|
|
|
|
namespace = g_strdup (slash+1);
|
|
|
|
namespace[strlen(namespace)-4] = '\0';
|
|
|
|
|
2008-11-12 18:16:49 +01:00
|
|
|
/* Remove version */
|
|
|
|
dash = strstr (namespace, "-");
|
|
|
|
if (dash != NULL)
|
|
|
|
*dash = '\0';
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
if (!g_file_get_contents (filename, &buffer, &length, error))
|
|
|
|
return NULL;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-11-16 21:08:33 +01:00
|
|
|
module = _g_ir_parser_parse_string (parser, namespace, filename, buffer, length, error);
|
2008-10-02 16:07:38 +02:00
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
g_free (namespace);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
g_free (buffer);
|
|
|
|
|
2010-07-26 22:26:46 +02:00
|
|
|
return module;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|