2008-08-09 14:46:48 +02:00
|
|
|
/* GObject introspection: A parser for the XML GIR format
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008 Philip Van Hoof
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <glib.h>
|
2008-10-22 16:31:58 +02:00
|
|
|
#include "girparser.h"
|
2008-08-09 14:46:48 +02:00
|
|
|
#include "girmodule.h"
|
|
|
|
#include "girnode.h"
|
|
|
|
#include "gtypelib.h"
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
struct _GIrParser
|
|
|
|
{
|
|
|
|
gchar **includes;
|
2008-11-12 18:17:15 +01:00
|
|
|
GList *parsed_modules; /* All previously parsed modules */
|
2008-11-12 18:16:42 +01:00
|
|
|
};
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
STATE_START,
|
|
|
|
STATE_END,
|
|
|
|
STATE_REPOSITORY,
|
2008-08-23 18:11:01 +02:00
|
|
|
STATE_INCLUDE,
|
2008-08-09 14:46:48 +02:00
|
|
|
STATE_NAMESPACE,
|
2008-08-23 18:11:01 +02:00
|
|
|
STATE_ENUM, /* 5 */
|
|
|
|
STATE_BITFIELD,
|
2008-08-09 14:46:48 +02:00
|
|
|
STATE_FUNCTION,
|
|
|
|
STATE_FUNCTION_RETURN,
|
|
|
|
STATE_FUNCTION_PARAMETERS,
|
2008-08-23 18:11:01 +02:00
|
|
|
STATE_FUNCTION_PARAMETER, /* 10 */
|
|
|
|
STATE_CLASS,
|
2008-08-09 14:46:48 +02:00
|
|
|
STATE_CLASS_FIELD,
|
|
|
|
STATE_CLASS_PROPERTY,
|
|
|
|
STATE_INTERFACE,
|
2008-08-23 18:11:01 +02:00
|
|
|
STATE_INTERFACE_PROPERTY, /* 15 */
|
|
|
|
STATE_INTERFACE_FIELD,
|
2008-08-09 14:46:48 +02:00
|
|
|
STATE_IMPLEMENTS,
|
2008-11-17 01:27:37 +01:00
|
|
|
STATE_PREREQUISITE,
|
2008-08-09 14:46:48 +02:00
|
|
|
STATE_BOXED,
|
2008-08-23 18:11:01 +02:00
|
|
|
STATE_BOXED_FIELD, /* 20 */
|
|
|
|
STATE_STRUCT,
|
2008-08-09 14:46:48 +02:00
|
|
|
STATE_STRUCT_FIELD,
|
|
|
|
STATE_ERRORDOMAIN,
|
|
|
|
STATE_UNION,
|
2008-08-23 18:11:01 +02:00
|
|
|
STATE_UNION_FIELD, /* 25 */
|
|
|
|
STATE_NAMESPACE_CONSTANT,
|
2008-08-20 17:05:46 +02:00
|
|
|
STATE_CLASS_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
|
|
|
STATE_INTERFACE_CONSTANT,
|
2008-08-22 22:05:23 +02:00
|
|
|
STATE_ALIAS,
|
2008-09-29 21:03:44 +02:00
|
|
|
STATE_TYPE
|
2008-08-09 14:46:48 +02:00
|
|
|
} ParseState;
|
|
|
|
|
|
|
|
typedef struct _ParseContext ParseContext;
|
|
|
|
struct _ParseContext
|
|
|
|
{
|
2008-11-12 18:16:42 +01:00
|
|
|
GIrParser *parser;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
ParseState state;
|
|
|
|
ParseState prev_state;
|
|
|
|
|
|
|
|
GList *modules;
|
2008-11-11 01:48:17 +01:00
|
|
|
GList *include_modules;
|
2008-08-30 22:31:07 +02:00
|
|
|
GList *dependencies;
|
2008-08-13 18:10:09 +02:00
|
|
|
GHashTable *aliases;
|
2008-11-11 00:58:49 +01:00
|
|
|
GHashTable *disguised_structures;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
const char *namespace;
|
2008-08-09 14:46:48 +02:00
|
|
|
GIrModule *current_module;
|
|
|
|
GIrNode *current_node;
|
|
|
|
GIrNode *current_typed;
|
2008-10-02 16:07:38 +02:00
|
|
|
gboolean is_varargs;
|
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;
|
2008-08-09 14:46:48 +02:00
|
|
|
};
|
|
|
|
|
2008-11-11 01:48:17 +01:00
|
|
|
static void start_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error);
|
|
|
|
static void end_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error);
|
|
|
|
static void text_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *text,
|
|
|
|
gsize text_len,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error);
|
|
|
|
static void cleanup (GMarkupParseContext *context,
|
|
|
|
GError *error,
|
|
|
|
gpointer user_data);
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
static GMarkupParser markup_parser =
|
2008-11-11 01:48:17 +01:00
|
|
|
{
|
|
|
|
start_element_handler,
|
|
|
|
end_element_handler,
|
|
|
|
text_handler,
|
|
|
|
NULL,
|
|
|
|
cleanup
|
|
|
|
};
|
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
static gboolean
|
|
|
|
start_alias (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error);
|
|
|
|
|
2008-11-11 00:58:49 +01:00
|
|
|
static const gchar *find_attribute (const gchar *name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values);
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
|
|
|
|
GIrParser *
|
|
|
|
g_ir_parser_new (void)
|
|
|
|
{
|
|
|
|
GIrParser *parser = g_slice_new0 (GIrParser);
|
|
|
|
|
|
|
|
return parser;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
g_ir_parser_free (GIrParser *parser)
|
|
|
|
{
|
2008-11-12 18:17:15 +01:00
|
|
|
GList *l;
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
if (parser->includes)
|
|
|
|
g_strfreev (parser->includes);
|
|
|
|
|
2008-11-12 18:17:15 +01:00
|
|
|
for (l = parser->parsed_modules; l; l = l->next)
|
|
|
|
g_ir_module_free (l->data);
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
g_slice_free (GIrParser, parser);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
g_ir_parser_set_includes (GIrParser *parser,
|
|
|
|
const gchar *const *includes)
|
|
|
|
{
|
|
|
|
if (parser->includes)
|
|
|
|
g_strfreev (parser->includes);
|
|
|
|
|
|
|
|
parser->includes = g_strdupv ((char **)includes);
|
|
|
|
}
|
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
static void
|
|
|
|
firstpass_start_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
ParseContext *ctx = user_data;
|
|
|
|
|
|
|
|
if (strcmp (element_name, "alias") == 0)
|
|
|
|
{
|
|
|
|
start_alias (context, element_name, attribute_names, attribute_values,
|
|
|
|
ctx, error);
|
|
|
|
}
|
2008-11-11 00:58:49 +01:00
|
|
|
else if (strcmp (element_name, "record") == 0)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *disguised;
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
disguised = find_attribute ("disguised", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (disguised && strcmp (disguised, "1") == 0)
|
|
|
|
{
|
|
|
|
char *key;
|
|
|
|
|
2008-11-12 18:17:01 +01:00
|
|
|
key = g_strdup_printf ("%s.%s", ctx->namespace, name);
|
2008-11-11 00:58:49 +01:00
|
|
|
g_hash_table_replace (ctx->disguised_structures, key, GINT_TO_POINTER (1));
|
|
|
|
}
|
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
firstpass_end_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static GMarkupParser firstpass_parser =
|
|
|
|
{
|
|
|
|
firstpass_start_element_handler,
|
|
|
|
firstpass_end_element_handler,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
static char *
|
2008-11-12 18:16:42 +01:00
|
|
|
locate_gir (GIrParser *parser,
|
|
|
|
const char *name,
|
|
|
|
const char *version)
|
2008-08-28 23:19:22 +02:00
|
|
|
{
|
|
|
|
const gchar *const *datadirs;
|
|
|
|
const gchar *const *dir;
|
|
|
|
char *girname;
|
|
|
|
char *path = NULL;
|
|
|
|
|
|
|
|
datadirs = g_get_system_data_dirs ();
|
|
|
|
|
2008-10-16 03:40:29 +02:00
|
|
|
girname = g_strdup_printf ("%s-%s.gir", name, version);
|
2008-08-28 23:19:22 +02:00
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
if (parser->includes != NULL)
|
2008-08-29 00:13:00 +02:00
|
|
|
{
|
2008-11-12 18:16:42 +01:00
|
|
|
for (dir = (const gchar *const *)parser->includes; *dir; dir++)
|
2008-08-31 18:01:02 +02:00
|
|
|
{
|
|
|
|
path = g_build_filename (*dir, girname, NULL);
|
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
|
|
|
return path;
|
|
|
|
g_free (path);
|
|
|
|
path = NULL;
|
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
2008-11-11 16:25:59 +01:00
|
|
|
for (dir = datadirs; *dir; dir++)
|
|
|
|
{
|
|
|
|
path = g_build_filename (*dir, "gir", girname, NULL);
|
|
|
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
|
|
|
return path;
|
|
|
|
g_free (path);
|
|
|
|
path = NULL;
|
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
g_free (girname);
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
#define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
|
|
|
|
do { \
|
|
|
|
int line_number, char_number; \
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number); \
|
|
|
|
g_set_error (error, \
|
|
|
|
G_MARKUP_ERROR, \
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT, \
|
|
|
|
"Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
|
|
|
|
line_number, char_number, attribute, element); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
static void
|
|
|
|
backtrace_stderr (void)
|
|
|
|
{
|
2008-10-15 22:44:29 +02:00
|
|
|
#if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
|
2008-08-09 14:46:48 +02:00
|
|
|
void *array[50];
|
|
|
|
int size;
|
|
|
|
char **strings;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
size = backtrace (array, 50);
|
|
|
|
strings = (char**) backtrace_symbols (array, size);
|
|
|
|
|
|
|
|
fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
|
|
|
|
|
|
|
|
for (i = 0; i < size; i++)
|
|
|
|
fprintf (stderr, "%s\n", strings[i]);
|
|
|
|
|
|
|
|
fprintf (stderr, "--- END BACKTRACE ---\n", size);
|
|
|
|
|
|
|
|
free (strings);
|
Make g-ir-scanner work on Windows. Still problems with the typelib code.
2008-08-27 Tor Lillqvist <tml@novell.com>
Make g-ir-scanner work on Windows. Still problems with the typelib
code. Changes okayed by jdahlin.
* configure.ac: Check for Windows, set Automake conditional
OS_WIN32. Change backslashes to forward slashes in pyexecdir to
avoid shell quoting issues
* girepository/Makefile.am: Use -no-undefined so that libtool
agrees to build a shared library on Windows.
* girepository/girparser.c (backtrace_stderr): No backtrace() on
Windows. Empty implementation on Windows so far.
* girepository/gtypelib.c (g_typelib_check_sanity): Give more
informative error message for the assertion failures. Tell also
what the expected size of the struct is. Check all sizes first and
fail afterwards if at least one size was different from expected.
* tools/Makefile.am: Reorder libraries into proper logical
dependency order.
* tools/generate.c: Don't include <dlfcn.h>, not used.
* giscanner/Makefile.am: On Windows, link with the Python library,
and install the module DLL as _giscanner.pyd. Remove the
unnecessary import library and libtool library that libtool has
installed.
* giscanner/scannerlexer.l: Recognize the gcc __attribute__ syntax
and just skip it. Recognize also two "l" suffixes for long long
constants. Recognize also __inline__.
* giscanner/grealpath.h (g_realpath): Implement on Windows, using
GetFullPathName(). As such, GetFullPathName() does more than the
UNIX realpath(). It also changes relative paths into absolute
paths. But for our purposes that shouldn't matter.
* giscanner/giscannermodule.c (pygi_source_scanner_parse_file): On
Windows the file descriptor passed to us is from Python. Python
Python2.5 uses the msvcr71.dll C library, while mingw-built code
uses msvcrt.dll. On Windows, file descriptors are specific to
which C library is used. So we must find out what underlying OS
handle corresponds to the file descriptor Python passes us, and
then make that into a file descriptor valid for the C library this
code uses.
* giscanner/sourcescanner.py (_parse): Don't need to bypass
__attribute__ as the lexer now handles it. The definition as empty
was ineffective for mingw anyway, as mingw's _mingw.h undefines
__attribute__. Close the temp file before unlinking it.
* giscanner/cgobject.py: Use correct library name for the gobject
DLL on Windows.
* gir/Makefile.am: Must pass the full basename of the DLLs on
Windows to g-ir-scanner. It's a bit ugly that we have to "know"
that the names of the GLib DLLs are like libglib-2.0-0.dll, but in
reality they won't change, until there is a GLib 3, and then also
the Unix code here needs changing.
Must pass CPPFLAGS to g-ir-scanner when building GLib.gir so that
libintl.h is found.
svn path=/trunk/; revision=503
2008-08-27 15:33:21 +02:00
|
|
|
#endif
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const gchar *
|
|
|
|
find_attribute (const gchar *name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values)
|
|
|
|
{
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
for (i = 0; attribute_names[i] != NULL; i++)
|
|
|
|
if (strcmp (attribute_names[i], name) == 0)
|
|
|
|
return attribute_values[i];
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
state_switch (ParseContext *ctx, ParseState newstate)
|
|
|
|
{
|
2008-08-14 18:09:06 +02:00
|
|
|
g_debug ("State: %d", newstate);
|
2008-08-09 14:46:48 +02:00
|
|
|
ctx->prev_state = ctx->state;
|
|
|
|
ctx->state = newstate;
|
|
|
|
}
|
|
|
|
|
2008-10-02 15:25:46 +02:00
|
|
|
static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib,
|
|
|
|
gboolean in_gobject);
|
2008-08-13 18:10:09 +02:00
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
typedef struct {
|
|
|
|
const gchar *str;
|
|
|
|
gint tag;
|
|
|
|
gboolean pointer;
|
|
|
|
} BasicTypeInfo;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
static BasicTypeInfo basic_types[] = {
|
2008-08-12 17:34:27 +02:00
|
|
|
{ "none", GI_TYPE_TAG_VOID, 0 },
|
2008-08-12 20:49:16 +02:00
|
|
|
{ "any", GI_TYPE_TAG_VOID, 1 },
|
2008-08-16 23:55:06 +02:00
|
|
|
|
2008-08-12 17:34:27 +02:00
|
|
|
{ "bool", GI_TYPE_TAG_BOOLEAN, 0 },
|
|
|
|
{ "char", GI_TYPE_TAG_INT8, 0 },
|
|
|
|
{ "int8", GI_TYPE_TAG_INT8, 0 },
|
|
|
|
{ "uint8", GI_TYPE_TAG_UINT8, 0 },
|
|
|
|
{ "int16", GI_TYPE_TAG_INT16, 0 },
|
|
|
|
{ "uint16", GI_TYPE_TAG_UINT16, 0 },
|
|
|
|
{ "int32", GI_TYPE_TAG_INT32, 0 },
|
|
|
|
{ "uint32", GI_TYPE_TAG_UINT32, 0 },
|
|
|
|
{ "int64", GI_TYPE_TAG_INT64, 0 },
|
|
|
|
{ "uint64", GI_TYPE_TAG_UINT64, 0 },
|
|
|
|
{ "int", GI_TYPE_TAG_INT, 0 },
|
|
|
|
{ "uint", GI_TYPE_TAG_UINT, 0 },
|
|
|
|
{ "long", GI_TYPE_TAG_LONG, 0 },
|
|
|
|
{ "ulong", GI_TYPE_TAG_ULONG, 0 },
|
|
|
|
{ "ssize_t", GI_TYPE_TAG_SSIZE, 0 },
|
2008-08-16 23:55:06 +02:00
|
|
|
{ "ssize", GI_TYPE_TAG_SSIZE, 0 },
|
2008-08-12 17:34:27 +02:00
|
|
|
{ "size_t", GI_TYPE_TAG_SIZE, 0 },
|
2008-08-16 23:55:06 +02:00
|
|
|
{ "size", GI_TYPE_TAG_SIZE, 0 },
|
2008-08-12 17:34:27 +02:00
|
|
|
{ "float", GI_TYPE_TAG_FLOAT, 0 },
|
|
|
|
{ "double", GI_TYPE_TAG_DOUBLE, 0 },
|
2008-09-23 20:20:25 +02:00
|
|
|
{ "time_t", GI_TYPE_TAG_TIME_T, 0 },
|
2008-10-02 15:25:46 +02:00
|
|
|
{ "GType", GI_TYPE_TAG_GTYPE, 0 },
|
2008-08-12 17:34:27 +02:00
|
|
|
{ "utf8", GI_TYPE_TAG_UTF8, 1 },
|
|
|
|
{ "filename", GI_TYPE_TAG_FILENAME,1 },
|
2008-08-29 22:06:10 +02: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)
|
|
|
|
{
|
|
|
|
gint i;
|
|
|
|
gint n_basic = G_N_ELEMENTS (basic_types);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
for (i = 0; i < n_basic; i++)
|
|
|
|
{
|
|
|
|
if (g_str_has_prefix (str, basic_types[i].str))
|
|
|
|
return &(basic_types[i]);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GIrNodeType *
|
2008-10-02 15:25:46 +02:00
|
|
|
parse_type_internal (const gchar *str, char **next, gboolean in_glib,
|
|
|
|
gboolean in_gobject)
|
2008-08-29 22:06:10 +02:00
|
|
|
{
|
|
|
|
const BasicTypeInfo *basic;
|
2008-08-09 14:46:48 +02:00
|
|
|
GIrNodeType *type;
|
2008-08-29 22:06:10 +02:00
|
|
|
char *temporary_type = NULL;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
|
|
|
|
|
|
|
|
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 */
|
|
|
|
if (in_gobject && strcmp (str, "Type") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup ("GLib.Type");
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
* special.
|
|
|
|
*/
|
2008-08-29 21:33:09 +02:00
|
|
|
if (g_str_has_prefix (str, "List<") ||
|
|
|
|
strcmp (str, "List") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
|
|
|
else if (g_str_has_prefix (str, "SList<") ||
|
|
|
|
strcmp (str, "SList") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
|
|
|
else if (g_str_has_prefix (str, "HashTable<") ||
|
|
|
|
strcmp (str, "HashTable") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
|
|
|
else if (g_str_has_prefix (str, "Error<") ||
|
|
|
|
strcmp (str, "Error") == 0)
|
|
|
|
{
|
|
|
|
temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
|
|
|
|
str = temporary_type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
if (basic != NULL)
|
2008-08-09 14:46:48 +02:00
|
|
|
/* found a basic type */;
|
2008-08-29 21:33:09 +02:00
|
|
|
else if (g_str_has_prefix (str, "GLib.List") ||
|
|
|
|
g_str_has_prefix (str, "GLib.SList"))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("GLib.");
|
|
|
|
if (g_str_has_prefix (str, "List"))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-12 17:34:27 +02:00
|
|
|
type->tag = GI_TYPE_TAG_GLIST;
|
2008-08-09 14:46:48 +02:00
|
|
|
type->is_glist = TRUE;
|
|
|
|
type->is_pointer = TRUE;
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("List");
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-08-12 17:34:27 +02:00
|
|
|
type->tag = GI_TYPE_TAG_GSLIST;
|
2008-08-09 14:46:48 +02:00
|
|
|
type->is_gslist = TRUE;
|
|
|
|
type->is_pointer = TRUE;
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("SList");
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
}
|
2008-08-29 21:33:09 +02:00
|
|
|
else if (g_str_has_prefix (str, "GLib.HashTable"))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("GLib.");
|
2008-08-29 20:19:26 +02:00
|
|
|
|
2008-08-12 17:34:27 +02:00
|
|
|
type->tag = GI_TYPE_TAG_GHASH;
|
2008-08-09 14:46:48 +02:00
|
|
|
type->is_ghashtable = TRUE;
|
|
|
|
type->is_pointer = TRUE;
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("HashTable");
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
2008-08-29 21:33:09 +02:00
|
|
|
else if (g_str_has_prefix (str, "GLib.Error"))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("GLib.");
|
2008-08-29 20:19:26 +02:00
|
|
|
|
2008-08-12 17:34:27 +02:00
|
|
|
type->tag = GI_TYPE_TAG_ERROR;
|
2008-08-09 14:46:48 +02:00
|
|
|
type->is_error = TRUE;
|
|
|
|
type->is_pointer = TRUE;
|
2008-08-29 21:33:09 +02:00
|
|
|
str += strlen ("Error");
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-29 21:33:09 +02:00
|
|
|
if (*str == '<')
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-29 21:33:09 +02:00
|
|
|
(str)++;
|
2008-08-29 22:06:10 +02:00
|
|
|
char *tmp, *end;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-29 21:33:09 +02:00
|
|
|
end = strchr (str, '>');
|
|
|
|
tmp = g_strndup (str, end - str);
|
|
|
|
type->errors = g_strsplit (tmp, ",", 0);
|
|
|
|
g_free (tmp);
|
|
|
|
|
|
|
|
str = end;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-08-12 17:34:27 +02:00
|
|
|
type->tag = GI_TYPE_TAG_INTERFACE;
|
2008-08-09 14:46:48 +02:00
|
|
|
type->is_interface = TRUE;
|
2008-08-29 22:06:10 +02:00
|
|
|
const char *start = str;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
/* must be an interface type */
|
2008-08-29 21:33:09 +02:00
|
|
|
while (g_ascii_isalnum (*str) ||
|
|
|
|
*str == '.' ||
|
|
|
|
*str == '-' ||
|
|
|
|
*str == '_' ||
|
|
|
|
*str == ':')
|
|
|
|
(str)++;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-29 21:33:09 +02:00
|
|
|
type->interface = g_strndup (start, str - start);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2008-08-29 21:33:09 +02:00
|
|
|
if (next)
|
|
|
|
*next = (char*)str;
|
2008-08-12 17:34:27 +02:00
|
|
|
g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
|
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: */
|
2008-08-09 14:46:48 +02:00
|
|
|
g_ir_node_free ((GIrNode *)type);
|
2008-08-29 21:33:09 +02:00
|
|
|
g_free (temporary_type);
|
2008-08-09 14:46:48 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-08-13 18:10:09 +02:00
|
|
|
static const char *
|
|
|
|
resolve_aliases (ParseContext *ctx, const gchar *type)
|
|
|
|
{
|
|
|
|
gpointer orig;
|
|
|
|
gpointer value;
|
2008-08-20 21:01:20 +02:00
|
|
|
GSList *seen_values = NULL;
|
2008-11-12 18:17:01 +01:00
|
|
|
const gchar *lookup;
|
|
|
|
gchar *prefixed;
|
2008-11-11 23:02:37 +01:00
|
|
|
|
2008-11-12 18:17:01 +01:00
|
|
|
if (strchr (type, '.') == NULL)
|
2008-11-11 23:02:37 +01:00
|
|
|
{
|
|
|
|
prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
|
|
|
|
lookup = prefixed;
|
|
|
|
}
|
|
|
|
else
|
2008-11-12 18:17:01 +01:00
|
|
|
{
|
|
|
|
lookup = type;
|
|
|
|
prefixed = NULL;
|
|
|
|
}
|
2008-08-13 18:10:09 +02:00
|
|
|
|
2008-11-11 23:02:37 +01:00
|
|
|
seen_values = g_slist_prepend (seen_values, (char*)lookup);
|
2008-11-12 18:17:01 +01:00
|
|
|
while (g_hash_table_lookup_extended (ctx->current_module->aliases, lookup, &orig, &value))
|
2008-08-13 18:10:09 +02:00
|
|
|
{
|
2008-11-11 23:02:37 +01:00
|
|
|
g_debug ("Resolved: %s => %s\n", lookup, (char*)value);
|
|
|
|
lookup = value;
|
|
|
|
if (g_slist_find_custom (seen_values, lookup,
|
2008-08-21 10:20:07 +02:00
|
|
|
(GCompareFunc)strcmp) != NULL)
|
2008-08-20 21:01:20 +02:00
|
|
|
break;
|
2008-11-11 23:02:37 +01:00
|
|
|
seen_values = g_slist_prepend (seen_values, (gchar*)lookup);
|
2008-08-13 18:10:09 +02:00
|
|
|
}
|
2008-08-21 10:20:07 +02:00
|
|
|
g_slist_free (seen_values);
|
2008-11-11 23:02:37 +01:00
|
|
|
|
|
|
|
if (lookup == prefixed)
|
|
|
|
lookup = type;
|
2008-11-12 18:17:01 +01:00
|
|
|
|
2008-11-11 23:02:37 +01:00
|
|
|
g_free (prefixed);
|
|
|
|
|
|
|
|
return lookup;
|
2008-08-13 18:10:09 +02:00
|
|
|
}
|
|
|
|
|
2008-11-12 18:17:01 +01:00
|
|
|
static gboolean
|
|
|
|
is_disguised_structure (ParseContext *ctx, const gchar *type)
|
|
|
|
{
|
|
|
|
const gchar *lookup;
|
|
|
|
gchar *prefixed;
|
|
|
|
gboolean result;
|
|
|
|
|
|
|
|
if (strchr (type, '.') == NULL)
|
|
|
|
{
|
|
|
|
prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
|
|
|
|
lookup = prefixed;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lookup = type;
|
|
|
|
prefixed = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = g_hash_table_lookup (ctx->current_module->disguised_structures,
|
|
|
|
lookup) != NULL;
|
|
|
|
|
|
|
|
g_free (prefixed);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static GIrNodeType *
|
2008-08-13 18:10:09 +02:00
|
|
|
parse_type (ParseContext *ctx, const gchar *type)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
GIrNodeType *node;
|
2008-08-29 22:06:10 +02:00
|
|
|
const BasicTypeInfo *basic;
|
2008-10-02 15:25:46 +02:00
|
|
|
gboolean in_glib, in_gobject;
|
2008-08-29 21:33:09 +02:00
|
|
|
|
|
|
|
in_glib = strcmp (ctx->namespace, "GLib") == 0;
|
2008-10-02 15:25:46 +02:00
|
|
|
in_gobject = strcmp (ctx->namespace, "GObject") == 0;
|
2008-08-29 21:33:09 +02:00
|
|
|
|
2008-08-29 22:06:10 +02:00
|
|
|
/* Do not search aliases for basic types */
|
|
|
|
basic = parse_basic (type);
|
|
|
|
if (basic == NULL)
|
|
|
|
type = resolve_aliases (ctx, type);
|
|
|
|
|
2008-10-02 15:25:46 +02:00
|
|
|
node = parse_type_internal (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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_glib_boxed (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *typename;
|
|
|
|
const gchar *typeinit;
|
|
|
|
const gchar *deprecated;
|
|
|
|
GIrNodeBoxed *boxed;
|
|
|
|
|
|
|
|
if (!(strcmp (element_name, "glib:boxed") == 0 &&
|
|
|
|
ctx->state == STATE_NAMESPACE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
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
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
((GIrNode *)boxed)->name = g_strdup (name);
|
|
|
|
boxed->gtype_name = g_strdup (typename);
|
|
|
|
boxed->gtype_init = g_strdup (typeinit);
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-08-24 13:01:44 +02:00
|
|
|
boxed->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
boxed->deprecated = FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
ctx->current_node = (GIrNode *)boxed;
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, boxed);
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_BOXED);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_function (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *symbol;
|
|
|
|
const gchar *deprecated;
|
2008-10-21 19:04:11 +02:00
|
|
|
const gchar *throws;
|
2008-08-24 13:01:44 +02:00
|
|
|
GIrNodeFunction *function;
|
|
|
|
gboolean found = FALSE;
|
|
|
|
|
|
|
|
switch (ctx->state)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
case STATE_NAMESPACE:
|
|
|
|
found = (strcmp (element_name, "function") == 0 ||
|
|
|
|
strcmp (element_name, "callback") == 0);
|
|
|
|
break;
|
|
|
|
case STATE_CLASS:
|
|
|
|
case STATE_BOXED:
|
|
|
|
case STATE_STRUCT:
|
|
|
|
case STATE_UNION:
|
|
|
|
found = strcmp (element_name, "constructor") == 0;
|
|
|
|
/* fallthrough */
|
|
|
|
case STATE_INTERFACE:
|
|
|
|
found = (found ||
|
|
|
|
strcmp (element_name, "method") == 0 ||
|
|
|
|
strcmp (element_name, "callback") == 0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
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);
|
2008-08-09 14:46:48 +02: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;
|
|
|
|
}
|
|
|
|
|
|
|
|
function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
|
|
|
|
|
|
|
|
((GIrNode *)function)->name = g_strdup (name);
|
|
|
|
function->symbol = g_strdup (symbol);
|
|
|
|
function->parameters = NULL;
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-08-24 13:01:44 +02:00
|
|
|
function->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
function->deprecated = FALSE;
|
|
|
|
|
|
|
|
if (strcmp (element_name, "method") == 0 ||
|
|
|
|
strcmp (element_name, "constructor") == 0)
|
|
|
|
{
|
|
|
|
function->is_method = TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
if (strcmp (element_name, "constructor") == 0)
|
|
|
|
function->is_constructor = TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
else
|
2008-08-24 13:01:44 +02:00
|
|
|
function->is_constructor = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
function->is_method = FALSE;
|
|
|
|
function->is_setter = FALSE;
|
|
|
|
function->is_getter = FALSE;
|
|
|
|
function->is_constructor = FALSE;
|
|
|
|
if (strcmp (element_name, "callback") == 0)
|
|
|
|
((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
|
|
|
|
}
|
2008-10-21 19:04:11 +02:00
|
|
|
|
|
|
|
if (throws && strcmp (throws, "1") == 0)
|
|
|
|
function->throws = TRUE;
|
|
|
|
else
|
|
|
|
function->throws = FALSE;
|
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
if (ctx->current_node == NULL)
|
|
|
|
{
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, function);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
switch (ctx->current_node->type)
|
|
|
|
{
|
|
|
|
case G_IR_NODE_INTERFACE:
|
|
|
|
case G_IR_NODE_OBJECT:
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
GIrNodeInterface *iface;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
iface = (GIrNodeInterface *)ctx->current_node;
|
|
|
|
iface->members = g_list_append (iface->members, function);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_BOXED:
|
|
|
|
{
|
|
|
|
GIrNodeBoxed *boxed;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
boxed = (GIrNodeBoxed *)ctx->current_node;
|
|
|
|
boxed->members = g_list_append (boxed->members, function);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_STRUCT:
|
|
|
|
{
|
|
|
|
GIrNodeStruct *struct_;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
struct_ = (GIrNodeStruct *)ctx->current_node;
|
|
|
|
struct_->members = g_list_append (struct_->members, function); }
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_UNION:
|
|
|
|
{
|
|
|
|
GIrNodeUnion *union_;
|
|
|
|
|
|
|
|
union_ = (GIrNodeUnion *)ctx->current_node;
|
|
|
|
union_->members = g_list_append (union_->members, function);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
2008-08-24 13:01:44 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->current_node = (GIrNode *)function;
|
|
|
|
state_switch (ctx, STATE_FUNCTION);
|
|
|
|
|
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2008-10-12 23:07:22 +02:00
|
|
|
static void
|
|
|
|
parse_param_transfer (GIrNodeParam *param, const gchar *transfer)
|
|
|
|
{
|
2008-10-23 19:42:25 +02:00
|
|
|
if (transfer == NULL)
|
|
|
|
{
|
|
|
|
g_warning ("required attribute 'transfer-ownership' missing");
|
|
|
|
}
|
|
|
|
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
|
|
|
|
{
|
|
|
|
g_warning ("Unknown transfer-ownership value: %s", transfer);
|
|
|
|
}
|
2008-10-12 23:07:22 +02:00
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
|
|
|
start_parameter (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *direction;
|
|
|
|
const gchar *retval;
|
|
|
|
const gchar *dipper;
|
|
|
|
const gchar *optional;
|
2008-10-22 16:02:02 +02:00
|
|
|
const gchar *allow_none;
|
2008-08-09 14:46:48 +02:00
|
|
|
const gchar *transfer;
|
|
|
|
GIrNodeParam *param;
|
|
|
|
|
|
|
|
if (!(strcmp (element_name, "parameter") == 0 &&
|
|
|
|
ctx->state == STATE_FUNCTION_PARAMETERS))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
direction = find_attribute ("direction", attribute_names, attribute_values);
|
|
|
|
retval = find_attribute ("retval", attribute_names, attribute_values);
|
|
|
|
dipper = find_attribute ("dipper", 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);
|
2008-10-17 16:59:23 +02:00
|
|
|
transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
name = "unknown";
|
|
|
|
|
|
|
|
param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
|
|
|
|
|
|
|
|
ctx->current_typed = (GIrNode*) param;
|
2008-08-12 17:34:27 +02:00
|
|
|
ctx->current_typed->name = g_strdup (name);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
state_switch (ctx, STATE_FUNCTION_PARAMETER);
|
|
|
|
|
|
|
|
if (direction && strcmp (direction, "out") == 0)
|
|
|
|
{
|
|
|
|
param->in = FALSE;
|
|
|
|
param->out = TRUE;
|
|
|
|
}
|
|
|
|
else if (direction && strcmp (direction, "inout") == 0)
|
|
|
|
{
|
|
|
|
param->in = TRUE;
|
|
|
|
param->out = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
param->in = TRUE;
|
|
|
|
param->out = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retval && strcmp (retval, "1") == 0)
|
|
|
|
param->retval = TRUE;
|
|
|
|
else
|
|
|
|
param->retval = FALSE;
|
|
|
|
|
|
|
|
if (dipper && strcmp (dipper, "1") == 0)
|
|
|
|
param->dipper = TRUE;
|
|
|
|
else
|
|
|
|
param->dipper = FALSE;
|
|
|
|
|
|
|
|
if (optional && strcmp (optional, "1") == 0)
|
|
|
|
param->optional = TRUE;
|
|
|
|
else
|
|
|
|
param->optional = FALSE;
|
|
|
|
|
2008-10-22 16:02:02 +02:00
|
|
|
if (allow_none && strcmp (allow_none, "1") == 0)
|
|
|
|
param->allow_none = TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
else
|
2008-10-22 16:02:02 +02:00
|
|
|
param->allow_none = FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-10-12 23:07:22 +02:00
|
|
|
parse_param_transfer (param, transfer);
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
((GIrNode *)param)->name = g_strdup (name);
|
|
|
|
|
|
|
|
switch (ctx->current_node->type)
|
|
|
|
{
|
|
|
|
case G_IR_NODE_FUNCTION:
|
|
|
|
case G_IR_NODE_CALLBACK:
|
|
|
|
{
|
|
|
|
GIrNodeFunction *func;
|
|
|
|
|
|
|
|
func = (GIrNodeFunction *)ctx->current_node;
|
|
|
|
func->parameters = g_list_append (func->parameters, param);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_SIGNAL:
|
|
|
|
{
|
|
|
|
GIrNodeSignal *signal;
|
|
|
|
|
|
|
|
signal = (GIrNodeSignal *)ctx->current_node;
|
|
|
|
signal->parameters = g_list_append (signal->parameters, param);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_VFUNC:
|
|
|
|
{
|
|
|
|
GIrNodeVFunc *vfunc;
|
|
|
|
|
|
|
|
vfunc = (GIrNodeVFunc *)ctx->current_node;
|
|
|
|
vfunc->parameters = g_list_append (vfunc->parameters, param);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_field (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *readable;
|
|
|
|
const gchar *writable;
|
|
|
|
const gchar *bits;
|
|
|
|
const gchar *branch;
|
|
|
|
GIrNodeField *field;
|
|
|
|
|
|
|
|
switch (ctx->state)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
2008-08-24 13:01:44 +02:00
|
|
|
case STATE_CLASS:
|
|
|
|
case STATE_BOXED:
|
|
|
|
case STATE_STRUCT:
|
|
|
|
case STATE_UNION:
|
|
|
|
case STATE_INTERFACE:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp (element_name, "field") != 0)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
|
|
|
|
ctx->current_typed = (GIrNode*) field;
|
|
|
|
((GIrNode *)field)->name = g_strdup (name);
|
2008-10-17 16:58:37 +02:00
|
|
|
/* Fields are assumed to be read-only.
|
|
|
|
* (see also girwriter.py and generate.c)
|
|
|
|
*/
|
|
|
|
field->readable = readable == NULL || strcmp (readable, "0") == 0;
|
|
|
|
field->writable = writable != NULL && strcmp (writable, "1") == 0;
|
2008-08-24 13:01:44 +02:00
|
|
|
|
|
|
|
if (bits)
|
|
|
|
field->bits = atoi (bits);
|
|
|
|
else
|
|
|
|
field->bits = 0;
|
|
|
|
|
|
|
|
switch (ctx->current_node->type)
|
|
|
|
{
|
|
|
|
case G_IR_NODE_OBJECT:
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
|
|
|
|
iface = (GIrNodeInterface *)ctx->current_node;
|
|
|
|
iface->members = g_list_append (iface->members, field);
|
|
|
|
state_switch (ctx, STATE_CLASS_FIELD);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_INTERFACE:
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
|
|
|
|
iface = (GIrNodeInterface *)ctx->current_node;
|
|
|
|
iface->members = g_list_append (iface->members, field);
|
|
|
|
state_switch (ctx, STATE_INTERFACE_FIELD);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_BOXED:
|
|
|
|
{
|
|
|
|
GIrNodeBoxed *boxed;
|
|
|
|
|
|
|
|
boxed = (GIrNodeBoxed *)ctx->current_node;
|
2008-08-09 14:46:48 +02:00
|
|
|
boxed->members = g_list_append (boxed->members, field);
|
|
|
|
state_switch (ctx, STATE_BOXED_FIELD);
|
2008-08-24 13:01:44 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_STRUCT:
|
|
|
|
{
|
|
|
|
GIrNodeStruct *struct_;
|
|
|
|
|
|
|
|
struct_ = (GIrNodeStruct *)ctx->current_node;
|
|
|
|
struct_->members = g_list_append (struct_->members, field);
|
|
|
|
state_switch (ctx, STATE_STRUCT_FIELD);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_UNION:
|
|
|
|
{
|
|
|
|
GIrNodeUnion *union_;
|
|
|
|
|
|
|
|
union_ = (GIrNodeUnion *)ctx->current_node;
|
|
|
|
union_->members = g_list_append (union_->members, field);
|
|
|
|
if (branch)
|
|
|
|
{
|
|
|
|
GIrNodeConstant *constant;
|
|
|
|
|
|
|
|
constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
|
|
|
|
((GIrNode *)constant)->name = g_strdup (name);
|
|
|
|
constant->value = g_strdup (branch);
|
|
|
|
constant->type = union_->discriminator_type;
|
|
|
|
constant->deprecated = FALSE;
|
|
|
|
|
|
|
|
union_->discriminators = g_list_append (union_->discriminators, constant);
|
|
|
|
}
|
|
|
|
state_switch (ctx, STATE_UNION_FIELD);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2008-08-24 13:01:44 +02:00
|
|
|
return TRUE;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
2008-08-13 18:10:09 +02:00
|
|
|
static gboolean
|
|
|
|
start_alias (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *target;
|
2008-08-28 23:19:22 +02:00
|
|
|
char *key;
|
|
|
|
char *value;
|
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
|
|
|
|
|
|
|
target = find_attribute ("target", attribute_names, attribute_values);
|
2008-08-24 13:01:44 +02:00
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "target");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-08-13 18:10:09 +02:00
|
|
|
|
2008-08-29 22:41:26 +02:00
|
|
|
value = g_strdup (target);
|
2008-11-12 18:17:01 +01:00
|
|
|
key = g_strdup_printf ("%s.%s", ctx->namespace, name);
|
|
|
|
if (!strchr (target, '.'))
|
2008-08-29 22:41:26 +02:00
|
|
|
{
|
2008-11-12 18:17:01 +01:00
|
|
|
const BasicTypeInfo *basic = parse_basic (target);
|
|
|
|
if (!basic)
|
2008-08-29 22:41:26 +02:00
|
|
|
{
|
2008-11-12 18:17:01 +01:00
|
|
|
g_free (value);
|
|
|
|
/* For non-basic types, re-qualify the interface */
|
|
|
|
value = g_strdup_printf ("%s.%s", ctx->namespace, target);
|
2008-08-29 22:41:26 +02:00
|
|
|
}
|
|
|
|
}
|
2008-11-12 18:17:01 +01:00
|
|
|
g_hash_table_replace (ctx->aliases, key, value);
|
2008-08-24 13:01:44 +02:00
|
|
|
|
2008-08-13 18:10:09 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
|
|
|
start_enum (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
|
|
|
|
(strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *typename;
|
|
|
|
const gchar *typeinit;
|
|
|
|
const gchar *deprecated;
|
|
|
|
|
|
|
|
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);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeEnum *enum_;
|
|
|
|
|
|
|
|
if (strcmp (element_name, "enumeration") == 0)
|
|
|
|
enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
|
|
|
|
else
|
|
|
|
enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
|
|
|
|
((GIrNode *)enum_)->name = g_strdup (name);
|
|
|
|
enum_->gtype_name = g_strdup (typename);
|
|
|
|
enum_->gtype_init = g_strdup (typeinit);
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-08-09 14:46:48 +02:00
|
|
|
enum_->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
enum_->deprecated = FALSE;
|
|
|
|
|
|
|
|
ctx->current_node = (GIrNode *) enum_;
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, enum_);
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_ENUM);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_property (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "property") == 0 &&
|
|
|
|
(ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE))
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *readable;
|
|
|
|
const gchar *writable;
|
|
|
|
const gchar *construct;
|
|
|
|
const gchar *construct_only;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeProperty *property;
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
|
|
|
|
property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
|
|
|
|
ctx->current_typed = (GIrNode*) property;
|
|
|
|
|
|
|
|
((GIrNode *)property)->name = g_strdup (name);
|
|
|
|
|
2008-09-09 00:24:09 +02:00
|
|
|
/* Assume properties are readable */
|
|
|
|
if (readable == NULL || strcmp (readable, "1") == 0)
|
2008-08-09 14:46:48 +02:00
|
|
|
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;
|
|
|
|
|
|
|
|
iface = (GIrNodeInterface *)ctx->current_node;
|
|
|
|
iface->members = g_list_append (iface->members, property);
|
|
|
|
|
|
|
|
if (ctx->state == STATE_CLASS)
|
|
|
|
state_switch (ctx, STATE_CLASS_PROPERTY);
|
|
|
|
else if (ctx->state == STATE_INTERFACE)
|
|
|
|
state_switch (ctx, STATE_INTERFACE_PROPERTY);
|
|
|
|
else
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
parse_value (const gchar *str)
|
|
|
|
{
|
|
|
|
gchar *shift_op;
|
|
|
|
|
|
|
|
/* FIXME just a quick hack */
|
|
|
|
shift_op = strstr (str, "<<");
|
|
|
|
|
|
|
|
if (shift_op)
|
|
|
|
{
|
|
|
|
gint base, shift;
|
|
|
|
|
|
|
|
base = strtol (str, NULL, 10);
|
|
|
|
shift = strtol (shift_op + 3, NULL, 10);
|
|
|
|
|
|
|
|
return base << shift;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return strtol (str, NULL, 10);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_member (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "member") == 0 &&
|
|
|
|
ctx->state == STATE_ENUM)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *value;
|
|
|
|
const gchar *deprecated;
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
value = find_attribute ("value", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeEnum *enum_;
|
|
|
|
GIrNodeValue *value_;
|
|
|
|
|
|
|
|
value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
|
|
|
|
|
|
|
|
((GIrNode *)value_)->name = g_strdup (name);
|
|
|
|
|
|
|
|
value_->value = parse_value (value);
|
|
|
|
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-08-09 14:46:48 +02:00
|
|
|
value_->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
value_->deprecated = FALSE;
|
|
|
|
|
|
|
|
enum_ = (GIrNodeEnum *)ctx->current_node;
|
|
|
|
enum_->values = g_list_append (enum_->values, value_);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_constant (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "constant") == 0 &&
|
|
|
|
(ctx->state == STATE_NAMESPACE ||
|
|
|
|
ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE))
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *value;
|
|
|
|
const gchar *deprecated;
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
value = find_attribute ("value", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else if (value == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "value");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeConstant *constant;
|
|
|
|
|
|
|
|
constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
|
|
|
|
|
|
|
|
((GIrNode *)constant)->name = g_strdup (name);
|
|
|
|
constant->value = g_strdup (value);
|
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
|
|
|
|
|
|
|
ctx->current_typed = (GIrNode*) constant;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-08-09 14:46:48 +02:00
|
|
|
constant->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
constant->deprecated = FALSE;
|
|
|
|
|
|
|
|
if (ctx->state == STATE_NAMESPACE)
|
|
|
|
{
|
|
|
|
ctx->current_node = (GIrNode *) constant;
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, constant);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
|
|
|
|
iface = (GIrNodeInterface *)ctx->current_node;
|
|
|
|
iface->members = g_list_append (iface->members, 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
|
|
|
|
|
|
|
switch (ctx->state)
|
|
|
|
{
|
|
|
|
case STATE_NAMESPACE:
|
|
|
|
state_switch (ctx, STATE_NAMESPACE_CONSTANT);
|
|
|
|
break;
|
|
|
|
case STATE_CLASS:
|
|
|
|
state_switch (ctx, STATE_CLASS_CONSTANT);
|
|
|
|
break;
|
|
|
|
case STATE_INTERFACE:
|
|
|
|
state_switch (ctx, STATE_INTERFACE_CONSTANT);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_errordomain (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "errordomain") == 0 &&
|
|
|
|
ctx->state == STATE_NAMESPACE)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *getquark;
|
|
|
|
const gchar *codes;
|
|
|
|
const gchar *deprecated;
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
getquark = find_attribute ("get-quark", attribute_names, attribute_values);
|
|
|
|
codes = find_attribute ("codes", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else if (getquark == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "getquark");
|
|
|
|
else if (codes == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "codes");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeErrorDomain *domain;
|
|
|
|
|
|
|
|
domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
|
|
|
|
|
|
|
|
((GIrNode *)domain)->name = g_strdup (name);
|
|
|
|
domain->getquark = g_strdup (getquark);
|
|
|
|
domain->codes = g_strdup (codes);
|
|
|
|
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-08-09 14:46:48 +02:00
|
|
|
domain->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
domain->deprecated = FALSE;
|
|
|
|
|
|
|
|
ctx->current_node = (GIrNode *) domain;
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, domain);
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_ERRORDOMAIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_interface (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "interface") == 0 &&
|
|
|
|
ctx->state == STATE_NAMESPACE)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *typename;
|
|
|
|
const gchar *typeinit;
|
|
|
|
const gchar *deprecated;
|
|
|
|
|
|
|
|
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);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else if (typename == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
|
|
|
|
else if (typeinit == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
|
|
|
|
iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
|
|
|
|
((GIrNode *)iface)->name = g_strdup (name);
|
|
|
|
iface->gtype_name = g_strdup (typename);
|
|
|
|
iface->gtype_init = g_strdup (typeinit);
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-08-09 14:46:48 +02:00
|
|
|
iface->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
iface->deprecated = FALSE;
|
|
|
|
|
|
|
|
ctx->current_node = (GIrNode *) iface;
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, iface);
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_class (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "class") == 0 &&
|
|
|
|
ctx->state == STATE_NAMESPACE)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *parent;
|
|
|
|
const gchar *typename;
|
|
|
|
const gchar *typeinit;
|
|
|
|
const gchar *deprecated;
|
2008-10-20 19:04:17 +02:00
|
|
|
const gchar *abstract;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
parent = find_attribute ("parent", 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);
|
2008-10-20 19:04:17 +02:00
|
|
|
abstract = find_attribute ("abstract", attribute_names, attribute_values);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else if (typename == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
|
2008-08-13 23:44:38 +02:00
|
|
|
else if (typeinit == NULL && strcmp (typename, "GObject"))
|
2008-08-09 14:46:48 +02:00
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
|
|
|
|
iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
|
|
|
|
((GIrNode *)iface)->name = g_strdup (name);
|
|
|
|
iface->gtype_name = g_strdup (typename);
|
|
|
|
iface->gtype_init = g_strdup (typeinit);
|
|
|
|
iface->parent = g_strdup (parent);
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-08-09 14:46:48 +02:00
|
|
|
iface->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
iface->deprecated = FALSE;
|
2008-10-20 19:04:17 +02:00
|
|
|
|
|
|
|
iface->abstract = abstract && strcmp (abstract, "1") == 0;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
ctx->current_node = (GIrNode *) iface;
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, iface);
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_type (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
2008-09-01 20:52:34 +02:00
|
|
|
const gchar *ctype;
|
2008-09-29 21:03:44 +02:00
|
|
|
gboolean is_array;
|
2008-10-02 16:07:38 +02:00
|
|
|
gboolean is_varargs;
|
2008-09-01 20:52:34 +02:00
|
|
|
GIrNodeType *typenode;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
is_array = strcmp (element_name, "array") == 0;
|
2008-10-02 16:07:38 +02:00
|
|
|
is_varargs = strcmp (element_name, "varargs") == 0;
|
2008-09-29 21:03:44 +02:00
|
|
|
|
2008-10-02 16:07:38 +02:00
|
|
|
if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
|
2008-08-09 14:46:48 +02:00
|
|
|
return FALSE;
|
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
if (ctx->state == STATE_TYPE)
|
|
|
|
{
|
|
|
|
ctx->type_depth++;
|
|
|
|
ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
|
|
|
|
ctx->type_parameters = NULL;
|
|
|
|
}
|
2008-08-22 22:05:23 +02:00
|
|
|
else if (ctx->state == STATE_FUNCTION_PARAMETER ||
|
|
|
|
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
|
|
|
|
)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_TYPE);
|
|
|
|
ctx->type_depth = 1;
|
2008-10-02 16:07:38 +02:00
|
|
|
if (is_varargs)
|
|
|
|
{
|
|
|
|
switch (ctx->current_node->type)
|
|
|
|
{
|
|
|
|
case G_IR_NODE_FUNCTION:
|
|
|
|
case G_IR_NODE_CALLBACK:
|
|
|
|
{
|
|
|
|
GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
|
|
|
|
func->is_varargs = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_VFUNC:
|
|
|
|
{
|
|
|
|
GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
|
|
|
|
vfunc->is_varargs = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
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
|
|
|
/* list others individually rather than with default: so that compiler
|
|
|
|
* warns if new node types are added without adding them to the switch
|
|
|
|
*/
|
|
|
|
case G_IR_NODE_INVALID:
|
|
|
|
case G_IR_NODE_ENUM:
|
|
|
|
case G_IR_NODE_FLAGS:
|
|
|
|
case G_IR_NODE_CONSTANT:
|
|
|
|
case G_IR_NODE_ERROR_DOMAIN:
|
|
|
|
case G_IR_NODE_PARAM:
|
|
|
|
case G_IR_NODE_TYPE:
|
|
|
|
case G_IR_NODE_PROPERTY:
|
|
|
|
case G_IR_NODE_SIGNAL:
|
|
|
|
case G_IR_NODE_VALUE:
|
|
|
|
case G_IR_NODE_FIELD:
|
|
|
|
case G_IR_NODE_XREF:
|
|
|
|
case G_IR_NODE_STRUCT:
|
|
|
|
case G_IR_NODE_BOXED:
|
|
|
|
case G_IR_NODE_OBJECT:
|
|
|
|
case G_IR_NODE_INTERFACE:
|
|
|
|
case G_IR_NODE_UNION:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
2008-10-02 16:07:38 +02:00
|
|
|
}
|
|
|
|
}
|
2008-09-29 21:03:44 +02:00
|
|
|
ctx->type_stack = NULL;
|
|
|
|
ctx->type_parameters = NULL;
|
2008-08-22 22:05:23 +02:00
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
if (!ctx->current_typed)
|
|
|
|
{
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"The element <type> is invalid here");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-10-02 16:07:38 +02:00
|
|
|
if (is_varargs)
|
|
|
|
return TRUE;
|
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
if (is_array)
|
|
|
|
{
|
|
|
|
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
|
|
|
|
|
|
|
typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
|
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;
|
|
|
|
|
|
|
|
zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
|
|
|
|
len = find_attribute ("length", attribute_names, attribute_values);
|
2008-10-25 17:20:54 +02:00
|
|
|
size = find_attribute ("fixed-size", attribute_names, attribute_values);
|
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
|
|
|
|
typenode->has_length = len != NULL;
|
|
|
|
typenode->length = typenode->has_length ? atoi (len) : -1;
|
2008-10-25 17:20:54 +02:00
|
|
|
|
|
|
|
typenode->has_size = size != NULL;
|
|
|
|
typenode->size = typenode->has_size ? atoi (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
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
|
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++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx->current_typed->type == G_IR_NODE_PARAM &&
|
|
|
|
((GIrNodeParam *)ctx->current_typed)->out &&
|
|
|
|
pointer_depth > 0)
|
|
|
|
pointer_depth--;
|
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
typenode = parse_type (ctx, name);
|
|
|
|
|
2008-11-11 00:58:49 +01:00
|
|
|
/* A 'disguised' structure is one where the c:type is a typedef that
|
|
|
|
* doesn't look like a pointer, but is internally.
|
|
|
|
*/
|
|
|
|
if (typenode->tag == GI_TYPE_TAG_INTERFACE &&
|
2008-11-12 18:17:01 +01:00
|
|
|
is_disguised_structure (ctx, typenode->interface))
|
2008-11-16 21:58:35 +01:00
|
|
|
pointer_depth++;
|
2008-11-11 00:58:49 +01:00
|
|
|
|
2008-11-16 21:58:35 +01:00
|
|
|
if (pointer_depth > 0)
|
|
|
|
typenode->is_pointer = TRUE;
|
2008-09-29 21:03:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
end_type_top (ParseContext *ctx)
|
|
|
|
{
|
2008-10-02 16:07:38 +02:00
|
|
|
GIrNodeType *typenode;
|
|
|
|
|
|
|
|
if (!ctx->type_parameters)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
typenode = (GIrNodeType*)ctx->type_parameters->data;
|
2008-09-29 21:03:44 +02:00
|
|
|
|
|
|
|
/* Default to pointer for unspecified containers */
|
|
|
|
if (typenode->tag == GI_TYPE_TAG_ARRAY ||
|
|
|
|
typenode->tag == GI_TYPE_TAG_GLIST ||
|
|
|
|
typenode->tag == GI_TYPE_TAG_GSLIST)
|
|
|
|
{
|
2008-09-29 21:03:46 +02:00
|
|
|
if (typenode->parameter_type1 == NULL)
|
|
|
|
typenode->parameter_type1 = parse_type (ctx, "any");
|
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)
|
|
|
|
{
|
|
|
|
typenode->parameter_type1 = parse_type (ctx, "any");
|
|
|
|
typenode->parameter_type2 = parse_type (ctx, "any");
|
|
|
|
}
|
2008-09-29 21:03:44 +02:00
|
|
|
}
|
2008-09-01 20:52:34 +02:00
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
switch (ctx->current_typed->type)
|
|
|
|
{
|
|
|
|
case G_IR_NODE_PARAM:
|
|
|
|
{
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
|
2008-09-01 20:52:34 +02:00
|
|
|
param->type = typenode;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_FIELD:
|
|
|
|
{
|
|
|
|
GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
|
2008-09-01 20:52:34 +02:00
|
|
|
field->type = typenode;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_PROPERTY:
|
|
|
|
{
|
|
|
|
GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
|
2008-09-01 20:52:34 +02:00
|
|
|
property->type = typenode;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
case G_IR_NODE_CONSTANT:
|
|
|
|
{
|
|
|
|
GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
|
2008-09-01 20:52:34 +02:00
|
|
|
constant->type = typenode;
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
}
|
|
|
|
break;
|
2008-08-09 14:46:48 +02:00
|
|
|
default:
|
|
|
|
g_printerr("current node is %d\n", ctx->current_node->type);
|
|
|
|
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
|
|
|
|
|
|
|
out:
|
2008-09-29 21:03:44 +02:00
|
|
|
ctx->type_depth = 0;
|
|
|
|
ctx->type_parameters = NULL;
|
|
|
|
ctx->current_typed = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
end_type_recurse (ParseContext *ctx)
|
|
|
|
{
|
|
|
|
GIrNodeType *parent;
|
2008-10-16 00:08:26 +02:00
|
|
|
GIrNodeType *param = NULL;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
|
2008-10-16 00:08:26 +02:00
|
|
|
if (ctx->type_parameters)
|
|
|
|
param = (GIrNodeType *) ctx->type_parameters->data;
|
2008-09-01 20:52:34 +02:00
|
|
|
|
2008-09-29 21:03:44 +02:00
|
|
|
if (parent->tag == GI_TYPE_TAG_ARRAY ||
|
|
|
|
parent->tag == GI_TYPE_TAG_GLIST ||
|
|
|
|
parent->tag == GI_TYPE_TAG_GSLIST)
|
|
|
|
{
|
2008-10-16 00:08:26 +02:00
|
|
|
g_assert (param != NULL);
|
|
|
|
|
|
|
|
if (parent->parameter_type1 == NULL)
|
|
|
|
parent->parameter_type1 = param;
|
2008-09-29 21:03:44 +02:00
|
|
|
else
|
2008-10-16 00:08:26 +02:00
|
|
|
g_assert_not_reached ();
|
2008-09-29 21:03:44 +02:00
|
|
|
}
|
|
|
|
else if (parent->tag == GI_TYPE_TAG_GHASH)
|
|
|
|
{
|
2008-10-16 00:08:26 +02:00
|
|
|
g_assert (param != NULL);
|
|
|
|
|
|
|
|
if (parent->parameter_type1 == NULL)
|
|
|
|
parent->parameter_type1 = param;
|
|
|
|
else if (parent->parameter_type2 == NULL)
|
|
|
|
parent->parameter_type2 = param;
|
2008-09-29 21:03:44 +02:00
|
|
|
else
|
2008-10-16 00:08:26 +02:00
|
|
|
g_assert_not_reached ();
|
2008-09-29 21:03:44 +02:00
|
|
|
}
|
|
|
|
g_list_free (ctx->type_parameters);
|
|
|
|
ctx->type_parameters = (GList *)ctx->type_stack->data;
|
|
|
|
ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
end_type (ParseContext *ctx)
|
|
|
|
{
|
|
|
|
if (ctx->type_depth == 1)
|
|
|
|
{
|
|
|
|
end_type_top (ctx);
|
|
|
|
state_switch (ctx, ctx->prev_state);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
end_type_recurse (ctx);
|
|
|
|
ctx->type_depth--;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_return_value (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "return-value") == 0 &&
|
|
|
|
ctx->state == STATE_FUNCTION)
|
|
|
|
{
|
|
|
|
GIrNodeParam *param;
|
2008-10-12 23:07:33 +02:00
|
|
|
const gchar *transfer;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
|
|
|
|
param->in = FALSE;
|
|
|
|
param->out = FALSE;
|
|
|
|
param->retval = TRUE;
|
|
|
|
|
|
|
|
ctx->current_typed = (GIrNode*) param;
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_FUNCTION_RETURN);
|
|
|
|
|
2008-10-12 23:07:33 +02:00
|
|
|
transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
|
|
|
|
parse_param_transfer (param, transfer);
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
switch (ctx->current_node->type)
|
|
|
|
{
|
|
|
|
case G_IR_NODE_FUNCTION:
|
|
|
|
case G_IR_NODE_CALLBACK:
|
|
|
|
{
|
|
|
|
GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
|
|
|
|
func->result = param;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_SIGNAL:
|
|
|
|
{
|
|
|
|
GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
|
|
|
|
signal->result = param;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case G_IR_NODE_VFUNC:
|
|
|
|
{
|
|
|
|
GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
|
|
|
|
vfunc->result = param;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-08-25 17:22:39 +02:00
|
|
|
static gboolean
|
|
|
|
start_implements (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
if (strcmp (element_name, "implements") != 0 ||
|
|
|
|
!(ctx->state == STATE_CLASS))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_IMPLEMENTS);
|
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
iface = (GIrNodeInterface *)ctx->current_node;
|
|
|
|
iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
static gboolean
|
|
|
|
start_glib_signal (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "glib:signal") == 0 &&
|
|
|
|
(ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE))
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *when;
|
|
|
|
const gchar *no_recurse;
|
|
|
|
const gchar *detailed;
|
|
|
|
const gchar *action;
|
|
|
|
const gchar *no_hooks;
|
|
|
|
const gchar *has_class_closure;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
GIrNodeSignal *signal;
|
|
|
|
|
|
|
|
signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
|
|
|
|
|
|
|
|
((GIrNode *)signal)->name = g_strdup (name);
|
|
|
|
|
|
|
|
signal->run_first = FALSE;
|
|
|
|
signal->run_last = FALSE;
|
|
|
|
signal->run_cleanup = FALSE;
|
|
|
|
if (when == NULL || strcmp (when, "LAST") == 0)
|
|
|
|
signal->run_last = TRUE;
|
|
|
|
else if (strcmp (when, "FIRST") == 0)
|
|
|
|
signal->run_first = TRUE;
|
|
|
|
else
|
|
|
|
signal->run_cleanup = TRUE;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
iface = (GIrNodeInterface *)ctx->current_node;
|
|
|
|
iface->members = g_list_append (iface->members, signal);
|
|
|
|
|
|
|
|
ctx->current_node = (GIrNode *)signal;
|
|
|
|
state_switch (ctx, STATE_FUNCTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_vfunc (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "vfunc") == 0 &&
|
|
|
|
(ctx->state == STATE_CLASS ||
|
|
|
|
ctx->state == STATE_INTERFACE))
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *must_chain_up;
|
|
|
|
const gchar *override;
|
|
|
|
const gchar *is_class_closure;
|
|
|
|
const gchar *offset;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
GIrNodeVFunc *vfunc;
|
|
|
|
|
|
|
|
vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
|
|
|
|
|
|
|
|
((GIrNode *)vfunc)->name = g_strdup (name);
|
|
|
|
|
|
|
|
if (must_chain_up && strcmp (must_chain_up, "1") == 0)
|
|
|
|
vfunc->must_chain_up = TRUE;
|
|
|
|
else
|
|
|
|
vfunc->must_chain_up = FALSE;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_class_closure && strcmp (is_class_closure, "1") == 0)
|
|
|
|
vfunc->is_class_closure = TRUE;
|
|
|
|
else
|
|
|
|
vfunc->is_class_closure = FALSE;
|
|
|
|
|
|
|
|
if (offset)
|
|
|
|
vfunc->offset = atoi (offset);
|
|
|
|
else
|
|
|
|
vfunc->offset = 0;
|
|
|
|
|
|
|
|
iface = (GIrNodeInterface *)ctx->current_node;
|
|
|
|
iface->members = g_list_append (iface->members, vfunc);
|
|
|
|
|
|
|
|
ctx->current_node = (GIrNode *)vfunc;
|
|
|
|
state_switch (ctx, STATE_FUNCTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_struct (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "record") == 0 &&
|
|
|
|
ctx->state == STATE_NAMESPACE)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *deprecated;
|
2008-11-11 00:58:49 +01:00
|
|
|
const gchar *disguised;
|
2008-09-06 22:33:51 +02:00
|
|
|
const gchar *gtype_name;
|
|
|
|
const gchar *gtype_init;
|
|
|
|
GIrNodeStruct *struct_;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
|
2008-11-11 00:58:49 +01:00
|
|
|
disguised = find_attribute ("disguised", attribute_names, attribute_values);
|
2008-09-06 22:33:51 +02:00
|
|
|
gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
|
|
|
|
gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
if (name == NULL)
|
|
|
|
{
|
2008-09-06 22:33:51 +02:00
|
|
|
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;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-09-06 22:33:51 +02:00
|
|
|
struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
|
|
|
|
|
|
|
|
((GIrNode *)struct_)->name = g_strdup (name);
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-09-06 22:33:51 +02:00
|
|
|
struct_->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
struct_->deprecated = FALSE;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-11-11 00:58:49 +01:00
|
|
|
if (disguised && strcmp (disguised, "1") == 0)
|
|
|
|
struct_->disguised = TRUE;
|
|
|
|
|
2008-09-06 22:33:51 +02:00
|
|
|
struct_->gtype_name = g_strdup (gtype_name);
|
|
|
|
struct_->gtype_init = g_strdup (gtype_init);
|
|
|
|
|
|
|
|
ctx->current_node = (GIrNode *)struct_;
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, struct_);
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_STRUCT);
|
2008-08-09 14:46:48 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_union (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "union") == 0 &&
|
|
|
|
ctx->state == STATE_NAMESPACE)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
|
|
|
const gchar *deprecated;
|
|
|
|
const gchar *typename;
|
|
|
|
const gchar *typeinit;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeUnion *union_;
|
|
|
|
|
|
|
|
union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
|
|
|
|
|
|
|
|
((GIrNode *)union_)->name = g_strdup (name);
|
|
|
|
union_->gtype_name = g_strdup (typename);
|
|
|
|
union_->gtype_init = g_strdup (typeinit);
|
2008-09-15 16:46:19 +02:00
|
|
|
if (deprecated)
|
2008-08-09 14:46:48 +02:00
|
|
|
union_->deprecated = TRUE;
|
|
|
|
else
|
|
|
|
union_->deprecated = FALSE;
|
|
|
|
|
|
|
|
ctx->current_node = (GIrNode *)union_;
|
|
|
|
ctx->current_module->entries =
|
|
|
|
g_list_append (ctx->current_module->entries, union_);
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_UNION);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
start_discriminator (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
ParseContext *ctx,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (strcmp (element_name, "discriminator") == 0 &&
|
|
|
|
ctx->state == STATE_UNION)
|
|
|
|
{
|
|
|
|
const gchar *type;
|
|
|
|
const gchar *offset;
|
|
|
|
|
|
|
|
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");
|
|
|
|
else if (offset == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "offset");
|
|
|
|
{
|
|
|
|
((GIrNodeUnion *)ctx->current_node)->discriminator_type
|
2008-08-13 18:10:09 +02:00
|
|
|
= parse_type (ctx, type);
|
2008-08-09 14:46:48 +02:00
|
|
|
((GIrNodeUnion *)ctx->current_node)->discriminator_offset
|
|
|
|
= atoi (offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
|
|
|
|
static gboolean
|
|
|
|
parse_include (GMarkupParseContext *context,
|
|
|
|
ParseContext *ctx,
|
|
|
|
const char *name,
|
2008-10-16 03:40:29 +02:00
|
|
|
const char *version,
|
2008-08-28 23:19:22 +02:00
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
gchar *buffer;
|
|
|
|
gsize length;
|
|
|
|
char *girpath;
|
2008-11-11 01:48:17 +01:00
|
|
|
gboolean success = FALSE;
|
2008-11-12 18:17:01 +01:00
|
|
|
GList *modules;
|
2008-11-11 01:48:17 +01:00
|
|
|
GList *l;
|
|
|
|
|
2008-11-12 18:17:15 +01:00
|
|
|
for (l = ctx->parser->parsed_modules; l; l = l->next)
|
2008-11-11 01:48:17 +01:00
|
|
|
{
|
|
|
|
GIrModule *m = l->data;
|
|
|
|
|
|
|
|
if (strcmp (m->name, name) == 0)
|
|
|
|
{
|
|
|
|
if (strcmp (m->version, version) == 0)
|
|
|
|
{
|
2008-11-12 18:17:15 +01:00
|
|
|
ctx->include_modules = g_list_prepend (ctx->include_modules, m);
|
|
|
|
|
2008-11-11 01:48:17 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Module '%s' imported with conflicting versions '%s' and '%s'",
|
|
|
|
name, m->version, version);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
girpath = locate_gir (ctx->parser, name, version);
|
2008-08-28 23:19:22 +02:00
|
|
|
|
|
|
|
if (girpath == NULL)
|
|
|
|
{
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
2008-10-12 06:51:48 +02:00
|
|
|
"Could not find GIR file '%s.gir'; check XDG_DATA_DIRS or use --includedir",
|
2008-08-28 23:19:22 +02:00
|
|
|
name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_debug ("Parsing include %s", girpath);
|
|
|
|
|
|
|
|
if (!g_file_get_contents (girpath, &buffer, &length, error))
|
|
|
|
{
|
|
|
|
g_free (girpath);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
g_free (girpath);
|
|
|
|
|
2008-11-12 18:17:01 +01:00
|
|
|
modules = g_ir_parser_parse_string (ctx->parser, name, buffer, length, error);
|
|
|
|
success = error != NULL;
|
2008-11-11 01:48:17 +01:00
|
|
|
|
|
|
|
ctx->include_modules = g_list_concat (ctx->include_modules,
|
2008-11-12 18:17:01 +01:00
|
|
|
modules);
|
2008-11-11 01:48:17 +01:00
|
|
|
|
|
|
|
g_free (buffer);
|
|
|
|
|
|
|
|
return success;
|
2008-08-28 23:19:22 +02:00
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
extern GLogLevelFlags logged_levels;
|
|
|
|
|
|
|
|
static void
|
|
|
|
start_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
ParseContext *ctx = user_data;
|
|
|
|
gint line_number, char_number;
|
|
|
|
|
|
|
|
if (logged_levels & G_LOG_LEVEL_DEBUG)
|
|
|
|
{
|
|
|
|
GString *tags = g_string_new ("");
|
|
|
|
int i;
|
|
|
|
for (i = 0; attribute_names[i]; i++)
|
|
|
|
g_string_append_printf (tags, "%s=\"%s\" ",
|
|
|
|
attribute_names[i],
|
|
|
|
attribute_values[i]);
|
|
|
|
|
|
|
|
if (i)
|
|
|
|
{
|
|
|
|
g_string_insert_c (tags, 0, ' ');
|
|
|
|
g_string_truncate (tags, tags->len - 1);
|
|
|
|
}
|
|
|
|
g_debug ("<%s%s>", element_name, tags->str);
|
|
|
|
g_string_free (tags, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (element_name[0])
|
|
|
|
{
|
2008-08-13 18:10:09 +02:00
|
|
|
case 'a':
|
|
|
|
if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_ALIAS);
|
|
|
|
goto out;
|
|
|
|
}
|
2008-09-29 21:03:44 +02:00
|
|
|
if (start_type (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-13 18:10:09 +02:00
|
|
|
break;
|
2008-08-09 14:46:48 +02:00
|
|
|
case 'b':
|
|
|
|
if (start_enum (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
if (start_function (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
else if (start_constant (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
else if (start_class (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'd':
|
|
|
|
if (start_discriminator (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'e':
|
|
|
|
if (start_enum (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
else if (start_errordomain (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'f':
|
|
|
|
if (start_function (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
else if (start_field (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'g':
|
|
|
|
if (start_glib_boxed (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
else if (start_glib_signal (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'i':
|
2008-08-23 18:11:01 +02:00
|
|
|
if (strcmp (element_name, "include") == 0 &&
|
|
|
|
ctx->state == STATE_REPOSITORY)
|
|
|
|
{
|
2008-08-28 23:19:22 +02:00
|
|
|
const gchar *name;
|
2008-10-16 03:40:29 +02:00
|
|
|
const gchar *version;
|
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
2008-10-16 03:40:29 +02:00
|
|
|
version = find_attribute ("version", attribute_names, attribute_values);
|
2008-08-28 23:19:22 +02:00
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
break;
|
|
|
|
}
|
2008-10-16 03:40:29 +02:00
|
|
|
if (version == NULL)
|
|
|
|
{
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "version");
|
|
|
|
break;
|
|
|
|
}
|
2008-08-28 23:19:22 +02:00
|
|
|
|
2008-10-16 03:40:29 +02:00
|
|
|
if (!parse_include (context, ctx, name, version, error))
|
2008-08-28 23:19:22 +02:00
|
|
|
break;
|
|
|
|
|
2008-10-16 03:40:29 +02:00
|
|
|
ctx->dependencies = g_list_prepend (ctx->dependencies,
|
|
|
|
g_strdup_printf ("%s-%s", name, version));
|
2008-08-30 22:31:07 +02:00
|
|
|
|
|
|
|
|
2008-08-23 18:11:01 +02:00
|
|
|
state_switch (ctx, STATE_INCLUDE);
|
|
|
|
goto out;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
if (start_interface (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-25 17:22:39 +02:00
|
|
|
else if (start_implements (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'm':
|
|
|
|
if (start_function (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
else if (start_member (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
|
|
|
|
{
|
2008-10-12 06:51:48 +02:00
|
|
|
const gchar *name, *version, *shared_library;
|
2008-11-12 18:16:49 +01:00
|
|
|
|
|
|
|
if (ctx->current_module != NULL)
|
|
|
|
{
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Only one <namespace/> element is currently allowed per <repository/>");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
2008-10-12 06:51:48 +02:00
|
|
|
version = find_attribute ("version", attribute_names, attribute_values);
|
2008-08-09 14:46:48 +02:00
|
|
|
shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
2008-10-12 06:51:48 +02:00
|
|
|
else if (version == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "version");
|
2008-08-09 14:46:48 +02:00
|
|
|
else
|
|
|
|
{
|
2008-11-12 18:17:01 +01:00
|
|
|
GList *l;
|
|
|
|
|
2008-11-12 18:16:49 +01:00
|
|
|
if (strcmp (name, ctx->namespace) != 0)
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"<namespace/> name element '%s' doesn't match file name '%s'",
|
|
|
|
name, ctx->namespace);
|
|
|
|
|
2008-10-12 06:51:48 +02:00
|
|
|
ctx->current_module = g_ir_module_new (name, version, shared_library);
|
2008-11-12 18:17:01 +01:00
|
|
|
|
|
|
|
ctx->current_module->aliases = ctx->aliases;
|
|
|
|
ctx->aliases = NULL;
|
|
|
|
ctx->current_module->disguised_structures = ctx->disguised_structures;
|
|
|
|
ctx->disguised_structures = NULL;
|
|
|
|
|
|
|
|
for (l = ctx->include_modules; l; l = l->next)
|
|
|
|
g_ir_module_add_include_module (ctx->current_module, l->data);
|
|
|
|
|
2008-11-12 18:17:08 +01:00
|
|
|
g_list_free (ctx->include_modules);
|
|
|
|
ctx->include_modules = NULL;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
ctx->modules = g_list_append (ctx->modules, ctx->current_module);
|
2008-08-30 22:31:07 +02:00
|
|
|
ctx->current_module->dependencies = ctx->dependencies;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
2008-08-29 22:41:26 +02:00
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'p':
|
|
|
|
if (start_property (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
else if (strcmp (element_name, "parameters") == 0 &&
|
|
|
|
ctx->state == STATE_FUNCTION)
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION_PARAMETERS);
|
|
|
|
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
else if (start_parameter (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-11-17 01:27:37 +01:00
|
|
|
else if (strcmp (element_name, "prerequisite") == 0 &&
|
|
|
|
ctx->state == STATE_INTERFACE)
|
|
|
|
{
|
|
|
|
const gchar *name;
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-11-17 01:27:37 +01:00
|
|
|
name = find_attribute ("name", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
state_switch (ctx, STATE_PREREQUISITE);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface;
|
|
|
|
|
|
|
|
iface = (GIrNodeInterface *)ctx->current_node;
|
|
|
|
iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
|
|
|
|
}
|
|
|
|
goto out;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'r':
|
|
|
|
if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
|
|
|
|
{
|
|
|
|
const gchar *version;
|
|
|
|
|
|
|
|
version = find_attribute ("version", attribute_names, attribute_values);
|
|
|
|
|
|
|
|
if (version == NULL)
|
|
|
|
MISSING_ATTRIBUTE (context, error, element_name, "version");
|
|
|
|
else if (strcmp (version, "1.0") != 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;
|
|
|
|
}
|
|
|
|
else if (start_return_value (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
else if (start_struct (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'u':
|
|
|
|
if (start_union (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 't':
|
|
|
|
if (start_type (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'v':
|
|
|
|
if (start_vfunc (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
2008-10-02 16:07:38 +02:00
|
|
|
goto out;
|
|
|
|
if (start_type (context, element_name,
|
|
|
|
attribute_names, attribute_values,
|
|
|
|
ctx, error))
|
|
|
|
goto out;
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
|
|
|
2008-08-22 22:05:23 +02:00
|
|
|
if (error && *error == NULL)
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_UNKNOWN_ELEMENT,
|
|
|
|
"Unexpected start tag '%s' on line %d char %d; current state=%d",
|
|
|
|
element_name,
|
|
|
|
line_number, char_number, ctx->state);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
out: ;
|
|
|
|
if (*error)
|
|
|
|
{
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
|
|
|
|
|
|
fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
|
|
|
|
backtrace_stderr ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
require_one_of_end_elements (GMarkupParseContext *context,
|
2008-08-14 18:09:06 +02:00
|
|
|
ParseContext *ctx,
|
2008-08-09 14:46:48 +02:00
|
|
|
const char *actual_name,
|
|
|
|
GError **error,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
int line_number, char_number;
|
|
|
|
const char *expected;
|
|
|
|
gboolean matched = FALSE;
|
|
|
|
|
|
|
|
va_start (args, error);
|
|
|
|
|
|
|
|
while ((expected = va_arg (args, const char*)) != NULL)
|
|
|
|
{
|
|
|
|
if (strcmp (expected, actual_name) == 0)
|
|
|
|
{
|
|
|
|
matched = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
va_end (args);
|
|
|
|
|
|
|
|
if (matched)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
2008-08-14 18:09:06 +02:00
|
|
|
"Unexpected end tag '%s' on line %d char %d; current state=%d",
|
2008-08-09 14:46:48 +02:00
|
|
|
actual_name,
|
2008-08-14 18:09:06 +02:00
|
|
|
line_number, char_number, ctx->state);
|
2008-08-09 14:46:48 +02:00
|
|
|
backtrace_stderr();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
require_end_element (GMarkupParseContext *context,
|
2008-08-14 18:09:06 +02:00
|
|
|
ParseContext *ctx,
|
2008-08-09 14:46:48 +02:00
|
|
|
const char *expected_name,
|
|
|
|
const char *actual_name,
|
|
|
|
GError **error)
|
|
|
|
{
|
2008-08-14 18:09:06 +02:00
|
|
|
return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
end_element_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
ParseContext *ctx = user_data;
|
|
|
|
|
|
|
|
g_debug ("</%s>", element_name);
|
|
|
|
|
|
|
|
switch (ctx->state)
|
|
|
|
{
|
|
|
|
case STATE_START:
|
|
|
|
case STATE_END:
|
|
|
|
/* no need to GError here, GMarkup already catches this */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_REPOSITORY:
|
|
|
|
state_switch (ctx, STATE_END);
|
|
|
|
break;
|
|
|
|
|
2008-08-23 18:11:01 +02:00
|
|
|
case STATE_INCLUDE:
|
|
|
|
if (require_end_element (context, ctx, "include", element_name, error))
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_REPOSITORY);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
case STATE_NAMESPACE:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "namespace", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ctx->current_module = NULL;
|
|
|
|
state_switch (ctx, STATE_REPOSITORY);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-08-13 18:10:09 +02:00
|
|
|
case STATE_ALIAS:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "alias", element_name, error))
|
2008-08-13 18:10:09 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
case STATE_FUNCTION_RETURN:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "return-value", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_FUNCTION_PARAMETERS:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "parameters", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_FUNCTION_PARAMETER:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "parameter", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_FUNCTION_PARAMETERS);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_FUNCTION:
|
2008-10-02 16:07:38 +02:00
|
|
|
{
|
|
|
|
gboolean current_is_toplevel;
|
|
|
|
GList *last = g_list_last (ctx->current_module->entries);
|
|
|
|
|
|
|
|
current_is_toplevel = ctx->current_node == last->data;
|
|
|
|
|
|
|
|
if (current_is_toplevel)
|
|
|
|
{
|
|
|
|
ctx->current_node = NULL;
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ctx->current_node = g_list_last (ctx->current_module->entries)->data;
|
|
|
|
if (ctx->current_node->type == G_IR_NODE_INTERFACE)
|
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
else if (ctx->current_node->type == G_IR_NODE_OBJECT)
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
else if (ctx->current_node->type == G_IR_NODE_BOXED)
|
|
|
|
state_switch (ctx, STATE_BOXED);
|
|
|
|
else if (ctx->current_node->type == G_IR_NODE_STRUCT)
|
|
|
|
state_switch (ctx, STATE_STRUCT);
|
|
|
|
else if (ctx->current_node->type == G_IR_NODE_UNION)
|
|
|
|
state_switch (ctx, STATE_UNION);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int line_number, char_number;
|
|
|
|
g_markup_parse_context_get_position (context, &line_number, &char_number);
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Unexpected end tag '%s' on line %d char %d",
|
|
|
|
element_name,
|
|
|
|
line_number, char_number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_CLASS_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_CLASS_PROPERTY:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "property", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_CLASS:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "class", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ctx->current_node = NULL;
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_ERRORDOMAIN:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "errordomain", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ctx->current_node = NULL;
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_INTERFACE_PROPERTY:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
|
|
|
if (require_end_element (context, ctx, "property", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_INTERFACE_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_INTERFACE:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "interface", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ctx->current_node = NULL;
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_ENUM:
|
|
|
|
if (strcmp ("member", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
else if (require_one_of_end_elements (context, ctx,
|
|
|
|
element_name, error, "enumeration",
|
|
|
|
"bitfield", NULL))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ctx->current_node = NULL;
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_BOXED:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "glib:boxed", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ctx->current_node = NULL;
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_BOXED_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_BOXED);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_STRUCT_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_STRUCT);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_STRUCT:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "record", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ctx->current_node = NULL;
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
2008-08-20 17:05:46 +02:00
|
|
|
|
|
|
|
case STATE_UNION_FIELD:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
|
|
|
if (require_end_element (context, ctx, "field", element_name, error))
|
|
|
|
{
|
|
|
|
state_switch (ctx, STATE_UNION);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
case STATE_UNION:
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "union", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ctx->current_node = NULL;
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_IMPLEMENTS:
|
|
|
|
if (strcmp ("interface", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "implements", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
break;
|
2008-11-17 01:27:37 +01:00
|
|
|
case STATE_PREREQUISITE:
|
|
|
|
if (require_end_element (context, ctx, "prerequisite", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
break;
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
case STATE_NAMESPACE_CONSTANT:
|
|
|
|
case STATE_CLASS_CONSTANT:
|
|
|
|
case STATE_INTERFACE_CONSTANT:
|
|
|
|
if (strcmp ("type", element_name) == 0)
|
|
|
|
break;
|
2008-08-14 18:09:06 +02:00
|
|
|
if (require_end_element (context, ctx, "constant", element_name, error))
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ctx->current_node = NULL;
|
Clear up constant parsing
2008-08-14 Johan Dahlin <johan@gnome.org>
* girepository/girparser.c (start_field), (start_constant),
(start_type), (end_element_handler):
Clear up constant parsing
* tests/object.gir:
Update
* tools/generate.c (write_callable_info), (write_function_info),
(write_callback_info), (write_constant_info), (write_signal_info),
(write_vfunc_info), (write_property_info), (write_object_info),
(write_interface_info):
Constants/Signals are handled now.
svn path=/trunk/; revision=377
2008-08-14 21:32:26 +02:00
|
|
|
switch (ctx->state)
|
|
|
|
{
|
|
|
|
case STATE_NAMESPACE_CONSTANT:
|
|
|
|
state_switch (ctx, STATE_NAMESPACE);
|
|
|
|
break;
|
|
|
|
case STATE_CLASS_CONSTANT:
|
|
|
|
state_switch (ctx, STATE_CLASS);
|
|
|
|
break;
|
|
|
|
case STATE_INTERFACE_CONSTANT:
|
|
|
|
state_switch (ctx, STATE_INTERFACE);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2008-08-22 22:05:23 +02:00
|
|
|
case STATE_TYPE:
|
2008-10-02 16:07:38 +02:00
|
|
|
if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
|
|
|
|
(strcmp ("varargs", element_name) == 0))
|
2008-08-22 22:05:23 +02:00
|
|
|
{
|
2008-09-29 21:03:44 +02:00
|
|
|
end_type (ctx);
|
2008-08-22 22:05:23 +02:00
|
|
|
break;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
default:
|
|
|
|
g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
text_handler (GMarkupParseContext *context,
|
|
|
|
const gchar *text,
|
|
|
|
gsize text_len,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
/* FIXME warn about non-whitespace text */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cleanup (GMarkupParseContext *context,
|
|
|
|
GError *error,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
ParseContext *ctx = user_data;
|
|
|
|
GList *m;
|
|
|
|
|
|
|
|
for (m = ctx->modules; m; m = m->next)
|
|
|
|
g_ir_module_free (m->data);
|
|
|
|
g_list_free (ctx->modules);
|
|
|
|
ctx->modules = NULL;
|
|
|
|
|
|
|
|
ctx->current_module = NULL;
|
|
|
|
}
|
|
|
|
|
2008-10-02 16:07:38 +02:00
|
|
|
static GList *
|
|
|
|
post_filter_varargs_functions (GList *list)
|
|
|
|
{
|
|
|
|
GList *iter;
|
|
|
|
|
|
|
|
iter = list;
|
|
|
|
while (iter)
|
|
|
|
{
|
|
|
|
GList *link = iter;
|
|
|
|
GIrNode *node = iter->data;
|
|
|
|
|
|
|
|
iter = iter->next;
|
|
|
|
|
|
|
|
if (node->type == G_IR_NODE_FUNCTION)
|
|
|
|
{
|
|
|
|
if (((GIrNodeFunction*)node)->is_varargs)
|
|
|
|
{
|
|
|
|
list = g_list_delete_link (list, link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
post_filter (GIrModule *module)
|
|
|
|
{
|
|
|
|
GList *iter;
|
|
|
|
|
|
|
|
module->entries = post_filter_varargs_functions (module->entries);
|
|
|
|
iter = module->entries;
|
|
|
|
while (iter)
|
|
|
|
{
|
|
|
|
GIrNode *node = iter->data;
|
|
|
|
|
|
|
|
iter = iter->next;
|
|
|
|
|
|
|
|
if (node->type == G_IR_NODE_OBJECT ||
|
|
|
|
node->type == G_IR_NODE_INTERFACE)
|
|
|
|
{
|
|
|
|
GIrNodeInterface *iface = (GIrNodeInterface*)node;
|
|
|
|
iface->members = post_filter_varargs_functions (iface->members);
|
|
|
|
}
|
|
|
|
else if (node->type == G_IR_NODE_BOXED)
|
|
|
|
{
|
|
|
|
GIrNodeBoxed *boxed = (GIrNodeBoxed*)node;
|
|
|
|
boxed->members = post_filter_varargs_functions (boxed->members);
|
|
|
|
}
|
|
|
|
else if (node->type == G_IR_NODE_STRUCT)
|
|
|
|
{
|
|
|
|
GIrNodeStruct *iface = (GIrNodeStruct*)node;
|
|
|
|
iface->members = post_filter_varargs_functions (iface->members);
|
|
|
|
}
|
|
|
|
else if (node->type == G_IR_NODE_UNION)
|
|
|
|
{
|
|
|
|
GIrNodeUnion *iface = (GIrNodeUnion*)node;
|
|
|
|
iface->members = post_filter_varargs_functions (iface->members);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
/**
|
|
|
|
* g_ir_parser_parse_string:
|
|
|
|
* @parser: a #GIrParser
|
|
|
|
* @error: return location for a #GError, or %NULL
|
|
|
|
*
|
|
|
|
* Parse a string that holds a complete GIR XML file, and return a list of a
|
|
|
|
* a #GirModule for each <namespace/> element within the file.
|
|
|
|
*
|
|
|
|
* @returns: a newly allocated list of #GIrModule. The modules themselves
|
|
|
|
* are owned by the #GIrParser and will be freed along with the parser.
|
|
|
|
*/
|
|
|
|
GList *
|
|
|
|
g_ir_parser_parse_string (GIrParser *parser,
|
|
|
|
const gchar *namespace,
|
|
|
|
const gchar *buffer,
|
|
|
|
gssize length,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
ParseContext ctx = { 0 };
|
|
|
|
GMarkupParseContext *context;
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
ctx.parser = parser;
|
2008-08-09 14:46:48 +02:00
|
|
|
ctx.state = STATE_START;
|
2008-08-28 23:19:22 +02:00
|
|
|
ctx.namespace = namespace;
|
2008-11-12 18:17:08 +01:00
|
|
|
ctx.include_modules = NULL;
|
2008-08-13 18:10:09 +02:00
|
|
|
ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
2008-11-11 00:58:49 +01:00
|
|
|
ctx.disguised_structures = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
2008-08-22 22:05:23 +02:00
|
|
|
ctx.type_depth = 0;
|
2008-08-30 22:31:07 +02:00
|
|
|
ctx.dependencies = NULL;
|
2008-08-29 22:41:26 +02:00
|
|
|
ctx.current_module = NULL;
|
2008-08-13 18:10:09 +02:00
|
|
|
|
|
|
|
context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
|
|
|
|
|
|
|
|
if (!g_markup_parse_context_parse (context, buffer, length, error))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (!g_markup_parse_context_end_parse (context, error))
|
|
|
|
goto out;
|
2008-08-28 23:19:22 +02:00
|
|
|
|
|
|
|
g_markup_parse_context_free (context);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
context = g_markup_parse_context_new (&markup_parser, 0, &ctx, NULL);
|
2008-08-09 14:46:48 +02:00
|
|
|
if (!g_markup_parse_context_parse (context, buffer, length, error))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (!g_markup_parse_context_end_parse (context, error))
|
|
|
|
goto out;
|
|
|
|
|
2008-11-12 18:17:15 +01:00
|
|
|
parser->parsed_modules = g_list_concat (g_list_copy (ctx.modules),
|
|
|
|
parser->parsed_modules);
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
out:
|
2008-08-13 18:10:09 +02:00
|
|
|
|
2008-11-12 18:17:01 +01:00
|
|
|
if (ctx.modules == NULL)
|
|
|
|
{
|
2008-11-12 18:17:08 +01:00
|
|
|
/* An error occurred before we created a module, so we haven't
|
|
|
|
* transferred ownership of these hash tables to the module.
|
|
|
|
*/
|
2008-11-12 18:17:01 +01:00
|
|
|
if (ctx.aliases != NULL)
|
|
|
|
g_hash_table_destroy (ctx.aliases);
|
|
|
|
if (ctx.disguised_structures != NULL)
|
|
|
|
g_hash_table_destroy (ctx.disguised_structures);
|
2008-11-12 18:17:08 +01:00
|
|
|
g_list_free (ctx.include_modules);
|
2008-11-12 18:17:01 +01:00
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
g_markup_parse_context_free (context);
|
|
|
|
|
|
|
|
return ctx.modules;
|
|
|
|
}
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
/**
|
|
|
|
* g_ir_parser_parse_file:
|
|
|
|
* @parser: a #GIrParser
|
|
|
|
* @error: return location for a #GError, or %NULL
|
|
|
|
*
|
|
|
|
* Parse GIR XML file, and return a list of a a #GirModule for each
|
|
|
|
* <namespace/> element within the file.
|
|
|
|
*
|
|
|
|
* @returns: a newly allocated list of #GIrModule. The modules themselves
|
|
|
|
* are owned by the #GIrParser and will be freed along with the parser.
|
|
|
|
*/
|
2008-08-09 14:46:48 +02:00
|
|
|
GList *
|
2008-11-12 18:16:42 +01:00
|
|
|
g_ir_parser_parse_file (GIrParser *parser,
|
|
|
|
const gchar *filename,
|
|
|
|
GError **error)
|
2008-08-09 14:46:48 +02:00
|
|
|
{
|
|
|
|
gchar *buffer;
|
|
|
|
gsize length;
|
|
|
|
GList *modules;
|
2008-10-02 16:07:38 +02:00
|
|
|
GList *iter;
|
2008-08-28 23:19:22 +02:00
|
|
|
const char *slash;
|
2008-11-12 18:16:49 +01:00
|
|
|
char *dash;
|
2008-08-28 23:19:22 +02:00
|
|
|
char *namespace;
|
|
|
|
|
|
|
|
if (!g_str_has_suffix (filename, ".gir"))
|
|
|
|
{
|
|
|
|
g_set_error (error,
|
|
|
|
G_MARKUP_ERROR,
|
|
|
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
|
|
|
"Expected filename to end with '.gir'");
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
g_debug ("[parsing] filename %s", filename);
|
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
slash = g_strrstr (filename, "/");
|
|
|
|
if (!slash)
|
|
|
|
namespace = g_strdup (filename);
|
|
|
|
else
|
|
|
|
namespace = g_strdup (slash+1);
|
|
|
|
namespace[strlen(namespace)-4] = '\0';
|
|
|
|
|
2008-11-12 18:16:49 +01:00
|
|
|
/* Remove version */
|
|
|
|
dash = strstr (namespace, "-");
|
|
|
|
if (dash != NULL)
|
|
|
|
*dash = '\0';
|
|
|
|
|
2008-08-09 14:46:48 +02:00
|
|
|
if (!g_file_get_contents (filename, &buffer, &length, error))
|
|
|
|
return NULL;
|
|
|
|
|
2008-11-12 18:16:42 +01:00
|
|
|
modules = g_ir_parser_parse_string (parser, namespace, buffer, length, error);
|
2008-08-28 23:19:22 +02:00
|
|
|
|
2008-10-02 16:07:38 +02:00
|
|
|
for (iter = modules; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
post_filter ((GIrModule*)iter->data);
|
|
|
|
}
|
|
|
|
|
2008-08-28 23:19:22 +02:00
|
|
|
g_free (namespace);
|
2008-08-09 14:46:48 +02:00
|
|
|
|
|
|
|
g_free (buffer);
|
|
|
|
|
|
|
|
return modules;
|
|
|
|
}
|
|
|
|
|
|
|
|
|