3
* demarshal.c - type demarshalling
5
* Copyright © 2009 Scott James Remnant <scott@netsplit.com>.
6
* Copyright © 2009 Canonical Ltd.
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2, as
10
* published by the Free Software Foundation.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License along
18
* with this program; if not, write to the Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
#endif /* HAVE_CONFIG_H */
27
#include <dbus/dbus.h>
31
#include <nih/macros.h>
32
#include <nih/alloc.h>
34
#include <nih/string.h>
35
#include <nih/logging.h>
40
#include "demarshal.h"
43
/* Prototypes for static functions */
44
static char *demarshal_basic (const void *parent,
45
DBusSignatureIter *iter,
46
const char *parent_name,
47
const char *iter_name, const char *name,
48
const char *oom_error_code,
49
const char *type_error_code,
50
NihList *outputs, NihList *locals,
51
const char *prefix, const char *interface_symbol,
52
const char *member_symbol, const char *symbol,
54
__attribute__ ((warn_unused_result, malloc));
55
static char *demarshal_array (const void *parent,
56
DBusSignatureIter *iter,
57
const char *parent_name,
58
const char *iter_name, const char *name,
59
const char *oom_error_code,
60
const char *type_error_code,
61
NihList *outputs, NihList *locals,
62
const char *prefix, const char *interface_symbol,
63
const char *member_symbol, const char *symbol,
65
__attribute__ ((warn_unused_result, malloc));
66
static char *demarshal_struct (const void *parent,
67
DBusSignatureIter *iter,
68
const char *parent_name,
69
const char *iter_name, const char *name,
70
const char *oom_error_code,
71
const char *type_error_code,
72
NihList *outputs, NihList *locals,
73
const char *prefix, const char *interface_symbol,
74
const char *member_symbol, const char *symbol,
76
__attribute__ ((warn_unused_result, malloc));
81
* @parent: parent object for new string,
82
* @signature: signature of type,
83
* @parent_name: name of parent variable,
84
* @iter_name: name of iterator variable,
85
* @name: name of variable,
86
* @oom_error_code: code to execute on OOM Error,
87
* @type_error_code: code to exectute on type error,
88
* @outputs: list to append output variables to,
89
* @locals: list to append local variables to,
90
* @interface_symbol: symbol of interface for structure names,
91
* @member_symbol: symbol of interface member for structure names,
92
* @symbol: symbol of argument or variable for structure names,
93
* @structs: list to append structure definitions to.
95
* Generates C code to demarshal any D-Bus type from the D-Bus iterator
96
* variable named @iter_name into an appropriately typed variable named
99
* The type should be the current element of the signature iterator @iter.
100
* This then simply calls demarshal_fixed(), demarshal_string(),
101
* demarshal_fixed_array(), demarshal_flexible_array() or demarshal_struct()
104
* The generated code detects out-of-memory conditions but does not know
105
* how to handle them, therefore you need to pass the appropriate handling
106
* code in @oom_error_code. This code will be inserted wherever an OOM
107
* condition is detected.
109
* Likewise the code detects an invalid type in the iterator, but requires
110
* that you pass the appropriate handling code in @type_error_code.
112
* The expected output variable types and names are given as TypeVar objects
113
* appended to the @outputs list, each name is guaranteed to begin with @name
114
* and the first member will always be @name itself. Should the C code
115
* require local variables, similar TypeVar objects will be appended to
118
* If the variable requires a structure to be defined, the definition is
119
* returned as a TypeStruct object appended to the @structs list. The name
120
* is generated from @prefix, @interface_symbol, @member_symbol and @symbol.
122
* If @parent is not NULL, it should be a pointer to another object which
123
* will be used as a parent for the returned string. When all parents
124
* of the returned string are freed, the returned string will also be
127
* Demarshalling may require that memory is allocated, the parent object
128
* is the variable named in @parent_name which may of course be "NULL".
130
* Returns: newly allocated string or NULL if insufficient memory.
133
demarshal (const void * parent,
134
DBusSignatureIter *iter,
135
const char * parent_name,
136
const char * iter_name,
138
const char * oom_error_code,
139
const char * type_error_code,
143
const char * interface_symbol,
144
const char * member_symbol,
150
nih_assert (iter != NULL);
151
nih_assert (parent_name != NULL);
152
nih_assert (iter_name != NULL);
153
nih_assert (name != NULL);
154
nih_assert (oom_error_code != NULL);
155
nih_assert (type_error_code != NULL);
156
nih_assert (outputs != NULL);
157
nih_assert (locals != NULL);
158
nih_assert (prefix != NULL);
159
nih_assert (member_symbol != NULL);
160
nih_assert (structs != NULL);
162
dbus_type = dbus_signature_iter_get_current_type (iter);
164
if (dbus_type_is_basic (dbus_type)) {
165
return demarshal_basic (parent, iter,
168
oom_error_code, type_error_code,
170
prefix, interface_symbol,
171
member_symbol, symbol,
173
} else if (dbus_type == DBUS_TYPE_ARRAY) {
174
return demarshal_array (parent, iter,
180
prefix, interface_symbol,
181
member_symbol, symbol,
183
} else if ((dbus_type == DBUS_TYPE_STRUCT)
184
|| (dbus_type == DBUS_TYPE_DICT_ENTRY)) {
185
return demarshal_struct (parent, iter,
188
oom_error_code, type_error_code,
190
prefix, interface_symbol,
191
member_symbol, symbol,
194
nih_assert_not_reached ();
201
* @parent: parent object for new string,
202
* @iter: D-Bus signature iterator,
203
* @parent_name: name of parent variable,
204
* @name: name of variable,
205
* @oom_error_code: code to execute on OOM Error,
206
* @type_error_code: code to exectute on type error,
207
* @outputs: list to append output variables to,
208
* @locals: list to append local variables to,
209
* @interface_symbol: symbol of interface for structure names,
210
* @member_symbol: symbol of interface member for structure names,
211
* @symbol: symbol of argument or variable for structure names,
212
* @structs: list to append structure definitions to.
214
* Generates C code to demarshal a D-Bus basic type (ie. numerics and
215
* strings) from the D-Bus iterator variable named @iter_name into an
216
* appropriately typed variable pointer named @name.
218
* The type should be the current element of the signature iterator @iter.
220
* The generated code detects out-of-memory conditions but does not know
221
* how to handle them, therefore you need to pass the appropriate handling
222
* code in @oom_error_code. This code will be inserted wherever an OOM
223
* condition is detected.
225
* Likewise the code detects an invalid type in the iterator, but requires
226
* that you pass the appropriate handling code in @type_error_code.
228
* The expected output variable types and names are given as TypeVar objects
229
* appended to the @outputs list, each name is guaranteed to begin with @name
230
* and the first member will always be @name itself. Should the C code
231
* require local variables, similar TypeVar objects will be appended to
234
* If the variable requires a structure to be defined, the definition is
235
* returned as a TypeStruct object appended to the @structs list. The name
236
* is generated from @prefix, @interface_symbol, @member_symbol and @symbol.
238
* If @parent is not NULL, it should be a pointer to another object which
239
* will be used as a parent for the returned string. When all parents
240
* of the returned string are freed, the returned string will also be
243
* Demarshalling may require that memory is allocated, the parent object
244
* is the variable named in @parent_name which may of course be "NULL".
246
* Returns: newly allocated string or NULL if insufficient memory.
249
demarshal_basic (const void * parent,
250
DBusSignatureIter *iter,
251
const char * parent_name,
252
const char * iter_name,
254
const char * oom_error_code,
255
const char * type_error_code,
259
const char * interface_symbol,
260
const char * member_symbol,
265
const char * dbus_const;
266
nih_local char *oom_error_block = NULL;
267
nih_local char *type_error_block = NULL;
268
nih_local char *c_type = NULL;
272
nih_assert (iter != NULL);
273
nih_assert (parent_name != NULL);
274
nih_assert (iter_name != NULL);
275
nih_assert (name != NULL);
276
nih_assert (oom_error_code != NULL);
277
nih_assert (type_error_code != NULL);
278
nih_assert (outputs != NULL);
279
nih_assert (locals != NULL);
280
nih_assert (prefix != NULL);
281
nih_assert (member_symbol != NULL);
282
nih_assert (structs != NULL);
284
dbus_type = dbus_signature_iter_get_current_type (iter);
285
dbus_const = type_const (dbus_type);
287
oom_error_block = nih_strdup (NULL, oom_error_code);
288
if (! oom_error_block)
290
if (! indent (&oom_error_block, NULL, 1))
293
type_error_block = nih_strdup (NULL, type_error_code);
294
if (! type_error_block)
296
if (! indent (&type_error_block, NULL, 1))
299
c_type = type_of (NULL, iter);
303
if (! nih_strcat_sprintf (&code, parent,
304
"/* Demarshal a %s from the message */\n"
305
"if (dbus_message_iter_get_arg_type (&%s) != %s) {\n"
310
iter_name, dbus_const,
314
if (dbus_type_is_fixed (dbus_type)) {
315
if (! nih_strcat_sprintf (&code, parent,
316
"dbus_message_iter_get_basic (&%s, &%s);\n"
323
nih_local char *local_name = NULL;
324
nih_local char *local_type = NULL;
326
/* We need a local variable to store the const value we get
327
* from D-Bus before we allocate the copy that we return.
329
local_name = nih_sprintf (NULL, "%s_dbus", name);
335
local_type = nih_strdup (NULL, c_type);
341
if (! type_to_const (&local_type, NULL)) {
346
if (! nih_strcat_sprintf (&code, parent,
347
"dbus_message_iter_get_basic (&%s, &%s);\n"
349
"%s = nih_strdup (%s, %s);\n"
354
iter_name, local_name,
355
name, parent_name, local_name,
362
var = type_var_new (code, local_type, local_name);
368
nih_list_add (locals, &var->entry);
371
if (! nih_strcat_sprintf (&code, parent,
372
"dbus_message_iter_next (&%s);\n",
378
/* Append our required output variable */
379
var = type_var_new (code, c_type, name);
385
nih_list_add (outputs, &var->entry);
393
* @parent: parent object for new string,
394
* @iter: D-Bus signature iterator,
395
* @parent_name: name of parent variable,
396
* @name: name of variable,
397
* @oom_error_code: code to execute on OOM Error,
398
* @type_error_code: code to exectute on type error,
399
* @outputs: list to append output variables to,
400
* @locals: list to append local variables to,
401
* @interface_symbol: symbol of interface for structure names,
402
* @member_symbol: symbol of interface member for structure names,
403
* @symbol: symbol of argument or variable for structure names,
404
* @structs: list to append structure definitions to.
406
* Generates C code to demarshal a D-Bus array type from the D-Bus
407
* iterator variable named @iter_name into an appropriately typed,
408
* NULL-terminated, array variable pointer named @name. In the case
409
* of arrays (of any number of levels) ultimately to a fixed type, an
410
* additional input named "@name"_len is required of size_t type or an
411
* appropriate number of pointers to it.
413
* The type should be the current element of the signature iterator @iter.
415
* The generated code detects out-of-memory conditions but does not know
416
* how to handle them, therefore you need to pass the appropriate handling
417
* code in @oom_error_code. This code will be inserted wherever an OOM
418
* condition is detected.
420
* Likewise the code detects an invalid type in the iterator, but requires
421
* that you pass the appropriate handling code in @type_error_code.
423
* The expected output variable types and names are given as TypeVar objects
424
* appended to the @outputs list, each name is guaranteed to begin with @name
425
* and the first member will always be @name itself. Should the C code
426
* require local variables, similar TypeVar objects will be appended to
429
* If the variable requires a structure to be defined, the definition is
430
* returned as a TypeStruct object appended to the @structs list. The name
431
* is generated from @prefix, @interface_symbol, @member_symbol and @symbol.
433
* If @parent is not NULL, it should be a pointer to another object which
434
* will be used as a parent for the returned string. When all parents
435
* of the returned string are freed, the returned string will also be
438
* Demarshalling may require that memory is allocated, the parent object
439
* is the variable named in @parent_name which may of course be "NULL".
441
* Returns: newly allocated string or NULL if insufficient memory.
444
demarshal_array (const void * parent,
445
DBusSignatureIter *iter,
446
const char * parent_name,
447
const char * iter_name,
449
const char * oom_error_code,
450
const char * type_error_code,
454
const char * interface_symbol,
455
const char * member_symbol,
459
nih_local char * array_iter_name = NULL;
460
nih_local char * element_name = NULL;
461
nih_local char * element_symbol = NULL;
462
nih_local char * size_name = NULL;
463
nih_local char * oom_error_block = NULL;
464
nih_local char * child_oom_error_code = NULL;
465
nih_local char * child_oom_error_block = NULL;
466
nih_local char * type_error_block = NULL;
467
nih_local char * child_type_error_code = NULL;
468
nih_local char * child_type_error_block = NULL;
469
DBusSignatureIter subiter;
472
TypeVar * array_iter_var;
474
NihList element_outputs;
475
NihList element_locals;
476
NihList element_structs;
477
nih_local char * element_block = NULL;
478
nih_local char * alloc_block = NULL;
479
nih_local char * block = NULL;
480
nih_local char * vars_block = NULL;
482
nih_assert (iter != NULL);
483
nih_assert (parent_name != NULL);
484
nih_assert (iter_name != NULL);
485
nih_assert (name != NULL);
486
nih_assert (oom_error_code != NULL);
487
nih_assert (outputs != NULL);
488
nih_assert (locals != NULL);
489
nih_assert (prefix != NULL);
490
nih_assert (member_symbol != NULL);
491
nih_assert (structs != NULL);
493
dbus_signature_iter_recurse (iter, &subiter);
494
element_type = dbus_signature_iter_get_current_type (&subiter);
496
array_iter_name = nih_sprintf (NULL, "%s_iter", name);
497
if (! array_iter_name)
500
element_name = nih_sprintf (NULL, "%s_element", name);
504
element_symbol = (symbol
505
? nih_sprintf (NULL, "%s_element", symbol)
506
: nih_strdup (NULL, "element"));
507
if (! element_symbol)
510
if (dbus_type_is_fixed (element_type)) {
511
size_name = nih_sprintf (NULL, "%s_len", name);
515
size_name = nih_sprintf (NULL, "%s_size", name);
520
oom_error_block = nih_strdup (NULL, oom_error_code);
521
if (! oom_error_block)
523
if (! indent (&oom_error_block, NULL, 1))
526
child_oom_error_code = nih_sprintf (NULL, ("if (%s)\n"
529
name, name, oom_error_code);
530
if (! child_oom_error_code)
533
child_oom_error_block = nih_strdup (NULL, child_oom_error_code);
534
if (! child_oom_error_block)
536
if (! indent (&child_oom_error_block, NULL, 1))
539
type_error_block = nih_strdup (NULL, type_error_code);
540
if (! type_error_block)
542
if (! indent (&type_error_block, NULL, 1))
545
child_type_error_code = nih_sprintf (NULL, ("if (%s)\n"
548
name, name, type_error_code);
549
if (! child_type_error_code)
552
child_type_error_block = nih_strdup (NULL, child_type_error_code);
553
if (! child_type_error_block)
555
if (! indent (&child_type_error_block, NULL, 1))
558
/* Recurse into the array */
559
if (! nih_strcat_sprintf (&code, parent,
560
"/* Demarshal an array from the message */\n"
561
"if (dbus_message_iter_get_arg_type (&%s) != DBUS_TYPE_ARRAY) {\n"
565
"dbus_message_iter_recurse (&%s, &%s);\n"
569
iter_name, array_iter_name))
572
array_iter_var = type_var_new (code, "DBusMessageIter",
574
if (! array_iter_var) {
579
nih_list_add (locals, &array_iter_var->entry);
581
/* We need a variable to keep track of the array sizes for
582
* allocation; for fixed types, this is an output but for non-fixed
583
* types it's a local.
585
size_var = type_var_new (code, "size_t", size_name);
591
if (! dbus_type_is_fixed (element_type))
592
nih_list_add (locals, &size_var->entry);
595
if (! nih_strcat_sprintf (&code, parent,
602
/* Get the code that will demarshal the individual elements, and
603
* any output and local variables it needs.
605
nih_list_init (&element_outputs);
606
nih_list_init (&element_locals);
607
nih_list_init (&element_structs);
608
element_block = demarshal (NULL, &subiter,
609
name, array_iter_name, element_name,
610
child_oom_error_code,
611
child_type_error_code,
612
&element_outputs, &element_locals,
613
prefix, interface_symbol,
614
member_symbol, element_symbol,
616
if (! element_block) {
621
/* Each of the outputs of the demarshalling code equates to one
622
* of our own outputs, except that we add another level of pointers
623
* for the array; at the same time, we keep the suffix and append
624
* it to our own name.
626
* Since the outputs are all arrays, they need to be initialised
627
* or allocated before demarshalling begins. Those of fixed types
628
* simply need to be set to NULL, those of pointer types need
629
* to be allocated with a single element containing the terminating
632
* Instead of mucking around with pointers and structure members,
633
* we also append the outputs onto the local lists and fill in our
634
* variable from this.
636
NIH_LIST_FOREACH_SAFE (&element_outputs, iter) {
637
TypeVar * output_var = (TypeVar *)iter;
639
nih_local char *var_type = NULL;
641
nih_local char *var_name = NULL;
643
nih_local char *tmp_name = NULL;
644
const char * var_parent;
646
/* Output variable */
647
var_type = nih_strdup (NULL, output_var->type);
653
if (! type_to_pointer (&var_type, NULL)) {
658
nih_assert (! strncmp (output_var->name, element_name,
659
strlen (element_name)));
660
suffix = output_var->name + strlen (element_name);
662
var_name = nih_sprintf (NULL, "%s%s", name, suffix);
668
var = type_var_new (code, var_type, var_name);
674
nih_list_add (outputs, &var->entry);
676
/* For array reallocation we need yet another variable to
677
* capture the output and make sure it didn't fail, we could
678
* just cheat and use void * but instead we use the proper
679
* type which is the same as the output variable.
681
tmp_name = nih_sprintf (NULL, "%s_tmp", var_name);
687
var = type_var_new (element_block, var_type, tmp_name);
693
nih_list_add (&element_locals, &var->entry);
695
/* Code to allocate and reallocate */
696
var_parent = (*suffix ? name : parent_name);
698
if (! nih_strcat_sprintf (&code, parent,
705
ptr = output_var->type + strlen (output_var->type) - 1;
707
if (! nih_strcat_sprintf (&block, NULL,
708
"if (%s + 1 > SIZE_MAX / sizeof (%s)) {\n"
712
"%s = nih_realloc (%s, %s, sizeof (%s) * (%s + 1));\n"
720
size_name, output_var->type,
721
child_type_error_block,
722
tmp_name, var_name, var_parent, output_var->type, size_name,
724
child_oom_error_block,
726
var_name, size_name, output_var->name)) {
731
if (! nih_strcat_sprintf (&alloc_block, NULL,
732
"%s = nih_alloc (%s, sizeof (%s));\n"
739
var_name, var_parent, output_var->type,
741
(*suffix ? child_oom_error_block : oom_error_block),
742
var_name, size_name)) {
747
if (! nih_strcat_sprintf (&block, NULL,
748
"if (%s + 2 > SIZE_MAX / sizeof (%s)) {\n"
752
"%s = nih_realloc (%s, %s, sizeof (%s) * (%s + 2));\n"
759
"%s[%s + 1] = NULL;\n"
761
size_name, output_var->type,
762
child_type_error_block,
763
tmp_name, var_name, var_parent, output_var->type, size_name,
765
child_oom_error_block,
767
var_name, size_name, output_var->name,
768
var_name, size_name)) {
774
nih_list_add (&element_locals, &output_var->entry);
777
if (! nih_strcat_sprintf (&code, parent,
780
alloc_block ?: "")) {
785
if (! nih_strcat_sprintf (&block, parent,
792
vars_block = type_var_layout (NULL, &element_locals);
798
NIH_LIST_FOREACH_SAFE (&element_structs, iter) {
799
TypeStruct *structure = (TypeStruct *)iter;
801
nih_ref (structure, code);
802
nih_list_add (structs, &structure->entry);
805
/* Iterate over the incoming message */
806
if (! nih_strcat_sprintf (&code, parent,
807
"while (dbus_message_iter_get_arg_type (&%s) != DBUS_TYPE_INVALID) {\n",
813
/* Lay all that out in an indented block inside the while loop.
814
* Make sure that we increase the size of the array as we go,
815
* which varies depending on whether we are using a fixed type or
818
if (! indent (&vars_block, NULL, 1)) {
823
if (! indent (&element_block, NULL, 1)) {
828
if (! indent (&block, NULL, 1)) {
833
if (! nih_strcat_sprintf (&code, parent,
846
/* Finish off the iteration and move onto the next message item */
847
if (! nih_strcat_sprintf (&code, parent,
850
"dbus_message_iter_next (&%s);\n",
856
if (dbus_type_is_fixed (element_type))
857
nih_list_add (outputs, &size_var->entry);
865
* @parent: parent object for new string,
866
* @iter: D-Bus signature iterator,
867
* @parent_name: name of parent variable,
868
* @name: name of variable,
869
* @oom_error_code: code to execute on OOM Error,
870
* @type_error_code: code to exectute on type error,
871
* @outputs: list to append output variables to,
872
* @locals: list to append local variables to,
873
* @interface_symbol: symbol of interface for structure names,
874
* @member_symbol: symbol of interface member for structure names,
875
* @symbol: symbol of argument or variable for structure names,
876
* @structs: list to append structure definitions to.
878
* Generates C code to demarshal a D-Bus structure type, and its members,
879
* from the D-Bus iterator variable named @iter_name into an appropriately
880
* typed variable pointer named @name.
882
* The type should be the current element of the signature iterator @iter.
884
* The generated code detects out-of-memory conditions but does not know
885
* how to handle them, therefore you need to pass the appropriate handling
886
* code in @oom_error_code. This code will be inserted wherever an OOM
887
* condition is detected.
889
* Likewise the code detects an invalid type in the iterator, but requires
890
* that you pass the appropriate handling code in @type_error_code.
892
* The expected output variable types and names are given as TypeVar objects
893
* appended to the @outputs list, each name is guaranteed to begin with @name
894
* and the first member will always be @name itself. Should the C code
895
* require local variables, similar TypeVar objects will be appended to
898
* If the variable requires a structure to be defined, the definition is
899
* returned as a TypeStruct object appended to the @structs list. The name
900
* is generated from @prefix, @interface_symbol, @member_symbol and @symbol.
902
* If @parent is not NULL, it should be a pointer to another object which
903
* will be used as a parent for the returned string. When all parents
904
* of the returned string are freed, the returned string will also be
907
* Demarshalling may require that memory is allocated, the parent object
908
* is the variable named in @parent_name which may of course be "NULL".
910
* Returns: newly allocated string or NULL if insufficient memory.
913
demarshal_struct (const void * parent,
914
DBusSignatureIter *iter,
915
const char * parent_name,
916
const char * iter_name,
918
const char * oom_error_code,
919
const char * type_error_code,
923
const char * interface_symbol,
924
const char * member_symbol,
928
nih_local char * struct_iter_name = NULL;
929
nih_local char * oom_error_block = NULL;
930
nih_local char * child_oom_error_code = NULL;
931
nih_local char * child_oom_error_block = NULL;
932
nih_local char * type_error_block = NULL;
933
nih_local char * child_type_error_code = NULL;
934
nih_local char * child_type_error_block = NULL;
936
const char * dbus_const;
937
DBusSignatureIter subiter;
939
TypeVar * struct_iter_var;
940
nih_local char * c_type = NULL;
941
nih_local char * alloc_type = NULL;
942
TypeStruct * structure;
946
nih_assert (iter != NULL);
947
nih_assert (parent_name != NULL);
948
nih_assert (iter_name != NULL);
949
nih_assert (name != NULL);
950
nih_assert (oom_error_code != NULL);
951
nih_assert (type_error_code != NULL);
952
nih_assert (outputs != NULL);
953
nih_assert (locals != NULL);
954
nih_assert (prefix != NULL);
955
nih_assert (member_symbol != NULL);
956
nih_assert (structs != NULL);
958
struct_iter_name = nih_sprintf (NULL, "%s_iter", name);
959
if (! struct_iter_name)
962
oom_error_block = nih_strdup (NULL, oom_error_code);
963
if (! oom_error_block)
965
if (! indent (&oom_error_block, NULL, 1))
968
child_oom_error_code = nih_sprintf (NULL, ("nih_free (%s);\n"
970
name, oom_error_code);
971
if (! child_oom_error_code)
974
child_oom_error_block = nih_strdup (NULL, child_oom_error_code);
975
if (! child_oom_error_block)
977
if (! indent (&child_oom_error_block, NULL, 1))
980
type_error_block = nih_strdup (NULL, type_error_code);
981
if (! type_error_block)
983
if (! indent (&type_error_block, NULL, 1))
986
child_type_error_code = nih_sprintf (NULL, ("nih_free (%s);\n"
988
name, type_error_code);
989
if (! child_type_error_code)
992
child_type_error_block = nih_strdup (NULL, child_type_error_code);
993
if (! child_type_error_block)
995
if (! indent (&child_type_error_block, NULL, 1))
998
/* Open the struct container, for that we need to know whether this
999
* is a struct or a dictionary entry even through we handled the two
1000
* identically. We'll obviously need a local variable for the
1001
* recursed iterator.
1003
dbus_type = dbus_signature_iter_get_current_type (iter);
1004
dbus_const = type_const (dbus_type);
1006
dbus_signature_iter_recurse (iter, &subiter);
1008
if (! nih_strcat_sprintf (&code, parent,
1009
"/* Demarshal a structure from the message */\n"
1010
"if (dbus_message_iter_get_arg_type (&%s) != %s) {\n"
1014
"dbus_message_iter_recurse (&%s, &%s);\n"
1016
iter_name, dbus_const,
1018
iter_name, struct_iter_name))
1021
struct_iter_var = type_var_new (code, "DBusMessageIter",
1023
if (! struct_iter_var) {
1028
nih_list_add (locals, &struct_iter_var->entry);
1030
/* FIXME there should be a way to override this to a different type
1031
* name by annotation.
1033
alloc_type = symbol_typedef (NULL, prefix, interface_symbol, NULL,
1034
member_symbol, symbol);
1040
c_type = nih_strdup (NULL, alloc_type);
1046
structure = type_struct_new (code, c_type);
1052
nih_list_add (structs, &structure->entry);
1054
if (! type_to_pointer (&c_type, NULL)) {
1059
/* Allocate the new structure */
1060
if (! nih_strcat_sprintf (&code, parent,
1061
"%s = nih_new (%s, %s);\n"
1066
name, parent_name, alloc_type,
1073
/* Deal with each structure element individually, however we have
1074
* to end up with just one set of locals and one block so we
1075
* append directly onto our locals.
1078
nih_local char *item_member = NULL;
1079
nih_local char *item_name = NULL;
1080
nih_local char *item_symbol = NULL;
1081
NihList item_outputs;
1082
NihList item_locals;
1083
NihList item_structs;
1084
nih_local char *item_code = NULL;
1086
/* FIXME there should be a way to override the item names
1087
* via an annotation, which would also show up in the
1088
* structure definition itself.
1090
item_member = nih_sprintf (NULL, "item%zu", count);
1091
if (! item_member) {
1096
item_name = nih_sprintf (NULL, "%s_%s", name, item_member);
1102
item_symbol = (symbol
1103
? nih_sprintf (NULL, "%s_%s", symbol, item_member)
1104
: nih_strdup (NULL, item_member));
1105
if (! item_symbol) {
1110
/* Get the code to do the demarshalling of this item */
1111
nih_list_init (&item_outputs);
1112
nih_list_init (&item_locals);
1113
nih_list_init (&item_structs);
1114
item_code = demarshal (NULL, &subiter,
1115
name, struct_iter_name, item_name,
1116
child_oom_error_code,
1117
child_type_error_code,
1118
&item_outputs, &item_locals,
1119
prefix, interface_symbol,
1120
member_symbol, item_symbol,
1127
/* Append the item locals onto our locals list, we have
1128
* to reference these as we go.
1130
NIH_LIST_FOREACH_SAFE (&item_locals, iter) {
1131
TypeVar *item_local_var = (TypeVar *)iter;
1133
nih_list_add (locals, &item_local_var->entry);
1134
nih_ref (item_local_var, code);
1137
/* Append item demarshalling code block */
1138
if (! nih_strcat_sprintf (&code, parent,
1146
/* Instead of mucking around with pointers and structure
1147
* members, each of the marshalling code outputs is appended
1148
* onto the local list and we copy from the local into
1149
* our output variable.
1151
NIH_LIST_FOREACH_SAFE (&item_outputs, iter) {
1152
TypeVar * output_var = (TypeVar *)iter;
1154
nih_local char *member_name = NULL;
1155
TypeVar * member_var;
1157
nih_assert (! strncmp (output_var->name, item_name,
1158
strlen (item_name)));
1159
suffix = output_var->name + strlen (item_name);
1161
/* Create the structure member entry */
1162
member_name = nih_sprintf (NULL, "%s%s",
1163
item_member, suffix);
1164
if (! member_name) {
1169
member_var = type_var_new (structure,
1177
nih_list_add (&structure->members, &member_var->entry);
1179
/* Add code to copy from local variable */
1180
if (! nih_strcat_sprintf (&code, parent,
1183
output_var->name)) {
1189
nih_list_add (locals, &output_var->entry);
1190
nih_ref (output_var, code);
1193
NIH_LIST_FOREACH_SAFE (&item_structs, iter) {
1194
TypeStruct *structure = (TypeStruct *)iter;
1196
nih_ref (structure, code);
1197
nih_list_add (structs, &structure->entry);
1200
if (! nih_strcat (&code, parent, "\n")) {
1205
nih_assert (++count > 0);
1206
} while (dbus_signature_iter_next (&subiter));
1208
/* Close the container again */
1209
if (! nih_strcat_sprintf (&code, parent,
1210
"if (dbus_message_iter_get_arg_type (&%s) != DBUS_TYPE_INVALID) {\n"
1214
"dbus_message_iter_next (&%s);\n",
1216
child_type_error_block,
1222
/* Append our required output variable */
1223
var = type_var_new (code, c_type, name);
1229
nih_list_add (outputs, &var->entry);