ofdbus/dbus-glib/dbus/dbus-gparser.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* -*- mode: C; c-file-style: "gnu" -*- */
       
     2 /* dbus-gparser.c parse DBus description files
       
     3  *
       
     4  * Copyright (C) 2003, 2005  Red Hat, Inc.
       
     5  * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
       
     6  * Licensed under the Academic Free License version 2.1
       
     7  * 
       
     8  * This program is free software; you can redistribute it and/or modify
       
     9  * it under the terms of the GNU General Public License as published by
       
    10  * the Free Software Foundation; either version 2 of the License, or
       
    11  * (at your option) any later version.
       
    12  *
       
    13  * This program is distributed in the hope that it will be useful,
       
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    16  * GNU General Public License for more details.
       
    17  * 
       
    18  * You should have received a copy of the GNU General Public License
       
    19  * along with this program; if not, write to the Free Software
       
    20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    21  *
       
    22  */
       
    23 #include "dbus-gparser.h"
       
    24 #include "dbus/dbus-glib-lowlevel.h"
       
    25 #include "dbus-gidl.h"
       
    26 #include "dbus-gobject.h"
       
    27 #include "dbus/dbus-signature.h"
       
    28 #include <string.h>
       
    29 
       
    30 
       
    31 
       
    32 #ifndef __SYMBIAN32__
       
    33 #include <libintl.h>
       
    34 #define _(x) gettext ((x))
       
    35 #define N_(x) x
       
    36 #else
       
    37 
       
    38 #define _(x) x
       
    39 #define N_(x) x
       
    40 #endif
       
    41 
       
    42 
       
    43 #ifndef DOXYGEN_SHOULD_SKIP_THIS
       
    44 
       
    45 #define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0)
       
    46 
       
    47 typedef struct
       
    48 {
       
    49   const char  *name;
       
    50   const char **retloc;
       
    51 } LocateAttr;
       
    52 
       
    53 static gboolean
       
    54 locate_attributes (const char  *element_name,
       
    55                    const char **attribute_names,
       
    56                    const char **attribute_values,
       
    57                    GError     **error,
       
    58                    const char  *first_attribute_name,
       
    59                    const char **first_attribute_retloc,
       
    60                    ...)
       
    61 {
       
    62   va_list args;
       
    63   const char *name;
       
    64   const char **retloc;
       
    65   int n_attrs;
       
    66 #define MAX_ATTRS 24
       
    67   LocateAttr attrs[MAX_ATTRS];
       
    68   gboolean retval;
       
    69   int i;
       
    70 
       
    71   g_return_val_if_fail (first_attribute_name != NULL, FALSE);
       
    72   g_return_val_if_fail (first_attribute_retloc != NULL, FALSE);
       
    73 
       
    74   retval = TRUE;
       
    75 
       
    76   n_attrs = 1;
       
    77   attrs[0].name = first_attribute_name;
       
    78   attrs[0].retloc = first_attribute_retloc;
       
    79   *first_attribute_retloc = NULL;
       
    80   
       
    81   va_start (args, first_attribute_retloc);
       
    82 
       
    83   name = va_arg (args, const char*);
       
    84   retloc = va_arg (args, const char**);
       
    85 
       
    86   while (name != NULL)
       
    87     {
       
    88       g_return_val_if_fail (retloc != NULL, FALSE);
       
    89 
       
    90       g_assert (n_attrs < MAX_ATTRS);
       
    91       
       
    92       attrs[n_attrs].name = name;
       
    93       attrs[n_attrs].retloc = retloc;
       
    94       n_attrs += 1;
       
    95       *retloc = NULL;      
       
    96 
       
    97       name = va_arg (args, const char*);
       
    98       retloc = va_arg (args, const char**);
       
    99     }
       
   100 
       
   101   va_end (args);
       
   102 
       
   103   if (!retval)
       
   104     return retval;
       
   105 
       
   106   i = 0;
       
   107   while (attribute_names[i])
       
   108     {
       
   109       int j;
       
   110       gboolean found;
       
   111 
       
   112       found = FALSE;
       
   113       j = 0;
       
   114       while (j < n_attrs)
       
   115         {
       
   116           if (strcmp (attrs[j].name, attribute_names[i]) == 0)
       
   117             {
       
   118               retloc = attrs[j].retloc;
       
   119 
       
   120               if (*retloc != NULL)
       
   121                 {
       
   122                   g_set_error (error,
       
   123                                G_MARKUP_ERROR,
       
   124                                G_MARKUP_ERROR_PARSE,
       
   125                                _("Attribute \"%s\" repeated twice on the same <%s> element"),
       
   126                                attrs[j].name, element_name);
       
   127                   retval = FALSE;
       
   128                   goto out;
       
   129                 }
       
   130 
       
   131               *retloc = attribute_values[i];
       
   132               found = TRUE;
       
   133             }
       
   134 
       
   135           ++j;
       
   136         }
       
   137 
       
   138       if (!found)
       
   139         {
       
   140           g_set_error (error,
       
   141                        G_MARKUP_ERROR,
       
   142                        G_MARKUP_ERROR_PARSE,
       
   143                        _("Attribute \"%s\" is invalid on <%s> element in this context"),
       
   144                        attribute_names[i], element_name);
       
   145           retval = FALSE;
       
   146           goto out;
       
   147         }
       
   148 
       
   149       ++i;
       
   150     }
       
   151 
       
   152  out:
       
   153   return retval;
       
   154 }
       
   155 
       
   156 #if 0
       
   157 static gboolean
       
   158 check_no_attributes (const char  *element_name,
       
   159                      const char **attribute_names,
       
   160                      const char **attribute_values,
       
   161                      GError     **error)
       
   162 {
       
   163   if (attribute_names[0] != NULL)
       
   164     {
       
   165       g_set_error (error,
       
   166                    G_MARKUP_ERROR,
       
   167                    G_MARKUP_ERROR_PARSE,
       
   168                    _("Attribute \"%s\" is invalid on <%s> element in this context"),
       
   169                    attribute_names[0], element_name);
       
   170       return FALSE;
       
   171     }
       
   172 
       
   173   return TRUE;
       
   174 }
       
   175 #endif
       
   176 
       
   177 struct Parser
       
   178 {
       
   179   int refcount;
       
   180 
       
   181   NodeInfo *result; /* Filled in when we pop the last node */
       
   182   GSList *node_stack;
       
   183   InterfaceInfo *interface;
       
   184   MethodInfo *method;
       
   185   SignalInfo *signal;
       
   186   PropertyInfo *property;
       
   187   ArgInfo *arg;
       
   188   gboolean in_annotation;
       
   189 };
       
   190 
       
   191 Parser*
       
   192 parser_new (void)
       
   193 {
       
   194   Parser *parser;
       
   195 
       
   196   parser = g_new0 (Parser, 1);
       
   197 
       
   198   parser->refcount = 1;
       
   199 
       
   200   return parser;
       
   201 }
       
   202 
       
   203 Parser *
       
   204 parser_ref (Parser *parser)
       
   205 {
       
   206   parser->refcount += 1;
       
   207 
       
   208   return parser;
       
   209 }
       
   210 
       
   211 void
       
   212 parser_unref (Parser *parser)
       
   213 {
       
   214   parser->refcount -= 1;
       
   215   if (parser->refcount == 0)
       
   216     {
       
   217       if (parser->result)
       
   218         node_info_unref (parser->result);
       
   219 
       
   220       g_free (parser);
       
   221     }
       
   222 }
       
   223 
       
   224 gboolean
       
   225 parser_check_doctype (Parser      *parser,
       
   226                       const char  *doctype,
       
   227                       GError     **error)
       
   228 {
       
   229   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
       
   230   
       
   231   if (strcmp (doctype, "node") != 0)
       
   232     {
       
   233       g_set_error (error,
       
   234                    G_MARKUP_ERROR,
       
   235                    G_MARKUP_ERROR_PARSE,
       
   236                    "D-BUS description file has the wrong document type %s, use node or interface",
       
   237                    doctype);
       
   238       return FALSE;
       
   239     }
       
   240   else
       
   241     return TRUE;
       
   242 }
       
   243 
       
   244 static gboolean
       
   245 parse_node (Parser      *parser,
       
   246             const char  *element_name,
       
   247             const char **attribute_names,
       
   248             const char **attribute_values,
       
   249             GError     **error)
       
   250 {
       
   251   const char *name;
       
   252   NodeInfo *node;
       
   253   
       
   254   if (parser->interface ||
       
   255       parser->method ||
       
   256       parser->signal ||
       
   257       parser->property ||
       
   258       parser->arg ||
       
   259       parser->in_annotation)
       
   260     {
       
   261       g_set_error (error, G_MARKUP_ERROR,
       
   262                    G_MARKUP_ERROR_PARSE,
       
   263                    _("Can't put <%s> element here"),
       
   264                    element_name);
       
   265       return FALSE;      
       
   266     }
       
   267 
       
   268   name = NULL;
       
   269   if (!locate_attributes (element_name, attribute_names,
       
   270                           attribute_values, error,
       
   271                           "name", &name,
       
   272                           NULL))
       
   273     return FALSE;
       
   274 
       
   275   /* Only the root node can have no name */
       
   276   if (parser->node_stack != NULL && name == NULL)
       
   277     {
       
   278       g_set_error (error, G_MARKUP_ERROR,
       
   279                    G_MARKUP_ERROR_PARSE,
       
   280                    _("\"%s\" attribute required on <%s> element "),
       
   281                    "name", element_name);
       
   282       return FALSE;
       
   283     }
       
   284 
       
   285   /* Root element name must be absolute */
       
   286   if (parser->node_stack == NULL && name && *name != '/')
       
   287     {
       
   288       g_set_error (error, G_MARKUP_ERROR,
       
   289                    G_MARKUP_ERROR_PARSE,
       
   290                    _("\"%s\" attribute on <%s> element must be an absolute object path, \"%s\" not OK"),
       
   291                    "name", element_name, name);
       
   292       return FALSE;
       
   293     }
       
   294 
       
   295   /* Other element names must not be absolute */
       
   296   if (parser->node_stack != NULL && name && *name == '/')
       
   297     {
       
   298       g_set_error (error, G_MARKUP_ERROR,
       
   299                    G_MARKUP_ERROR_PARSE,
       
   300                    _("\"%s\" attribute on <%s> element must not be an absolute object path, \"%s\" starts with /"),
       
   301                    "name", element_name, name);
       
   302       return FALSE;
       
   303     }
       
   304   
       
   305   node = node_info_new (name);
       
   306 
       
   307   if (parser->node_stack != NULL)
       
   308     {
       
   309       node_info_add_node (parser->node_stack->data,
       
   310                           node);
       
   311     }
       
   312   
       
   313   parser->node_stack = g_slist_prepend (parser->node_stack,
       
   314                                         node);
       
   315   
       
   316   return TRUE;
       
   317 }
       
   318 
       
   319 static gboolean
       
   320 parse_interface (Parser      *parser,
       
   321                  const char  *element_name,
       
   322                  const char **attribute_names,
       
   323                  const char **attribute_values,
       
   324                  GError     **error)
       
   325 {
       
   326   const char *name;
       
   327   InterfaceInfo *iface;
       
   328   NodeInfo *top;
       
   329   
       
   330   if (parser->interface ||
       
   331       parser->method ||
       
   332       parser->signal ||
       
   333       parser->property ||
       
   334       parser->arg ||
       
   335       parser->in_annotation ||
       
   336       (parser->node_stack == NULL))
       
   337     {
       
   338       g_set_error (error, G_MARKUP_ERROR,
       
   339                    G_MARKUP_ERROR_PARSE,
       
   340                    _("Can't put <%s> element here"),
       
   341                    element_name);
       
   342       return FALSE;      
       
   343     }
       
   344 
       
   345   name = NULL;
       
   346   if (!locate_attributes (element_name, attribute_names,
       
   347                           attribute_values, error,
       
   348                           "name", &name,
       
   349                           NULL))
       
   350     return FALSE;
       
   351 
       
   352   if (name == NULL)
       
   353     {
       
   354       g_set_error (error, G_MARKUP_ERROR,
       
   355                    G_MARKUP_ERROR_PARSE,
       
   356                    _("\"%s\" attribute required on <%s> element "),
       
   357                    "name", element_name);
       
   358       return FALSE;
       
   359     }
       
   360 
       
   361   top = parser->node_stack->data;
       
   362   
       
   363   iface = interface_info_new (name);
       
   364   node_info_add_interface (top, iface);
       
   365   interface_info_unref (iface);
       
   366 
       
   367   parser->interface = iface;
       
   368   
       
   369   return TRUE;
       
   370 }
       
   371 
       
   372 static gboolean
       
   373 parse_method (Parser      *parser,
       
   374               const char  *element_name,
       
   375               const char **attribute_names,
       
   376               const char **attribute_values,
       
   377               GError     **error)
       
   378 {
       
   379   const char *name;
       
   380   MethodInfo *method;
       
   381   
       
   382   if (parser->interface == NULL ||
       
   383       parser->node_stack == NULL ||
       
   384       parser->method ||
       
   385       parser->signal ||
       
   386       parser->property ||
       
   387       parser->in_annotation ||
       
   388       parser->arg)
       
   389     {
       
   390       g_set_error (error, G_MARKUP_ERROR,
       
   391                    G_MARKUP_ERROR_PARSE,
       
   392                    _("Can't put <%s> element here"),
       
   393                    element_name);
       
   394       return FALSE;      
       
   395     }
       
   396 
       
   397   name = NULL;
       
   398   if (!locate_attributes (element_name, attribute_names,
       
   399                           attribute_values, error,
       
   400                           "name", &name,
       
   401                           NULL))
       
   402     return FALSE;
       
   403 
       
   404   if (name == NULL)
       
   405     {
       
   406       g_set_error (error, G_MARKUP_ERROR,
       
   407                    G_MARKUP_ERROR_PARSE,
       
   408                    _("\"%s\" attribute required on <%s> element "),
       
   409                    "name", element_name);
       
   410       return FALSE;
       
   411     }
       
   412 
       
   413   method = method_info_new (name);
       
   414   interface_info_add_method (parser->interface, method);
       
   415   method_info_unref (method);
       
   416 
       
   417   parser->method = method;
       
   418   
       
   419   return TRUE;
       
   420 }
       
   421 
       
   422 static gboolean
       
   423 parse_signal (Parser      *parser,
       
   424               const char  *element_name,
       
   425               const char **attribute_names,
       
   426               const char **attribute_values,
       
   427               GError     **error)
       
   428 {
       
   429   const char *name;
       
   430   SignalInfo *signal;
       
   431   
       
   432   if (parser->interface == NULL ||
       
   433       parser->node_stack == NULL ||
       
   434       parser->signal ||
       
   435       parser->method ||
       
   436       parser->property ||
       
   437       parser->in_annotation ||
       
   438       parser->arg)
       
   439     {
       
   440       g_set_error (error, G_MARKUP_ERROR,
       
   441                    G_MARKUP_ERROR_PARSE,
       
   442                    _("Can't put <%s> element here"),
       
   443                    element_name);
       
   444       return FALSE;      
       
   445     }
       
   446 
       
   447   name = NULL;
       
   448   if (!locate_attributes (element_name, attribute_names,
       
   449                           attribute_values, error,
       
   450                           "name", &name,
       
   451                           NULL))
       
   452     return FALSE;
       
   453 
       
   454   if (name == NULL)
       
   455     {
       
   456       g_set_error (error, G_MARKUP_ERROR,
       
   457                    G_MARKUP_ERROR_PARSE,
       
   458                    _("\"%s\" attribute required on <%s> element "),
       
   459                    "name", element_name);
       
   460       return FALSE;
       
   461     }
       
   462 
       
   463   signal = signal_info_new (name);
       
   464   interface_info_add_signal (parser->interface, signal);
       
   465   signal_info_unref (signal);
       
   466 
       
   467   parser->signal = signal;
       
   468   
       
   469   return TRUE;
       
   470 }
       
   471 
       
   472 static gboolean
       
   473 validate_signature (const char *str,
       
   474 		    const char *element_name,
       
   475 		    GError    **error)
       
   476 {
       
   477   DBusError derror;
       
   478 
       
   479   dbus_error_init (&derror);
       
   480   
       
   481   if (!dbus_signature_validate (str, &derror))
       
   482     {
       
   483       dbus_set_g_error (error, &derror);
       
   484       return FALSE;
       
   485     }
       
   486   return TRUE;
       
   487 }
       
   488 
       
   489 static gboolean
       
   490 parse_property (Parser      *parser,
       
   491                 const char  *element_name,
       
   492                 const char **attribute_names,
       
   493                 const char **attribute_values,
       
   494                 GError     **error)
       
   495 {
       
   496   const char *name;
       
   497   const char *access;
       
   498   const char *type;
       
   499   PropertyInfo *property;
       
   500   PropertyAccessFlags access_flags;
       
   501   
       
   502   if (parser->interface == NULL ||
       
   503       parser->node_stack == NULL ||
       
   504       parser->signal ||
       
   505       parser->method ||
       
   506       parser->property ||
       
   507       parser->in_annotation ||
       
   508       parser->arg)
       
   509     {
       
   510       g_set_error (error, G_MARKUP_ERROR,
       
   511                    G_MARKUP_ERROR_PARSE,
       
   512                    _("Can't put <%s> element here"),
       
   513                    element_name);
       
   514       return FALSE;      
       
   515     }
       
   516 
       
   517   name = NULL;
       
   518   if (!locate_attributes (element_name, attribute_names,
       
   519                           attribute_values, error,
       
   520                           "name", &name,
       
   521                           "access", &access,
       
   522                           "type", &type,
       
   523                           NULL))
       
   524     return FALSE;
       
   525 
       
   526   if (name == NULL)
       
   527     {
       
   528       g_set_error (error, G_MARKUP_ERROR,
       
   529                    G_MARKUP_ERROR_PARSE,
       
   530                    _("\"%s\" attribute required on <%s> element "),
       
   531                    "name", element_name);
       
   532       return FALSE;
       
   533     }
       
   534 
       
   535   if (access == NULL)
       
   536     {
       
   537       g_set_error (error, G_MARKUP_ERROR,
       
   538                    G_MARKUP_ERROR_PARSE,
       
   539                    _("\"%s\" attribute required on <%s> element "),
       
   540                    "access", element_name);
       
   541       return FALSE;
       
   542     }
       
   543 
       
   544   if (type == NULL)
       
   545     {
       
   546       g_set_error (error, G_MARKUP_ERROR,
       
   547                    G_MARKUP_ERROR_PARSE,
       
   548                    _("\"%s\" attribute required on <%s> element "),
       
   549                    "type", element_name);
       
   550       return FALSE;
       
   551     }
       
   552 
       
   553   if (!validate_signature (type, element_name, error))
       
   554     return FALSE;
       
   555 
       
   556   access_flags = 0;
       
   557   if (strcmp (access, "readwrite") == 0)
       
   558     access_flags = PROPERTY_READ | PROPERTY_WRITE;
       
   559   else if (strcmp (access, "read") == 0)
       
   560     access_flags = PROPERTY_READ;
       
   561   else if (strcmp (access, "write") == 0)
       
   562     access_flags = PROPERTY_WRITE;
       
   563   else
       
   564     {
       
   565       g_set_error (error, G_MARKUP_ERROR,
       
   566                    G_MARKUP_ERROR_PARSE,
       
   567                    _("access=\"%s\" must have value readwrite, read, or write on %s\n"),
       
   568                    access, element_name);
       
   569       return FALSE;
       
   570     }
       
   571   
       
   572   property = property_info_new (name, type, access_flags);
       
   573   interface_info_add_property (parser->interface, property);
       
   574   property_info_unref (property);
       
   575 
       
   576   parser->property = property;
       
   577   
       
   578   return TRUE;
       
   579 }
       
   580 
       
   581 static gboolean
       
   582 parse_arg (Parser      *parser,
       
   583            const char  *element_name,
       
   584            const char **attribute_names,
       
   585            const char **attribute_values,
       
   586            GError     **error)
       
   587 {
       
   588   const char *name;
       
   589   const char *type;
       
   590   const char *direction;
       
   591   ArgDirection dir;
       
   592   ArgInfo *arg;
       
   593   char *generated_name;
       
   594   
       
   595   if (!(parser->method || parser->signal) ||
       
   596       parser->node_stack == NULL ||
       
   597       parser->property ||
       
   598       parser->in_annotation ||
       
   599       parser->arg)
       
   600     {
       
   601       g_set_error (error, G_MARKUP_ERROR,
       
   602                    G_MARKUP_ERROR_PARSE,
       
   603                    _("Can't put <%s> element here"),
       
   604                    element_name);
       
   605       return FALSE;      
       
   606     }
       
   607 
       
   608   name = NULL;
       
   609   if (!locate_attributes (element_name, attribute_names,
       
   610                           attribute_values, error,
       
   611                           "name", &name,
       
   612                           "type", &type,
       
   613                           "direction", &direction,
       
   614                           NULL))
       
   615     return FALSE;
       
   616 
       
   617   /* name can be null for args */
       
   618   
       
   619   if (type == NULL)
       
   620     {
       
   621       g_set_error (error, G_MARKUP_ERROR,
       
   622                    G_MARKUP_ERROR_PARSE,
       
   623                    _("\"%s\" attribute required on <%s> element "),
       
   624                    "type", element_name);
       
   625       return FALSE;
       
   626     }
       
   627 
       
   628   if (direction == NULL)
       
   629     {
       
   630       /* methods default to in, signal to out */
       
   631       if (parser->method)
       
   632         direction = "in";
       
   633       else if (parser->signal)
       
   634         direction = "out";
       
   635       else
       
   636         g_assert_not_reached ();
       
   637     }
       
   638 
       
   639   dir = ARG_INVALID;
       
   640   
       
   641   if (strcmp (direction, "in") == 0)
       
   642     dir = ARG_IN;
       
   643   else if (strcmp (direction, "out") == 0)
       
   644     dir = ARG_OUT;
       
   645   
       
   646   if (dir == ARG_INVALID ||
       
   647       (parser->signal && dir == ARG_IN))
       
   648     {
       
   649       if (parser->signal)
       
   650         g_set_error (error, G_MARKUP_ERROR,
       
   651                      G_MARKUP_ERROR_PARSE,
       
   652                      _("Signals must have direction=\"out\" (just omit the direction attribute)"));
       
   653       else
       
   654         g_set_error (error, G_MARKUP_ERROR,
       
   655                      G_MARKUP_ERROR_PARSE,
       
   656                      _("\"%s\" attribute on <%s> has value \"in\" or \"out\""),
       
   657                      "direction", element_name);
       
   658       return FALSE;
       
   659     }
       
   660 
       
   661   if (!validate_signature (type, element_name, error))
       
   662     return FALSE;
       
   663 
       
   664   generated_name = NULL;
       
   665   if (name == NULL)
       
   666     generated_name = g_strdup_printf ("arg%d",
       
   667                                       parser->method ?
       
   668                                       method_info_get_n_args (parser->method) :
       
   669                                       signal_info_get_n_args (parser->signal));
       
   670                                       
       
   671   arg = arg_info_new (name ? name : generated_name, dir, type);
       
   672   if (parser->method)
       
   673     method_info_add_arg (parser->method, arg);
       
   674   else if (parser->signal)
       
   675     signal_info_add_arg (parser->signal, arg);
       
   676   else
       
   677     g_assert_not_reached ();
       
   678 
       
   679   g_free (generated_name);
       
   680   
       
   681   arg_info_unref (arg);
       
   682 
       
   683   parser->arg = arg;
       
   684   
       
   685   return TRUE;
       
   686 }
       
   687 
       
   688 static gboolean
       
   689 parse_annotation (Parser      *parser,
       
   690 		  const char  *element_name,
       
   691 		  const char **attribute_names,
       
   692 		  const char **attribute_values,
       
   693 		  GError     **error)
       
   694 {
       
   695   const char *name;
       
   696   const char *value;
       
   697   
       
   698   if (!(parser->method || parser->interface || parser->arg) || 
       
   699       parser->node_stack == NULL ||
       
   700       parser->signal ||
       
   701       parser->property ||
       
   702       parser->in_annotation)
       
   703     {
       
   704       g_set_error (error, G_MARKUP_ERROR,
       
   705                    G_MARKUP_ERROR_PARSE,
       
   706                    _("Can't put <%s> element here"),
       
   707                    element_name);
       
   708       return FALSE;      
       
   709     }
       
   710 
       
   711   name = NULL;
       
   712   if (!locate_attributes (element_name, attribute_names,
       
   713                           attribute_values, error,
       
   714                           "name", &name,
       
   715                           "value", &value,
       
   716                           NULL))
       
   717     return FALSE;
       
   718 
       
   719   if (name == NULL)
       
   720     {
       
   721       g_set_error (error, G_MARKUP_ERROR,
       
   722                    G_MARKUP_ERROR_PARSE,
       
   723                    _("\"%s\" attribute required on <%s> element "),
       
   724                    "name", element_name);
       
   725       return FALSE;
       
   726     }
       
   727   if (value == NULL)
       
   728     {
       
   729       g_set_error (error, G_MARKUP_ERROR,
       
   730                    G_MARKUP_ERROR_PARSE,
       
   731                    _("\"%s\" attribute required on <%s> element "),
       
   732                    "value", element_name);
       
   733       return FALSE;
       
   734     }
       
   735 
       
   736   if (parser->arg)
       
   737     arg_info_add_annotation (parser->arg, name, value);
       
   738   else if (parser->method)
       
   739     method_info_add_annotation (parser->method, name, value);
       
   740   else if (parser->interface)
       
   741     interface_info_add_annotation (parser->interface, name, value);
       
   742   else
       
   743     g_assert_not_reached ();
       
   744 
       
   745   parser->in_annotation = TRUE;
       
   746 
       
   747   return TRUE;
       
   748 }
       
   749 
       
   750 gboolean
       
   751 parser_start_element (Parser      *parser,
       
   752                       const char  *element_name,
       
   753                       const char **attribute_names,
       
   754                       const char **attribute_values,
       
   755                       GError     **error)
       
   756 {
       
   757   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
       
   758 
       
   759   if (ELEMENT_IS ("node"))
       
   760     {
       
   761       if (!parse_node (parser, element_name, attribute_names,
       
   762                        attribute_values, error))
       
   763         return FALSE;
       
   764     }
       
   765   else if (ELEMENT_IS ("interface"))
       
   766     {
       
   767       if (!parse_interface (parser, element_name, attribute_names,
       
   768                             attribute_values, error))
       
   769         return FALSE;
       
   770     }
       
   771   else if (ELEMENT_IS ("method"))
       
   772     {
       
   773       if (!parse_method (parser, element_name, attribute_names,
       
   774                          attribute_values, error))
       
   775         return FALSE;
       
   776     }
       
   777   else if (ELEMENT_IS ("signal"))
       
   778     {
       
   779       if (!parse_signal (parser, element_name, attribute_names,
       
   780                          attribute_values, error))
       
   781         return FALSE;
       
   782     }
       
   783   else if (ELEMENT_IS ("property"))
       
   784     {
       
   785       if (!parse_property (parser, element_name, attribute_names,
       
   786                            attribute_values, error))
       
   787         return FALSE;
       
   788     }
       
   789   else if (ELEMENT_IS ("arg"))
       
   790     {
       
   791       if (!parse_arg (parser, element_name, attribute_names,
       
   792                       attribute_values, error))
       
   793         return FALSE;
       
   794     }
       
   795   else if (ELEMENT_IS ("annotation"))
       
   796     {
       
   797       if (!parse_annotation (parser, element_name, attribute_names,
       
   798 			     attribute_values, error))
       
   799         return FALSE;
       
   800     }
       
   801   else
       
   802     {
       
   803       g_set_error (error, G_MARKUP_ERROR,
       
   804                    G_MARKUP_ERROR_PARSE,
       
   805                    _("Element <%s> not recognized"),
       
   806                    element_name);
       
   807     }
       
   808   
       
   809   return TRUE;
       
   810 }
       
   811 
       
   812 gboolean
       
   813 parser_end_element (Parser      *parser,
       
   814                     const char  *element_name,
       
   815                     GError     **error)
       
   816 {
       
   817   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
       
   818 
       
   819   if (ELEMENT_IS ("interface"))
       
   820     {
       
   821       parser->interface = NULL;
       
   822     }
       
   823   else if (ELEMENT_IS ("method"))
       
   824     {
       
   825       parser->method = NULL;
       
   826     }
       
   827   else if (ELEMENT_IS ("signal"))
       
   828     {
       
   829       parser->signal = NULL;
       
   830     }
       
   831   else if (ELEMENT_IS ("property"))
       
   832     {
       
   833       parser->property = NULL;
       
   834     }
       
   835   else if (ELEMENT_IS ("arg"))
       
   836     {
       
   837       parser->arg = NULL;
       
   838     }
       
   839   else if (ELEMENT_IS ("annotation"))
       
   840     {
       
   841       parser->in_annotation = FALSE;
       
   842     }
       
   843   else if (ELEMENT_IS ("node"))
       
   844     {
       
   845       NodeInfo *top;
       
   846 
       
   847       g_assert (parser->node_stack != NULL);
       
   848       top = parser->node_stack->data;
       
   849 
       
   850       parser->node_stack = g_slist_remove (parser->node_stack,
       
   851                                            top);
       
   852 
       
   853       if (parser->node_stack == NULL)
       
   854         parser->result = top; /* We are done, store the result */      
       
   855     }
       
   856   else
       
   857     g_assert_not_reached (); /* should have had an error on start_element */
       
   858   
       
   859   return TRUE;
       
   860 }
       
   861 
       
   862 gboolean
       
   863 parser_content (Parser      *parser,
       
   864                 const char  *content,
       
   865                 int          len,
       
   866                 GError     **error)
       
   867 {
       
   868   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
       
   869 
       
   870   /* FIXME check that it's all whitespace */
       
   871   
       
   872   return TRUE;
       
   873 }
       
   874 
       
   875 gboolean
       
   876 parser_finished (Parser      *parser,
       
   877                  GError     **error)
       
   878 {
       
   879   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
       
   880 
       
   881   return TRUE;
       
   882 }
       
   883 
       
   884 NodeInfo*
       
   885 parser_get_nodes (Parser *parser)
       
   886 {
       
   887   return parser->result;
       
   888 }
       
   889 
       
   890 #endif /* DOXYGEN_SHOULD_SKIP_THIS */