1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 * GObject introspection: A parser for the XML GIR format
3 *
4 * Copyright (C) 2005 Matthias Clasen
5 * Copyright (C) 2008 Philip Van Hoof
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28
29 #include <glib.h>
30 #include "girparser.h"
31 #include "girmodule.h"
32 #include "girnode.h"
33 #include "gitypelib-internal.h"
34
35 /* This is a "major" version in the sense that it's only bumped
36 * for incompatible changes.
37 */
38 #define SUPPORTED_GIR_VERSION "1.2"
39
40 #ifdef G_OS_WIN32
41
42 #include <windows.h>
43
44 #ifdef GIR_DIR
45 #undef GIR_DIR
46 #endif
47
48 /* GIR_DIR is used only in code called just once,
49 * so no problem leaking this
50 */
51 #define GIR_DIR \
52 g_build_filename (g_win32_get_package_installation_directory_of_module(NULL), \
53 "share", \
54 GIR_SUFFIX, \
55 NULL)
56 #endif
57
58 struct _GIrParser
59 {
60 gchar **includes;
61 GList *parsed_modules; /* All previously parsed modules */
62 };
63
64 typedef enum
65 {
66 STATE_NONE = 0,
67 STATE_START,
68 STATE_END,
69 STATE_REPOSITORY,
70 STATE_INCLUDE,
71 STATE_C_INCLUDE, /* 5 */
72 STATE_PACKAGE,
73 STATE_NAMESPACE,
74 STATE_ENUM,
75 STATE_BITFIELD,
76 STATE_FUNCTION, /* 10 */
77 STATE_FUNCTION_RETURN,
78 STATE_FUNCTION_PARAMETERS,
79 STATE_FUNCTION_PARAMETER,
80 STATE_CLASS,
81 STATE_CLASS_FIELD, /* 15 */
82 STATE_CLASS_PROPERTY,
83 STATE_INTERFACE,
84 STATE_INTERFACE_PROPERTY,
85 STATE_INTERFACE_FIELD,
86 STATE_IMPLEMENTS, /* 20 */
87 STATE_PREREQUISITE,
88 STATE_BOXED,
89 STATE_BOXED_FIELD,
90 STATE_STRUCT,
91 STATE_STRUCT_FIELD, /* 25 */
92 STATE_UNION,
93 STATE_UNION_FIELD,
94 STATE_NAMESPACE_CONSTANT,
95 STATE_CLASS_CONSTANT,
96 STATE_INTERFACE_CONSTANT, /* 30 */
97 STATE_ALIAS,
98 STATE_TYPE,
99 STATE_ATTRIBUTE,
100 STATE_PASSTHROUGH
101 } ParseState;
102
103 typedef struct _ParseContext ParseContext;
104 struct _ParseContext
105 {
106 GIrParser *parser;
107
108 ParseState state;
109 int unknown_depth;
110 ParseState prev_state;
111
112 GList *modules;
113 GList *include_modules;
114 GList *dependencies;
115 GHashTable *aliases;
116 GHashTable *disguised_structures;
117
118 const char *file_path;
119 const char *namespace;
120 const char *c_prefix;
121 GIrModule *current_module;
122 GSList *node_stack;
123 char *current_alias;
124 GIrNode *current_typed;
125 GList *type_stack;
126 GList *type_parameters;
127 int type_depth;
128 ParseState in_embedded_state;
129 };
130 #define CURRENT_NODE(ctx) ((GIrNode *)((ctx)->node_stack->data))
131
132 static void start_element_handler (GMarkupParseContext *context,
133 const gchar *element_name,
134 const gchar **attribute_names,
135 const gchar **attribute_values,
136 gpointer user_data,
137 GError **error);
138 static void end_element_handler (GMarkupParseContext *context,
139 const gchar *element_name,
140 gpointer user_data,
141 GError **error);
142 static void text_handler (GMarkupParseContext *context,
143 const gchar *text,
144 gsize text_len,
145 gpointer user_data,
146 GError **error);
147 static void cleanup (GMarkupParseContext *context,
148 GError *error,
149 gpointer user_data);
150 static void state_switch (ParseContext *ctx, ParseState newstate);
151
152
153 static GMarkupParser markup_parser =
154 {
155 start_element_handler,
156 end_element_handler,
157 text_handler,
158 NULL,
159 cleanup
160 };
161
162 static gboolean
163 start_alias (GMarkupParseContext *context,
164 const gchar *element_name,
165 const gchar **attribute_names,
166 const gchar **attribute_values,
167 ParseContext *ctx,
168 GError **error);
169 static gboolean
170 start_type (GMarkupParseContext *context,
171 const gchar *element_name,
172 const gchar **attribute_names,
173 const gchar **attribute_values,
174 ParseContext *ctx,
175 GError **error);
176
177 static const gchar *find_attribute (const gchar *name,
178 const gchar **attribute_names,
179 const gchar **attribute_values);
180
181
182 GIrParser *
_g_ir_parser_new(void)183 _g_ir_parser_new (void)
184 {
185 GIrParser *parser = g_slice_new0 (GIrParser);
186
187 return parser;
188 }
189
190 void
_g_ir_parser_free(GIrParser * parser)191 _g_ir_parser_free (GIrParser *parser)
192 {
193 GList *l;
194
195 if (parser->includes)
196 g_strfreev (parser->includes);
197
198 for (l = parser->parsed_modules; l; l = l->next)
199 _g_ir_module_free (l->data);
200
201 g_slice_free (GIrParser, parser);
202 }
203
204 void
_g_ir_parser_set_includes(GIrParser * parser,const gchar * const * includes)205 _g_ir_parser_set_includes (GIrParser *parser,
206 const gchar *const *includes)
207 {
208 if (parser->includes)
209 g_strfreev (parser->includes);
210
211 parser->includes = g_strdupv ((char **)includes);
212 }
213
214 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)215 firstpass_start_element_handler (GMarkupParseContext *context,
216 const gchar *element_name,
217 const gchar **attribute_names,
218 const gchar **attribute_values,
219 gpointer user_data,
220 GError **error)
221 {
222 ParseContext *ctx = user_data;
223
224 if (strcmp (element_name, "alias") == 0)
225 {
226 start_alias (context, element_name, attribute_names, attribute_values,
227 ctx, error);
228 }
229 else if (ctx->state == STATE_ALIAS && strcmp (element_name, "type") == 0)
230 {
231 start_type (context, element_name, attribute_names, attribute_values,
232 ctx, error);
233 }
234 else if (strcmp (element_name, "record") == 0)
235 {
236 const gchar *name;
237 const gchar *disguised;
238
239 name = find_attribute ("name", attribute_names, attribute_values);
240 disguised = find_attribute ("disguised", attribute_names, attribute_values);
241
242 if (disguised && strcmp (disguised, "1") == 0)
243 {
244 char *key;
245
246 key = g_strdup_printf ("%s.%s", ctx->namespace, name);
247 g_hash_table_replace (ctx->disguised_structures, key, GINT_TO_POINTER (1));
248 }
249 }
250 }
251
252 static void
firstpass_end_element_handler(GMarkupParseContext * context,const gchar * element_name,gpointer user_data,GError ** error)253 firstpass_end_element_handler (GMarkupParseContext *context,
254 const gchar *element_name,
255 gpointer user_data,
256 GError **error)
257 {
258 ParseContext *ctx = user_data;
259 if (strcmp (element_name, "alias") == 0)
260 {
261 state_switch (ctx, STATE_NAMESPACE);
262 g_free (ctx->current_alias);
263 ctx->current_alias = NULL;
264 }
265 else if (strcmp (element_name, "type") == 0 && ctx->state == STATE_TYPE)
266 state_switch (ctx, ctx->prev_state);
267 }
268
269 static GMarkupParser firstpass_parser =
270 {
271 firstpass_start_element_handler,
272 firstpass_end_element_handler,
273 NULL,
274 NULL,
275 NULL,
276 };
277
278 static char *
locate_gir(GIrParser * parser,const char * girname)279 locate_gir (GIrParser *parser,
280 const char *girname)
281 {
282 const gchar *const *datadirs;
283 const gchar *const *dir;
284 char *path = NULL;
285
286 datadirs = g_get_system_data_dirs ();
287
288 if (parser->includes != NULL)
289 {
290 for (dir = (const gchar *const *)parser->includes; *dir; dir++)
291 {
292 path = g_build_filename (*dir, girname, NULL);
293 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
294 return path;
295 g_free (path);
296 path = NULL;
297 }
298 }
299 for (dir = datadirs; *dir; dir++)
300 {
301 path = g_build_filename (*dir, GIR_SUFFIX, girname, NULL);
302 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
303 return path;
304 g_free (path);
305 path = NULL;
306 }
307
308 path = g_build_filename (GIR_DIR, girname, NULL);
309 if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
310 return path;
311 g_free (path);
312 return NULL;
313 }
314
315 #define MISSING_ATTRIBUTE(context,error,element,attribute) \
316 do { \
317 int line_number, char_number; \
318 g_markup_parse_context_get_position (context, &line_number, &char_number); \
319 g_set_error (error, \
320 G_MARKUP_ERROR, \
321 G_MARKUP_ERROR_INVALID_CONTENT, \
322 "Line %d, character %d: The attribute '%s' on the element '%s' must be specified", \
323 line_number, char_number, attribute, element); \
324 } while (0)
325
326 static const gchar *
find_attribute(const gchar * name,const gchar ** attribute_names,const gchar ** attribute_values)327 find_attribute (const gchar *name,
328 const gchar **attribute_names,
329 const gchar **attribute_values)
330 {
331 gint i;
332
333 for (i = 0; attribute_names[i] != NULL; i++)
334 if (strcmp (attribute_names[i], name) == 0)
335 return attribute_values[i];
336
337 return 0;
338 }
339
340 static void
state_switch(ParseContext * ctx,ParseState newstate)341 state_switch (ParseContext *ctx, ParseState newstate)
342 {
343 g_assert (ctx->state != newstate);
344 ctx->prev_state = ctx->state;
345 ctx->state = newstate;
346
347 if (ctx->state == STATE_PASSTHROUGH)
348 ctx->unknown_depth = 1;
349 }
350
351 static GIrNode *
pop_node(ParseContext * ctx)352 pop_node (ParseContext *ctx)
353 {
354 GSList *top;
355 GIrNode *node;
356 g_assert (ctx->node_stack != 0);
357
358 top = ctx->node_stack;
359 node = top->data;
360
361 g_debug ("popping node %d %s", node->type, node->name);
362 ctx->node_stack = top->next;
363 g_slist_free_1 (top);
364 return node;
365 }
366
367 static void
push_node(ParseContext * ctx,GIrNode * node)368 push_node (ParseContext *ctx, GIrNode *node)
369 {
370 g_assert (node != NULL);
371 g_debug ("pushing node %d %s", node->type, node->name);
372 ctx->node_stack = g_slist_prepend (ctx->node_stack, node);
373 }
374
375 static GIrNodeType * parse_type_internal (GIrModule *module,
376 const gchar *str, gchar **next, gboolean in_glib,
377 gboolean in_gobject);
378
379 typedef struct {
380 const gchar *str;
381 guint size;
382 guint is_signed : 1;
383 } IntegerAliasInfo;
384
385 static IntegerAliasInfo integer_aliases[] = {
386 { "gchar", SIZEOF_CHAR, 1 },
387 { "guchar", SIZEOF_CHAR, 0 },
388 { "gshort", SIZEOF_SHORT, 1 },
389 { "gushort", SIZEOF_SHORT, 0 },
390 { "gint", SIZEOF_INT, 1 },
391 { "guint", SIZEOF_INT, 0 },
392 { "glong", SIZEOF_LONG, 1 },
393 { "gulong", SIZEOF_LONG, 0 },
394 { "gssize", GLIB_SIZEOF_SIZE_T, 1 },
395 { "gsize", GLIB_SIZEOF_SIZE_T, 0 },
396 { "gintptr", GLIB_SIZEOF_SIZE_T, 1 },
397 { "guintptr", GLIB_SIZEOF_SIZE_T, 0 },
398 };
399
400 typedef struct {
401 const gchar *str;
402 gint tag;
403 gboolean pointer;
404 } BasicTypeInfo;
405
406 #define BASIC_TYPE_FIXED_OFFSET 3
407
408 static BasicTypeInfo basic_types[] = {
409 { "none", GI_TYPE_TAG_VOID, 0 },
410 { "gpointer", GI_TYPE_TAG_VOID, 1 },
411
412 { "gboolean", GI_TYPE_TAG_BOOLEAN, 0 },
413 { "gint8", GI_TYPE_TAG_INT8, 0 }, /* Start of BASIC_TYPE_FIXED_OFFSET */
414 { "guint8", GI_TYPE_TAG_UINT8, 0 },
415 { "gint16", GI_TYPE_TAG_INT16, 0 },
416 { "guint16", GI_TYPE_TAG_UINT16, 0 },
417 { "gint32", GI_TYPE_TAG_INT32, 0 },
418 { "guint32", GI_TYPE_TAG_UINT32, 0 },
419 { "gint64", GI_TYPE_TAG_INT64, 0 },
420 { "guint64", GI_TYPE_TAG_UINT64, 0 },
421 { "gfloat", GI_TYPE_TAG_FLOAT, 0 },
422 { "gdouble", GI_TYPE_TAG_DOUBLE, 0 },
423 { "GType", GI_TYPE_TAG_GTYPE, 0 },
424 { "utf8", GI_TYPE_TAG_UTF8, 1 },
425 { "filename", GI_TYPE_TAG_FILENAME,1 },
426 { "gunichar", GI_TYPE_TAG_UNICHAR, 0 },
427 };
428
429 static const BasicTypeInfo *
parse_basic(const char * str)430 parse_basic (const char *str)
431 {
432 guint i;
433 guint n_basic = G_N_ELEMENTS (basic_types);
434
435 for (i = 0; i < n_basic; i++)
436 {
437 if (strcmp (str, basic_types[i].str) == 0)
438 return &(basic_types[i]);
439 }
440 for (i = 0; i < G_N_ELEMENTS (integer_aliases); i++)
441 {
442 if (strcmp (str, integer_aliases[i].str) == 0)
443 {
444 switch (integer_aliases[i].size)
445 {
446 case sizeof(guint8):
447 if (integer_aliases[i].is_signed)
448 return &basic_types[BASIC_TYPE_FIXED_OFFSET];
449 else
450 return &basic_types[BASIC_TYPE_FIXED_OFFSET+1];
451 break;
452 case sizeof(guint16):
453 if (integer_aliases[i].is_signed)
454 return &basic_types[BASIC_TYPE_FIXED_OFFSET+2];
455 else
456 return &basic_types[BASIC_TYPE_FIXED_OFFSET+3];
457 break;
458 case sizeof(guint32):
459 if (integer_aliases[i].is_signed)
460 return &basic_types[BASIC_TYPE_FIXED_OFFSET+4];
461 else
462 return &basic_types[BASIC_TYPE_FIXED_OFFSET+5];
463 break;
464 case sizeof(guint64):
465 if (integer_aliases[i].is_signed)
466 return &basic_types[BASIC_TYPE_FIXED_OFFSET+6];
467 else
468 return &basic_types[BASIC_TYPE_FIXED_OFFSET+7];
469 break;
470 default:
471 g_assert_not_reached ();
472 }
473 }
474 }
475 return NULL;
476 }
477
478 static GIrNodeType *
parse_type_internal(GIrModule * module,const gchar * str,char ** next,gboolean in_glib,gboolean in_gobject)479 parse_type_internal (GIrModule *module,
480 const gchar *str, char **next, gboolean in_glib,
481 gboolean in_gobject)
482 {
483 const BasicTypeInfo *basic;
484 GIrNodeType *type;
485 char *temporary_type = NULL;
486
487 type = (GIrNodeType *)_g_ir_node_new (G_IR_NODE_TYPE, module);
488
489 type->unparsed = g_strdup (str);
490
491 /* See comment below on GLib.List handling */
492 if (in_gobject && strcmp (str, "Type") == 0)
493 {
494 temporary_type = g_strdup ("GLib.Type");
495 str = temporary_type;
496 }
497
498 basic = parse_basic (str);
499 if (basic != NULL)
500 {
501 type->is_basic = TRUE;
502 type->tag = basic->tag;
503 type->is_pointer = basic->pointer;
504
505 str += strlen(basic->str);
506 }
507 else if (in_glib)
508 {
509 /* If we're inside GLib, handle "List" etc. by prefixing with
510 * "GLib." so the parsing code below doesn't have to get more
511 * special.
512 */
513 if (g_str_has_prefix (str, "List<") ||
514 strcmp (str, "List") == 0)
515 {
516 temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
517 str = temporary_type;
518 }
519 else if (g_str_has_prefix (str, "SList<") ||
520 strcmp (str, "SList") == 0)
521 {
522 temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
523 str = temporary_type;
524 }
525 else if (g_str_has_prefix (str, "HashTable<") ||
526 strcmp (str, "HashTable") == 0)
527 {
528 temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
529 str = temporary_type;
530 }
531 else if (g_str_has_prefix (str, "Error<") ||
532 strcmp (str, "Error") == 0)
533 {
534 temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
535 str = temporary_type;
536 }
537 }
538
539 if (basic != NULL)
540 /* found a basic type */;
541 else if (g_str_has_prefix (str, "GLib.List") ||
542 g_str_has_prefix (str, "GLib.SList"))
543 {
544 str += strlen ("GLib.");
545 if (g_str_has_prefix (str, "List"))
546 {
547 type->tag = GI_TYPE_TAG_GLIST;
548 type->is_glist = TRUE;
549 type->is_pointer = TRUE;
550 str += strlen ("List");
551 }
552 else
553 {
554 type->tag = GI_TYPE_TAG_GSLIST;
555 type->is_gslist = TRUE;
556 type->is_pointer = TRUE;
557 str += strlen ("SList");
558 }
559 }
560 else if (g_str_has_prefix (str, "GLib.HashTable"))
561 {
562 str += strlen ("GLib.");
563
564 type->tag = GI_TYPE_TAG_GHASH;
565 type->is_ghashtable = TRUE;
566 type->is_pointer = TRUE;
567 str += strlen ("HashTable");
568 }
569 else if (g_str_has_prefix (str, "GLib.Error"))
570 {
571 str += strlen ("GLib.");
572
573 type->tag = GI_TYPE_TAG_ERROR;
574 type->is_error = TRUE;
575 type->is_pointer = TRUE;
576 str += strlen ("Error");
577
578 if (*str == '<')
579 {
580 char *tmp, *end;
581 (str)++;
582
583 end = strchr (str, '>');
584 tmp = g_strndup (str, end - str);
585 type->errors = g_strsplit (tmp, ",", 0);
586 g_free (tmp);
587
588 str = end;
589 }
590 }
591 else
592 {
593 const char *start;
594 type->tag = GI_TYPE_TAG_INTERFACE;
595 type->is_interface = TRUE;
596 start = str;
597
598 /* must be an interface type */
599 while (g_ascii_isalnum (*str) ||
600 *str == '.' ||
601 *str == '-' ||
602 *str == '_' ||
603 *str == ':')
604 (str)++;
605
606 type->giinterface = g_strndup (start, str - start);
607 }
608
609 if (next)
610 *next = (char*)str;
611 g_assert (type->tag >= 0 && type->tag < GI_TYPE_TAG_N_TYPES);
612 g_free (temporary_type);
613 return type;
614
615 /* error: */
616 _g_ir_node_free ((GIrNode *)type);
617 g_free (temporary_type);
618 return NULL;
619 }
620
621 static const char *
resolve_aliases(ParseContext * ctx,const gchar * type)622 resolve_aliases (ParseContext *ctx, const gchar *type)
623 {
624 gpointer orig;
625 gpointer value;
626 GSList *seen_values = NULL;
627 const gchar *lookup;
628 gchar *prefixed;
629
630 if (strchr (type, '.') == NULL)
631 {
632 prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
633 lookup = prefixed;
634 }
635 else
636 {
637 lookup = type;
638 prefixed = NULL;
639 }
640
641 seen_values = g_slist_prepend (seen_values, (char*)lookup);
642 while (g_hash_table_lookup_extended (ctx->current_module->aliases, lookup, &orig, &value))
643 {
644 g_debug ("Resolved: %s => %s\n", lookup, (char*)value);
645 lookup = value;
646 if (g_slist_find_custom (seen_values, lookup,
647 (GCompareFunc)strcmp) != NULL)
648 break;
649 seen_values = g_slist_prepend (seen_values, (gchar*)lookup);
650 }
651 g_slist_free (seen_values);
652
653 if (lookup == prefixed)
654 lookup = type;
655
656 g_free (prefixed);
657
658 return lookup;
659 }
660
661 static gboolean
is_disguised_structure(ParseContext * ctx,const gchar * type)662 is_disguised_structure (ParseContext *ctx, const gchar *type)
663 {
664 const gchar *lookup;
665 gchar *prefixed;
666 gboolean result;
667
668 if (strchr (type, '.') == NULL)
669 {
670 prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
671 lookup = prefixed;
672 }
673 else
674 {
675 lookup = type;
676 prefixed = NULL;
677 }
678
679 result = g_hash_table_lookup (ctx->current_module->disguised_structures,
680 lookup) != NULL;
681
682 g_free (prefixed);
683
684 return result;
685 }
686
687 static GIrNodeType *
parse_type(ParseContext * ctx,const gchar * type)688 parse_type (ParseContext *ctx, const gchar *type)
689 {
690 GIrNodeType *node;
691 const BasicTypeInfo *basic;
692 gboolean in_glib, in_gobject;
693
694 in_glib = strcmp (ctx->namespace, "GLib") == 0;
695 in_gobject = strcmp (ctx->namespace, "GObject") == 0;
696
697 /* Do not search aliases for basic types */
698 basic = parse_basic (type);
699 if (basic == NULL)
700 type = resolve_aliases (ctx, type);
701
702 node = parse_type_internal (ctx->current_module, type, NULL, in_glib, in_gobject);
703 if (node)
704 g_debug ("Parsed type: %s => %d", type, node->tag);
705 else
706 g_critical ("Failed to parse type: '%s'", type);
707
708 return node;
709 }
710
711 static gboolean
introspectable_prelude(GMarkupParseContext * context,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,ParseState new_state)712 introspectable_prelude (GMarkupParseContext *context,
713 const gchar **attribute_names,
714 const gchar **attribute_values,
715 ParseContext *ctx,
716 ParseState new_state)
717 {
718 const gchar *introspectable_arg;
719 const gchar *shadowed_by;
720 gboolean introspectable;
721
722 g_assert (ctx->state != STATE_PASSTHROUGH);
723
724 introspectable_arg = find_attribute ("introspectable", attribute_names, attribute_values);
725 shadowed_by = find_attribute ("shadowed-by", attribute_names, attribute_values);
726
727 introspectable = !(introspectable_arg && atoi (introspectable_arg) == 0) && shadowed_by == NULL;
728
729 if (introspectable)
730 state_switch (ctx, new_state);
731 else
732 state_switch (ctx, STATE_PASSTHROUGH);
733
734 return introspectable;
735 }
736
737 static gboolean
start_glib_boxed(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)738 start_glib_boxed (GMarkupParseContext *context,
739 const gchar *element_name,
740 const gchar **attribute_names,
741 const gchar **attribute_values,
742 ParseContext *ctx,
743 GError **error)
744 {
745 const gchar *name;
746 const gchar *typename;
747 const gchar *typeinit;
748 const gchar *deprecated;
749 GIrNodeBoxed *boxed;
750
751 if (!(strcmp (element_name, "glib:boxed") == 0 &&
752 ctx->state == STATE_NAMESPACE))
753 return FALSE;
754
755 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_BOXED))
756 return TRUE;
757
758 name = find_attribute ("glib:name", attribute_names, attribute_values);
759 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
760 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
761 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
762
763 if (name == NULL)
764 {
765 MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
766 return FALSE;
767 }
768 else if (typename == NULL)
769 {
770 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
771 return FALSE;
772 }
773 else if (typeinit == NULL)
774 {
775 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
776 return FALSE;
777 }
778
779 boxed = (GIrNodeBoxed *) _g_ir_node_new (G_IR_NODE_BOXED,
780 ctx->current_module);
781
782 ((GIrNode *)boxed)->name = g_strdup (name);
783 boxed->gtype_name = g_strdup (typename);
784 boxed->gtype_init = g_strdup (typeinit);
785 if (deprecated)
786 boxed->deprecated = TRUE;
787 else
788 boxed->deprecated = FALSE;
789
790 push_node (ctx, (GIrNode *)boxed);
791 ctx->current_module->entries =
792 g_list_append (ctx->current_module->entries, boxed);
793
794 return TRUE;
795 }
796
797 static gboolean
start_function(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)798 start_function (GMarkupParseContext *context,
799 const gchar *element_name,
800 const gchar **attribute_names,
801 const gchar **attribute_values,
802 ParseContext *ctx,
803 GError **error)
804 {
805 const gchar *name;
806 const gchar *shadows;
807 const gchar *symbol;
808 const gchar *deprecated;
809 const gchar *throws;
810 const gchar *set_property;
811 const gchar *get_property;
812 GIrNodeFunction *function;
813 gboolean found = FALSE;
814 ParseState in_embedded_state = STATE_NONE;
815
816 switch (ctx->state)
817 {
818 case STATE_NAMESPACE:
819 found = (strcmp (element_name, "function") == 0 ||
820 strcmp (element_name, "callback") == 0);
821 break;
822 case STATE_CLASS:
823 case STATE_BOXED:
824 case STATE_STRUCT:
825 case STATE_UNION:
826 found = strcmp (element_name, "constructor") == 0;
827 /* fallthrough */
828 case STATE_INTERFACE:
829 found = (found ||
830 strcmp (element_name, "function") == 0 ||
831 strcmp (element_name, "method") == 0 ||
832 strcmp (element_name, "callback") == 0);
833 break;
834 case STATE_ENUM:
835 found = strcmp (element_name, "function") == 0;
836 break;
837 case STATE_CLASS_FIELD:
838 case STATE_STRUCT_FIELD:
839 found = (found || strcmp (element_name, "callback") == 0);
840 in_embedded_state = ctx->state;
841 break;
842 default:
843 break;
844 }
845
846 if (!found)
847 return FALSE;
848
849 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_FUNCTION))
850 return TRUE;
851
852 ctx->in_embedded_state = in_embedded_state;
853
854 name = find_attribute ("name", attribute_names, attribute_values);
855 shadows = find_attribute ("shadows", attribute_names, attribute_values);
856 symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
857 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
858 throws = find_attribute ("throws", attribute_names, attribute_values);
859 set_property = find_attribute ("glib:set-property", attribute_names, attribute_values);
860 get_property = find_attribute ("glib:get-property", attribute_names, attribute_values);
861
862 if (name == NULL)
863 {
864 MISSING_ATTRIBUTE (context, error, element_name, "name");
865 return FALSE;
866 }
867 else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
868 {
869 MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
870 return FALSE;
871 }
872
873 if (shadows)
874 name = shadows;
875
876 function = (GIrNodeFunction *) _g_ir_node_new (G_IR_NODE_FUNCTION,
877 ctx->current_module);
878
879 ((GIrNode *)function)->name = g_strdup (name);
880 function->symbol = g_strdup (symbol);
881 function->parameters = NULL;
882 if (deprecated)
883 function->deprecated = TRUE;
884 else
885 function->deprecated = FALSE;
886
887 if (strcmp (element_name, "method") == 0 ||
888 strcmp (element_name, "constructor") == 0)
889 {
890 function->is_method = TRUE;
891
892 if (strcmp (element_name, "constructor") == 0)
893 function->is_constructor = TRUE;
894 else
895 function->is_constructor = FALSE;
896
897 if (set_property != NULL)
898 {
899 function->is_setter = TRUE;
900 function->is_getter = FALSE;
901 function->property = g_strdup (set_property);
902 }
903 else if (get_property != NULL)
904 {
905 function->is_setter = FALSE;
906 function->is_getter = TRUE;
907 function->property = g_strdup (get_property);
908 }
909 else
910 {
911 function->is_setter = FALSE;
912 function->is_getter = FALSE;
913 function->property = NULL;
914 }
915 }
916 else
917 {
918 function->is_method = FALSE;
919 function->is_setter = FALSE;
920 function->is_getter = FALSE;
921 function->is_constructor = FALSE;
922 if (strcmp (element_name, "callback") == 0)
923 ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
924 }
925
926 if (throws && strcmp (throws, "1") == 0)
927 function->throws = TRUE;
928 else
929 function->throws = FALSE;
930
931 if (ctx->node_stack == NULL)
932 {
933 ctx->current_module->entries =
934 g_list_append (ctx->current_module->entries, function);
935 }
936 else if (ctx->current_typed)
937 {
938 GIrNodeField *field;
939
940 field = (GIrNodeField *)ctx->current_typed;
941 field->callback = function;
942 }
943 else
944 switch (CURRENT_NODE (ctx)->type)
945 {
946 case G_IR_NODE_INTERFACE:
947 case G_IR_NODE_OBJECT:
948 {
949 GIrNodeInterface *iface;
950
951 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
952 iface->members = g_list_append (iface->members, function);
953 }
954 break;
955 case G_IR_NODE_BOXED:
956 {
957 GIrNodeBoxed *boxed;
958
959 boxed = (GIrNodeBoxed *)CURRENT_NODE (ctx);
960 boxed->members = g_list_append (boxed->members, function);
961 }
962 break;
963 case G_IR_NODE_STRUCT:
964 {
965 GIrNodeStruct *struct_;
966
967 struct_ = (GIrNodeStruct *)CURRENT_NODE (ctx);
968 struct_->members = g_list_append (struct_->members, function); }
969 break;
970 case G_IR_NODE_UNION:
971 {
972 GIrNodeUnion *union_;
973
974 union_ = (GIrNodeUnion *)CURRENT_NODE (ctx);
975 union_->members = g_list_append (union_->members, function);
976 }
977 break;
978 case G_IR_NODE_ENUM:
979 case G_IR_NODE_FLAGS:
980 {
981 GIrNodeEnum *enum_;
982
983 enum_ = (GIrNodeEnum *)CURRENT_NODE (ctx);
984 enum_->methods = g_list_append (enum_->methods, function);
985 }
986 break;
987 default:
988 g_assert_not_reached ();
989 }
990
991 push_node(ctx, (GIrNode *)function);
992
993 return TRUE;
994 }
995
996 static void
parse_property_transfer(GIrNodeProperty * property,const gchar * transfer,ParseContext * ctx)997 parse_property_transfer (GIrNodeProperty *property,
998 const gchar *transfer,
999 ParseContext *ctx)
1000 {
1001 if (transfer == NULL)
1002 {
1003 #if 0
1004 GIrNodeInterface *iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1005
1006 g_debug ("required attribute 'transfer-ownership' is missing from "
1007 "property '%s' in type '%s.%s'. Assuming 'none'\n",
1008 property->node.name, ctx->namespace, iface->node.name);
1009 #endif
1010 transfer = "none";
1011 }
1012 if (strcmp (transfer, "none") == 0)
1013 {
1014 property->transfer = FALSE;
1015 property->shallow_transfer = FALSE;
1016 }
1017 else if (strcmp (transfer, "container") == 0)
1018 {
1019 property->transfer = FALSE;
1020 property->shallow_transfer = TRUE;
1021 }
1022 else if (strcmp (transfer, "full") == 0)
1023 {
1024 property->transfer = TRUE;
1025 property->shallow_transfer = FALSE;
1026 }
1027 else
1028 {
1029 GIrNodeInterface *iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1030
1031 g_warning ("Unknown transfer-ownership value: '%s' for property '%s' in "
1032 "type '%s.%s'", transfer, property->node.name, ctx->namespace,
1033 iface->node.name);
1034 }
1035 }
1036
1037 static gboolean
parse_param_transfer(GIrNodeParam * param,const gchar * transfer,const gchar * name,GError ** error)1038 parse_param_transfer (GIrNodeParam *param, const gchar *transfer, const gchar *name,
1039 GError **error)
1040 {
1041 if (transfer == NULL)
1042 {
1043 g_set_error (error, G_MARKUP_ERROR,
1044 G_MARKUP_ERROR_INVALID_CONTENT,
1045 "required attribute 'transfer-ownership' missing");
1046 return FALSE;
1047 }
1048 else if (strcmp (transfer, "none") == 0)
1049 {
1050 param->transfer = FALSE;
1051 param->shallow_transfer = FALSE;
1052 }
1053 else if (strcmp (transfer, "container") == 0)
1054 {
1055 param->transfer = FALSE;
1056 param->shallow_transfer = TRUE;
1057 }
1058 else if (strcmp (transfer, "full") == 0)
1059 {
1060 param->transfer = TRUE;
1061 param->shallow_transfer = FALSE;
1062 }
1063 else
1064 {
1065 g_set_error (error, G_MARKUP_ERROR,
1066 G_MARKUP_ERROR_INVALID_CONTENT,
1067 "invalid value for 'transfer-ownership': %s", transfer);
1068 return FALSE;
1069 }
1070 return TRUE;
1071 }
1072
1073 static gboolean
start_instance_parameter(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)1074 start_instance_parameter (GMarkupParseContext *context,
1075 const gchar *element_name,
1076 const gchar **attribute_names,
1077 const gchar **attribute_values,
1078 ParseContext *ctx,
1079 GError **error)
1080 {
1081 const gchar *transfer;
1082 gboolean transfer_full;
1083
1084 if (!(strcmp (element_name, "instance-parameter") == 0 &&
1085 ctx->state == STATE_FUNCTION_PARAMETERS))
1086 return FALSE;
1087
1088 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1089
1090 state_switch (ctx, STATE_PASSTHROUGH);
1091
1092 if (g_strcmp0 (transfer, "full") == 0)
1093 transfer_full = TRUE;
1094 else if (g_strcmp0 (transfer, "none") == 0)
1095 transfer_full = FALSE;
1096 else
1097 {
1098 g_set_error (error, G_MARKUP_ERROR,
1099 G_MARKUP_ERROR_INVALID_CONTENT,
1100 "invalid value for 'transfer-ownership' for instance parameter: %s", transfer);
1101 return FALSE;
1102 }
1103
1104 switch (CURRENT_NODE (ctx)->type)
1105 {
1106 case G_IR_NODE_FUNCTION:
1107 case G_IR_NODE_CALLBACK:
1108 {
1109 GIrNodeFunction *func;
1110
1111 func = (GIrNodeFunction *)CURRENT_NODE (ctx);
1112 func->instance_transfer_full = transfer_full;
1113 }
1114 break;
1115 case G_IR_NODE_SIGNAL:
1116 {
1117 GIrNodeSignal *signal;
1118
1119 signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
1120 signal->instance_transfer_full = transfer_full;
1121 }
1122 break;
1123 case G_IR_NODE_VFUNC:
1124 {
1125 GIrNodeVFunc *vfunc;
1126
1127 vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
1128 vfunc->instance_transfer_full = transfer_full;
1129 }
1130 break;
1131 default:
1132 g_assert_not_reached ();
1133 }
1134
1135 return TRUE;
1136 }
1137
1138 static gboolean
start_parameter(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)1139 start_parameter (GMarkupParseContext *context,
1140 const gchar *element_name,
1141 const gchar **attribute_names,
1142 const gchar **attribute_values,
1143 ParseContext *ctx,
1144 GError **error)
1145 {
1146 const gchar *name;
1147 const gchar *direction;
1148 const gchar *retval;
1149 const gchar *optional;
1150 const gchar *caller_allocates;
1151 const gchar *allow_none;
1152 const gchar *transfer;
1153 const gchar *scope;
1154 const gchar *closure;
1155 const gchar *destroy;
1156 const gchar *skip;
1157 const gchar *nullable;
1158 GIrNodeParam *param;
1159
1160 if (!(strcmp (element_name, "parameter") == 0 &&
1161 ctx->state == STATE_FUNCTION_PARAMETERS))
1162 return FALSE;
1163
1164 name = find_attribute ("name", attribute_names, attribute_values);
1165 direction = find_attribute ("direction", attribute_names, attribute_values);
1166 retval = find_attribute ("retval", attribute_names, attribute_values);
1167 optional = find_attribute ("optional", attribute_names, attribute_values);
1168 allow_none = find_attribute ("allow-none", attribute_names, attribute_values);
1169 caller_allocates = find_attribute ("caller-allocates", attribute_names, attribute_values);
1170 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1171 scope = find_attribute ("scope", attribute_names, attribute_values);
1172 closure = find_attribute ("closure", attribute_names, attribute_values);
1173 destroy = find_attribute ("destroy", attribute_names, attribute_values);
1174 skip = find_attribute ("skip", attribute_names, attribute_values);
1175 nullable = find_attribute ("nullable", attribute_names, attribute_values);
1176
1177 if (name == NULL)
1178 name = "unknown";
1179
1180 param = (GIrNodeParam *)_g_ir_node_new (G_IR_NODE_PARAM,
1181 ctx->current_module);
1182
1183 ctx->current_typed = (GIrNode*) param;
1184 ctx->current_typed->name = g_strdup (name);
1185
1186 state_switch (ctx, STATE_FUNCTION_PARAMETER);
1187
1188 if (direction && strcmp (direction, "out") == 0)
1189 {
1190 param->in = FALSE;
1191 param->out = TRUE;
1192 if (caller_allocates == NULL)
1193 param->caller_allocates = FALSE;
1194 else
1195 param->caller_allocates = strcmp (caller_allocates, "1") == 0;
1196 }
1197 else if (direction && strcmp (direction, "inout") == 0)
1198 {
1199 param->in = TRUE;
1200 param->out = TRUE;
1201 param->caller_allocates = FALSE;
1202 }
1203 else
1204 {
1205 param->in = TRUE;
1206 param->out = FALSE;
1207 param->caller_allocates = FALSE;
1208 }
1209
1210 if (retval && strcmp (retval, "1") == 0)
1211 param->retval = TRUE;
1212 else
1213 param->retval = FALSE;
1214
1215 if (optional && strcmp (optional, "1") == 0)
1216 param->optional = TRUE;
1217 else
1218 param->optional = FALSE;
1219
1220 if (nullable && strcmp (nullable, "1") == 0)
1221 param->nullable = TRUE;
1222 else
1223 param->nullable = FALSE;
1224
1225 if (allow_none && strcmp (allow_none, "1") == 0)
1226 {
1227 if (param->out)
1228 param->optional = TRUE;
1229 else
1230 param->nullable = TRUE;
1231 }
1232
1233 if (skip && strcmp (skip, "1") == 0)
1234 param->skip = TRUE;
1235 else
1236 param->skip = FALSE;
1237
1238 if (!parse_param_transfer (param, transfer, name, error))
1239 return FALSE;
1240
1241 if (scope && strcmp (scope, "call") == 0)
1242 param->scope = GI_SCOPE_TYPE_CALL;
1243 else if (scope && strcmp (scope, "async") == 0)
1244 param->scope = GI_SCOPE_TYPE_ASYNC;
1245 else if (scope && strcmp (scope, "notified") == 0)
1246 param->scope = GI_SCOPE_TYPE_NOTIFIED;
1247 else
1248 param->scope = GI_SCOPE_TYPE_INVALID;
1249
1250 param->closure = closure ? atoi (closure) : -1;
1251 param->destroy = destroy ? atoi (destroy) : -1;
1252
1253 ((GIrNode *)param)->name = g_strdup (name);
1254
1255 switch (CURRENT_NODE (ctx)->type)
1256 {
1257 case G_IR_NODE_FUNCTION:
1258 case G_IR_NODE_CALLBACK:
1259 {
1260 GIrNodeFunction *func;
1261
1262 func = (GIrNodeFunction *)CURRENT_NODE (ctx);
1263 func->parameters = g_list_append (func->parameters, param);
1264 }
1265 break;
1266 case G_IR_NODE_SIGNAL:
1267 {
1268 GIrNodeSignal *signal;
1269
1270 signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
1271 signal->parameters = g_list_append (signal->parameters, param);
1272 }
1273 break;
1274 case G_IR_NODE_VFUNC:
1275 {
1276 GIrNodeVFunc *vfunc;
1277
1278 vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
1279 vfunc->parameters = g_list_append (vfunc->parameters, param);
1280 }
1281 break;
1282 default:
1283 g_assert_not_reached ();
1284 }
1285
1286 return TRUE;
1287 }
1288
1289 static gboolean
start_field(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)1290 start_field (GMarkupParseContext *context,
1291 const gchar *element_name,
1292 const gchar **attribute_names,
1293 const gchar **attribute_values,
1294 ParseContext *ctx,
1295 GError **error)
1296 {
1297 const gchar *name;
1298 const gchar *readable;
1299 const gchar *writable;
1300 const gchar *bits;
1301 const gchar *branch;
1302 GIrNodeField *field;
1303 ParseState target_state;
1304 gboolean introspectable;
1305
1306 switch (ctx->state)
1307 {
1308 case STATE_CLASS:
1309 target_state = STATE_CLASS_FIELD;
1310 break;
1311 case STATE_BOXED:
1312 target_state = STATE_BOXED_FIELD;
1313 break;
1314 case STATE_STRUCT:
1315 target_state = STATE_STRUCT_FIELD;
1316 break;
1317 case STATE_UNION:
1318 target_state = STATE_UNION_FIELD;
1319 break;
1320 case STATE_INTERFACE:
1321 target_state = STATE_INTERFACE_FIELD;
1322 break;
1323 default:
1324 return FALSE;
1325 }
1326
1327 if (strcmp (element_name, "field") != 0)
1328 return FALSE;
1329
1330 g_assert (ctx->state != STATE_PASSTHROUGH);
1331
1332 /* We handle introspectability specially here; we replace with just gpointer
1333 * for the type.
1334 */
1335 introspectable = introspectable_prelude (context, attribute_names, attribute_values, ctx, target_state);
1336
1337 name = find_attribute ("name", attribute_names, attribute_values);
1338 readable = find_attribute ("readable", attribute_names, attribute_values);
1339 writable = find_attribute ("writable", attribute_names, attribute_values);
1340 bits = find_attribute ("bits", attribute_names, attribute_values);
1341 branch = find_attribute ("branch", attribute_names, attribute_values);
1342
1343 if (name == NULL)
1344 {
1345 MISSING_ATTRIBUTE (context, error, element_name, "name");
1346 return FALSE;
1347 }
1348
1349 field = (GIrNodeField *)_g_ir_node_new (G_IR_NODE_FIELD,
1350 ctx->current_module);
1351 if (introspectable)
1352 {
1353 ctx->current_typed = (GIrNode*) field;
1354 }
1355 else
1356 {
1357 field->type = parse_type (ctx, "gpointer");
1358 }
1359
1360 ((GIrNode *)field)->name = g_strdup (name);
1361 /* Fields are assumed to be read-only.
1362 * (see also girwriter.py and generate.c)
1363 */
1364 field->readable = readable == NULL || strcmp (readable, "0") == 0;
1365 field->writable = writable != NULL && strcmp (writable, "1") == 0;
1366
1367 if (bits)
1368 field->bits = atoi (bits);
1369 else
1370 field->bits = 0;
1371
1372 switch (CURRENT_NODE (ctx)->type)
1373 {
1374 case G_IR_NODE_OBJECT:
1375 {
1376 GIrNodeInterface *iface;
1377
1378 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1379 iface->members = g_list_append (iface->members, field);
1380 }
1381 break;
1382 case G_IR_NODE_INTERFACE:
1383 {
1384 GIrNodeInterface *iface;
1385
1386 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1387 iface->members = g_list_append (iface->members, field);
1388 }
1389 break;
1390 case G_IR_NODE_BOXED:
1391 {
1392 GIrNodeBoxed *boxed;
1393
1394 boxed = (GIrNodeBoxed *)CURRENT_NODE (ctx);
1395 boxed->members = g_list_append (boxed->members, field);
1396 }
1397 break;
1398 case G_IR_NODE_STRUCT:
1399 {
1400 GIrNodeStruct *struct_;
1401
1402 struct_ = (GIrNodeStruct *)CURRENT_NODE (ctx);
1403 struct_->members = g_list_append (struct_->members, field);
1404 }
1405 break;
1406 case G_IR_NODE_UNION:
1407 {
1408 GIrNodeUnion *union_;
1409
1410 union_ = (GIrNodeUnion *)CURRENT_NODE (ctx);
1411 union_->members = g_list_append (union_->members, field);
1412 if (branch)
1413 {
1414 GIrNodeConstant *constant;
1415
1416 constant = (GIrNodeConstant *) _g_ir_node_new (G_IR_NODE_CONSTANT,
1417 ctx->current_module);
1418 ((GIrNode *)constant)->name = g_strdup (name);
1419 constant->value = g_strdup (branch);
1420 constant->type = union_->discriminator_type;
1421 constant->deprecated = FALSE;
1422
1423 union_->discriminators = g_list_append (union_->discriminators, constant);
1424 }
1425 }
1426 break;
1427 default:
1428 g_assert_not_reached ();
1429 }
1430
1431 return TRUE;
1432 }
1433
1434 static gboolean
start_alias(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)1435 start_alias (GMarkupParseContext *context,
1436 const gchar *element_name,
1437 const gchar **attribute_names,
1438 const gchar **attribute_values,
1439 ParseContext *ctx,
1440 GError **error)
1441 {
1442 const gchar *name;
1443
1444 name = find_attribute ("name", attribute_names, attribute_values);
1445 if (name == NULL)
1446 {
1447 MISSING_ATTRIBUTE (context, error, element_name, "name");
1448 return FALSE;
1449 }
1450
1451 ctx->current_alias = g_strdup (name);
1452 state_switch (ctx, STATE_ALIAS);
1453
1454 return TRUE;
1455 }
1456
1457 static gboolean
start_enum(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)1458 start_enum (GMarkupParseContext *context,
1459 const gchar *element_name,
1460 const gchar **attribute_names,
1461 const gchar **attribute_values,
1462 ParseContext *ctx,
1463 GError **error)
1464 {
1465 const gchar *name;
1466 const gchar *typename;
1467 const gchar *typeinit;
1468 const gchar *deprecated;
1469 const gchar *error_domain;
1470 GIrNodeEnum *enum_;
1471
1472 if (!((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
1473 (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE)))
1474 return FALSE;
1475
1476 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_ENUM))
1477 return TRUE;
1478
1479 name = find_attribute ("name", attribute_names, attribute_values);
1480 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1481 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1482 error_domain = find_attribute ("glib:error-domain", attribute_names, attribute_values);
1483 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1484
1485 if (name == NULL)
1486 {
1487 MISSING_ATTRIBUTE (context, error, element_name, "name");
1488 return FALSE;
1489 }
1490
1491 if (strcmp (element_name, "enumeration") == 0)
1492 enum_ = (GIrNodeEnum *) _g_ir_node_new (G_IR_NODE_ENUM,
1493 ctx->current_module);
1494 else
1495 enum_ = (GIrNodeEnum *) _g_ir_node_new (G_IR_NODE_FLAGS,
1496 ctx->current_module);
1497 ((GIrNode *)enum_)->name = g_strdup (name);
1498 enum_->gtype_name = g_strdup (typename);
1499 enum_->gtype_init = g_strdup (typeinit);
1500 enum_->error_domain = g_strdup (error_domain);
1501
1502 if (deprecated)
1503 enum_->deprecated = TRUE;
1504 else
1505 enum_->deprecated = FALSE;
1506
1507 push_node (ctx, (GIrNode *) enum_);
1508 ctx->current_module->entries =
1509 g_list_append (ctx->current_module->entries, enum_);
1510
1511 return TRUE;
1512 }
1513
1514 static gboolean
start_property(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)1515 start_property (GMarkupParseContext *context,
1516 const gchar *element_name,
1517 const gchar **attribute_names,
1518 const gchar **attribute_values,
1519 ParseContext *ctx,
1520 GError **error)
1521 {
1522 ParseState target_state;
1523 const gchar *name;
1524 const gchar *readable;
1525 const gchar *writable;
1526 const gchar *construct;
1527 const gchar *construct_only;
1528 const gchar *transfer;
1529 const gchar *setter;
1530 const gchar *getter;
1531 GIrNodeProperty *property;
1532 GIrNodeInterface *iface;
1533
1534 if (!(strcmp (element_name, "property") == 0 &&
1535 (ctx->state == STATE_CLASS ||
1536 ctx->state == STATE_INTERFACE)))
1537 return FALSE;
1538
1539 if (ctx->state == STATE_CLASS)
1540 target_state = STATE_CLASS_PROPERTY;
1541 else if (ctx->state == STATE_INTERFACE)
1542 target_state = STATE_INTERFACE_PROPERTY;
1543 else
1544 g_assert_not_reached ();
1545
1546 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, target_state))
1547 return TRUE;
1548
1549
1550 name = find_attribute ("name", attribute_names, attribute_values);
1551 readable = find_attribute ("readable", attribute_names, attribute_values);
1552 writable = find_attribute ("writable", attribute_names, attribute_values);
1553 construct = find_attribute ("construct", attribute_names, attribute_values);
1554 construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1555 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1556 setter = find_attribute ("setter", attribute_names, attribute_values);
1557 getter = find_attribute ("getter", attribute_names, attribute_values);
1558
1559 if (name == NULL)
1560 {
1561 MISSING_ATTRIBUTE (context, error, element_name, "name");
1562 return FALSE;
1563 }
1564
1565 property = (GIrNodeProperty *) _g_ir_node_new (G_IR_NODE_PROPERTY,
1566 ctx->current_module);
1567 ctx->current_typed = (GIrNode*) property;
1568
1569 ((GIrNode *)property)->name = g_strdup (name);
1570
1571 /* Assume properties are readable */
1572 if (readable == NULL || strcmp (readable, "1") == 0)
1573 property->readable = TRUE;
1574 else
1575 property->readable = FALSE;
1576 if (writable && strcmp (writable, "1") == 0)
1577 property->writable = TRUE;
1578 else
1579 property->writable = FALSE;
1580 if (construct && strcmp (construct, "1") == 0)
1581 property->construct = TRUE;
1582 else
1583 property->construct = FALSE;
1584 if (construct_only && strcmp (construct_only, "1") == 0)
1585 property->construct_only = TRUE;
1586 else
1587 property->construct_only = FALSE;
1588
1589 property->setter = g_strdup (setter);
1590 property->getter = g_strdup (getter);
1591
1592 parse_property_transfer (property, transfer, ctx);
1593
1594 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1595 iface->members = g_list_append (iface->members, property);
1596
1597 return TRUE;
1598 }
1599
1600 static gint64
parse_value(const gchar * str)1601 parse_value (const gchar *str)
1602 {
1603 gchar *shift_op;
1604
1605 /* FIXME just a quick hack */
1606 shift_op = strstr (str, "<<");
1607
1608 if (shift_op)
1609 {
1610 gint64 base, shift;
1611
1612 base = g_ascii_strtoll (str, NULL, 10);
1613 shift = g_ascii_strtoll (shift_op + 3, NULL, 10);
1614
1615 return base << shift;
1616 }
1617 else
1618 return g_ascii_strtoll (str, NULL, 10);
1619
1620 return 0;
1621 }
1622
1623 static gboolean
start_member(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)1624 start_member (GMarkupParseContext *context,
1625 const gchar *element_name,
1626 const gchar **attribute_names,
1627 const gchar **attribute_values,
1628 ParseContext *ctx,
1629 GError **error)
1630 {
1631 const gchar *name;
1632 const gchar *value;
1633 const gchar *deprecated;
1634 const gchar *c_identifier;
1635 GIrNodeEnum *enum_;
1636 GIrNodeValue *value_;
1637
1638 if (!(strcmp (element_name, "member") == 0 &&
1639 ctx->state == STATE_ENUM))
1640 return FALSE;
1641
1642 name = find_attribute ("name", attribute_names, attribute_values);
1643 value = find_attribute ("value", attribute_names, attribute_values);
1644 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1645 c_identifier = find_attribute ("c:identifier", attribute_names, attribute_values);
1646
1647 if (name == NULL)
1648 {
1649 MISSING_ATTRIBUTE (context, error, element_name, "name");
1650 return FALSE;
1651 }
1652
1653 value_ = (GIrNodeValue *) _g_ir_node_new (G_IR_NODE_VALUE,
1654 ctx->current_module);
1655
1656 ((GIrNode *)value_)->name = g_strdup (name);
1657
1658 value_->value = parse_value (value);
1659
1660 if (deprecated)
1661 value_->deprecated = TRUE;
1662 else
1663 value_->deprecated = FALSE;
1664
1665 g_hash_table_insert (((GIrNode *)value_)->attributes,
1666 g_strdup ("c:identifier"),
1667 g_strdup (c_identifier));
1668
1669 enum_ = (GIrNodeEnum *)CURRENT_NODE (ctx);
1670 enum_->values = g_list_append (enum_->values, value_);
1671
1672 return TRUE;
1673 }
1674
1675 static gboolean
start_constant(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)1676 start_constant (GMarkupParseContext *context,
1677 const gchar *element_name,
1678 const gchar **attribute_names,
1679 const gchar **attribute_values,
1680 ParseContext *ctx,
1681 GError **error)
1682 {
1683 ParseState prev_state;
1684 ParseState target_state;
1685 const gchar *name;
1686 const gchar *value;
1687 const gchar *deprecated;
1688 GIrNodeConstant *constant;
1689
1690 if (!(strcmp (element_name, "constant") == 0 &&
1691 (ctx->state == STATE_NAMESPACE ||
1692 ctx->state == STATE_CLASS ||
1693 ctx->state == STATE_INTERFACE)))
1694 return FALSE;
1695
1696 switch (ctx->state)
1697 {
1698 case STATE_NAMESPACE:
1699 target_state = STATE_NAMESPACE_CONSTANT;
1700 break;
1701 case STATE_CLASS:
1702 target_state = STATE_CLASS_CONSTANT;
1703 break;
1704 case STATE_INTERFACE:
1705 target_state = STATE_INTERFACE_CONSTANT;
1706 break;
1707 default:
1708 g_assert_not_reached ();
1709 }
1710
1711 prev_state = ctx->state;
1712
1713 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, target_state))
1714 return TRUE;
1715
1716 name = find_attribute ("name", attribute_names, attribute_values);
1717 value = find_attribute ("value", attribute_names, attribute_values);
1718 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1719
1720 if (name == NULL)
1721 {
1722 MISSING_ATTRIBUTE (context, error, element_name, "name");
1723 return FALSE;
1724 }
1725 else if (value == NULL)
1726 {
1727 MISSING_ATTRIBUTE (context, error, element_name, "value");
1728 return FALSE;
1729 }
1730
1731 constant = (GIrNodeConstant *) _g_ir_node_new (G_IR_NODE_CONSTANT,
1732 ctx->current_module);
1733
1734 ((GIrNode *)constant)->name = g_strdup (name);
1735 constant->value = g_strdup (value);
1736
1737 ctx->current_typed = (GIrNode*) constant;
1738
1739 if (deprecated)
1740 constant->deprecated = TRUE;
1741 else
1742 constant->deprecated = FALSE;
1743
1744 if (prev_state == STATE_NAMESPACE)
1745 {
1746 push_node (ctx, (GIrNode *) constant);
1747 ctx->current_module->entries =
1748 g_list_append (ctx->current_module->entries, constant);
1749 }
1750 else
1751 {
1752 GIrNodeInterface *iface;
1753
1754 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
1755 iface->members = g_list_append (iface->members, constant);
1756 }
1757
1758 return TRUE;
1759 }
1760
1761 static gboolean
start_interface(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)1762 start_interface (GMarkupParseContext *context,
1763 const gchar *element_name,
1764 const gchar **attribute_names,
1765 const gchar **attribute_values,
1766 ParseContext *ctx,
1767 GError **error)
1768 {
1769 const gchar *name;
1770 const gchar *typename;
1771 const gchar *typeinit;
1772 const gchar *deprecated;
1773 const gchar *glib_type_struct;
1774 GIrNodeInterface *iface;
1775
1776 if (!(strcmp (element_name, "interface") == 0 &&
1777 ctx->state == STATE_NAMESPACE))
1778 return FALSE;
1779
1780 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_INTERFACE))
1781 return TRUE;
1782
1783 name = find_attribute ("name", attribute_names, attribute_values);
1784 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1785 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1786 glib_type_struct = find_attribute ("glib:type-struct", attribute_names, attribute_values);
1787 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1788
1789 if (name == NULL)
1790 {
1791 MISSING_ATTRIBUTE (context, error, element_name, "name");
1792 return FALSE;
1793 }
1794 else if (typename == NULL)
1795 {
1796 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1797 return FALSE;
1798 }
1799 else if (typeinit == NULL)
1800 {
1801 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1802 return FALSE;
1803 }
1804
1805 iface = (GIrNodeInterface *) _g_ir_node_new (G_IR_NODE_INTERFACE,
1806 ctx->current_module);
1807 ((GIrNode *)iface)->name = g_strdup (name);
1808 iface->gtype_name = g_strdup (typename);
1809 iface->gtype_init = g_strdup (typeinit);
1810 iface->glib_type_struct = g_strdup (glib_type_struct);
1811 if (deprecated)
1812 iface->deprecated = TRUE;
1813 else
1814 iface->deprecated = FALSE;
1815
1816 push_node (ctx, (GIrNode *) iface);
1817 ctx->current_module->entries =
1818 g_list_append (ctx->current_module->entries, iface);
1819
1820 return TRUE;
1821 }
1822
1823 static gboolean
start_class(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)1824 start_class (GMarkupParseContext *context,
1825 const gchar *element_name,
1826 const gchar **attribute_names,
1827 const gchar **attribute_values,
1828 ParseContext *ctx,
1829 GError **error)
1830 {
1831 const gchar *name;
1832 const gchar *parent;
1833 const gchar *glib_type_struct;
1834 const gchar *typename;
1835 const gchar *typeinit;
1836 const gchar *deprecated;
1837 const gchar *abstract;
1838 const gchar *fundamental;
1839 const gchar *final;
1840 const gchar *ref_func;
1841 const gchar *unref_func;
1842 const gchar *set_value_func;
1843 const gchar *get_value_func;
1844 GIrNodeInterface *iface;
1845
1846 if (!(strcmp (element_name, "class") == 0 &&
1847 ctx->state == STATE_NAMESPACE))
1848 return FALSE;
1849
1850 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_CLASS))
1851 return TRUE;
1852
1853 name = find_attribute ("name", attribute_names, attribute_values);
1854 parent = find_attribute ("parent", attribute_names, attribute_values);
1855 glib_type_struct = find_attribute ("glib:type-struct", attribute_names, attribute_values);
1856 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1857 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1858 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1859 abstract = find_attribute ("abstract", attribute_names, attribute_values);
1860 final = find_attribute ("final", attribute_names, attribute_values);
1861 fundamental = find_attribute ("glib:fundamental", attribute_names, attribute_values);
1862 ref_func = find_attribute ("glib:ref-func", attribute_names, attribute_values);
1863 unref_func = find_attribute ("glib:unref-func", attribute_names, attribute_values);
1864 set_value_func = find_attribute ("glib:set-value-func", attribute_names, attribute_values);
1865 get_value_func = find_attribute ("glib:get-value-func", attribute_names, attribute_values);
1866
1867 if (name == NULL)
1868 {
1869 MISSING_ATTRIBUTE (context, error, element_name, "name");
1870 return FALSE;
1871 }
1872 else if (typename == NULL)
1873 {
1874 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1875 return FALSE;
1876 }
1877 else if (typeinit == NULL && strcmp (typename, "GObject"))
1878 {
1879 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1880 return FALSE;
1881 }
1882
1883 iface = (GIrNodeInterface *) _g_ir_node_new (G_IR_NODE_OBJECT,
1884 ctx->current_module);
1885 ((GIrNode *)iface)->name = g_strdup (name);
1886 iface->gtype_name = g_strdup (typename);
1887 iface->gtype_init = g_strdup (typeinit);
1888 iface->parent = g_strdup (parent);
1889 iface->glib_type_struct = g_strdup (glib_type_struct);
1890 if (deprecated)
1891 iface->deprecated = TRUE;
1892 else
1893 iface->deprecated = FALSE;
1894
1895 iface->abstract = abstract && strcmp (abstract, "1") == 0;
1896 iface->final_ = final && strcmp (final, "1") == 0;
1897
1898 if (fundamental)
1899 iface->fundamental = TRUE;
1900 if (ref_func)
1901 iface->ref_func = g_strdup (ref_func);
1902 if (unref_func)
1903 iface->unref_func = g_strdup (unref_func);
1904 if (set_value_func)
1905 iface->set_value_func = g_strdup (set_value_func);
1906 if (get_value_func)
1907 iface->get_value_func = g_strdup (get_value_func);
1908
1909 push_node (ctx, (GIrNode *) iface);
1910 ctx->current_module->entries =
1911 g_list_append (ctx->current_module->entries, iface);
1912
1913 return TRUE;
1914 }
1915
1916 static gboolean
start_type(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)1917 start_type (GMarkupParseContext *context,
1918 const gchar *element_name,
1919 const gchar **attribute_names,
1920 const gchar **attribute_values,
1921 ParseContext *ctx,
1922 GError **error)
1923 {
1924 const gchar *name;
1925 const gchar *ctype;
1926 gboolean in_alias = FALSE;
1927 gboolean is_array;
1928 gboolean is_varargs;
1929 GIrNodeType *typenode;
1930
1931 is_array = strcmp (element_name, "array") == 0;
1932 is_varargs = strcmp (element_name, "varargs") == 0;
1933
1934 if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
1935 return FALSE;
1936
1937 if (ctx->state == STATE_TYPE)
1938 {
1939 ctx->type_depth++;
1940 ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
1941 ctx->type_parameters = NULL;
1942 }
1943 else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1944 ctx->state == STATE_FUNCTION_RETURN ||
1945 ctx->state == STATE_STRUCT_FIELD ||
1946 ctx->state == STATE_UNION_FIELD ||
1947 ctx->state == STATE_CLASS_PROPERTY ||
1948 ctx->state == STATE_CLASS_FIELD ||
1949 ctx->state == STATE_INTERFACE_FIELD ||
1950 ctx->state == STATE_INTERFACE_PROPERTY ||
1951 ctx->state == STATE_BOXED_FIELD ||
1952 ctx->state == STATE_NAMESPACE_CONSTANT ||
1953 ctx->state == STATE_CLASS_CONSTANT ||
1954 ctx->state == STATE_INTERFACE_CONSTANT ||
1955 ctx->state == STATE_ALIAS
1956 )
1957 {
1958 if (ctx->state == STATE_ALIAS)
1959 in_alias = TRUE;
1960 state_switch (ctx, STATE_TYPE);
1961 ctx->type_depth = 1;
1962 ctx->type_stack = NULL;
1963 ctx->type_parameters = NULL;
1964 }
1965
1966 name = find_attribute ("name", attribute_names, attribute_values);
1967
1968 if (in_alias && ctx->current_alias)
1969 {
1970 char *key;
1971 char *value;
1972
1973 if (name == NULL)
1974 {
1975 MISSING_ATTRIBUTE (context, error, element_name, "name");
1976 return FALSE;
1977 }
1978
1979 key = g_strdup_printf ("%s.%s", ctx->namespace, ctx->current_alias);
1980 if (!strchr (name, '.'))
1981 {
1982 const BasicTypeInfo *basic = parse_basic (name);
1983 if (!basic)
1984 {
1985 /* For non-basic types, re-qualify the interface */
1986 value = g_strdup_printf ("%s.%s", ctx->namespace, name);
1987 }
1988 else
1989 {
1990 value = g_strdup (name);
1991 }
1992 }
1993 else
1994 value = g_strdup (name);
1995
1996 g_hash_table_replace (ctx->aliases, key, value);
1997
1998 return TRUE;
1999 }
2000 else if (!ctx->current_module || in_alias)
2001 return TRUE;
2002
2003 if (!ctx->current_typed)
2004 {
2005 g_set_error (error,
2006 G_MARKUP_ERROR,
2007 G_MARKUP_ERROR_INVALID_CONTENT,
2008 "The element <type> is invalid here");
2009 return FALSE;
2010 }
2011
2012 if (is_varargs)
2013 return TRUE;
2014
2015 if (is_array)
2016 {
2017 const char *zero;
2018 const char *len;
2019 const char *size;
2020
2021 typenode = (GIrNodeType *)_g_ir_node_new (G_IR_NODE_TYPE,
2022 ctx->current_module);
2023
2024 typenode->tag = GI_TYPE_TAG_ARRAY;
2025 typenode->is_pointer = TRUE;
2026 typenode->is_array = TRUE;
2027
2028 if (name && strcmp (name, "GLib.Array") == 0) {
2029 typenode->array_type = GI_ARRAY_TYPE_ARRAY;
2030 } else if (name && strcmp (name, "GLib.ByteArray") == 0) {
2031 typenode->array_type = GI_ARRAY_TYPE_BYTE_ARRAY;
2032 } else if (name && strcmp (name, "GLib.PtrArray") == 0) {
2033 typenode->array_type = GI_ARRAY_TYPE_PTR_ARRAY;
2034 } else {
2035 typenode->array_type = GI_ARRAY_TYPE_C;
2036 }
2037
2038 if (typenode->array_type == GI_ARRAY_TYPE_C) {
2039 zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
2040 len = find_attribute ("length", attribute_names, attribute_values);
2041 size = find_attribute ("fixed-size", attribute_names, attribute_values);
2042
2043 typenode->has_length = len != NULL;
2044 typenode->length = typenode->has_length ? atoi (len) : -1;
2045
2046 typenode->has_size = size != NULL;
2047 typenode->size = typenode->has_size ? atoi (size) : -1;
2048
2049 if (zero)
2050 typenode->zero_terminated = strcmp(zero, "1") == 0;
2051 else
2052 /* If neither zero-terminated nor length nor fixed-size is given, assume zero-terminated. */
2053 typenode->zero_terminated = !(typenode->has_length || typenode->has_size);
2054
2055 if (typenode->has_size && ctx->current_typed->type == G_IR_NODE_FIELD)
2056 typenode->is_pointer = FALSE;
2057 } else {
2058 typenode->zero_terminated = FALSE;
2059 typenode->has_length = FALSE;
2060 typenode->length = -1;
2061 typenode->has_size = FALSE;
2062 typenode->size = -1;
2063 }
2064 }
2065 else
2066 {
2067 int pointer_depth;
2068
2069 if (name == NULL)
2070 {
2071 MISSING_ATTRIBUTE (context, error, element_name, "name");
2072 return FALSE;
2073 }
2074
2075 pointer_depth = 0;
2076 ctype = find_attribute ("c:type", attribute_names, attribute_values);
2077 if (ctype != NULL)
2078 {
2079 const char *cp = ctype + strlen(ctype) - 1;
2080 while (cp > ctype && *cp-- == '*')
2081 pointer_depth++;
2082
2083 if (g_str_has_prefix (ctype, "gpointer")
2084 || g_str_has_prefix (ctype, "gconstpointer"))
2085 pointer_depth++;
2086 }
2087
2088 if (ctx->current_typed->type == G_IR_NODE_PARAM &&
2089 ((GIrNodeParam *)ctx->current_typed)->out &&
2090 pointer_depth > 0)
2091 pointer_depth--;
2092
2093 typenode = parse_type (ctx, name);
2094
2095 /* A 'disguised' structure is one where the c:type is a typedef that
2096 * doesn't look like a pointer, but is internally.
2097 */
2098 if (typenode->tag == GI_TYPE_TAG_INTERFACE &&
2099 is_disguised_structure (ctx, typenode->giinterface))
2100 pointer_depth++;
2101
2102 if (pointer_depth > 0)
2103 typenode->is_pointer = TRUE;
2104 }
2105
2106 ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
2107
2108 return TRUE;
2109 }
2110
2111 static void
end_type_top(ParseContext * ctx)2112 end_type_top (ParseContext *ctx)
2113 {
2114 GIrNodeType *typenode;
2115
2116 if (!ctx->type_parameters)
2117 goto out;
2118
2119 typenode = (GIrNodeType*)ctx->type_parameters->data;
2120
2121 /* Default to pointer for unspecified containers */
2122 if (typenode->tag == GI_TYPE_TAG_ARRAY ||
2123 typenode->tag == GI_TYPE_TAG_GLIST ||
2124 typenode->tag == GI_TYPE_TAG_GSLIST)
2125 {
2126 if (typenode->parameter_type1 == NULL)
2127 typenode->parameter_type1 = parse_type (ctx, "gpointer");
2128 }
2129 else if (typenode->tag == GI_TYPE_TAG_GHASH)
2130 {
2131 if (typenode->parameter_type1 == NULL)
2132 {
2133 typenode->parameter_type1 = parse_type (ctx, "gpointer");
2134 typenode->parameter_type2 = parse_type (ctx, "gpointer");
2135 }
2136 }
2137
2138 switch (ctx->current_typed->type)
2139 {
2140 case G_IR_NODE_PARAM:
2141 {
2142 GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
2143 param->type = typenode;
2144 }
2145 break;
2146 case G_IR_NODE_FIELD:
2147 {
2148 GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
2149 field->type = typenode;
2150 }
2151 break;
2152 case G_IR_NODE_PROPERTY:
2153 {
2154 GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
2155 property->type = typenode;
2156 }
2157 break;
2158 case G_IR_NODE_CONSTANT:
2159 {
2160 GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
2161 constant->type = typenode;
2162 }
2163 break;
2164 default:
2165 g_printerr("current node is %d\n", CURRENT_NODE (ctx)->type);
2166 g_assert_not_reached ();
2167 }
2168 g_list_free (ctx->type_parameters);
2169
2170 out:
2171 ctx->type_depth = 0;
2172 ctx->type_parameters = NULL;
2173 ctx->current_typed = NULL;
2174 }
2175
2176 static void
end_type_recurse(ParseContext * ctx)2177 end_type_recurse (ParseContext *ctx)
2178 {
2179 GIrNodeType *parent;
2180 GIrNodeType *param = NULL;
2181
2182 parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
2183 if (ctx->type_parameters)
2184 param = (GIrNodeType *) ctx->type_parameters->data;
2185
2186 if (parent->tag == GI_TYPE_TAG_ARRAY ||
2187 parent->tag == GI_TYPE_TAG_GLIST ||
2188 parent->tag == GI_TYPE_TAG_GSLIST)
2189 {
2190 g_assert (param != NULL);
2191
2192 if (parent->parameter_type1 == NULL)
2193 parent->parameter_type1 = param;
2194 else
2195 g_assert_not_reached ();
2196 }
2197 else if (parent->tag == GI_TYPE_TAG_GHASH)
2198 {
2199 g_assert (param != NULL);
2200
2201 if (parent->parameter_type1 == NULL)
2202 parent->parameter_type1 = param;
2203 else if (parent->parameter_type2 == NULL)
2204 parent->parameter_type2 = param;
2205 else
2206 g_assert_not_reached ();
2207 }
2208 g_list_free (ctx->type_parameters);
2209 ctx->type_parameters = (GList *)ctx->type_stack->data;
2210 ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
2211 }
2212
2213 static void
end_type(ParseContext * ctx)2214 end_type (ParseContext *ctx)
2215 {
2216 if (ctx->type_depth == 1)
2217 {
2218 end_type_top (ctx);
2219 state_switch (ctx, ctx->prev_state);
2220 }
2221 else
2222 {
2223 end_type_recurse (ctx);
2224 ctx->type_depth--;
2225 }
2226 }
2227
2228 static gboolean
start_attribute(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)2229 start_attribute (GMarkupParseContext *context,
2230 const gchar *element_name,
2231 const gchar **attribute_names,
2232 const gchar **attribute_values,
2233 ParseContext *ctx,
2234 GError **error)
2235 {
2236 const gchar *name;
2237 const gchar *value;
2238 GIrNode *curnode;
2239
2240 if (strcmp (element_name, "attribute") != 0 || ctx->node_stack == NULL)
2241 return FALSE;
2242
2243 name = find_attribute ("name", attribute_names, attribute_values);
2244 value = find_attribute ("value", attribute_names, attribute_values);
2245
2246 if (name == NULL)
2247 {
2248 MISSING_ATTRIBUTE (context, error, element_name, "name");
2249 return FALSE;
2250 }
2251 if (value == NULL)
2252 {
2253 MISSING_ATTRIBUTE (context, error, element_name, "value");
2254 return FALSE;
2255 }
2256
2257 state_switch (ctx, STATE_ATTRIBUTE);
2258
2259 curnode = CURRENT_NODE (ctx);
2260
2261 if (ctx->current_typed && ctx->current_typed->type == G_IR_NODE_PARAM)
2262 {
2263 g_hash_table_insert (ctx->current_typed->attributes, g_strdup (name), g_strdup (value));
2264 }
2265 else
2266 {
2267 g_hash_table_insert (curnode->attributes, g_strdup (name), g_strdup (value));
2268 }
2269
2270 return TRUE;
2271 }
2272
2273 static gboolean
start_return_value(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)2274 start_return_value (GMarkupParseContext *context,
2275 const gchar *element_name,
2276 const gchar **attribute_names,
2277 const gchar **attribute_values,
2278 ParseContext *ctx,
2279 GError **error)
2280 {
2281 GIrNodeParam *param;
2282 const gchar *transfer;
2283 const gchar *skip;
2284 const gchar *nullable;
2285
2286 if (!(strcmp (element_name, "return-value") == 0 &&
2287 ctx->state == STATE_FUNCTION))
2288 return FALSE;
2289
2290 param = (GIrNodeParam *)_g_ir_node_new (G_IR_NODE_PARAM,
2291 ctx->current_module);
2292 param->in = FALSE;
2293 param->out = FALSE;
2294 param->retval = TRUE;
2295
2296 ctx->current_typed = (GIrNode*) param;
2297
2298 state_switch (ctx, STATE_FUNCTION_RETURN);
2299
2300 skip = find_attribute ("skip", attribute_names, attribute_values);
2301 if (skip && strcmp (skip, "1") == 0)
2302 param->skip = TRUE;
2303 else
2304 param->skip = FALSE;
2305
2306 transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
2307 if (!parse_param_transfer (param, transfer, NULL, error))
2308 return FALSE;
2309
2310 nullable = find_attribute ("nullable", attribute_names, attribute_values);
2311 if (nullable && g_str_equal (nullable, "1"))
2312 param->nullable = TRUE;
2313
2314 switch (CURRENT_NODE (ctx)->type)
2315 {
2316 case G_IR_NODE_FUNCTION:
2317 case G_IR_NODE_CALLBACK:
2318 {
2319 GIrNodeFunction *func = (GIrNodeFunction *)CURRENT_NODE (ctx);
2320 func->result = param;
2321 }
2322 break;
2323 case G_IR_NODE_SIGNAL:
2324 {
2325 GIrNodeSignal *signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
2326 signal->result = param;
2327 }
2328 break;
2329 case G_IR_NODE_VFUNC:
2330 {
2331 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
2332 vfunc->result = param;
2333 }
2334 break;
2335 default:
2336 g_assert_not_reached ();
2337 }
2338
2339 return TRUE;
2340 }
2341
2342 static gboolean
start_implements(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)2343 start_implements (GMarkupParseContext *context,
2344 const gchar *element_name,
2345 const gchar **attribute_names,
2346 const gchar **attribute_values,
2347 ParseContext *ctx,
2348 GError **error)
2349 {
2350 GIrNodeInterface *iface;
2351 const char *name;
2352
2353 if (strcmp (element_name, "implements") != 0 ||
2354 !(ctx->state == STATE_CLASS))
2355 return FALSE;
2356
2357 state_switch (ctx, STATE_IMPLEMENTS);
2358
2359 name = find_attribute ("name", attribute_names, attribute_values);
2360 if (name == NULL)
2361 {
2362 MISSING_ATTRIBUTE (context, error, element_name, "name");
2363 return FALSE;
2364 }
2365
2366 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2367 iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
2368
2369 return TRUE;
2370 }
2371
2372 static gboolean
start_glib_signal(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)2373 start_glib_signal (GMarkupParseContext *context,
2374 const gchar *element_name,
2375 const gchar **attribute_names,
2376 const gchar **attribute_values,
2377 ParseContext *ctx,
2378 GError **error)
2379 {
2380 const gchar *name;
2381 const gchar *when;
2382 const gchar *no_recurse;
2383 const gchar *detailed;
2384 const gchar *action;
2385 const gchar *no_hooks;
2386 const gchar *has_class_closure;
2387 GIrNodeInterface *iface;
2388 GIrNodeSignal *signal;
2389
2390 if (!(strcmp (element_name, "glib:signal") == 0 &&
2391 (ctx->state == STATE_CLASS ||
2392 ctx->state == STATE_INTERFACE)))
2393 return FALSE;
2394
2395 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_FUNCTION))
2396 return TRUE;
2397
2398 name = find_attribute ("name", attribute_names, attribute_values);
2399 when = find_attribute ("when", attribute_names, attribute_values);
2400 no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
2401 detailed = find_attribute ("detailed", attribute_names, attribute_values);
2402 action = find_attribute ("action", attribute_names, attribute_values);
2403 no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
2404 has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
2405
2406 if (name == NULL)
2407 {
2408 MISSING_ATTRIBUTE (context, error, element_name, "name");
2409 return FALSE;
2410 }
2411 signal = (GIrNodeSignal *)_g_ir_node_new (G_IR_NODE_SIGNAL,
2412 ctx->current_module);
2413
2414 ((GIrNode *)signal)->name = g_strdup (name);
2415
2416 signal->run_first = FALSE;
2417 signal->run_last = FALSE;
2418 signal->run_cleanup = FALSE;
2419 if (when == NULL || g_ascii_strcasecmp (when, "LAST") == 0)
2420 signal->run_last = TRUE;
2421 else if (g_ascii_strcasecmp (when, "FIRST") == 0)
2422 signal->run_first = TRUE;
2423 else
2424 signal->run_cleanup = TRUE;
2425
2426 if (no_recurse && strcmp (no_recurse, "1") == 0)
2427 signal->no_recurse = TRUE;
2428 else
2429 signal->no_recurse = FALSE;
2430 if (detailed && strcmp (detailed, "1") == 0)
2431 signal->detailed = TRUE;
2432 else
2433 signal->detailed = FALSE;
2434 if (action && strcmp (action, "1") == 0)
2435 signal->action = TRUE;
2436 else
2437 signal->action = FALSE;
2438 if (no_hooks && strcmp (no_hooks, "1") == 0)
2439 signal->no_hooks = TRUE;
2440 else
2441 signal->no_hooks = FALSE;
2442 if (has_class_closure && strcmp (has_class_closure, "1") == 0)
2443 signal->has_class_closure = TRUE;
2444 else
2445 signal->has_class_closure = FALSE;
2446
2447 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2448 iface->members = g_list_append (iface->members, signal);
2449
2450 push_node (ctx, (GIrNode *)signal);
2451
2452 return TRUE;
2453 }
2454
2455 static gboolean
start_vfunc(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)2456 start_vfunc (GMarkupParseContext *context,
2457 const gchar *element_name,
2458 const gchar **attribute_names,
2459 const gchar **attribute_values,
2460 ParseContext *ctx,
2461 GError **error)
2462 {
2463 const gchar *name;
2464 const gchar *must_chain_up;
2465 const gchar *override;
2466 const gchar *is_class_closure;
2467 const gchar *offset;
2468 const gchar *invoker;
2469 const gchar *throws;
2470 GIrNodeInterface *iface;
2471 GIrNodeVFunc *vfunc;
2472
2473 if (!(strcmp (element_name, "virtual-method") == 0 &&
2474 (ctx->state == STATE_CLASS ||
2475 ctx->state == STATE_INTERFACE)))
2476 return FALSE;
2477
2478 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_FUNCTION))
2479 return TRUE;
2480
2481 name = find_attribute ("name", attribute_names, attribute_values);
2482 must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
2483 override = find_attribute ("override", attribute_names, attribute_values);
2484 is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
2485 offset = find_attribute ("offset", attribute_names, attribute_values);
2486 invoker = find_attribute ("invoker", attribute_names, attribute_values);
2487 throws = find_attribute ("throws", attribute_names, attribute_values);
2488
2489 if (name == NULL)
2490 {
2491 MISSING_ATTRIBUTE (context, error, element_name, "name");
2492 return FALSE;
2493 }
2494
2495 vfunc = (GIrNodeVFunc *)_g_ir_node_new (G_IR_NODE_VFUNC,
2496 ctx->current_module);
2497
2498 ((GIrNode *)vfunc)->name = g_strdup (name);
2499
2500 if (must_chain_up && strcmp (must_chain_up, "1") == 0)
2501 vfunc->must_chain_up = TRUE;
2502 else
2503 vfunc->must_chain_up = FALSE;
2504
2505 if (override && strcmp (override, "always") == 0)
2506 {
2507 vfunc->must_be_implemented = TRUE;
2508 vfunc->must_not_be_implemented = FALSE;
2509 }
2510 else if (override && strcmp (override, "never") == 0)
2511 {
2512 vfunc->must_be_implemented = FALSE;
2513 vfunc->must_not_be_implemented = TRUE;
2514 }
2515 else
2516 {
2517 vfunc->must_be_implemented = FALSE;
2518 vfunc->must_not_be_implemented = FALSE;
2519 }
2520
2521 if (is_class_closure && strcmp (is_class_closure, "1") == 0)
2522 vfunc->is_class_closure = TRUE;
2523 else
2524 vfunc->is_class_closure = FALSE;
2525
2526 if (throws && strcmp (throws, "1") == 0)
2527 vfunc->throws = TRUE;
2528 else
2529 vfunc->throws = FALSE;
2530
2531 if (offset)
2532 vfunc->offset = atoi (offset);
2533 else
2534 vfunc->offset = 0xFFFF;
2535
2536 vfunc->invoker = g_strdup (invoker);
2537
2538 iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
2539 iface->members = g_list_append (iface->members, vfunc);
2540
2541 push_node (ctx, (GIrNode *)vfunc);
2542
2543 return TRUE;
2544 }
2545
2546 static gboolean
start_struct(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)2547 start_struct (GMarkupParseContext *context,
2548 const gchar *element_name,
2549 const gchar **attribute_names,
2550 const gchar **attribute_values,
2551 ParseContext *ctx,
2552 GError **error)
2553 {
2554 const gchar *name;
2555 const gchar *deprecated;
2556 const gchar *disguised;
2557 const gchar *gtype_name;
2558 const gchar *gtype_init;
2559 const gchar *gtype_struct;
2560 const gchar *foreign;
2561 GIrNodeStruct *struct_;
2562
2563 if (!(strcmp (element_name, "record") == 0 &&
2564 (ctx->state == STATE_NAMESPACE ||
2565 ctx->state == STATE_UNION ||
2566 ctx->state == STATE_STRUCT ||
2567 ctx->state == STATE_CLASS)))
2568 return FALSE;
2569
2570 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_STRUCT))
2571 return TRUE;
2572
2573 name = find_attribute ("name", attribute_names, attribute_values);
2574 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2575 disguised = find_attribute ("disguised", attribute_names, attribute_values);
2576 gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
2577 gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
2578 gtype_struct = find_attribute ("glib:is-gtype-struct-for", attribute_names, attribute_values);
2579 foreign = find_attribute ("foreign", attribute_names, attribute_values);
2580
2581 if (name == NULL && ctx->node_stack == NULL)
2582 {
2583 MISSING_ATTRIBUTE (context, error, element_name, "name");
2584 return FALSE;
2585 }
2586 if ((gtype_name == NULL && gtype_init != NULL))
2587 {
2588 MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
2589 return FALSE;
2590 }
2591 if ((gtype_name != NULL && gtype_init == NULL))
2592 {
2593 MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
2594 return FALSE;
2595 }
2596
2597 struct_ = (GIrNodeStruct *) _g_ir_node_new (G_IR_NODE_STRUCT,
2598 ctx->current_module);
2599
2600 ((GIrNode *)struct_)->name = g_strdup (name ? name : "");
2601 if (deprecated)
2602 struct_->deprecated = TRUE;
2603 else
2604 struct_->deprecated = FALSE;
2605
2606 if (disguised && strcmp (disguised, "1") == 0)
2607 struct_->disguised = TRUE;
2608
2609 struct_->is_gtype_struct = gtype_struct != NULL;
2610
2611 struct_->gtype_name = g_strdup (gtype_name);
2612 struct_->gtype_init = g_strdup (gtype_init);
2613
2614 struct_->foreign = (g_strcmp0 (foreign, "1") == 0);
2615
2616 if (ctx->node_stack == NULL)
2617 ctx->current_module->entries =
2618 g_list_append (ctx->current_module->entries, struct_);
2619 push_node (ctx, (GIrNode *)struct_);
2620 return TRUE;
2621 }
2622
2623 static gboolean
start_union(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)2624 start_union (GMarkupParseContext *context,
2625 const gchar *element_name,
2626 const gchar **attribute_names,
2627 const gchar **attribute_values,
2628 ParseContext *ctx,
2629 GError **error)
2630 {
2631 const gchar *name;
2632 const gchar *deprecated;
2633 const gchar *typename;
2634 const gchar *typeinit;
2635 GIrNodeUnion *union_;
2636
2637 if (!(strcmp (element_name, "union") == 0 &&
2638 (ctx->state == STATE_NAMESPACE ||
2639 ctx->state == STATE_UNION ||
2640 ctx->state == STATE_STRUCT ||
2641 ctx->state == STATE_CLASS)))
2642 return FALSE;
2643
2644 if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_UNION))
2645 return TRUE;
2646
2647 name = find_attribute ("name", attribute_names, attribute_values);
2648 deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2649 typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
2650 typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
2651
2652 if (name == NULL && ctx->node_stack == NULL)
2653 {
2654 MISSING_ATTRIBUTE (context, error, element_name, "name");
2655 return FALSE;
2656 }
2657
2658 union_ = (GIrNodeUnion *) _g_ir_node_new (G_IR_NODE_UNION,
2659 ctx->current_module);
2660
2661 ((GIrNode *)union_)->name = g_strdup (name ? name : "");
2662 union_->gtype_name = g_strdup (typename);
2663 union_->gtype_init = g_strdup (typeinit);
2664 if (deprecated)
2665 union_->deprecated = TRUE;
2666 else
2667 union_->deprecated = FALSE;
2668
2669 if (ctx->node_stack == NULL)
2670 ctx->current_module->entries =
2671 g_list_append (ctx->current_module->entries, union_);
2672 push_node (ctx, (GIrNode *)union_);
2673 return TRUE;
2674 }
2675
2676 static gboolean
start_discriminator(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,ParseContext * ctx,GError ** error)2677 start_discriminator (GMarkupParseContext *context,
2678 const gchar *element_name,
2679 const gchar **attribute_names,
2680 const gchar **attribute_values,
2681 ParseContext *ctx,
2682 GError **error)
2683 {
2684 const gchar *type;
2685 const gchar *offset;
2686 if (!(strcmp (element_name, "discriminator") == 0 &&
2687 ctx->state == STATE_UNION))
2688 return FALSE;
2689
2690 type = find_attribute ("type", attribute_names, attribute_values);
2691 offset = find_attribute ("offset", attribute_names, attribute_values);
2692 if (type == NULL)
2693 {
2694 MISSING_ATTRIBUTE (context, error, element_name, "type");
2695 return FALSE;
2696 }
2697 else if (offset == NULL)
2698 {
2699 MISSING_ATTRIBUTE (context, error, element_name, "offset");
2700 return FALSE;
2701 }
2702
2703 ((GIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_type
2704 = parse_type (ctx, type);
2705 ((GIrNodeUnion *)CURRENT_NODE (ctx))->discriminator_offset
2706 = atoi (offset);
2707
2708 return TRUE;
2709 }
2710
2711 static gboolean
parse_include(GMarkupParseContext * context,ParseContext * ctx,const char * name,const char * version)2712 parse_include (GMarkupParseContext *context,
2713 ParseContext *ctx,
2714 const char *name,
2715 const char *version)
2716 {
2717 GError *error = NULL;
2718 gchar *buffer;
2719 gsize length;
2720 gchar *girpath, *girname;
2721 GIrModule *module;
2722 GList *l;
2723
2724 for (l = ctx->parser->parsed_modules; l; l = l->next)
2725 {
2726 GIrModule *m = l->data;
2727
2728 if (strcmp (m->name, name) == 0)
2729 {
2730 if (strcmp (m->version, version) == 0)
2731 {
2732 ctx->include_modules = g_list_prepend (ctx->include_modules, m);
2733
2734 return TRUE;
2735 }
2736 else
2737 {
2738 g_printerr ("Module '%s' imported with conflicting versions '%s' and '%s'\n",
2739 name, m->version, version);
2740 return FALSE;
2741 }
2742 }
2743 }
2744
2745 girname = g_strdup_printf ("%s-%s.gir", name, version);
2746 girpath = locate_gir (ctx->parser, girname);
2747
2748 if (girpath == NULL)
2749 {
2750 g_printerr ("Could not find GIR file '%s'; check XDG_DATA_DIRS or use --includedir\n",
2751 girname);
2752 g_free (girname);
2753 return FALSE;
2754 }
2755 g_free (girname);
2756
2757 g_debug ("Parsing include %s\n", girpath);
2758
2759 if (!g_file_get_contents (girpath, &buffer, &length, &error))
2760 {
2761 g_printerr ("%s: %s\n", girpath, error->message);
2762 g_clear_error (&error);
2763 g_free (girpath);
2764 return FALSE;
2765 }
2766
2767 module = _g_ir_parser_parse_string (ctx->parser, name, girpath, buffer, length, &error);
2768 g_free (buffer);
2769 if (error != NULL)
2770 {
2771 int line_number, char_number;
2772 g_markup_parse_context_get_position (context, &line_number, &char_number);
2773 g_printerr ("%s:%d:%d: error: %s\n", girpath, line_number, char_number, error->message);
2774 g_clear_error (&error);
2775 g_free (girpath);
2776 return FALSE;
2777 }
2778 g_free (girpath);
2779
2780 ctx->include_modules = g_list_append (ctx->include_modules,
2781 module);
2782
2783 return TRUE;
2784 }
2785
2786 extern GLogLevelFlags logged_levels;
2787
2788 static void
start_element_handler(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,gpointer user_data,GError ** error)2789 start_element_handler (GMarkupParseContext *context,
2790 const gchar *element_name,
2791 const gchar **attribute_names,
2792 const gchar **attribute_values,
2793 gpointer user_data,
2794 GError **error)
2795 {
2796 ParseContext *ctx = user_data;
2797
2798 if (logged_levels & G_LOG_LEVEL_DEBUG)
2799 {
2800 GString *tags = g_string_new ("");
2801 int i;
2802 for (i = 0; attribute_names[i]; i++)
2803 g_string_append_printf (tags, "%s=\"%s\" ",
2804 attribute_names[i],
2805 attribute_values[i]);
2806
2807 if (i)
2808 {
2809 g_string_insert_c (tags, 0, ' ');
2810 g_string_truncate (tags, tags->len - 1);
2811 }
2812 g_debug ("<%s%s>", element_name, tags->str);
2813 g_string_free (tags, TRUE);
2814 }
2815
2816 if (ctx->state == STATE_PASSTHROUGH)
2817 {
2818 ctx->unknown_depth += 1;
2819 return;
2820 }
2821
2822 switch (element_name[0])
2823 {
2824 case 'a':
2825 if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0)
2826 {
2827 state_switch (ctx, STATE_ALIAS);
2828 goto out;
2829 }
2830 if (start_type (context, element_name,
2831 attribute_names, attribute_values,
2832 ctx, error))
2833 goto out;
2834 else if (start_attribute (context, element_name,
2835 attribute_names, attribute_values,
2836 ctx, error))
2837 goto out;
2838 break;
2839 case 'b':
2840 if (start_enum (context, element_name,
2841 attribute_names, attribute_values,
2842 ctx, error))
2843 goto out;
2844 break;
2845 case 'c':
2846 if (start_function (context, element_name,
2847 attribute_names, attribute_values,
2848 ctx, error))
2849 goto out;
2850 else if (start_constant (context, element_name,
2851 attribute_names, attribute_values,
2852 ctx, error))
2853 goto out;
2854 else if (start_class (context, element_name,
2855 attribute_names, attribute_values,
2856 ctx, error))
2857 goto out;
2858 break;
2859
2860 case 'd':
2861 if (start_discriminator (context, element_name,
2862 attribute_names, attribute_values,
2863 ctx, error))
2864 goto out;
2865 if (strcmp ("doc", element_name) == 0 || strcmp ("doc-deprecated", element_name) == 0 ||
2866 strcmp ("doc-stability", element_name) == 0 || strcmp ("doc-version", element_name) == 0 ||
2867 strcmp ("docsection", element_name) == 0)
2868 {
2869 state_switch (ctx, STATE_PASSTHROUGH);
2870 goto out;
2871 }
2872 break;
2873
2874 case 'e':
2875 if (start_enum (context, element_name,
2876 attribute_names, attribute_values,
2877 ctx, error))
2878 goto out;
2879 break;
2880
2881 case 'f':
2882 if (strcmp ("function-macro", element_name) == 0)
2883 {
2884 state_switch (ctx, STATE_PASSTHROUGH);
2885 goto out;
2886 }
2887 else if (start_function (context, element_name,
2888 attribute_names, attribute_values,
2889 ctx, error))
2890 goto out;
2891 else if (start_field (context, element_name,
2892 attribute_names, attribute_values,
2893 ctx, error))
2894 goto out;
2895 break;
2896
2897 case 'g':
2898 if (start_glib_boxed (context, element_name,
2899 attribute_names, attribute_values,
2900 ctx, error))
2901 goto out;
2902 else if (start_glib_signal (context, element_name,
2903 attribute_names, attribute_values,
2904 ctx, error))
2905 goto out;
2906 break;
2907
2908 case 'i':
2909 if (strcmp (element_name, "include") == 0 &&
2910 ctx->state == STATE_REPOSITORY)
2911 {
2912 const gchar *name;
2913 const gchar *version;
2914
2915 name = find_attribute ("name", attribute_names, attribute_values);
2916 version = find_attribute ("version", attribute_names, attribute_values);
2917
2918 if (name == NULL)
2919 {
2920 MISSING_ATTRIBUTE (context, error, element_name, "name");
2921 break;
2922 }
2923 if (version == NULL)
2924 {
2925 MISSING_ATTRIBUTE (context, error, element_name, "version");
2926 break;
2927 }
2928
2929 if (!parse_include (context, ctx, name, version))
2930 {
2931 g_set_error (error,
2932 G_MARKUP_ERROR,
2933 G_MARKUP_ERROR_INVALID_CONTENT,
2934 "Failed to parse included gir %s-%s",
2935 name,
2936 version);
2937 return;
2938 }
2939
2940 ctx->dependencies = g_list_prepend (ctx->dependencies,
2941 g_strdup_printf ("%s-%s", name, version));
2942
2943
2944 state_switch (ctx, STATE_INCLUDE);
2945 goto out;
2946 }
2947 if (start_interface (context, element_name,
2948 attribute_names, attribute_values,
2949 ctx, error))
2950 goto out;
2951 else if (start_implements (context, element_name,
2952 attribute_names, attribute_values,
2953 ctx, error))
2954 goto out;
2955 else if (start_instance_parameter (context, element_name,
2956 attribute_names, attribute_values,
2957 ctx, error))
2958 goto out;
2959 else if (strcmp (element_name, "c:include") == 0)
2960 {
2961 state_switch (ctx, STATE_C_INCLUDE);
2962 goto out;
2963 }
2964 break;
2965
2966 case 'm':
2967 if (start_function (context, element_name,
2968 attribute_names, attribute_values,
2969 ctx, error))
2970 goto out;
2971 else if (start_member (context, element_name,
2972 attribute_names, attribute_values,
2973 ctx, error))
2974 goto out;
2975 break;
2976
2977 case 'n':
2978 if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2979 {
2980 const gchar *name, *version, *shared_library, *cprefix;
2981
2982 if (ctx->current_module != NULL)
2983 {
2984 g_set_error (error,
2985 G_MARKUP_ERROR,
2986 G_MARKUP_ERROR_INVALID_CONTENT,
2987 "Only one <namespace/> element is currently allowed per <repository/>");
2988 goto out;
2989 }
2990
2991 name = find_attribute ("name", attribute_names, attribute_values);
2992 version = find_attribute ("version", attribute_names, attribute_values);
2993 shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2994 cprefix = find_attribute ("c:identifier-prefixes", attribute_names, attribute_values);
2995 /* Backwards compatibility; vala currently still generates this */
2996 if (cprefix == NULL)
2997 cprefix = find_attribute ("c:prefix", attribute_names, attribute_values);
2998
2999 if (name == NULL)
3000 MISSING_ATTRIBUTE (context, error, element_name, "name");
3001 else if (version == NULL)
3002 MISSING_ATTRIBUTE (context, error, element_name, "version");
3003 else
3004 {
3005 GList *l;
3006
3007 if (strcmp (name, ctx->namespace) != 0)
3008 g_set_error (error,
3009 G_MARKUP_ERROR,
3010 G_MARKUP_ERROR_INVALID_CONTENT,
3011 "<namespace/> name element '%s' doesn't match file name '%s'",
3012 name, ctx->namespace);
3013
3014 ctx->current_module = _g_ir_module_new (name, version, shared_library, cprefix);
3015
3016 ctx->current_module->aliases = ctx->aliases;
3017 ctx->aliases = NULL;
3018 ctx->current_module->disguised_structures = ctx->disguised_structures;
3019 ctx->disguised_structures = NULL;
3020
3021 for (l = ctx->include_modules; l; l = l->next)
3022 _g_ir_module_add_include_module (ctx->current_module, l->data);
3023
3024 g_list_free (ctx->include_modules);
3025 ctx->include_modules = NULL;
3026
3027 ctx->modules = g_list_append (ctx->modules, ctx->current_module);
3028 ctx->current_module->dependencies = ctx->dependencies;
3029
3030 state_switch (ctx, STATE_NAMESPACE);
3031 goto out;
3032 }
3033 }
3034 break;
3035
3036 case 'p':
3037 if (start_property (context, element_name,
3038 attribute_names, attribute_values,
3039 ctx, error))
3040 goto out;
3041 else if (strcmp (element_name, "parameters") == 0 &&
3042 ctx->state == STATE_FUNCTION)
3043 {
3044 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
3045
3046 goto out;
3047 }
3048 else if (start_parameter (context, element_name,
3049 attribute_names, attribute_values,
3050 ctx, error))
3051 goto out;
3052 else if (strcmp (element_name, "prerequisite") == 0 &&
3053 ctx->state == STATE_INTERFACE)
3054 {
3055 const gchar *name;
3056
3057 name = find_attribute ("name", attribute_names, attribute_values);
3058
3059 state_switch (ctx, STATE_PREREQUISITE);
3060
3061 if (name == NULL)
3062 MISSING_ATTRIBUTE (context, error, element_name, "name");
3063 else
3064 {
3065 GIrNodeInterface *iface;
3066
3067 iface = (GIrNodeInterface *)CURRENT_NODE(ctx);
3068 iface->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
3069 }
3070 goto out;
3071 }
3072 else if (strcmp (element_name, "package") == 0 &&
3073 ctx->state == STATE_REPOSITORY)
3074 {
3075 state_switch (ctx, STATE_PACKAGE);
3076 goto out;
3077 }
3078 break;
3079
3080 case 'r':
3081 if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
3082 {
3083 const gchar *version;
3084
3085 version = find_attribute ("version", attribute_names, attribute_values);
3086
3087 if (version == NULL)
3088 MISSING_ATTRIBUTE (context, error, element_name, "version");
3089 else if (strcmp (version, SUPPORTED_GIR_VERSION) != 0)
3090 g_set_error (error,
3091 G_MARKUP_ERROR,
3092 G_MARKUP_ERROR_INVALID_CONTENT,
3093 "Unsupported version '%s'",
3094 version);
3095 else
3096 state_switch (ctx, STATE_REPOSITORY);
3097
3098 goto out;
3099 }
3100 else if (start_return_value (context, element_name,
3101 attribute_names, attribute_values,
3102 ctx, error))
3103 goto out;
3104 else if (start_struct (context, element_name,
3105 attribute_names, attribute_values,
3106 ctx, error))
3107 goto out;
3108 break;
3109
3110 case 's':
3111 if (strcmp ("source-position", element_name) == 0)
3112 {
3113 state_switch (ctx, STATE_PASSTHROUGH);
3114 goto out;
3115 }
3116 break;
3117 case 'u':
3118 if (start_union (context, element_name,
3119 attribute_names, attribute_values,
3120 ctx, error))
3121 goto out;
3122 break;
3123
3124 case 't':
3125 if (start_type (context, element_name,
3126 attribute_names, attribute_values,
3127 ctx, error))
3128 goto out;
3129 break;
3130
3131 case 'v':
3132 if (start_vfunc (context, element_name,
3133 attribute_names, attribute_values,
3134 ctx, error))
3135 goto out;
3136 if (start_type (context, element_name,
3137 attribute_names, attribute_values,
3138 ctx, error))
3139 goto out;
3140 break;
3141 default:
3142 break;
3143 }
3144
3145 if (*error == NULL && ctx->state != STATE_PASSTHROUGH)
3146 {
3147 gint line_number, char_number;
3148 g_markup_parse_context_get_position (context, &line_number, &char_number);
3149 if (!g_str_has_prefix (element_name, "c:"))
3150 g_printerr ("%s:%d:%d: warning: element %s from state %d is unknown, ignoring\n",
3151 ctx->file_path, line_number, char_number, element_name,
3152 ctx->state);
3153 state_switch (ctx, STATE_PASSTHROUGH);
3154 }
3155
3156 out:
3157 if (*error)
3158 {
3159 gint line_number, char_number;
3160 g_markup_parse_context_get_position (context, &line_number, &char_number);
3161
3162 g_printerr ("%s:%d:%d: error: %s\n", ctx->file_path, line_number, char_number, (*error)->message);
3163 }
3164 }
3165
3166 static gboolean
require_one_of_end_elements(GMarkupParseContext * context,ParseContext * ctx,const char * actual_name,GError ** error,...)3167 require_one_of_end_elements (GMarkupParseContext *context,
3168 ParseContext *ctx,
3169 const char *actual_name,
3170 GError **error,
3171 ...)
3172 {
3173 va_list args;
3174 int line_number, char_number;
3175 const char *expected;
3176 gboolean matched = FALSE;
3177
3178 va_start (args, error);
3179
3180 while ((expected = va_arg (args, const char*)) != NULL)
3181 {
3182 if (strcmp (expected, actual_name) == 0)
3183 {
3184 matched = TRUE;
3185 break;
3186 }
3187 }
3188
3189 va_end (args);
3190
3191 if (matched)
3192 return TRUE;
3193
3194 g_markup_parse_context_get_position (context, &line_number, &char_number);
3195 g_set_error (error,
3196 G_MARKUP_ERROR,
3197 G_MARKUP_ERROR_INVALID_CONTENT,
3198 "Unexpected end tag '%s' on line %d char %d; current state=%d (prev=%d)",
3199 actual_name,
3200 line_number, char_number, ctx->state, ctx->prev_state);
3201 return FALSE;
3202 }
3203
3204 static gboolean
state_switch_end_struct_or_union(GMarkupParseContext * context,ParseContext * ctx,const gchar * element_name,GError ** error)3205 state_switch_end_struct_or_union (GMarkupParseContext *context,
3206 ParseContext *ctx,
3207 const gchar *element_name,
3208 GError **error)
3209 {
3210 pop_node (ctx);
3211 if (ctx->node_stack == NULL)
3212 {
3213 state_switch (ctx, STATE_NAMESPACE);
3214 }
3215 else
3216 {
3217 if (CURRENT_NODE (ctx)->type == G_IR_NODE_STRUCT)
3218 state_switch (ctx, STATE_STRUCT);
3219 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION)
3220 state_switch (ctx, STATE_UNION);
3221 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT)
3222 state_switch (ctx, STATE_CLASS);
3223 else
3224 {
3225 int line_number, char_number;
3226 g_markup_parse_context_get_position (context, &line_number, &char_number);
3227 g_set_error (error,
3228 G_MARKUP_ERROR,
3229 G_MARKUP_ERROR_INVALID_CONTENT,
3230 "Unexpected end tag '%s' on line %d char %d",
3231 element_name,
3232 line_number, char_number);
3233 return FALSE;
3234 }
3235 }
3236 return TRUE;
3237 }
3238
3239 static gboolean
require_end_element(GMarkupParseContext * context,ParseContext * ctx,const char * expected_name,const char * actual_name,GError ** error)3240 require_end_element (GMarkupParseContext *context,
3241 ParseContext *ctx,
3242 const char *expected_name,
3243 const char *actual_name,
3244 GError **error)
3245 {
3246 return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
3247 }
3248
3249 static void
end_element_handler(GMarkupParseContext * context,const gchar * element_name,gpointer user_data,GError ** error)3250 end_element_handler (GMarkupParseContext *context,
3251 const gchar *element_name,
3252 gpointer user_data,
3253 GError **error)
3254 {
3255 ParseContext *ctx = user_data;
3256
3257 g_debug ("</%s>", element_name);
3258
3259 switch (ctx->state)
3260 {
3261 case STATE_START:
3262 case STATE_END:
3263 /* no need to GError here, GMarkup already catches this */
3264 break;
3265
3266 case STATE_REPOSITORY:
3267 state_switch (ctx, STATE_END);
3268 break;
3269
3270 case STATE_INCLUDE:
3271 if (require_end_element (context, ctx, "include", element_name, error))
3272 {
3273 state_switch (ctx, STATE_REPOSITORY);
3274 }
3275 break;
3276
3277 case STATE_C_INCLUDE:
3278 if (require_end_element (context, ctx, "c:include", element_name, error))
3279 {
3280 state_switch (ctx, STATE_REPOSITORY);
3281 }
3282 break;
3283
3284 case STATE_PACKAGE:
3285 if (require_end_element (context, ctx, "package", element_name, error))
3286 {
3287 state_switch (ctx, STATE_REPOSITORY);
3288 }
3289 break;
3290
3291 case STATE_NAMESPACE:
3292 if (require_end_element (context, ctx, "namespace", element_name, error))
3293 {
3294 ctx->current_module = NULL;
3295 state_switch (ctx, STATE_REPOSITORY);
3296 }
3297 break;
3298
3299 case STATE_ALIAS:
3300 if (require_end_element (context, ctx, "alias", element_name, error))
3301 {
3302 g_free (ctx->current_alias);
3303 ctx->current_alias = NULL;
3304 state_switch (ctx, STATE_NAMESPACE);
3305 }
3306 break;
3307
3308 case STATE_FUNCTION_RETURN:
3309 if (strcmp ("type", element_name) == 0)
3310 break;
3311 if (require_end_element (context, ctx, "return-value", element_name, error))
3312 {
3313 state_switch (ctx, STATE_FUNCTION);
3314 }
3315 break;
3316
3317 case STATE_FUNCTION_PARAMETERS:
3318 if (require_end_element (context, ctx, "parameters", element_name, error))
3319 {
3320 state_switch (ctx, STATE_FUNCTION);
3321 }
3322 break;
3323
3324 case STATE_FUNCTION_PARAMETER:
3325 if (strcmp ("type", element_name) == 0)
3326 break;
3327 if (require_end_element (context, ctx, "parameter", element_name, error))
3328 {
3329 state_switch (ctx, STATE_FUNCTION_PARAMETERS);
3330 }
3331 break;
3332
3333 case STATE_FUNCTION:
3334 {
3335 pop_node (ctx);
3336 if (ctx->node_stack == NULL)
3337 {
3338 state_switch (ctx, STATE_NAMESPACE);
3339 }
3340 else
3341 {
3342 g_debug("case STATE_FUNCTION %d", CURRENT_NODE (ctx)->type);
3343 if (ctx->in_embedded_state != STATE_NONE)
3344 {
3345 state_switch (ctx, ctx->in_embedded_state);
3346 ctx->in_embedded_state = STATE_NONE;
3347 }
3348 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_INTERFACE)
3349 state_switch (ctx, STATE_INTERFACE);
3350 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT)
3351 state_switch (ctx, STATE_CLASS);
3352 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_BOXED)
3353 state_switch (ctx, STATE_BOXED);
3354 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_STRUCT)
3355 state_switch (ctx, STATE_STRUCT);
3356 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION)
3357 state_switch (ctx, STATE_UNION);
3358 else if (CURRENT_NODE (ctx)->type == G_IR_NODE_ENUM ||
3359 CURRENT_NODE (ctx)->type == G_IR_NODE_FLAGS)
3360 state_switch (ctx, STATE_ENUM);
3361 else
3362 {
3363 int line_number, char_number;
3364 g_markup_parse_context_get_position (context, &line_number, &char_number);
3365 g_set_error (error,
3366 G_MARKUP_ERROR,
3367 G_MARKUP_ERROR_INVALID_CONTENT,
3368 "Unexpected end tag '%s' on line %d char %d",
3369 element_name,
3370 line_number, char_number);
3371 }
3372 }
3373 }
3374 break;
3375
3376 case STATE_CLASS_FIELD:
3377 if (strcmp ("type", element_name) == 0)
3378 break;
3379 if (require_end_element (context, ctx, "field", element_name, error))
3380 {
3381 state_switch (ctx, STATE_CLASS);
3382 }
3383 break;
3384
3385 case STATE_CLASS_PROPERTY:
3386 if (strcmp ("type", element_name) == 0)
3387 break;
3388 if (require_end_element (context, ctx, "property", element_name, error))
3389 {
3390 state_switch (ctx, STATE_CLASS);
3391 }
3392 break;
3393
3394 case STATE_CLASS:
3395 if (require_end_element (context, ctx, "class", element_name, error))
3396 {
3397 pop_node (ctx);
3398 state_switch (ctx, STATE_NAMESPACE);
3399 }
3400 break;
3401
3402 case STATE_INTERFACE_PROPERTY:
3403 if (strcmp ("type", element_name) == 0)
3404 break;
3405 if (require_end_element (context, ctx, "property", element_name, error))
3406 {
3407 state_switch (ctx, STATE_INTERFACE);
3408 }
3409 break;
3410
3411 case STATE_INTERFACE_FIELD:
3412 if (strcmp ("type", element_name) == 0)
3413 break;
3414 if (require_end_element (context, ctx, "field", element_name, error))
3415 {
3416 state_switch (ctx, STATE_INTERFACE);
3417 }
3418 break;
3419
3420 case STATE_INTERFACE:
3421 if (require_end_element (context, ctx, "interface", element_name, error))
3422 {
3423 pop_node (ctx);
3424 state_switch (ctx, STATE_NAMESPACE);
3425 }
3426 break;
3427
3428 case STATE_ENUM:
3429 if (strcmp ("member", element_name) == 0)
3430 break;
3431 else if (strcmp ("function", element_name) == 0)
3432 break;
3433 else if (require_one_of_end_elements (context, ctx,
3434 element_name, error, "enumeration",
3435 "bitfield", NULL))
3436 {
3437 pop_node (ctx);
3438 state_switch (ctx, STATE_NAMESPACE);
3439 }
3440 break;
3441
3442 case STATE_BOXED:
3443 if (require_end_element (context, ctx, "glib:boxed", element_name, error))
3444 {
3445 pop_node (ctx);
3446 state_switch (ctx, STATE_NAMESPACE);
3447 }
3448 break;
3449
3450 case STATE_BOXED_FIELD:
3451 if (strcmp ("type", element_name) == 0)
3452 break;
3453 if (require_end_element (context, ctx, "field", element_name, error))
3454 {
3455 state_switch (ctx, STATE_BOXED);
3456 }
3457 break;
3458
3459 case STATE_STRUCT_FIELD:
3460 if (strcmp ("type", element_name) == 0)
3461 break;
3462 if (require_end_element (context, ctx, "field", element_name, error))
3463 {
3464 state_switch (ctx, STATE_STRUCT);
3465 }
3466 break;
3467
3468 case STATE_STRUCT:
3469 if (require_end_element (context, ctx, "record", element_name, error))
3470 {
3471 state_switch_end_struct_or_union (context, ctx, element_name, error);
3472 }
3473 break;
3474
3475 case STATE_UNION_FIELD:
3476 if (strcmp ("type", element_name) == 0)
3477 break;
3478 if (require_end_element (context, ctx, "field", element_name, error))
3479 {
3480 state_switch (ctx, STATE_UNION);
3481 }
3482 break;
3483
3484 case STATE_UNION:
3485 if (require_end_element (context, ctx, "union", element_name, error))
3486 {
3487 state_switch_end_struct_or_union (context, ctx, element_name, error);
3488 }
3489 break;
3490 case STATE_IMPLEMENTS:
3491 if (strcmp ("interface", element_name) == 0)
3492 break;
3493 if (require_end_element (context, ctx, "implements", element_name, error))
3494 state_switch (ctx, STATE_CLASS);
3495 break;
3496 case STATE_PREREQUISITE:
3497 if (require_end_element (context, ctx, "prerequisite", element_name, error))
3498 state_switch (ctx, STATE_INTERFACE);
3499 break;
3500 case STATE_NAMESPACE_CONSTANT:
3501 case STATE_CLASS_CONSTANT:
3502 case STATE_INTERFACE_CONSTANT:
3503 if (strcmp ("type", element_name) == 0)
3504 break;
3505 if (require_end_element (context, ctx, "constant", element_name, error))
3506 {
3507 switch (ctx->state)
3508 {
3509 case STATE_NAMESPACE_CONSTANT:
3510 pop_node (ctx);
3511 state_switch (ctx, STATE_NAMESPACE);
3512 break;
3513 case STATE_CLASS_CONSTANT:
3514 state_switch (ctx, STATE_CLASS);
3515 break;
3516 case STATE_INTERFACE_CONSTANT:
3517 state_switch (ctx, STATE_INTERFACE);
3518 break;
3519 default:
3520 g_assert_not_reached ();
3521 break;
3522 }
3523 }
3524 break;
3525 case STATE_TYPE:
3526 if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
3527 (strcmp ("varargs", element_name) == 0))
3528 {
3529 end_type (ctx);
3530 }
3531 break;
3532 case STATE_ATTRIBUTE:
3533 if (strcmp ("attribute", element_name) == 0)
3534 {
3535 state_switch (ctx, ctx->prev_state);
3536 }
3537 break;
3538
3539 case STATE_PASSTHROUGH:
3540 ctx->unknown_depth -= 1;
3541 g_assert (ctx->unknown_depth >= 0);
3542 if (ctx->unknown_depth == 0)
3543 state_switch (ctx, ctx->prev_state);
3544 break;
3545 default:
3546 g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
3547 }
3548 }
3549
3550 static void
text_handler(GMarkupParseContext * context,const gchar * text,gsize text_len,gpointer user_data,GError ** error)3551 text_handler (GMarkupParseContext *context,
3552 const gchar *text,
3553 gsize text_len,
3554 gpointer user_data,
3555 GError **error)
3556 {
3557 /* FIXME warn about non-whitespace text */
3558 }
3559
3560 static void
cleanup(GMarkupParseContext * context,GError * error,gpointer user_data)3561 cleanup (GMarkupParseContext *context,
3562 GError *error,
3563 gpointer user_data)
3564 {
3565 ParseContext *ctx = user_data;
3566 GList *m;
3567
3568 for (m = ctx->modules; m; m = m->next)
3569 _g_ir_module_free (m->data);
3570 g_list_free (ctx->modules);
3571 ctx->modules = NULL;
3572
3573 ctx->current_module = NULL;
3574 }
3575
3576 /**
3577 * _g_ir_parser_parse_string:
3578 * @parser: a #GIrParser
3579 * @namespace: the namespace of the string
3580 * @filename: (allow-none): Path to parsed file, or %NULL
3581 * @buffer: the data containing the XML
3582 * @length: length of the data
3583 * @error: return location for a #GError, or %NULL
3584 *
3585 * Parse a string that holds a complete GIR XML file, and return a list of a
3586 * a #GirModule for each <namespace/> element within the file.
3587 *
3588 * Returns: (transfer none): a new #GirModule
3589 */
3590 GIrModule *
_g_ir_parser_parse_string(GIrParser * parser,const gchar * namespace,const gchar * filename,const gchar * buffer,gssize length,GError ** error)3591 _g_ir_parser_parse_string (GIrParser *parser,
3592 const gchar *namespace,
3593 const gchar *filename,
3594 const gchar *buffer,
3595 gssize length,
3596 GError **error)
3597 {
3598 ParseContext ctx = { 0 };
3599 GMarkupParseContext *context;
3600
3601 ctx.parser = parser;
3602 ctx.state = STATE_START;
3603 ctx.file_path = filename;
3604 ctx.namespace = namespace;
3605 ctx.include_modules = NULL;
3606 ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
3607 ctx.disguised_structures = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
3608 ctx.type_depth = 0;
3609 ctx.dependencies = NULL;
3610 ctx.current_module = NULL;
3611
3612 context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
3613
3614 if (!g_markup_parse_context_parse (context, buffer, length, error))
3615 goto out;
3616
3617 if (!g_markup_parse_context_end_parse (context, error))
3618 goto out;
3619
3620 g_markup_parse_context_free (context);
3621
3622 ctx.state = STATE_START;
3623 context = g_markup_parse_context_new (&markup_parser, 0, &ctx, NULL);
3624 if (!g_markup_parse_context_parse (context, buffer, length, error))
3625 goto out;
3626
3627 if (!g_markup_parse_context_end_parse (context, error))
3628 goto out;
3629
3630 parser->parsed_modules = g_list_concat (g_list_copy (ctx.modules),
3631 parser->parsed_modules);
3632
3633 out:
3634
3635 if (ctx.modules == NULL)
3636 {
3637 /* An error occurred before we created a module, so we haven't
3638 * transferred ownership of these hash tables to the module.
3639 */
3640 if (ctx.aliases != NULL)
3641 g_hash_table_destroy (ctx.aliases);
3642 if (ctx.disguised_structures != NULL)
3643 g_hash_table_destroy (ctx.disguised_structures);
3644 g_list_free (ctx.include_modules);
3645 }
3646
3647 g_markup_parse_context_free (context);
3648
3649 if (ctx.modules)
3650 return ctx.modules->data;
3651
3652 if (error && *error == NULL)
3653 g_set_error (error,
3654 G_MARKUP_ERROR,
3655 G_MARKUP_ERROR_INVALID_CONTENT,
3656 "Expected namespace element in the gir file");
3657 return NULL;
3658 }
3659
3660 /**
3661 * _g_ir_parser_parse_file:
3662 * @parser: a #GIrParser
3663 * @filename: filename to parse
3664 * @error: return location for a #GError, or %NULL
3665 *
3666 * Parse GIR XML file, and return a list of a a #GirModule for each
3667 * <namespace/> element within the file.
3668 *
3669 * Returns: (transfer container): a newly allocated list of #GIrModule. The modules themselves
3670 * are owned by the #GIrParser and will be freed along with the parser.
3671 */
3672 GIrModule *
_g_ir_parser_parse_file(GIrParser * parser,const gchar * filename,GError ** error)3673 _g_ir_parser_parse_file (GIrParser *parser,
3674 const gchar *filename,
3675 GError **error)
3676 {
3677 gchar *buffer;
3678 gsize length;
3679 GIrModule *module;
3680 const char *slash;
3681 char *dash;
3682 char *namespace;
3683
3684 if (!g_str_has_suffix (filename, ".gir"))
3685 {
3686 g_set_error (error,
3687 G_MARKUP_ERROR,
3688 G_MARKUP_ERROR_INVALID_CONTENT,
3689 "Expected filename to end with '.gir'");
3690 return NULL;
3691 }
3692
3693 g_debug ("[parsing] filename %s", filename);
3694
3695 slash = g_strrstr (filename, "/");
3696 if (!slash)
3697 namespace = g_strdup (filename);
3698 else
3699 namespace = g_strdup (slash+1);
3700 namespace[strlen(namespace)-4] = '\0';
3701
3702 /* Remove version */
3703 dash = strstr (namespace, "-");
3704 if (dash != NULL)
3705 *dash = '\0';
3706
3707 if (!g_file_get_contents (filename, &buffer, &length, error))
3708 {
3709 g_free (namespace);
3710
3711 return NULL;
3712 }
3713
3714 module = _g_ir_parser_parse_string (parser, namespace, filename, buffer, length, error);
3715
3716 g_free (namespace);
3717
3718 g_free (buffer);
3719
3720 return module;
3721 }
3722
3723
3724