LCOV - code coverage report
Current view: top level - girepository - girparser.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 78.5 % 2174 1707
Test Date: 2026-07-14 05:12:09 Functions: 98.1 % 54 53
Branches: - 0 0

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

Generated by: LCOV version 2.0-1