00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "dbus-gparser.h"
00024
#include "dbus-gidl.h"
00025
#include <string.h>
00026
00027
#include <libintl.h>
00028
#define _(x) gettext ((x))
00029
#define N_(x) x
00030
00031
#ifndef DOXYGEN_SHOULD_SKIP_THIS
00032
00033
#define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0)
00034
00035
typedef struct
00036
{
00037
const char *name;
00038
const char **retloc;
00039 } LocateAttr;
00040
00041
static gboolean
00042 locate_attributes (
const char *element_name,
00043
const char **attribute_names,
00044
const char **attribute_values,
00045 GError **error,
00046
const char *first_attribute_name,
00047
const char **first_attribute_retloc,
00048 ...)
00049 {
00050 va_list args;
00051
const char *name;
00052
const char **retloc;
00053
int n_attrs;
00054
#define MAX_ATTRS 24
00055
LocateAttr attrs[MAX_ATTRS];
00056 gboolean retval;
00057
int i;
00058
00059 g_return_val_if_fail (first_attribute_name != NULL, FALSE);
00060 g_return_val_if_fail (first_attribute_retloc != NULL, FALSE);
00061
00062 retval =
TRUE;
00063
00064 n_attrs = 1;
00065 attrs[0].name = first_attribute_name;
00066 attrs[0].retloc = first_attribute_retloc;
00067 *first_attribute_retloc =
NULL;
00068
00069 va_start (args, first_attribute_retloc);
00070
00071 name = va_arg (args,
const char*);
00072 retloc = va_arg (args,
const char**);
00073
00074
while (name !=
NULL)
00075 {
00076 g_return_val_if_fail (retloc != NULL, FALSE);
00077
00078 g_assert (n_attrs < MAX_ATTRS);
00079
00080 attrs[n_attrs].name = name;
00081 attrs[n_attrs].retloc = retloc;
00082 n_attrs += 1;
00083 *retloc =
NULL;
00084
00085 name = va_arg (args,
const char*);
00086 retloc = va_arg (args,
const char**);
00087 }
00088
00089 va_end (args);
00090
00091
if (!retval)
00092
return retval;
00093
00094 i = 0;
00095
while (attribute_names[i])
00096 {
00097
int j;
00098 gboolean found;
00099
00100 found =
FALSE;
00101 j = 0;
00102
while (j < n_attrs)
00103 {
00104
if (strcmp (attrs[j].name, attribute_names[i]) == 0)
00105 {
00106 retloc = attrs[j].retloc;
00107
00108
if (*retloc !=
NULL)
00109 {
00110 g_set_error (error,
00111 G_MARKUP_ERROR,
00112 G_MARKUP_ERROR_PARSE,
00113 _(
"Attribute \"%s\" repeated twice on the same <%s> element"),
00114 attrs[j].name, element_name);
00115 retval =
FALSE;
00116
goto out;
00117 }
00118
00119 *retloc = attribute_values[i];
00120 found =
TRUE;
00121 }
00122
00123 ++j;
00124 }
00125
00126
if (!found)
00127 {
00128 g_set_error (error,
00129 G_MARKUP_ERROR,
00130 G_MARKUP_ERROR_PARSE,
00131 _(
"Attribute \"%s\" is invalid on <%s> element in this context"),
00132 attribute_names[i], element_name);
00133 retval =
FALSE;
00134
goto out;
00135 }
00136
00137 ++i;
00138 }
00139
00140 out:
00141
return retval;
00142 }
00143
00144
static gboolean
00145 check_no_attributes (
const char *element_name,
00146
const char **attribute_names,
00147
const char **attribute_values,
00148 GError **error)
00149 {
00150
if (attribute_names[0] !=
NULL)
00151 {
00152 g_set_error (error,
00153 G_MARKUP_ERROR,
00154 G_MARKUP_ERROR_PARSE,
00155 _(
"Attribute \"%s\" is invalid on <%s> element in this context"),
00156 attribute_names[0], element_name);
00157
return FALSE;
00158 }
00159
00160
return TRUE;
00161 }
00162
00163
struct Parser
00164 {
00165
int refcount;
00166
00167 NodeInfo *result;
00168 GSList *node_stack;
00169 InterfaceInfo *interface;
00170 MethodInfo *method;
00171 SignalInfo *signal;
00172 ArgInfo *arg;
00173 };
00174
00175 Parser*
00176 parser_new (
void)
00177 {
00178 Parser *parser;
00179
00180 parser = g_new0 (Parser, 1);
00181
00182 parser->refcount = 1;
00183
00184
return parser;
00185 }
00186
00187 Parser *
00188 parser_ref (Parser *parser)
00189 {
00190 parser->refcount += 1;
00191
00192
return parser;
00193 }
00194
00195
void
00196 parser_unref (Parser *parser)
00197 {
00198 parser->refcount -= 1;
00199
if (parser->refcount == 0)
00200 {
00201
if (parser->result)
00202 node_info_unref (parser->result);
00203
00204 g_free (parser);
00205 }
00206 }
00207
00208 gboolean
00209 parser_check_doctype (Parser *parser,
00210
const char *doctype,
00211 GError **error)
00212 {
00213 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
00214
00215
if (strcmp (doctype,
"node") != 0)
00216 {
00217 g_set_error (error,
00218 G_MARKUP_ERROR,
00219 G_MARKUP_ERROR_PARSE,
00220
"D-BUS description file has the wrong document type %s, use node or interface",
00221 doctype);
00222
return FALSE;
00223 }
00224
else
00225
return TRUE;
00226 }
00227
00228
static gboolean
00229 parse_node (Parser *parser,
00230
const char *element_name,
00231
const char **attribute_names,
00232
const char **attribute_values,
00233 GError **error)
00234 {
00235
const char *name;
00236 NodeInfo *node;
00237
00238
if (parser->interface ||
00239 parser->method ||
00240 parser->signal ||
00241 parser->arg)
00242 {
00243 g_set_error (error, G_MARKUP_ERROR,
00244 G_MARKUP_ERROR_PARSE,
00245 _(
"Can't put a <%s> element here"),
00246 element_name);
00247
return FALSE;
00248 }
00249
00250 name =
NULL;
00251
if (!locate_attributes (element_name, attribute_names,
00252 attribute_values, error,
00253
"name", &name,
00254 NULL))
00255
return FALSE;
00256
00257
00258
if (parser->node_stack !=
NULL && name ==
NULL)
00259 {
00260 g_set_error (error, G_MARKUP_ERROR,
00261 G_MARKUP_ERROR_PARSE,
00262 _(
"\"%s\" attribute required on <%s> element "),
00263
"name", element_name);
00264
return FALSE;
00265 }
00266
00267
00268 node = node_info_new (name);
00269
00270
if (parser->node_stack !=
NULL)
00271 {
00272 node_info_add_node (parser->node_stack->data,
00273 node);
00274 }
00275
00276 parser->node_stack = g_slist_prepend (parser->node_stack,
00277 node);
00278
00279
return TRUE;
00280 }
00281
00282
static gboolean
00283 parse_interface (Parser *parser,
00284
const char *element_name,
00285
const char **attribute_names,
00286
const char **attribute_values,
00287 GError **error)
00288 {
00289
const char *name;
00290 InterfaceInfo *iface;
00291 NodeInfo *top;
00292
00293
if (parser->interface ||
00294 parser->method ||
00295 parser->signal ||
00296 parser->arg ||
00297 (parser->node_stack ==
NULL))
00298 {
00299 g_set_error (error, G_MARKUP_ERROR,
00300 G_MARKUP_ERROR_PARSE,
00301 _(
"Can't put a <%s> element here"),
00302 element_name);
00303
return FALSE;
00304 }
00305
00306 name =
NULL;
00307
if (!locate_attributes (element_name, attribute_names,
00308 attribute_values, error,
00309
"name", &name,
00310 NULL))
00311
return FALSE;
00312
00313
if (name ==
NULL)
00314 {
00315 g_set_error (error, G_MARKUP_ERROR,
00316 G_MARKUP_ERROR_PARSE,
00317 _(
"\"%s\" attribute required on <%s> element "),
00318
"name", element_name);
00319
return FALSE;
00320 }
00321
00322 top = parser->node_stack->data;
00323
00324 iface = interface_info_new (name);
00325 node_info_add_interface (top, iface);
00326 interface_info_unref (iface);
00327
00328 parser->interface = iface;
00329
00330
return TRUE;
00331 }
00332
00333
static gboolean
00334 parse_method (Parser *parser,
00335
const char *element_name,
00336
const char **attribute_names,
00337
const char **attribute_values,
00338 GError **error)
00339 {
00340
const char *name;
00341 MethodInfo *method;
00342 NodeInfo *top;
00343
00344
if (parser->interface ==
NULL ||
00345 parser->node_stack ==
NULL ||
00346 parser->method ||
00347 parser->signal ||
00348 parser->arg)
00349 {
00350 g_set_error (error, G_MARKUP_ERROR,
00351 G_MARKUP_ERROR_PARSE,
00352 _(
"Can't put a <%s> element here"),
00353 element_name);
00354
return FALSE;
00355 }
00356
00357 name =
NULL;
00358
if (!locate_attributes (element_name, attribute_names,
00359 attribute_values, error,
00360
"name", &name,
00361 NULL))
00362
return FALSE;
00363
00364
if (name ==
NULL)
00365 {
00366 g_set_error (error, G_MARKUP_ERROR,
00367 G_MARKUP_ERROR_PARSE,
00368 _(
"\"%s\" attribute required on <%s> element "),
00369
"name", element_name);
00370
return FALSE;
00371 }
00372
00373 top = parser->node_stack->data;
00374
00375 method = method_info_new (name);
00376 interface_info_add_method (parser->interface, method);
00377 method_info_unref (method);
00378
00379 parser->method = method;
00380
00381
return TRUE;
00382 }
00383
00384
static gboolean
00385 parse_signal (Parser *parser,
00386
const char *element_name,
00387
const char **attribute_names,
00388
const char **attribute_values,
00389 GError **error)
00390 {
00391
const char *name;
00392 SignalInfo *signal;
00393 NodeInfo *top;
00394
00395
if (parser->interface ==
NULL ||
00396 parser->node_stack ==
NULL ||
00397 parser->signal ||
00398 parser->signal ||
00399 parser->arg)
00400 {
00401 g_set_error (error, G_MARKUP_ERROR,
00402 G_MARKUP_ERROR_PARSE,
00403 _(
"Can't put a <%s> element here"),
00404 element_name);
00405
return FALSE;
00406 }
00407
00408 name =
NULL;
00409
if (!locate_attributes (element_name, attribute_names,
00410 attribute_values, error,
00411
"name", &name,
00412 NULL))
00413
return FALSE;
00414
00415
if (name ==
NULL)
00416 {
00417 g_set_error (error, G_MARKUP_ERROR,
00418 G_MARKUP_ERROR_PARSE,
00419 _(
"\"%s\" attribute required on <%s> element "),
00420
"name", element_name);
00421
return FALSE;
00422 }
00423
00424 top = parser->node_stack->data;
00425
00426 signal = signal_info_new (name);
00427 interface_info_add_signal (parser->interface, signal);
00428 signal_info_unref (signal);
00429
00430 parser->signal = signal;
00431
00432
return TRUE;
00433 }
00434
00435
static int
00436 basic_type_from_string (
const char *str)
00437 {
00438
if (strcmp (str,
"string") == 0)
00439
return DBUS_TYPE_STRING;
00440
else if (strcmp (str,
"int32") == 0)
00441
return DBUS_TYPE_INT32;
00442
else if (strcmp (str,
"uint32") == 0)
00443
return DBUS_TYPE_UINT32;
00444
else if (strcmp (str,
"int64") == 0)
00445
return DBUS_TYPE_INT64;
00446
else if (strcmp (str,
"uint64") == 0)
00447
return DBUS_TYPE_UINT64;
00448
else if (strcmp (str,
"double") == 0)
00449
return DBUS_TYPE_DOUBLE;
00450
else if (strcmp (str,
"byte") == 0)
00451
return DBUS_TYPE_BYTE;
00452
else if (strcmp (str,
"boolean") == 0)
00453
return DBUS_TYPE_BOOLEAN;
00454
else if (strcmp (str,
"byte") == 0)
00455
return DBUS_TYPE_BYTE;
00456
else if (strcmp (str,
"object") == 0)
00457
return DBUS_TYPE_OBJECT_PATH;
00458
else
00459
return DBUS_TYPE_INVALID;
00460 }
00461
00462
static int
00463 type_from_string (
const char *str)
00464 {
00465
return basic_type_from_string (str);
00466 }
00467
00468
static gboolean
00469 parse_arg (Parser *parser,
00470
const char *element_name,
00471
const char **attribute_names,
00472
const char **attribute_values,
00473 GError **error)
00474 {
00475
const char *name;
00476
const char *type;
00477
const char *direction;
00478 ArgDirection dir;
00479
int t;
00480 ArgInfo *arg;
00481
00482
if (!(parser->method || parser->signal) ||
00483 parser->node_stack ==
NULL ||
00484 parser->arg)
00485 {
00486 g_set_error (error, G_MARKUP_ERROR,
00487 G_MARKUP_ERROR_PARSE,
00488 _(
"Can't put a <%s> element here"),
00489 element_name);
00490
return FALSE;
00491 }
00492
00493 name =
NULL;
00494
if (!locate_attributes (element_name, attribute_names,
00495 attribute_values, error,
00496
"name", &name,
00497
"type", &type,
00498
"direction", &direction,
00499 NULL))
00500
return FALSE;
00501
00502
00503
00504
if (type ==
NULL)
00505 {
00506 g_set_error (error, G_MARKUP_ERROR,
00507 G_MARKUP_ERROR_PARSE,
00508 _(
"\"%s\" attribute required on <%s> element "),
00509
"type", element_name);
00510
return FALSE;
00511 }
00512
00513
if (direction ==
NULL)
00514 {
00515
00516
if (parser->method)
00517 direction =
"in";
00518
else if (parser->signal)
00519 direction =
"out";
00520
else
00521 g_assert_not_reached ();
00522 }
00523
00524
if (strcmp (direction,
"in") == 0)
00525 dir = ARG_IN;
00526
else if (strcmp (direction,
"out") == 0)
00527 dir = ARG_OUT;
00528
else
00529 {
00530 g_set_error (error, G_MARKUP_ERROR,
00531 G_MARKUP_ERROR_PARSE,
00532 _(
"\"%s\" attribute on <%s> has value \"in\" or \"out\""),
00533
"direction", element_name);
00534
return FALSE;
00535 }
00536
00537 t = type_from_string (type);
00538
00539 arg = arg_info_new (name, dir, t);
00540
if (parser->method)
00541 method_info_add_arg (parser->method, arg);
00542
else if (parser->signal)
00543 signal_info_add_arg (parser->signal, arg);
00544
else
00545 g_assert_not_reached ();
00546
00547 arg_info_unref (arg);
00548
00549 parser->arg = arg;
00550
00551
return TRUE;
00552 }
00553
00554 gboolean
00555 parser_start_element (Parser *parser,
00556
const char *element_name,
00557
const char **attribute_names,
00558
const char **attribute_values,
00559 GError **error)
00560 {
00561 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
00562
00563
if (ELEMENT_IS (
"node"))
00564 {
00565
if (!parse_node (parser, element_name, attribute_names,
00566 attribute_values, error))
00567
return FALSE;
00568 }
00569
else if (ELEMENT_IS (
"interface"))
00570 {
00571
if (!parse_interface (parser, element_name, attribute_names,
00572 attribute_values, error))
00573
return FALSE;
00574 }
00575
else if (ELEMENT_IS (
"method"))
00576 {
00577
if (!parse_method (parser, element_name, attribute_names,
00578 attribute_values, error))
00579
return FALSE;
00580 }
00581
else if (ELEMENT_IS (
"signal"))
00582 {
00583
if (!parse_signal (parser, element_name, attribute_names,
00584 attribute_values, error))
00585
return FALSE;
00586 }
00587
else if (ELEMENT_IS (
"arg"))
00588 {
00589
if (!parse_arg (parser, element_name, attribute_names,
00590 attribute_values, error))
00591
return FALSE;
00592 }
00593
else
00594 {
00595 g_set_error (error, G_MARKUP_ERROR,
00596 G_MARKUP_ERROR_PARSE,
00597 _(
"Element <%s> not recognized"),
00598 element_name);
00599 }
00600
00601
return TRUE;
00602 }
00603
00604 gboolean
00605 parser_end_element (Parser *parser,
00606
const char *element_name,
00607 GError **error)
00608 {
00609 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
00610
00611
if (ELEMENT_IS (
"interface"))
00612 {
00613 parser->interface =
NULL;
00614 }
00615
else if (ELEMENT_IS (
"method"))
00616 {
00617 parser->method =
NULL;
00618 }
00619
else if (ELEMENT_IS (
"signal"))
00620 {
00621 parser->signal =
NULL;
00622 }
00623
else if (ELEMENT_IS (
"arg"))
00624 {
00625 parser->arg =
NULL;
00626 }
00627
else if (ELEMENT_IS (
"node"))
00628 {
00629 NodeInfo *top;
00630
00631 g_assert (parser->node_stack != NULL);
00632 top = parser->node_stack->data;
00633
00634 parser->node_stack = g_slist_remove (parser->node_stack,
00635 top);
00636
00637
if (parser->node_stack ==
NULL)
00638 parser->result = top;
00639 }
00640
else
00641 g_assert_not_reached ();
00642
00643
return TRUE;
00644 }
00645
00646 gboolean
00647 parser_content (Parser *parser,
00648
const char *content,
00649
int len,
00650 GError **error)
00651 {
00652 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
00653
00654
return TRUE;
00655 }
00656
00657 gboolean
00658 parser_finished (Parser *parser,
00659 GError **error)
00660 {
00661 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
00662
00663
return TRUE;
00664 }
00665
00666 NodeInfo*
00667 parser_get_nodes (Parser *parser)
00668 {
00669
return parser->result;
00670 }
00671
00672
#endif