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
|
|
|
|
*
|
2023-10-25 18:10:10 +02:00
|
|
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
*
|
2008-08-09 14:46:48 +02:00
|
|
|
* 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"
|
|
|
|
|
2023-11-08 01:07:11 +01:00
|
|
|
#include "girparser-private.h"
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2023-11-08 01:09:04 +01:00
|
|
|
#include "girnode-private.h"
|
2010-05-31 22:44:46 +02:00
|
|
|
#include "gitypelib-internal.h"
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2023-11-08 01:07:11 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2024-03-15 14:56:20 +01:00
|
|
|
#include <time.h> /* For time_t */
|
|
|
|
#include <sys/types.h> /* For off_t on both Unix and Windows */
|
|
|
|
|
|
|
|
#ifdef G_OS_UNIX
|
|
|
|
#include <sys/socket.h> /* For socklen_t */
|
|
|
|
#endif
|
2023-11-08 01:07:11 +01: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
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
struct _GIIrParser
|
2008-11-12 18:16:42 +01:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
char **includes;
|
|
|
|
char **gi_gir_path;
|
2008-11-12 18:17:15 +01:00
|
|
|
GList *parsed_modules; /* All previously parsed modules */
|
2024-02-14 11:36:23 +01:00
|
|
|
GLogLevelFlags logged_levels;
|
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
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrParser *parser;
|
2008-11-12 18:16:42 +01:00
|
|
|
|
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;
|
2022-07-13 14:26:44 +02:00
|
|
|
GHashTable *pointer_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;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrModule *current_module;
|
2009-02-04 01:48:17 +01:00
|
|
|
GSList *node_stack;
|
2010-08-03 19:01:35 +02:00
|
|
|
char *current_alias;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNode *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
|
|
|
};
|
2023-11-08 15:17:52 +01:00
|
|
|
#define CURRENT_NODE(ctx) ((GIIrNode *)((ctx)->node_stack->data))
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2024-01-16 02:34:02 +01:00
|
|
|
static void start_element_handler (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
void *user_data,
|
|
|
|
GError **error);
|
|
|
|
static void end_element_handler (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
void *user_data,
|
|
|
|
GError **error);
|
|
|
|
static void text_handler (GMarkupParseContext *context,
|
|
|
|
const char *text,
|
|
|
|
gsize text_len,
|
|
|
|
void *user_data,
|
|
|
|
GError **error);
|
2008-11-11 01:48:17 +01:00
|
|
|
static void cleanup (GMarkupParseContext *context,
|
2024-01-16 17:30:37 +01:00
|
|
|
GError *error,
|
2024-01-15 20:16:00 +01:00
|
|
|
void *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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_alias (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error);
|
2010-08-03 19:01:35 +02:00
|
|
|
static gboolean
|
2024-01-16 02:34:02 +01:00
|
|
|
start_type (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error);
|
|
|
|
|
|
|
|
static const char *find_attribute (const char *name,
|
2024-01-15 20:20:47 +01:00
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values);
|
2008-11-11 00:58:49 +01:00
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrParser *
|
2023-11-08 16:23:31 +01:00
|
|
|
gi_ir_parser_new (void)
|
2008-11-12 18:16:42 +01:00
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrParser *parser = g_slice_new0 (GIIrParser);
|
2021-02-10 12:45:26 +01:00
|
|
|
const char *gi_gir_path = g_getenv ("GI_GIR_PATH");
|
|
|
|
|
|
|
|
if (gi_gir_path != NULL)
|
|
|
|
parser->gi_gir_path = g_strsplit (gi_gir_path, G_SEARCHPATH_SEPARATOR_S, 0);
|
2008-11-12 18:16:42 +01:00
|
|
|
|
2024-02-14 11:36:23 +01:00
|
|
|
parser->logged_levels = G_LOG_LEVEL_MASK & ~(G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_DEBUG);
|
2008-11-12 18:16:42 +01:00
|
|
|
return parser;
|
|
|
|
}
|
|
|
|
|
2024-02-14 11:36:23 +01:00
|
|
|
void
|
|
|
|
gi_ir_parser_set_debug (GIIrParser *parser,
|
|
|
|
GLogLevelFlags logged_levels)
|
|
|
|
{
|
|
|
|
parser->logged_levels = logged_levels;
|
|
|
|
}
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
void
|
2023-11-08 16:23:31 +01:00
|
|
|
gi_ir_parser_free (GIIrParser *parser)
|
2008-11-12 18:16:42 +01:00
|
|
|
{
|
2008-11-12 18:17:15 +01:00
|
|
|
GList *l;
|
|
|
|
|
2021-02-10 12:45:26 +01:00
|
|
|
g_strfreev (parser->includes);
|
|
|
|
g_strfreev (parser->gi_gir_path);
|
2008-11-12 18:16:42 +01:00
|
|
|
|
2008-11-12 18:17:15 +01:00
|
|
|
for (l = parser->parsed_modules; l; l = l->next)
|
2023-11-08 16:23:31 +01:00
|
|
|
gi_ir_module_free (l->data);
|
2008-11-12 18:17:15 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
g_slice_free (GIIrParser, parser);
|
2008-11-12 18:16:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2023-11-08 16:23:31 +01:00
|
|
|
gi_ir_parser_set_includes (GIIrParser *parser,
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *const *includes)
|
2008-11-12 18:16:42 +01:00
|
|
|
{
|
2021-02-10 12:45:26 +01:00
|
|
|
g_strfreev (parser->includes);
|
2008-11-12 18:16:42 +01:00
|
|
|
|
|
|
|
parser->includes = g_strdupv ((char **)includes);
|
|
|
|
}
|
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
static void
|
2024-01-16 02:34:02 +01:00
|
|
|
firstpass_start_element_handler (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
void *user_data,
|
|
|
|
GError **error)
|
2008-08-28 23:19:22 +02:00
|
|
|
{
|
|
|
|
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,
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx, error);
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
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,
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx, error);
|
2010-08-03 19:01:35 +02:00
|
|
|
}
|
2008-11-11 00:58:49 +01:00
|
|
|
else if (strcmp (element_name, "record") == 0)
|
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *disguised;
|
|
|
|
const char *pointer;
|
2008-11-11 00:58:49 +01:00
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
disguised = find_attribute ("disguised", attribute_names, attribute_values);
|
2022-07-13 14:26:44 +02:00
|
|
|
pointer = find_attribute ("pointer", attribute_names, attribute_values);
|
2008-11-11 00:58:49 +01:00
|
|
|
|
2022-07-13 14:26:44 +02:00
|
|
|
if (g_strcmp0 (pointer, "1") == 0)
|
|
|
|
{
|
|
|
|
char *key;
|
|
|
|
|
|
|
|
key = g_strdup_printf ("%s.%s", ctx->namespace, name);
|
2024-01-16 17:30:37 +01:00
|
|
|
g_hash_table_replace (ctx->pointer_structures, key, GINT_TO_POINTER (1));
|
2022-07-13 14:26:44 +02:00
|
|
|
}
|
|
|
|
else if (g_strcmp0 (disguised, "1") == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
char *key;
|
2008-11-11 00:58:49 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
key = g_strdup_printf ("%s.%s", ctx->namespace, name);
|
|
|
|
g_hash_table_replace (ctx->disguised_structures, key, GINT_TO_POINTER (1));
|
|
|
|
}
|
2008-11-11 00:58:49 +01:00
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2024-01-16 02:34:02 +01:00
|
|
|
firstpass_end_element_handler (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
2008-08-28 23:19:22 +02:00
|
|
|
{
|
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 *
|
2023-11-08 15:17:52 +01:00
|
|
|
locate_gir (GIIrParser *parser,
|
|
|
|
const char *girname)
|
2008-08-28 23:19:22 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *const *datadirs;
|
|
|
|
const char *const *dir;
|
2008-08-28 23:19:22 +02:00
|
|
|
char *path = NULL;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-02-01 12:23:34 +01:00
|
|
|
g_debug ("Looking for %s", girname);
|
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
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
for (dir = (const char *const *)parser->includes; *dir; dir++)
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
path = g_build_filename (*dir, girname, NULL);
|
|
|
|
g_debug ("Trying %s from includes", path);
|
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
|
|
|
return g_steal_pointer (&path);
|
|
|
|
g_clear_pointer (&path, g_free);
|
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
2021-02-10 12:45:26 +01:00
|
|
|
|
|
|
|
if (parser->gi_gir_path != NULL)
|
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
for (dir = (const char *const *) parser->gi_gir_path; *dir; dir++)
|
2021-02-10 12:45:26 +01:00
|
|
|
{
|
|
|
|
if (**dir == '\0')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
path = g_build_filename (*dir, girname, NULL);
|
|
|
|
g_debug ("Trying %s from GI_GIR_PATH", path);
|
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
|
|
|
return g_steal_pointer (&path);
|
|
|
|
g_clear_pointer (&path, g_free);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-10 13:07:56 +01:00
|
|
|
path = g_build_filename (g_get_user_data_dir (), GIR_SUFFIX, girname, NULL);
|
|
|
|
g_debug ("Trying %s from user data dir", path);
|
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
|
|
|
return g_steal_pointer (&path);
|
|
|
|
g_clear_pointer (&path, g_free);
|
|
|
|
|
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);
|
2023-02-01 12:23:34 +01:00
|
|
|
g_debug ("Trying %s from system data dirs", path);
|
2008-11-11 16:25:59 +01:00
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
2023-08-09 12:45:07 +02:00
|
|
|
return g_steal_pointer (&path);
|
2023-08-09 12:46:07 +02:00
|
|
|
g_clear_pointer (&path, g_free);
|
2008-11-11 16:25:59 +01:00
|
|
|
}
|
2009-06-01 09:18:43 +02:00
|
|
|
|
|
|
|
path = g_build_filename (GIR_DIR, girname, NULL);
|
2023-02-01 12:23:34 +01:00
|
|
|
g_debug ("Trying %s from GIR_DIR", path);
|
2009-06-01 09:18:43 +02:00
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
2023-08-09 12:45:07 +02:00
|
|
|
return g_steal_pointer (&path);
|
2023-08-09 12:46:07 +02:00
|
|
|
g_clear_pointer (&path, g_free);
|
2023-02-01 12:23:34 +01:00
|
|
|
|
2021-02-10 13:01:44 +01:00
|
|
|
path = g_build_filename (GOBJECT_INTROSPECTION_DATADIR, GIR_SUFFIX, girname, NULL);
|
|
|
|
g_debug ("Trying %s from DATADIR", path);
|
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
|
|
|
return g_steal_pointer (&path);
|
|
|
|
g_clear_pointer (&path, g_free);
|
|
|
|
|
|
|
|
#ifdef G_OS_UNIX
|
|
|
|
path = g_build_filename ("/usr/share", GIR_SUFFIX, girname, NULL);
|
|
|
|
g_debug ("Trying %s", path);
|
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
|
|
|
return g_steal_pointer (&path);
|
|
|
|
g_clear_pointer (&path, g_free);
|
|
|
|
#endif
|
|
|
|
|
2023-02-01 12:23:34 +01:00
|
|
|
g_debug ("Did not find %s", girname);
|
2009-06-01 09:18:43 +02:00
|
|
|
return NULL;
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
|
|
|
|
2024-01-16 17:30:37 +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, \
|
2024-01-16 17:30:37 +01:00
|
|
|
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); \
|
2008-08-09 14:46:48 +02:00
|
|
|
} while (0)
|
|
|
|
|
2024-01-15 20:20:47 +01:00
|
|
|
static const char *
|
|
|
|
find_attribute (const char *name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-16 01:57:09 +01:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; attribute_names[i] != NULL; i++)
|
2008-08-09 14:46:48 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
static GIIrNode *
|
2009-02-04 01:48:17 +01:00
|
|
|
pop_node (ParseContext *ctx)
|
|
|
|
{
|
2012-07-24 10:09:38 +02:00
|
|
|
GSList *top;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNode *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
|
2023-11-08 15:17:52 +01:00
|
|
|
push_node (ParseContext *ctx, GIIrNode *node)
|
2009-02-04 01:48:17 +01:00
|
|
|
{
|
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);
|
|
|
|
}
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
static GIIrNodeType * parse_type_internal (GIIrModule *module,
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *str,
|
|
|
|
char **next,
|
|
|
|
gboolean in_glib,
|
2023-11-08 15:17:52 +01:00
|
|
|
gboolean in_gobject);
|
2008-08-13 18:10:09 +02:00
|
|
|
|
2010-07-07 20:07:17 +02:00
|
|
|
typedef struct {
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *str;
|
2024-01-16 00:35:23 +01:00
|
|
|
size_t size;
|
2024-01-15 22:20:02 +01:00
|
|
|
unsigned int is_signed : 1;
|
2010-07-07 20:07:17 +02:00
|
|
|
} IntegerAliasInfo;
|
|
|
|
|
2024-03-18 11:46:13 +01:00
|
|
|
/*
|
|
|
|
* signedness:
|
|
|
|
* @T: a numeric type
|
|
|
|
*
|
|
|
|
* Returns: 1 if @T is signed, 0 if it is unsigned
|
|
|
|
*/
|
2024-03-18 11:45:28 +01:00
|
|
|
#define signedness(T) (((T) -1) <= 0)
|
2024-03-15 14:56:20 +01:00
|
|
|
G_STATIC_ASSERT (signedness (int) == 1);
|
|
|
|
G_STATIC_ASSERT (signedness (unsigned int) == 0);
|
|
|
|
|
2010-07-07 20:07:17 +02:00
|
|
|
static IntegerAliasInfo integer_aliases[] = {
|
2024-03-17 13:34:09 +01:00
|
|
|
{ "gchar", sizeof (gchar), 1 },
|
|
|
|
{ "guchar", sizeof (guchar), 0 },
|
|
|
|
{ "gshort", sizeof (gshort), 1 },
|
|
|
|
{ "gushort", sizeof (gushort), 0 },
|
|
|
|
{ "gint", sizeof (gint), 1 },
|
|
|
|
{ "guint", sizeof (guint), 0 },
|
|
|
|
{ "glong", sizeof (glong), 1 },
|
|
|
|
{ "gulong", sizeof (gulong), 0 },
|
|
|
|
{ "gssize", sizeof (gssize), 1 },
|
|
|
|
{ "gsize", sizeof (gsize), 0 },
|
2024-03-15 14:49:47 +01:00
|
|
|
{ "gintptr", sizeof (gintptr), 1 },
|
|
|
|
{ "guintptr", sizeof (guintptr), 0 },
|
2024-03-15 14:56:20 +01:00
|
|
|
#define INTEGER_ALIAS(T) { #T, sizeof (T), signedness (T) }
|
|
|
|
INTEGER_ALIAS (off_t),
|
|
|
|
INTEGER_ALIAS (time_t),
|
|
|
|
#ifdef G_OS_UNIX
|
|
|
|
INTEGER_ALIAS (dev_t),
|
|
|
|
INTEGER_ALIAS (gid_t),
|
|
|
|
INTEGER_ALIAS (pid_t),
|
|
|
|
INTEGER_ALIAS (socklen_t),
|
|
|
|
INTEGER_ALIAS (uid_t),
|
|
|
|
#endif
|
|
|
|
#undef INTEGER_ALIAS
|
2010-07-07 20:07:17 +02:00
|
|
|
};
|
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
typedef struct {
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *str;
|
2024-01-15 22:20:02 +01:00
|
|
|
int tag;
|
2008-08-29 22:06:10 +02:00
|
|
|
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)
|
|
|
|
{
|
2024-01-16 01:57:09 +01:00
|
|
|
size_t i;
|
|
|
|
size_t 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)
|
2024-01-16 17:30:37 +01: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)
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
switch (integer_aliases[i].size)
|
|
|
|
{
|
2024-01-15 22:20:02 +01:00
|
|
|
case sizeof (uint8_t):
|
2024-01-16 17:30:37 +01:00
|
|
|
if (integer_aliases[i].is_signed)
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET];
|
|
|
|
else
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+1];
|
|
|
|
break;
|
2024-01-15 22:20:02 +01:00
|
|
|
case sizeof (uint16_t):
|
2024-01-16 17:30:37 +01:00
|
|
|
if (integer_aliases[i].is_signed)
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+2];
|
|
|
|
else
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+3];
|
|
|
|
break;
|
2024-01-15 22:20:02 +01:00
|
|
|
case sizeof (uint32_t):
|
2024-01-16 17:30:37 +01:00
|
|
|
if (integer_aliases[i].is_signed)
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+4];
|
|
|
|
else
|
|
|
|
return &basic_types[BASIC_TYPE_FIXED_OFFSET+5];
|
|
|
|
break;
|
2024-01-15 22:20:02 +01:00
|
|
|
case sizeof (uint64_t):
|
2024-01-16 17:30:37 +01:00
|
|
|
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 ();
|
|
|
|
}
|
|
|
|
}
|
2010-07-07 20:07:17 +02:00
|
|
|
}
|
2008-08-29 22:06:10 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
static GIIrNodeType *
|
|
|
|
parse_type_internal (GIIrModule *module,
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *str,
|
2023-11-08 15:17:52 +01:00
|
|
|
char **next,
|
|
|
|
gboolean in_glib,
|
|
|
|
gboolean in_gobject)
|
2008-08-29 22:06:10 +02:00
|
|
|
{
|
2010-03-24 19:00:06 +01:00
|
|
|
const BasicTypeInfo *basic;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeType *type;
|
2008-08-29 22:06:10 +02:00
|
|
|
char *temporary_type = NULL;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
type = (GIIrNodeType *)gi_ir_node_new (GI_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<") ||
|
2024-01-16 17:30:37 +01:00
|
|
|
strcmp (str, "List") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
2008-08-29 21:33:09 +02:00
|
|
|
else if (g_str_has_prefix (str, "SList<") ||
|
2024-01-16 17:30:37 +01:00
|
|
|
strcmp (str, "SList") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
2008-08-29 21:33:09 +02:00
|
|
|
else if (g_str_has_prefix (str, "HashTable<") ||
|
2024-01-16 17:30:37 +01:00
|
|
|
strcmp (str, "HashTable") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
2008-08-29 21:33:09 +02:00
|
|
|
else if (g_str_has_prefix (str, "Error<") ||
|
2024-01-16 17:30:37 +01:00
|
|
|
strcmp (str, "Error") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
2008-08-29 21:33:09 +02:00
|
|
|
}
|
|
|
|
|
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") ||
|
2024-01-16 17:30:37 +01:00
|
|
|
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"))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
type->tag = GI_TYPE_TAG_GLIST;
|
|
|
|
type->is_glist = TRUE;
|
|
|
|
type->is_pointer = TRUE;
|
|
|
|
str += strlen ("List");
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
else
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
type->tag = GI_TYPE_TAG_GSLIST;
|
|
|
|
type->is_gslist = TRUE;
|
|
|
|
type->is_pointer = TRUE;
|
|
|
|
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 == '<')
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
char *tmp, *end;
|
|
|
|
(str)++;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
end = strchr (str, '>');
|
|
|
|
tmp = g_strndup (str, end - str);
|
|
|
|
type->errors = g_strsplit (tmp, ",", 0);
|
|
|
|
g_free (tmp);
|
2008-08-29 21:33:09 +02:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
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) ||
|
2024-01-16 17:30:37 +01:00
|
|
|
*str == '.' ||
|
|
|
|
*str == '-' ||
|
|
|
|
*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: */
|
2023-11-08 16:23:31 +01:00
|
|
|
gi_ir_node_free ((GIIrNode *)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 *
|
2024-01-15 20:20:47 +01:00
|
|
|
resolve_aliases (ParseContext *ctx, const char *type)
|
2008-08-13 18:10:09 +02:00
|
|
|
{
|
2024-01-15 20:16:00 +01:00
|
|
|
void *orig;
|
|
|
|
void *value;
|
2008-08-20 21:01:20 +02:00
|
|
|
GSList *seen_values = NULL;
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *lookup;
|
|
|
|
char *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
|
|
|
{
|
2023-12-20 23:41:10 +01:00
|
|
|
g_debug ("Resolved: %s => %s", lookup, (char*)value);
|
2008-11-11 23:02:37 +01:00
|
|
|
lookup = value;
|
|
|
|
if (g_slist_find_custom (seen_values, lookup,
|
2024-01-16 17:30:37 +01:00
|
|
|
(GCompareFunc)strcmp) != NULL)
|
|
|
|
break;
|
2024-01-15 22:20:02 +01:00
|
|
|
seen_values = g_slist_prepend (seen_values, (char*) 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
|
|
|
}
|
|
|
|
|
2022-07-13 14:26:44 +02:00
|
|
|
static void
|
|
|
|
is_pointer_or_disguised_structure (ParseContext *ctx,
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *type,
|
2022-07-13 14:26:44 +02:00
|
|
|
gboolean *is_pointer,
|
|
|
|
gboolean *is_disguised)
|
2008-11-12 18:17:01 +01:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *lookup;
|
|
|
|
char *prefixed;
|
2008-11-12 18:17:01 +01:00
|
|
|
|
|
|
|
if (strchr (type, '.') == NULL)
|
|
|
|
{
|
|
|
|
prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
|
|
|
|
lookup = prefixed;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lookup = type;
|
|
|
|
prefixed = NULL;
|
|
|
|
}
|
|
|
|
|
2022-07-13 14:26:44 +02:00
|
|
|
if (is_pointer != NULL)
|
|
|
|
*is_pointer = g_hash_table_lookup (ctx->current_module->pointer_structures, lookup) != NULL;
|
|
|
|
if (is_disguised != NULL)
|
|
|
|
*is_disguised = 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);
|
|
|
|
}
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
static GIIrNodeType *
|
2024-01-15 20:20:47 +01:00
|
|
|
parse_type (ParseContext *ctx, const char *type)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeType *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
|
2024-01-16 02:34:02 +01:00
|
|
|
introspectable_prelude (GMarkupParseContext *context,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
ParseState new_state)
|
2010-06-17 02:34:18 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *introspectable_arg;
|
|
|
|
const char *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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_glib_boxed (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *typename;
|
|
|
|
const char *typeinit;
|
|
|
|
const char *deprecated;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeBoxed *boxed;
|
2008-08-24 13:01:44 +02:00
|
|
|
|
|
|
|
if (!(strcmp (element_name, "glib:boxed") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_NAMESPACE))
|
2008-08-24 13:01:44 +02:00
|
|
|
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
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
boxed = (GIIrNodeBoxed *) gi_ir_node_new (GI_IR_NODE_BOXED,
|
|
|
|
ctx->current_module);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)boxed)->name = g_strdup (name);
|
2008-08-24 13:01:44 +02:00
|
|
|
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
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
push_node (ctx, (GIIrNode *)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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_function (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *shadows;
|
|
|
|
const char *symbol;
|
|
|
|
const char *deprecated;
|
|
|
|
const char *throws;
|
|
|
|
const char *set_property;
|
|
|
|
const char *get_property;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeFunction *function;
|
2008-08-24 13:01:44 +02:00
|
|
|
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 ||
|
2024-01-16 17:30:37 +01:00
|
|
|
strcmp (element_name, "callback") == 0);
|
2008-08-24 13:01:44 +02:00
|
|
|
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 */
|
2023-10-25 19:38:30 +02:00
|
|
|
G_GNUC_FALLTHROUGH;
|
2008-08-24 13:01:44 +02:00
|
|
|
case STATE_INTERFACE:
|
|
|
|
found = (found ||
|
2024-01-16 17:30:37 +01:00
|
|
|
strcmp (element_name, "function") == 0 ||
|
|
|
|
strcmp (element_name, "method") == 0 ||
|
|
|
|
strcmp (element_name, "callback") == 0);
|
2008-08-24 13:01:44 +02:00
|
|
|
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);
|
2021-06-16 20:17:27 +02:00
|
|
|
set_property = find_attribute ("glib:set-property", attribute_names, attribute_values);
|
|
|
|
get_property = find_attribute ("glib:get-property", 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;
|
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
function = (GIIrNodeFunction *) gi_ir_node_new (GI_IR_NODE_FUNCTION,
|
|
|
|
ctx->current_module);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)function)->name = g_strdup (name);
|
2008-08-24 13:01:44 +02:00
|
|
|
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)
|
2024-01-16 17:30:37 +01:00
|
|
|
function->is_constructor = TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
else
|
2024-01-16 17:30:37 +01:00
|
|
|
function->is_constructor = FALSE;
|
2021-06-16 20:17:27 +02:00
|
|
|
|
|
|
|
if (set_property != NULL)
|
|
|
|
{
|
|
|
|
function->is_setter = TRUE;
|
|
|
|
function->is_getter = FALSE;
|
|
|
|
function->property = g_strdup (set_property);
|
|
|
|
}
|
|
|
|
else if (get_property != NULL)
|
|
|
|
{
|
|
|
|
function->is_setter = FALSE;
|
|
|
|
function->is_getter = TRUE;
|
|
|
|
function->property = g_strdup (get_property);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
function->is_setter = FALSE;
|
|
|
|
function->is_getter = FALSE;
|
|
|
|
function->property = NULL;
|
|
|
|
}
|
2008-08-24 13:01:44 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
function->is_method = FALSE;
|
|
|
|
function->is_setter = FALSE;
|
|
|
|
function->is_getter = FALSE;
|
|
|
|
function->is_constructor = FALSE;
|
|
|
|
if (strcmp (element_name, "callback") == 0)
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)function)->type = GI_IR_NODE_CALLBACK;
|
2008-08-24 13:01:44 +02:00
|
|
|
}
|
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 =
|
2024-01-16 17:30:37 +01:00
|
|
|
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)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeField *field;
|
2009-11-09 19:17:23 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
field = (GIIrNodeField *)ctx->current_typed;
|
2009-11-09 19:17:23 +01:00
|
|
|
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
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_INTERFACE:
|
|
|
|
case GI_IR_NODE_OBJECT:
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
GIIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
iface = (GIIrNodeInterface *)CURRENT_NODE (ctx);
|
|
|
|
iface->members = g_list_append (iface->members, function);
|
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_BOXED:
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
GIIrNodeBoxed *boxed;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
boxed = (GIIrNodeBoxed *)CURRENT_NODE (ctx);
|
|
|
|
boxed->members = g_list_append (boxed->members, function);
|
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_STRUCT:
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
GIIrNodeStruct *struct_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
struct_ = (GIIrNodeStruct *)CURRENT_NODE (ctx);
|
|
|
|
struct_->members = g_list_append (struct_->members, function); }
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_UNION:
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
GIIrNodeUnion *union_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
union_ = (GIIrNodeUnion *)CURRENT_NODE (ctx);
|
|
|
|
union_->members = g_list_append (union_->members, function);
|
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_ENUM:
|
|
|
|
case GI_IR_NODE_FLAGS:
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
GIIrNodeEnum *enum_;
|
2011-08-13 17:28:30 +02:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
enum_ = (GIIrNodeEnum *)CURRENT_NODE (ctx);
|
|
|
|
enum_->methods = g_list_append (enum_->methods, function);
|
|
|
|
}
|
|
|
|
break;
|
2008-08-24 13:01:44 +02:00
|
|
|
default:
|
2024-01-16 17:30:37 +01:00
|
|
|
g_assert_not_reached ();
|
2008-08-24 13:01:44 +02:00
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
push_node(ctx, (GIIrNode *)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
|
2023-11-08 15:17:52 +01:00
|
|
|
parse_property_transfer (GIIrNodeProperty *property,
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *transfer,
|
2023-11-08 15:17:52 +01:00
|
|
|
ParseContext *ctx)
|
2010-06-08 16:40:35 +02:00
|
|
|
{
|
|
|
|
if (transfer == NULL)
|
|
|
|
{
|
2010-06-08 19:20:06 +02:00
|
|
|
#if 0
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeInterface *iface = (GIIrNodeInterface *)CURRENT_NODE (ctx);
|
2010-06-08 16:40:35 +02:00
|
|
|
|
2010-06-08 19:20:06 +02:00
|
|
|
g_debug ("required attribute 'transfer-ownership' is missing from "
|
2023-12-20 23:41:10 +01:00
|
|
|
"property '%s' in type '%s.%s'. Assuming 'none'",
|
2010-06-08 19:20:06 +02:00
|
|
|
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
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeInterface *iface = (GIIrNodeInterface *)CURRENT_NODE (ctx);
|
2010-06-08 16:40:35 +02:00
|
|
|
|
|
|
|
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
|
2024-01-15 20:20:47 +01:00
|
|
|
parse_param_transfer (GIIrNodeParam *param, const char *transfer, const char *name,
|
2024-01-16 17:30:37 +01:00
|
|
|
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,
|
2024-01-16 17:30:37 +01:00
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"required attribute 'transfer-ownership' missing");
|
2010-07-27 12:16:37 +02:00
|
|
|
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,
|
2024-01-16 17:30:37 +01:00
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"invalid value for 'transfer-ownership': %s", transfer);
|
2010-07-27 12:16:37 +02:00
|
|
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_instance_parameter (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2014-05-06 18:53:21 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *transfer;
|
2014-05-06 18:53:21 +02:00
|
|
|
gboolean transfer_full;
|
|
|
|
|
|
|
|
if (!(strcmp (element_name, "instance-parameter") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_FUNCTION_PARAMETERS))
|
2014-05-06 18:53:21 +02:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_PASSTHROUGH);
|
|
|
|
|
2015-10-04 18:00:23 +02:00
|
|
|
if (g_strcmp0 (transfer, "full") == 0)
|
2014-05-06 18:53:21 +02:00
|
|
|
transfer_full = TRUE;
|
2015-10-04 18:00:23 +02:00
|
|
|
else if (g_strcmp0 (transfer, "none") == 0)
|
2014-05-06 18:53:21 +02:00
|
|
|
transfer_full = FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_set_error (error, G_MARKUP_ERROR,
|
2024-01-16 17:30:37 +01:00
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"invalid value for 'transfer-ownership' for instance parameter: %s", transfer);
|
2014-05-06 18:53:21 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (CURRENT_NODE (ctx)->type)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_FUNCTION:
|
|
|
|
case GI_IR_NODE_CALLBACK:
|
2014-05-06 18:53:21 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeFunction *func;
|
2014-05-06 18:53:21 +02:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
func = (GIIrNodeFunction *)CURRENT_NODE (ctx);
|
2014-05-06 18:53:21 +02:00
|
|
|
func->instance_transfer_full = transfer_full;
|
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_SIGNAL:
|
2014-05-06 18:53:21 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeSignal *signal;
|
2014-05-06 18:53:21 +02:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
signal = (GIIrNodeSignal *)CURRENT_NODE (ctx);
|
2014-05-06 18:53:21 +02:00
|
|
|
signal->instance_transfer_full = transfer_full;
|
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_VFUNC:
|
2014-05-06 18:53:21 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeVFunc *vfunc;
|
2014-05-06 18:53:21 +02:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
vfunc = (GIIrNodeVFunc *)CURRENT_NODE (ctx);
|
2014-05-06 18:53:21 +02:00
|
|
|
vfunc->instance_transfer_full = transfer_full;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
2024-01-16 02:34:02 +01:00
|
|
|
start_parameter (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *direction;
|
|
|
|
const char *retval;
|
|
|
|
const char *optional;
|
|
|
|
const char *caller_allocates;
|
|
|
|
const char *allow_none;
|
|
|
|
const char *transfer;
|
|
|
|
const char *scope;
|
|
|
|
const char *closure;
|
|
|
|
const char *destroy;
|
|
|
|
const char *skip;
|
|
|
|
const char *nullable;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeParam *param;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
if (!(strcmp (element_name, "parameter") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_FUNCTION_PARAMETERS))
|
2008-08-09 14:46:48 +02:00
|
|
|
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";
|
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
param = (GIIrNodeParam *)gi_ir_node_new (GI_IR_NODE_PARAM,
|
|
|
|
ctx->current_module);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
ctx->current_typed = (GIIrNode*) 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)
|
2024-01-16 17:30:37 +01:00
|
|
|
param->caller_allocates = FALSE;
|
2010-05-26 19:52:36 +02:00
|
|
|
else
|
2024-01-16 17:30:37 +01:00
|
|
|
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;
|
2020-04-08 21:04:03 +02:00
|
|
|
else if (scope && strcmp (scope, "forever") == 0)
|
|
|
|
param->scope = GI_SCOPE_TYPE_FOREVER;
|
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
|
|
|
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
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)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
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_FUNCTION:
|
|
|
|
case GI_IR_NODE_CALLBACK:
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeFunction *func;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
func = (GIIrNodeFunction *)CURRENT_NODE (ctx);
|
|
|
|
func->parameters = g_list_append (func->parameters, param);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_SIGNAL:
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeSignal *signal;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
signal = (GIIrNodeSignal *)CURRENT_NODE (ctx);
|
|
|
|
signal->parameters = g_list_append (signal->parameters, param);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_VFUNC:
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeVFunc *vfunc;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
vfunc = (GIIrNodeVFunc *)CURRENT_NODE (ctx);
|
|
|
|
vfunc->parameters = g_list_append (vfunc->parameters, param);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2024-01-16 02:34:02 +01:00
|
|
|
start_field (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *readable;
|
|
|
|
const char *writable;
|
|
|
|
const char *bits;
|
|
|
|
const char *branch;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeField *field;
|
2010-07-27 12:16:37 +02:00
|
|
|
ParseState target_state;
|
|
|
|
gboolean introspectable;
|
2024-01-26 10:20:07 +01:00
|
|
|
guint64 parsed_bits;
|
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
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
field = (GIIrNodeField *)gi_ir_node_new (GI_IR_NODE_FIELD,
|
|
|
|
ctx->current_module);
|
2010-07-27 12:16:37 +02:00
|
|
|
if (introspectable)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
ctx->current_typed = (GIIrNode*) field;
|
2010-07-27 12:16:37 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
field->type = parse_type (ctx, "gpointer");
|
|
|
|
}
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)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
|
|
|
|
2024-01-26 10:20:07 +01:00
|
|
|
if (bits == NULL)
|
2008-08-24 13:01:44 +02:00
|
|
|
field->bits = 0;
|
2024-01-26 10:20:07 +01:00
|
|
|
else if (g_ascii_string_to_unsigned (bits, 10, 0, G_MAXUINT, &parsed_bits, error))
|
|
|
|
field->bits = parsed_bits;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gi_ir_node_free ((GIIrNode *) field);
|
|
|
|
return FALSE;
|
|
|
|
}
|
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
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_OBJECT:
|
2008-08-24 13:01:44 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
iface = (GIIrNodeInterface *)CURRENT_NODE (ctx);
|
|
|
|
iface->members = g_list_append (iface->members, field);
|
2008-08-24 13:01:44 +02:00
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_INTERFACE:
|
2008-08-24 13:01:44 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
iface = (GIIrNodeInterface *)CURRENT_NODE (ctx);
|
|
|
|
iface->members = g_list_append (iface->members, field);
|
2008-08-24 13:01:44 +02:00
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_BOXED:
|
2008-08-24 13:01:44 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeBoxed *boxed;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
boxed = (GIIrNodeBoxed *)CURRENT_NODE (ctx);
|
|
|
|
boxed->members = g_list_append (boxed->members, field);
|
2008-08-24 13:01:44 +02:00
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_STRUCT:
|
2008-08-24 13:01:44 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeStruct *struct_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
struct_ = (GIIrNodeStruct *)CURRENT_NODE (ctx);
|
|
|
|
struct_->members = g_list_append (struct_->members, field);
|
2008-08-24 13:01:44 +02:00
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_UNION:
|
2008-08-24 13:01:44 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeUnion *union_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
union_ = (GIIrNodeUnion *)CURRENT_NODE (ctx);
|
|
|
|
union_->members = g_list_append (union_->members, field);
|
|
|
|
if (branch)
|
|
|
|
{
|
|
|
|
GIIrNodeConstant *constant;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
constant = (GIIrNodeConstant *) gi_ir_node_new (GI_IR_NODE_CONSTANT,
|
2023-11-08 16:23:31 +01:00
|
|
|
ctx->current_module);
|
2024-01-16 17:30:37 +01:00
|
|
|
((GIIrNode *)constant)->name = g_strdup (name);
|
|
|
|
constant->value = g_strdup (branch);
|
|
|
|
constant->type = union_->discriminator_type;
|
|
|
|
constant->deprecated = FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
union_->discriminators = g_list_append (union_->discriminators, constant);
|
|
|
|
}
|
2008-08-24 13:01:44 +02:00
|
|
|
}
|
|
|
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_alias (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-13 18:10:09 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
2008-08-13 18:10:09 +02:00
|
|
|
|
|
|
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_enum (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *typename;
|
|
|
|
const char *typeinit;
|
|
|
|
const char *deprecated;
|
|
|
|
const char *error_domain;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeEnum *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) ||
|
2024-01-16 17:30:37 +01:00
|
|
|
(strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE)))
|
2010-06-17 02:34:18 +02:00
|
|
|
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)
|
2023-11-08 16:23:31 +01:00
|
|
|
enum_ = (GIIrNodeEnum *) gi_ir_node_new (GI_IR_NODE_ENUM,
|
|
|
|
ctx->current_module);
|
2010-06-17 02:34:18 +02:00
|
|
|
else
|
2023-11-08 16:23:31 +01:00
|
|
|
enum_ = (GIIrNodeEnum *) gi_ir_node_new (GI_IR_NODE_FLAGS,
|
|
|
|
ctx->current_module);
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)enum_)->name = g_strdup (name);
|
2010-06-17 02:34:18 +02:00
|
|
|
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
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
push_node (ctx, (GIIrNode *) enum_);
|
2010-06-17 02:34:18 +02:00
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, enum_);
|
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2024-01-16 02:34:02 +01:00
|
|
|
start_property (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
ParseState target_state;
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *readable;
|
|
|
|
const char *writable;
|
|
|
|
const char *construct;
|
|
|
|
const char *construct_only;
|
|
|
|
const char *transfer;
|
|
|
|
const char *setter;
|
|
|
|
const char *getter;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeProperty *property;
|
|
|
|
GIIrNodeInterface *iface;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "property") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
(ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE)))
|
2010-06-17 02:34:18 +02:00
|
|
|
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);
|
Add introspection data for property accessors
A GObject property can be accessed generically through the GObject API,
e.g. g_object_set_property() and g_object_get_property(). Properties
typically also have public accessor functions, which are (according to
our own best practices) called through the generic API.
The introspection data is currently missing the relation between a
property and its public accessor functions. With this information, a
language binding could, for instance, avoid exposing the C API entirely,
thus minimizing the chances of collisions between property names and
accessor functions; alternatively, a binding could call the C API
directly instead of going through the generic GObject API, thus avoiding
the boxing and unboxing from a native type to a GIArgument and finally
into a GValue, and vice versa.
In the GIR, we add two new attributes to the `property` element:
- setter="SYMBOL"
- getter="SYMBOL"
where "symbol" is the C function identifier of the setter and getter
functions, respectively. The `setter` attribute is only applied to
writable, non-construct-only properties; the `getter` attribute is only
applied to readable properties.
We maintain the ABI compatibility of the typelib data by using 20 bits
of the 25 reserved bits inside the PropertyBlob structure. The data is
exposed through two new GIPropertyInfo methods:
- g_property_info_get_setter()
- g_property_info_get_getter()
which return the GIFunctionInfo for the setter and getter functions,
respectively.
2021-06-17 14:07:35 +02:00
|
|
|
setter = find_attribute ("setter", attribute_names, attribute_values);
|
|
|
|
getter = find_attribute ("getter", 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
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
property = (GIIrNodeProperty *) gi_ir_node_new (GI_IR_NODE_PROPERTY,
|
|
|
|
ctx->current_module);
|
2023-11-08 15:17:52 +01:00
|
|
|
ctx->current_typed = (GIIrNode*) property;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)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
|
|
|
|
Add introspection data for property accessors
A GObject property can be accessed generically through the GObject API,
e.g. g_object_set_property() and g_object_get_property(). Properties
typically also have public accessor functions, which are (according to
our own best practices) called through the generic API.
The introspection data is currently missing the relation between a
property and its public accessor functions. With this information, a
language binding could, for instance, avoid exposing the C API entirely,
thus minimizing the chances of collisions between property names and
accessor functions; alternatively, a binding could call the C API
directly instead of going through the generic GObject API, thus avoiding
the boxing and unboxing from a native type to a GIArgument and finally
into a GValue, and vice versa.
In the GIR, we add two new attributes to the `property` element:
- setter="SYMBOL"
- getter="SYMBOL"
where "symbol" is the C function identifier of the setter and getter
functions, respectively. The `setter` attribute is only applied to
writable, non-construct-only properties; the `getter` attribute is only
applied to readable properties.
We maintain the ABI compatibility of the typelib data by using 20 bits
of the 25 reserved bits inside the PropertyBlob structure. The data is
exposed through two new GIPropertyInfo methods:
- g_property_info_get_setter()
- g_property_info_get_getter()
which return the GIFunctionInfo for the setter and getter functions,
respectively.
2021-06-17 14:07:35 +02:00
|
|
|
property->setter = g_strdup (setter);
|
|
|
|
property->getter = g_strdup (getter);
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
parse_property_transfer (property, transfer, ctx);
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
iface = (GIIrNodeInterface *)CURRENT_NODE (ctx);
|
2010-06-17 02:34:18 +02:00
|
|
|
iface->members = g_list_append (iface->members, property);
|
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2024-01-15 22:20:02 +01:00
|
|
|
static int64_t
|
2024-01-15 20:20:47 +01:00
|
|
|
parse_value (const char *str)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
char *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)
|
|
|
|
{
|
2024-01-15 22:20:02 +01:00
|
|
|
int64_t 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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_member (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *value;
|
|
|
|
const char *deprecated;
|
|
|
|
const char *c_identifier;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeEnum *enum_;
|
|
|
|
GIIrNodeValue *value_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "member") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_ENUM))
|
2010-06-17 02:34:18 +02:00
|
|
|
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
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
value_ = (GIIrNodeValue *) gi_ir_node_new (GI_IR_NODE_VALUE,
|
|
|
|
ctx->current_module);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)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
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
g_hash_table_insert (((GIIrNode *)value_)->attributes,
|
2011-02-22 16:02:12 +01:00
|
|
|
g_strdup ("c:identifier"),
|
|
|
|
g_strdup (c_identifier));
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
enum_ = (GIIrNodeEnum *)CURRENT_NODE (ctx);
|
2010-06-17 02:34:18 +02:00
|
|
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_constant (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
ParseState prev_state;
|
|
|
|
ParseState target_state;
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *value;
|
|
|
|
const char *deprecated;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeConstant *constant;
|
2010-06-17 02:34:18 +02:00
|
|
|
|
|
|
|
if (!(strcmp (element_name, "constant") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
(ctx->state == STATE_NAMESPACE ||
|
|
|
|
ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE)))
|
2010-06-17 02:34:18 +02:00
|
|
|
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
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
constant = (GIIrNodeConstant *) gi_ir_node_new (GI_IR_NODE_CONSTANT,
|
|
|
|
ctx->current_module);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)constant)->name = g_strdup (name);
|
2010-06-17 02:34:18 +02:00
|
|
|
constant->value = g_strdup (value);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
ctx->current_typed = (GIIrNode*) 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)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
push_node (ctx, (GIIrNode *) constant);
|
2010-06-17 02:34:18 +02:00
|
|
|
ctx->current_module->entries =
|
2024-01-16 17:30:37 +01:00
|
|
|
g_list_append (ctx->current_module->entries, constant);
|
2010-06-17 02:34:18 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
iface = (GIIrNodeInterface *)CURRENT_NODE (ctx);
|
2010-06-17 02:34:18 +02:00
|
|
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_interface (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *typename;
|
|
|
|
const char *typeinit;
|
|
|
|
const char *deprecated;
|
|
|
|
const char *glib_type_struct;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "interface") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_NAMESPACE))
|
2010-06-17 02:34:18 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
iface = (GIIrNodeInterface *) gi_ir_node_new (GI_IR_NODE_INTERFACE,
|
|
|
|
ctx->current_module);
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)iface)->name = g_strdup (name);
|
2010-06-17 02:34:18 +02:00
|
|
|
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;
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
push_node (ctx, (GIIrNode *) iface);
|
2010-06-17 02:34:18 +02:00
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, iface);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
static gboolean
|
2024-01-16 02:34:02 +01:00
|
|
|
start_class (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *parent;
|
|
|
|
const char *glib_type_struct;
|
|
|
|
const char *typename;
|
|
|
|
const char *typeinit;
|
|
|
|
const char *deprecated;
|
|
|
|
const char *abstract;
|
|
|
|
const char *fundamental;
|
|
|
|
const char *final;
|
|
|
|
const char *ref_func;
|
|
|
|
const char *unref_func;
|
|
|
|
const char *set_value_func;
|
|
|
|
const char *get_value_func;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeInterface *iface;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "class") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_NAMESPACE))
|
2010-06-17 02:34:18 +02:00
|
|
|
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);
|
2021-02-09 12:38:27 +01:00
|
|
|
final = find_attribute ("final", 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
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
iface = (GIIrNodeInterface *) gi_ir_node_new (GI_IR_NODE_OBJECT,
|
|
|
|
ctx->current_module);
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)iface)->name = g_strdup (name);
|
2010-06-17 02:34:18 +02:00
|
|
|
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;
|
2021-02-09 12:38:27 +01:00
|
|
|
iface->final_ = final && strcmp (final, "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);
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
push_node (ctx, (GIIrNode *) iface);
|
2010-06-17 02:34:18 +02:00
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, iface);
|
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2024-01-16 02:34:02 +01:00
|
|
|
start_type (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *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;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeType *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 ||
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_FUNCTION_RETURN ||
|
|
|
|
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 ||
|
|
|
|
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)
|
2024-01-16 17:30:37 +01:00
|
|
|
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)
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-08-03 19:01:35 +02:00
|
|
|
|
|
|
|
key = g_strdup_printf ("%s.%s", ctx->namespace, ctx->current_alias);
|
|
|
|
if (!strchr (name, '.'))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2010-08-03 19:01:35 +02:00
|
|
|
else
|
2024-01-16 17:30:37 +01:00
|
|
|
value = g_strdup (name);
|
2010-08-03 19:01:35 +02:00
|
|
|
|
|
|
|
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,
|
2024-01-16 17:30:37 +01:00
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"The element <type> is invalid here");
|
2008-08-09 14:46:48 +02:00
|
|
|
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
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
typenode = (GIIrNodeType *)gi_ir_node_new (GI_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) {
|
2024-01-26 10:15:43 +01:00
|
|
|
guint64 parsed_uint;
|
|
|
|
|
2010-05-04 16:57:51 +02:00
|
|
|
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;
|
2024-01-26 10:15:43 +01:00
|
|
|
if (!typenode->has_length)
|
|
|
|
typenode->length = -1;
|
|
|
|
else if (g_ascii_string_to_unsigned (len, 10, 0, G_MAXUINT, &parsed_uint, error))
|
|
|
|
typenode->length = parsed_uint;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gi_ir_node_free ((GIIrNode *) typenode);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-05-04 16:57:51 +02:00
|
|
|
|
|
|
|
typenode->has_size = size != NULL;
|
2024-01-26 10:15:43 +01:00
|
|
|
if (!typenode->has_size)
|
|
|
|
typenode->size = -1;
|
|
|
|
else if (g_ascii_string_to_unsigned (size, 10, 0, G_MAXSIZE, &parsed_uint, error))
|
|
|
|
typenode->size = parsed_uint;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gi_ir_node_free ((GIIrNode *) typenode);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-05-04 16:57:51 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
if (typenode->has_size && ctx->current_typed->type == GI_IR_NODE_FIELD)
|
2010-06-02 19:36:59 +02:00
|
|
|
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)
|
2024-01-16 17:30:37 +01: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
|
|
|
|
2024-01-16 17:30:37 +01: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
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
if (ctx->current_typed->type == GI_IR_NODE_PARAM &&
|
|
|
|
((GIIrNodeParam *)ctx->current_typed)->out &&
|
2008-11-16 21:58:35 +01:00
|
|
|
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);
|
|
|
|
|
2022-07-13 14:26:44 +02:00
|
|
|
/* A "pointer" structure is one where the c:type is a typedef that
|
|
|
|
* to a pointer to a structure; we used to call them "disguised"
|
|
|
|
* structures as well.
|
2008-11-11 00:58:49 +01:00
|
|
|
*/
|
2022-07-13 14:26:44 +02:00
|
|
|
if (typenode->tag == GI_TYPE_TAG_INTERFACE)
|
|
|
|
{
|
|
|
|
gboolean is_pointer = FALSE;
|
|
|
|
gboolean is_disguised = FALSE;
|
|
|
|
|
|
|
|
is_pointer_or_disguised_structure (ctx, typenode->giinterface,
|
|
|
|
&is_pointer,
|
|
|
|
&is_disguised);
|
|
|
|
|
|
|
|
if (is_pointer || is_disguised)
|
2024-01-16 17:30:37 +01:00
|
|
|
pointer_depth++;
|
2022-07-13 14:26:44 +02:00
|
|
|
}
|
2008-11-11 00:58:49 +01:00
|
|
|
|
2008-11-16 21:58:35 +01:00
|
|
|
if (pointer_depth > 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
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)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeType *typenode;
|
2008-10-02 16:07:38 +02:00
|
|
|
|
|
|
|
if (!ctx->type_parameters)
|
|
|
|
goto out;
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
typenode = (GIIrNodeType*)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)
|
2024-01-16 17:30:37 +01: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)
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
typenode->parameter_type1 = parse_type (ctx, "gpointer");
|
|
|
|
typenode->parameter_type2 = parse_type (ctx, "gpointer");
|
|
|
|
}
|
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)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_PARAM:
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeParam *param = (GIIrNodeParam *)ctx->current_typed;
|
|
|
|
param->type = typenode;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_FIELD:
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeField *field = (GIIrNodeField *)ctx->current_typed;
|
|
|
|
field->type = typenode;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_PROPERTY:
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeProperty *property = (GIIrNodeProperty *) ctx->current_typed;
|
|
|
|
property->type = typenode;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_CONSTANT:
|
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
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeConstant *constant = (GIIrNodeConstant *)ctx->current_typed;
|
|
|
|
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)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeType *parent;
|
|
|
|
GIIrNodeType *param = NULL;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
parent = (GIIrNodeType *) ((GList*)ctx->type_stack->data)->data;
|
2008-10-16 00:08:26 +02:00
|
|
|
if (ctx->type_parameters)
|
2023-11-08 15:17:52 +01:00
|
|
|
param = (GIIrNodeType *) 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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_attribute (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2009-02-20 03:48:51 +01:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *value;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNode *curnode;
|
2009-02-20 03:48:51 +01:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
if (ctx->current_typed && ctx->current_typed->type == GI_IR_NODE_PARAM)
|
2010-06-15 17:01:37 +02:00
|
|
|
{
|
|
|
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_return_value (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeParam *param;
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *transfer;
|
|
|
|
const char *skip;
|
|
|
|
const char *nullable;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "return-value") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_FUNCTION))
|
2010-06-17 02:34:18 +02:00
|
|
|
return FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
param = (GIIrNodeParam *)gi_ir_node_new (GI_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
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
ctx->current_typed = (GIIrNode*) 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)
|
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_FUNCTION:
|
|
|
|
case GI_IR_NODE_CALLBACK:
|
2010-06-17 02:34:18 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeFunction *func = (GIIrNodeFunction *)CURRENT_NODE (ctx);
|
|
|
|
func->result = param;
|
2010-06-17 02:34:18 +02:00
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_SIGNAL:
|
2010-06-17 02:34:18 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeSignal *signal = (GIIrNodeSignal *)CURRENT_NODE (ctx);
|
|
|
|
signal->result = param;
|
2010-06-17 02:34:18 +02:00
|
|
|
}
|
|
|
|
break;
|
2023-11-08 15:17:52 +01:00
|
|
|
case GI_IR_NODE_VFUNC:
|
2010-06-17 02:34:18 +02:00
|
|
|
{
|
2024-01-16 17:30:37 +01:00
|
|
|
GIIrNodeVFunc *vfunc = (GIIrNodeVFunc *)CURRENT_NODE (ctx);
|
|
|
|
vfunc->result = param;
|
2010-06-17 02:34:18 +02:00
|
|
|
}
|
|
|
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_implements (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-25 17:22:39 +02:00
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeInterface *iface;
|
2008-08-25 17:22:39 +02:00
|
|
|
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
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
iface = (GIIrNodeInterface *)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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_glib_signal (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *when;
|
|
|
|
const char *no_recurse;
|
|
|
|
const char *detailed;
|
|
|
|
const char *action;
|
|
|
|
const char *no_hooks;
|
|
|
|
const char *has_class_closure;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeInterface *iface;
|
|
|
|
GIIrNodeSignal *signal;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "glib:signal") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
(ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE)))
|
2010-06-17 02:34:18 +02:00
|
|
|
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;
|
|
|
|
}
|
2023-11-08 16:23:31 +01:00
|
|
|
signal = (GIIrNodeSignal *)gi_ir_node_new (GI_IR_NODE_SIGNAL,
|
|
|
|
ctx->current_module);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)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
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
iface = (GIIrNodeInterface *)CURRENT_NODE (ctx);
|
2010-06-17 02:34:18 +02:00
|
|
|
iface->members = g_list_append (iface->members, signal);
|
2010-06-17 02:34:18 +02:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
push_node (ctx, (GIIrNode *)signal);
|
2010-06-17 02:34:18 +02:00
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2024-01-16 02:34:02 +01:00
|
|
|
start_vfunc (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *must_chain_up;
|
|
|
|
const char *override;
|
|
|
|
const char *is_class_closure;
|
|
|
|
const char *offset;
|
|
|
|
const char *invoker;
|
|
|
|
const char *throws;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeInterface *iface;
|
|
|
|
GIIrNodeVFunc *vfunc;
|
2024-01-26 10:19:11 +01:00
|
|
|
guint64 parsed_offset;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "virtual-method") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
(ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE)))
|
2010-06-17 02:34:18 +02:00
|
|
|
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
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
vfunc = (GIIrNodeVFunc *)gi_ir_node_new (GI_IR_NODE_VFUNC,
|
|
|
|
ctx->current_module);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)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;
|
|
|
|
|
2024-01-26 10:19:11 +01:00
|
|
|
if (offset == NULL)
|
2010-08-29 22:48:54 +02:00
|
|
|
vfunc->offset = 0xFFFF;
|
2024-01-26 10:19:11 +01:00
|
|
|
else if (g_ascii_string_to_unsigned (offset, 10, 0, G_MAXSIZE, &parsed_offset, error))
|
|
|
|
vfunc->offset = parsed_offset;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gi_ir_node_free ((GIIrNode *) vfunc);
|
|
|
|
return FALSE;
|
|
|
|
}
|
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
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
iface = (GIIrNodeInterface *)CURRENT_NODE (ctx);
|
2010-06-17 02:34:18 +02:00
|
|
|
iface->members = g_list_append (iface->members, vfunc);
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
push_node (ctx, (GIIrNode *)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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_struct (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *deprecated;
|
|
|
|
const char *disguised;
|
|
|
|
const char *opaque;
|
|
|
|
const char *pointer;
|
|
|
|
const char *gtype_name;
|
|
|
|
const char *gtype_init;
|
|
|
|
const char *gtype_struct;
|
|
|
|
const char *foreign;
|
|
|
|
const char *copy_func;
|
|
|
|
const char *free_func;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeStruct *struct_;
|
2010-06-17 02:34:18 +02:00
|
|
|
|
|
|
|
if (!(strcmp (element_name, "record") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
(ctx->state == STATE_NAMESPACE ||
|
|
|
|
ctx->state == STATE_UNION ||
|
|
|
|
ctx->state == STATE_STRUCT ||
|
|
|
|
ctx->state == STATE_CLASS)))
|
2010-06-17 02:34:18 +02:00
|
|
|
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);
|
2022-07-13 14:26:44 +02:00
|
|
|
pointer = find_attribute ("pointer", attribute_names, attribute_values);
|
|
|
|
opaque = find_attribute ("opaque", attribute_names, attribute_values);
|
2010-06-17 02:34:18 +02:00
|
|
|
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);
|
2022-10-29 19:09:23 +02:00
|
|
|
copy_func = find_attribute ("copy-function", attribute_names, attribute_values);
|
|
|
|
free_func = find_attribute ("free-function", 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
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
struct_ = (GIIrNodeStruct *) gi_ir_node_new (GI_IR_NODE_STRUCT,
|
|
|
|
ctx->current_module);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)struct_)->name = g_strdup (name ? name : "");
|
2010-06-17 02:34:18 +02:00
|
|
|
if (deprecated)
|
|
|
|
struct_->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
struct_->deprecated = FALSE;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2022-07-13 14:26:44 +02:00
|
|
|
if (g_strcmp0 (disguised, "1") == 0)
|
2010-06-17 02:34:18 +02:00
|
|
|
struct_->disguised = TRUE;
|
2008-11-11 00:58:49 +01:00
|
|
|
|
2022-07-13 14:26:44 +02:00
|
|
|
if (g_strcmp0 (pointer, "1") == 0)
|
|
|
|
struct_->pointer = TRUE;
|
|
|
|
|
|
|
|
if (g_strcmp0 (opaque, "1") == 0)
|
|
|
|
struct_->opaque = TRUE;
|
|
|
|
|
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
|
|
|
|
2022-10-29 19:09:23 +02:00
|
|
|
struct_->copy_func = g_strdup (copy_func);
|
|
|
|
struct_->free_func = g_strdup (free_func);
|
|
|
|
|
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_);
|
2023-11-08 15:17:52 +01:00
|
|
|
push_node (ctx, (GIIrNode *)struct_);
|
2010-06-17 02:34:18 +02:00
|
|
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
start_union (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *deprecated;
|
|
|
|
const char *typename;
|
|
|
|
const char *typeinit;
|
|
|
|
const char *copy_func;
|
|
|
|
const char *free_func;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrNodeUnion *union_;
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "union") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
(ctx->state == STATE_NAMESPACE ||
|
|
|
|
ctx->state == STATE_UNION ||
|
|
|
|
ctx->state == STATE_STRUCT ||
|
|
|
|
ctx->state == STATE_CLASS)))
|
2010-06-17 02:34:18 +02:00
|
|
|
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);
|
2022-10-29 19:09:23 +02:00
|
|
|
copy_func = find_attribute ("copy-function", attribute_names, attribute_values);
|
|
|
|
free_func = find_attribute ("free-function", 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
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
union_ = (GIIrNodeUnion *) gi_ir_node_new (GI_IR_NODE_UNION,
|
|
|
|
ctx->current_module);
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNode *)union_)->name = g_strdup (name ? name : "");
|
2010-06-17 02:34:18 +02:00
|
|
|
union_->gtype_name = g_strdup (typename);
|
|
|
|
union_->gtype_init = g_strdup (typeinit);
|
2022-10-29 19:09:23 +02:00
|
|
|
union_->copy_func = g_strdup (copy_func);
|
|
|
|
union_->free_func = g_strdup (free_func);
|
2010-06-17 02:34:18 +02:00
|
|
|
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_);
|
2023-11-08 15:17:52 +01:00
|
|
|
push_node (ctx, (GIIrNode *)union_);
|
2010-06-17 02:34:18 +02:00
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2024-01-16 02:34:02 +01:00
|
|
|
start_discriminator (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *type;
|
|
|
|
const char *offset;
|
2024-01-26 10:21:22 +01:00
|
|
|
guint64 parsed_offset;
|
|
|
|
|
2010-06-17 02:34:18 +02:00
|
|
|
if (!(strcmp (element_name, "discriminator") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_UNION))
|
2010-06-17 02:34:18 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-11-08 15:17:52 +01:00
|
|
|
((GIIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_type
|
2010-06-17 02:34:18 +02:00
|
|
|
= parse_type (ctx, type);
|
2024-01-26 10:21:22 +01:00
|
|
|
|
|
|
|
if (g_ascii_string_to_unsigned (offset, 10, 0, G_MAXSIZE, &parsed_offset, error))
|
|
|
|
((GIIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_offset = parsed_offset;
|
|
|
|
else
|
|
|
|
return FALSE;
|
2010-06-17 02:34:18 +02:00
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
|
|
|
|
static gboolean
|
|
|
|
parse_include (GMarkupParseContext *context,
|
2024-01-16 17:30:37 +01:00
|
|
|
ParseContext *ctx,
|
|
|
|
const char *name,
|
|
|
|
const char *version)
|
2008-08-28 23:19:22 +02:00
|
|
|
{
|
2010-06-17 02:34:18 +02:00
|
|
|
GError *error = NULL;
|
2024-01-15 20:20:47 +01:00
|
|
|
char *buffer;
|
2008-08-28 23:19:22 +02:00
|
|
|
gsize length;
|
2024-01-15 20:20:47 +01:00
|
|
|
char *girpath, *girname;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrModule *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
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrModule *m = l->data;
|
2008-11-11 01:48:17 +01:00
|
|
|
|
|
|
|
if (strcmp (m->name, name) == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
if (strcmp (m->version, version) == 0)
|
|
|
|
{
|
|
|
|
ctx->include_modules = g_list_prepend (ctx->include_modules, m);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_printerr ("Module '%s' imported with conflicting versions '%s' and '%s'\n",
|
|
|
|
name, m->version, version);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2008-11-11 01:48:17 +01:00
|
|
|
}
|
|
|
|
|
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",
|
2024-01-16 17:30:37 +01:00
|
|
|
girname);
|
2009-03-28 13:34:36 +01:00
|
|
|
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
|
|
|
|
2023-12-20 23:41:10 +01:00
|
|
|
g_debug ("Parsing include %s", 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
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
module = gi_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,
|
2024-01-16 17:30:37 +01:00
|
|
|
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
|
|
|
static void
|
2024-01-16 02:34:02 +01:00
|
|
|
start_element_handler (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
const char **attribute_names,
|
|
|
|
const char **attribute_values,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ParseContext *ctx = user_data;
|
|
|
|
|
2024-02-14 11:36:23 +01:00
|
|
|
if (ctx->parser->logged_levels & G_LOG_LEVEL_DEBUG)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
GString *tags = g_string_new ("");
|
|
|
|
int i;
|
|
|
|
for (i = 0; attribute_names[i]; i++)
|
|
|
|
g_string_append_printf (tags, "%s=\"%s\" ",
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names[i],
|
|
|
|
attribute_values[i]);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
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)
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_ALIAS);
|
|
|
|
goto out;
|
|
|
|
}
|
2008-09-29 21:03:44 +02:00
|
|
|
if (start_type (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
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,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
case 'c':
|
2010-03-24 19:00:06 +01:00
|
|
|
if (start_function (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
else if (start_constant (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2010-03-24 19:00:06 +01:00
|
|
|
else if (start_class (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'd':
|
2010-03-24 19:00:06 +01:00
|
|
|
if (start_discriminator (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
2018-11-20 01:49:13 +01:00
|
|
|
goto out;
|
2013-05-21 10:47:11 +02:00
|
|
|
if (strcmp ("doc", element_name) == 0 || strcmp ("doc-deprecated", element_name) == 0 ||
|
2020-06-06 02:13:38 +02:00
|
|
|
strcmp ("doc-stability", element_name) == 0 || strcmp ("doc-version", element_name) == 0 ||
|
|
|
|
strcmp ("docsection", 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,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'f':
|
2015-07-15 13:11:45 +02:00
|
|
|
if (strcmp ("function-macro", element_name) == 0)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_PASSTHROUGH);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
else if (start_function (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2010-03-24 19:00:06 +01:00
|
|
|
else if (start_field (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'g':
|
|
|
|
if (start_glib_boxed (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
else if (start_glib_signal (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'i':
|
2008-08-23 18:11:01 +02:00
|
|
|
if (strcmp (element_name, "include") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_REPOSITORY)
|
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
|
|
|
const char *version;
|
2024-01-16 17:30:37 +01:00
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
version = find_attribute ("version", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (version == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "version");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->dependencies = g_list_prepend (ctx->dependencies,
|
|
|
|
g_strdup_printf ("%s-%s", name, version));
|
|
|
|
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_INCLUDE);
|
|
|
|
goto out;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
if (start_interface (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-25 17:22:39 +02:00
|
|
|
else if (start_implements (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2014-05-06 18:53:21 +02:00
|
|
|
else if (start_instance_parameter (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2010-07-22 00:55:24 +02:00
|
|
|
else if (strcmp (element_name, "c:include") == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
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,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2010-03-24 19:00:06 +01:00
|
|
|
else if (start_member (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name, *version, *shared_library, *cprefix;
|
2024-01-16 17:30:37 +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;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
version = find_attribute ("version", attribute_names, attribute_values);
|
|
|
|
shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
|
|
|
|
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
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else if (version == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "version");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GList *l;
|
2008-11-12 18:17:01 +01:00
|
|
|
|
2024-01-16 17:30:37 +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);
|
2008-11-12 18:16:49 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->current_module = gi_ir_module_new (name, version, shared_library, cprefix);
|
2008-11-12 18:17:01 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->current_module->aliases = ctx->aliases;
|
|
|
|
ctx->aliases = NULL;
|
|
|
|
ctx->current_module->disguised_structures = ctx->disguised_structures;
|
|
|
|
ctx->current_module->pointer_structures = ctx->pointer_structures;
|
|
|
|
ctx->disguised_structures = NULL;
|
|
|
|
ctx->pointer_structures = NULL;
|
2008-11-12 18:17:01 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
for (l = ctx->include_modules; l; l = l->next)
|
|
|
|
gi_ir_module_add_include_module (ctx->current_module, l->data);
|
2008-11-12 18:17:01 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
g_list_free (ctx->include_modules);
|
|
|
|
ctx->include_modules = NULL;
|
2008-11-12 18:17:08 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->modules = g_list_append (ctx->modules, ctx->current_module);
|
|
|
|
ctx->current_module->dependencies = ctx->dependencies;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'p':
|
|
|
|
if (start_property (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
else if (strcmp (element_name, "parameters") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_FUNCTION)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION_PARAMETERS);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
goto out;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
else if (start_parameter (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-11-17 01:27:37 +01:00
|
|
|
else if (strcmp (element_name, "prerequisite") == 0 &&
|
2024-01-16 17:30:37 +01:00
|
|
|
ctx->state == STATE_INTERFACE)
|
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *name;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
2008-11-17 01:27:37 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
state_switch (ctx, STATE_PREREQUISITE);
|
2008-11-17 01:27:37 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIIrNodeInterface *iface;
|
2008-11-17 01:27:37 +01:00
|
|
|
|
2024-01-16 17:30:37 +01:00
|
|
|
iface = (GIIrNodeInterface *)CURRENT_NODE(ctx);
|
|
|
|
iface->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
|
|
|
|
}
|
|
|
|
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)
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *version;
|
2024-01-16 17:30:37 +01:00
|
|
|
|
|
|
|
version = find_attribute ("version", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (version == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "version");
|
|
|
|
else if (strcmp (version, SUPPORTED_GIR_VERSION) != 0)
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Unsupported version '%s'",
|
|
|
|
version);
|
|
|
|
else
|
|
|
|
state_switch (ctx, STATE_REPOSITORY);
|
|
|
|
|
|
|
|
goto out;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
else if (start_return_value (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
else if (start_struct (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
2018-11-20 01:49:13 +01:00
|
|
|
case 's':
|
|
|
|
if (strcmp ("source-position", element_name) == 0)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_PASSTHROUGH);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
break;
|
2008-08-09 14:46:48 +02:00
|
|
|
case 'u':
|
|
|
|
if (start_union (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 't':
|
|
|
|
if (start_type (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'v':
|
|
|
|
if (start_vfunc (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-10-02 16:07:38 +02:00
|
|
|
if (start_type (context, element_name,
|
2024-01-16 17:30:37 +01:00
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
2018-07-29 17:13:16 +02:00
|
|
|
default:
|
|
|
|
break;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2010-08-03 19:01:35 +02:00
|
|
|
if (*error == NULL && ctx->state != STATE_PASSTHROUGH)
|
2009-02-11 01:08:49 +01:00
|
|
|
{
|
2024-01-15 22:20:02 +01:00
|
|
|
int line_number, char_number;
|
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:"))
|
2024-01-16 17:30:37 +01: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
|
|
|
{
|
2024-01-15 22:20:02 +01:00
|
|
|
int line_number, char_number;
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
require_one_of_end_elements (GMarkupParseContext *context,
|
|
|
|
ParseContext *ctx,
|
|
|
|
const char *actual_name,
|
|
|
|
GError **error,
|
2024-01-16 17:30:37 +01:00
|
|
|
...)
|
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)
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
matched = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
va_end (args);
|
|
|
|
|
|
|
|
if (matched)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
|
|
g_set_error (error,
|
2024-01-16 17:30:37 +01:00
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Unexpected end tag '%s' on line %d char %d; current state=%d (prev=%d)",
|
|
|
|
actual_name,
|
|
|
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
state_switch_end_struct_or_union (GMarkupParseContext *context,
|
|
|
|
ParseContext *ctx,
|
|
|
|
const char *element_name,
|
|
|
|
GError **error)
|
2009-02-04 01:48:24 +01:00
|
|
|
{
|
|
|
|
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
|
|
|
{
|
2023-11-08 15:17:52 +01:00
|
|
|
if (CURRENT_NODE (ctx)->type == GI_IR_NODE_STRUCT)
|
2009-02-04 01:48:24 +01:00
|
|
|
state_switch (ctx, STATE_STRUCT);
|
2023-11-08 15:17:52 +01:00
|
|
|
else if (CURRENT_NODE (ctx)->type == GI_IR_NODE_UNION)
|
2009-02-04 01:48:24 +01:00
|
|
|
state_switch (ctx, STATE_UNION);
|
2023-11-08 15:17:52 +01:00
|
|
|
else if (CURRENT_NODE (ctx)->type == GI_IR_NODE_OBJECT)
|
2009-02-04 01:48:24 +01:00
|
|
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
require_end_element (GMarkupParseContext *context,
|
|
|
|
ParseContext *ctx,
|
|
|
|
const char *expected_name,
|
|
|
|
const char *actual_name,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
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
|
2024-01-16 02:34:02 +01:00
|
|
|
end_element_handler (GMarkupParseContext *context,
|
|
|
|
const char *element_name,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
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))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
2008-08-23 18:11:01 +02:00
|
|
|
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))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
2010-07-22 00:55:24 +02:00
|
|
|
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))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
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))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
g_free (ctx->current_alias);
|
|
|
|
ctx->current_alias = NULL;
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
2008-08-13 18:10:09 +02:00
|
|
|
break;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
case STATE_FUNCTION_RETURN:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "return-value", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_FUNCTION_PARAMETERS:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "parameters", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_FUNCTION_PARAMETER:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "parameter", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION_PARAMETERS);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_FUNCTION:
|
2008-10-02 16:07:38 +02:00
|
|
|
{
|
2009-02-04 01:48:17 +01:00
|
|
|
pop_node (ctx);
|
2024-01-16 17:30:37 +01:00
|
|
|
if (ctx->node_stack == NULL)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
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
|
|
|
}
|
2024-01-16 17:30:37 +01:00
|
|
|
else if (CURRENT_NODE (ctx)->type == GI_IR_NODE_INTERFACE)
|
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
else if (CURRENT_NODE (ctx)->type == GI_IR_NODE_OBJECT)
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
else if (CURRENT_NODE (ctx)->type == GI_IR_NODE_BOXED)
|
|
|
|
state_switch (ctx, STATE_BOXED);
|
|
|
|
else if (CURRENT_NODE (ctx)->type == GI_IR_NODE_STRUCT)
|
|
|
|
state_switch (ctx, STATE_STRUCT);
|
|
|
|
else if (CURRENT_NODE (ctx)->type == GI_IR_NODE_UNION)
|
|
|
|
state_switch (ctx, STATE_UNION);
|
|
|
|
else if (CURRENT_NODE (ctx)->type == GI_IR_NODE_ENUM ||
|
|
|
|
CURRENT_NODE (ctx)->type == GI_IR_NODE_FLAGS)
|
|
|
|
state_switch (ctx, STATE_ENUM);
|
|
|
|
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-10-02 16:07:38 +02:00
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_CLASS_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_CLASS_PROPERTY:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "property", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_CLASS:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "class", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
pop_node (ctx);
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_INTERFACE_PROPERTY:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (strcmp ("type", element_name) == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "property", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_INTERFACE_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_INTERFACE:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "interface", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
pop_node (ctx);
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_ENUM:
|
|
|
|
if (strcmp ("member", element_name) == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2011-08-13 17:28:30 +02:00
|
|
|
else if (strcmp ("function", element_name) == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2010-03-24 19:00:06 +01:00
|
|
|
else if (require_one_of_end_elements (context, ctx,
|
2024-01-16 17:30:37 +01:00
|
|
|
element_name, error, "enumeration",
|
|
|
|
"bitfield", NULL))
|
|
|
|
{
|
|
|
|
pop_node (ctx);
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_BOXED:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "glib:boxed", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
pop_node (ctx);
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_BOXED_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_BOXED);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_STRUCT_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_STRUCT);
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_STRUCT:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "record", element_name, error))
|
2024-01-16 17:30:37 +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)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2008-08-20 17:05:46 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_UNION);
|
|
|
|
}
|
2008-08-20 17:05:46 +02:00
|
|
|
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))
|
2024-01-16 17:30:37 +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)
|
2024-01-16 17:30:37 +01:00
|
|
|
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)
|
2024-01-16 17:30:37 +01:00
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "constant", element_name, error))
|
2024-01-16 17:30:37 +01:00
|
|
|
{
|
|
|
|
switch (ctx->state)
|
|
|
|
{
|
|
|
|
case STATE_NAMESPACE_CONSTANT:
|
|
|
|
pop_node (ctx);
|
|
|
|
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) ||
|
2024-01-16 17:30:37 +01:00
|
|
|
(strcmp ("varargs", element_name) == 0))
|
|
|
|
{
|
|
|
|
end_type (ctx);
|
|
|
|
}
|
2018-07-29 16:36:31 +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:
|
2023-12-20 23:41:10 +01:00
|
|
|
g_error ("Unhandled state %d in end_element_handler", ctx->state);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-24 19:00:06 +01:00
|
|
|
static void
|
2024-01-16 02:34:02 +01:00
|
|
|
text_handler (GMarkupParseContext *context,
|
|
|
|
const char *text,
|
|
|
|
gsize text_len,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
/* FIXME warn about non-whitespace text */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cleanup (GMarkupParseContext *context,
|
2024-01-16 17:30:37 +01:00
|
|
|
GError *error,
|
2024-01-15 20:16:00 +01:00
|
|
|
void *user_data)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ParseContext *ctx = user_data;
|
|
|
|
GList *m;
|
|
|
|
|
|
|
|
for (m = ctx->modules; m; m = m->next)
|
2023-11-08 16:23:31 +01:00
|
|
|
gi_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
|
|
|
/**
|
2023-11-08 16:23:31 +01:00
|
|
|
* gi_ir_parser_parse_string:
|
2023-11-08 15:17:52 +01:00
|
|
|
* @parser: a #GIIrParser
|
2009-02-12 04:32:25 +01:00
|
|
|
* @namespace: the namespace of the string
|
2023-12-13 14:25:02 +01:00
|
|
|
* @filename: (nullable) (type filename): Path to parsed file, or `NULL`
|
|
|
|
* @buffer: (array length=length): the data containing the XML
|
|
|
|
* @length: length of the data, in bytes
|
|
|
|
* @error: return location for a [type@GLib.Error], or `NULL`
|
2008-11-12 18:16:42 +01:00
|
|
|
*
|
|
|
|
* Parse a string that holds a complete GIR XML file, and return a list of a
|
2023-12-13 14:25:02 +01:00
|
|
|
* a [class@GIRepository.IrModule] for each `<namespace/>` element within the
|
|
|
|
* file.
|
2008-11-12 18:16:42 +01:00
|
|
|
*
|
2023-12-13 14:25:02 +01:00
|
|
|
* Returns: (transfer none): a new [class@GIRepository.IrModule]
|
|
|
|
* Since: 2.80
|
2008-11-12 18:16:42 +01:00
|
|
|
*/
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrModule *
|
2023-11-08 16:23:31 +01:00
|
|
|
gi_ir_parser_parse_string (GIIrParser *parser,
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *namespace,
|
|
|
|
const char *filename,
|
|
|
|
const char *buffer,
|
2023-11-08 16:23:31 +01:00
|
|
|
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);
|
2022-07-13 14:26:44 +02:00
|
|
|
ctx.pointer_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),
|
2024-01-16 17:30:37 +01:00
|
|
|
parser->parsed_modules);
|
2008-11-12 18:17:15 +01:00
|
|
|
|
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.
|
|
|
|
*/
|
2022-07-13 14:26:44 +02:00
|
|
|
g_clear_pointer (&ctx.aliases, g_hash_table_unref);
|
|
|
|
g_clear_pointer (&ctx.disguised_structures, g_hash_table_unref);
|
|
|
|
g_clear_pointer (&ctx.pointer_structures, g_hash_table_unref);
|
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
|
|
|
/**
|
2023-11-08 16:23:31 +01:00
|
|
|
* gi_ir_parser_parse_file:
|
2023-11-08 15:17:52 +01:00
|
|
|
* @parser: a #GIIrParser
|
2023-12-13 14:25:02 +01:00
|
|
|
* @filename: (type filename): filename to parse
|
|
|
|
* @error: return location for a [type@GLib.Error], or `NULL`
|
2008-11-12 18:16:42 +01:00
|
|
|
*
|
2023-12-13 14:25:02 +01:00
|
|
|
* Parse the given GIR XML file, and return a list of a
|
|
|
|
* [class@GIRepository.IrModule] for each `<namespace/>` element within the
|
|
|
|
* file.
|
2008-11-12 18:16:42 +01:00
|
|
|
*
|
2023-12-13 14:25:02 +01:00
|
|
|
* Returns: (transfer container): a newly allocated list of
|
|
|
|
* [class@GIRepository.IrModule]s. The modules themselves
|
|
|
|
* are owned by the `GIIrParser` and will be freed along with the parser.
|
|
|
|
* Since: 2.80
|
2008-11-12 18:16:42 +01:00
|
|
|
*/
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrModule *
|
2023-11-08 16:23:31 +01:00
|
|
|
gi_ir_parser_parse_file (GIIrParser *parser,
|
2024-01-15 20:20:47 +01:00
|
|
|
const char *filename,
|
2023-11-08 16:23:31 +01:00
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2024-01-15 20:20:47 +01:00
|
|
|
char *buffer;
|
2008-08-09 14:46:48 +02:00
|
|
|
gsize length;
|
2023-11-08 15:17:52 +01:00
|
|
|
GIIrModule *module;
|
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,
|
2024-01-16 17:30:37 +01:00
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Expected filename to end with '.gir'");
|
2008-08-28 23:19:22 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
g_debug ("[parsing] filename %s", filename);
|
|
|
|
|
2023-08-08 21:21:36 +02:00
|
|
|
namespace = g_path_get_basename (filename);
|
2008-08-28 23:19:22 +02:00
|
|
|
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))
|
2021-05-20 12:37:56 +02:00
|
|
|
{
|
|
|
|
g_free (namespace);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-03-24 19:00:06 +01:00
|
|
|
|
2023-11-08 16:23:31 +01:00
|
|
|
module = gi_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
|
|
|
}
|
|
|
|
|
|
|
|
|