~ubuntu-core-dev/ubuntu/karmic/mountall/ubuntu

« back to all changes in this revision

Viewing changes to nih-dbus-tool/demarshal.c

  • Committer: Scott James Remnant
  • Author(s): Scott James Remnant, Kees Cook, Johan Kiviniemi, Scott James Remnant
  • Date: 2009-10-26 09:30:41 UTC
  • Revision ID: scott@netsplit.com-20091026093041-spng4azkvfoppcs2
Tags: 1.0
[ Kees Cook ]
* Call out to restorecon after mounting tmpfs filesystems.  LP: #456942.

[ Johan Kiviniemi ]
* Fix a bug introduced by the 0.2.6 change. In certain situations, we’d
  quit even though we’re still waiting for some filesystems to be
  mounted.  LP: #456806.

[ Scott James Remnant ]
* Don't clear the splash screen when we're waiting for filesystems,
  instead just output following whatever else is there.  In non-verbose
  mode this won't look any different, but it means we don't clear previous
  verbose mode text.  LP: #458389.
* Only update the "waiting for one or more mounts" text if there's actually
  a change in the set we're waiting for; this removes the need for a CLEAR
  this case anyway.
* Don't say we're waiting for mounts we're, in fact, not waiting
  for.  LP: #459859.
* Stop mountall (normally) when entering recovery mode.  LP: #458060.

* Clean up source tarball.  LP: #460348.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* nih-dbus-tool
 
2
 *
 
3
 * demarshal.c - type demarshalling
 
4
 *
 
5
 * Copyright © 2009 Scott James Remnant <scott@netsplit.com>.
 
6
 * Copyright © 2009 Canonical Ltd.
 
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 version 2, as
 
10
 * published by the Free Software Foundation.
 
11
 *
 
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.
 
16
 *
 
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.
 
20
 */
 
21
 
 
22
#ifdef HAVE_CONFIG_H
 
23
# include <config.h>
 
24
#endif /* HAVE_CONFIG_H */
 
25
 
 
26
 
 
27
#include <dbus/dbus.h>
 
28
 
 
29
#include <string.h>
 
30
 
 
31
#include <nih/macros.h>
 
32
#include <nih/alloc.h>
 
33
#include <nih/list.h>
 
34
#include <nih/string.h>
 
35
#include <nih/logging.h>
 
36
 
 
37
#include "indent.h"
 
38
#include "symbol.h"
 
39
#include "type.h"
 
40
#include "demarshal.h"
 
41
 
 
42
 
 
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,
 
53
                               NihList *structs)
 
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,
 
64
                               NihList *structs)
 
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,
 
75
                               NihList *structs)
 
76
        __attribute__ ((warn_unused_result, malloc));
 
77
 
 
78
 
 
79
/**
 
80
 * demarshal:
 
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.
 
94
 *
 
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
 
97
 * @name.
 
98
 *
 
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()
 
102
 * as appropriate.
 
103
 *
 
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.
 
108
 *
 
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.
 
111
 *
 
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
 
116
 * the @locals list.
 
117
 *
 
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.
 
121
 *
 
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
 
125
 * freed.
 
126
 *
 
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".
 
129
 *
 
130
 * Returns: newly allocated string or NULL if insufficient memory.
 
131
 **/
 
132
char *
 
133
demarshal (const void *       parent,
 
134
           DBusSignatureIter *iter,
 
135
           const char *       parent_name,
 
136
           const char *       iter_name,
 
137
           const char *       name,
 
138
           const char *       oom_error_code,
 
139
           const char *       type_error_code,
 
140
           NihList *          outputs,
 
141
           NihList *          locals,
 
142
           const char *       prefix,
 
143
           const char *       interface_symbol,
 
144
           const char *       member_symbol,
 
145
           const char *       symbol,
 
146
           NihList *          structs)
 
147
{
 
148
        int dbus_type;
 
149
 
 
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);
 
161
 
 
162
        dbus_type = dbus_signature_iter_get_current_type (iter);
 
163
 
 
164
        if (dbus_type_is_basic (dbus_type)) {
 
165
                return demarshal_basic (parent, iter,
 
166
                                        parent_name,
 
167
                                        iter_name, name,
 
168
                                        oom_error_code, type_error_code,
 
169
                                        outputs, locals,
 
170
                                        prefix, interface_symbol,
 
171
                                        member_symbol, symbol,
 
172
                                        structs);
 
173
        } else if (dbus_type == DBUS_TYPE_ARRAY) {
 
174
                return demarshal_array (parent, iter,
 
175
                                        parent_name,
 
176
                                        iter_name, name,
 
177
                                        oom_error_code,
 
178
                                        type_error_code,
 
179
                                        outputs, locals,
 
180
                                        prefix, interface_symbol,
 
181
                                        member_symbol, symbol,
 
182
                                        structs);
 
183
        } else if ((dbus_type == DBUS_TYPE_STRUCT)
 
184
                   || (dbus_type == DBUS_TYPE_DICT_ENTRY)) {
 
185
                return demarshal_struct (parent, iter,
 
186
                                         parent_name,
 
187
                                         iter_name, name,
 
188
                                         oom_error_code, type_error_code,
 
189
                                         outputs, locals,
 
190
                                         prefix, interface_symbol,
 
191
                                         member_symbol, symbol,
 
192
                                         structs);
 
193
        } else {
 
194
                nih_assert_not_reached ();
 
195
        }
 
196
}
 
197
 
 
198
 
 
199
/**
 
200
 * demarshal_basic:
 
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.
 
213
 *
 
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.
 
217
 *
 
218
 * The type should be the current element of the signature iterator @iter.
 
219
 *
 
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.
 
224
 *
 
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.
 
227
 *
 
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
 
232
 * the @locals list.
 
233
 *
 
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.
 
237
 *
 
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
 
241
 * freed.
 
242
 *
 
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".
 
245
 *
 
246
 * Returns: newly allocated string or NULL if insufficient memory.
 
247
 **/
 
248
static char *
 
249
demarshal_basic (const void *       parent,
 
250
                 DBusSignatureIter *iter,
 
251
                 const char *       parent_name,
 
252
                 const char *       iter_name,
 
253
                 const char *       name,
 
254
                 const char *       oom_error_code,
 
255
                 const char *       type_error_code,
 
256
                 NihList *          outputs,
 
257
                 NihList *          locals,
 
258
                 const char *       prefix,
 
259
                 const char *       interface_symbol,
 
260
                 const char *       member_symbol,
 
261
                 const char *       symbol,
 
262
                 NihList *          structs)
 
263
{
 
264
        int             dbus_type;
 
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;
 
269
        char *          code = NULL;
 
270
        TypeVar *       var;
 
271
 
 
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);
 
283
 
 
284
        dbus_type = dbus_signature_iter_get_current_type (iter);
 
285
        dbus_const = type_const (dbus_type);
 
286
 
 
287
        oom_error_block = nih_strdup (NULL, oom_error_code);
 
288
        if (! oom_error_block)
 
289
                return NULL;
 
290
        if (! indent (&oom_error_block, NULL, 1))
 
291
                return NULL;
 
292
 
 
293
        type_error_block = nih_strdup (NULL, type_error_code);
 
294
        if (! type_error_block)
 
295
                return NULL;
 
296
        if (! indent (&type_error_block, NULL, 1))
 
297
                return NULL;
 
298
 
 
299
        c_type = type_of (NULL, iter);
 
300
        if (! c_type)
 
301
                return NULL;
 
302
 
 
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"
 
306
                                  "%s"
 
307
                                  "}\n"
 
308
                                  "\n",
 
309
                                  c_type,
 
310
                                  iter_name, dbus_const,
 
311
                                  type_error_block))
 
312
                return NULL;
 
313
 
 
314
        if (dbus_type_is_fixed (dbus_type)) {
 
315
                if (! nih_strcat_sprintf (&code, parent,
 
316
                                          "dbus_message_iter_get_basic (&%s, &%s);\n"
 
317
                                          "\n",
 
318
                                          iter_name, name)) {
 
319
                        nih_free (code);
 
320
                        return NULL;
 
321
                }
 
322
        } else {
 
323
                nih_local char *local_name = NULL;
 
324
                nih_local char *local_type = NULL;
 
325
 
 
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.
 
328
                 */
 
329
                local_name = nih_sprintf (NULL, "%s_dbus", name);
 
330
                if (! local_name) {
 
331
                        nih_free (code);
 
332
                        return NULL;
 
333
                }
 
334
 
 
335
                local_type = nih_strdup (NULL, c_type);
 
336
                if (! local_type) {
 
337
                        nih_free (code);
 
338
                        return NULL;
 
339
                }
 
340
 
 
341
                if (! type_to_const (&local_type, NULL)) {
 
342
                        nih_free (code);
 
343
                        return NULL;
 
344
                }
 
345
 
 
346
                if (! nih_strcat_sprintf (&code, parent,
 
347
                                          "dbus_message_iter_get_basic (&%s, &%s);\n"
 
348
                                          "\n"
 
349
                                          "%s = nih_strdup (%s, %s);\n"
 
350
                                          "if (! %s) {\n"
 
351
                                          "%s"
 
352
                                          "}\n"
 
353
                                          "\n",
 
354
                                          iter_name, local_name,
 
355
                                          name, parent_name, local_name,
 
356
                                          name,
 
357
                                          oom_error_block)) {
 
358
                        nih_free (code);
 
359
                        return NULL;
 
360
                }
 
361
 
 
362
                var = type_var_new (code, local_type, local_name);
 
363
                if (! var) {
 
364
                        nih_free (code);
 
365
                        return NULL;
 
366
                }
 
367
 
 
368
                nih_list_add (locals, &var->entry);
 
369
        }
 
370
 
 
371
        if (! nih_strcat_sprintf (&code, parent,
 
372
                                  "dbus_message_iter_next (&%s);\n",
 
373
                                  iter_name)) {
 
374
                nih_free (code);
 
375
                return NULL;
 
376
        }
 
377
 
 
378
        /* Append our required output variable */
 
379
        var = type_var_new (code, c_type, name);
 
380
        if (! var) {
 
381
                nih_free (code);
 
382
                return NULL;
 
383
        }
 
384
 
 
385
        nih_list_add (outputs, &var->entry);
 
386
 
 
387
        return code;
 
388
}
 
389
 
 
390
 
 
391
/**
 
392
 * demarshal_array:
 
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.
 
405
 *
 
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.
 
412
 *
 
413
 * The type should be the current element of the signature iterator @iter.
 
414
 *
 
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.
 
419
 *
 
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.
 
422
 *
 
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
 
427
 * the @locals list.
 
428
 *
 
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.
 
432
 *
 
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
 
436
 * freed.
 
437
 *
 
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".
 
440
 *
 
441
 * Returns: newly allocated string or NULL if insufficient memory.
 
442
 **/
 
443
static char *
 
444
demarshal_array (const void *       parent,
 
445
                 DBusSignatureIter *iter,
 
446
                 const char *       parent_name,
 
447
                 const char *       iter_name,
 
448
                 const char *       name,
 
449
                 const char *       oom_error_code,
 
450
                 const char *       type_error_code,
 
451
                 NihList *          outputs,
 
452
                 NihList *          locals,
 
453
                 const char *       prefix,
 
454
                 const char *       interface_symbol,
 
455
                 const char *       member_symbol,
 
456
                 const char *       symbol,
 
457
                 NihList *          structs)
 
458
{
 
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;
 
470
        int                element_type;
 
471
        char *             code = NULL;
 
472
        TypeVar *          array_iter_var;
 
473
        TypeVar *          size_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;
 
481
 
 
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);
 
492
 
 
493
        dbus_signature_iter_recurse (iter, &subiter);
 
494
        element_type = dbus_signature_iter_get_current_type (&subiter);
 
495
 
 
496
        array_iter_name = nih_sprintf (NULL, "%s_iter", name);
 
497
        if (! array_iter_name)
 
498
                return NULL;
 
499
 
 
500
        element_name = nih_sprintf (NULL, "%s_element", name);
 
501
        if (! element_name)
 
502
                return NULL;
 
503
 
 
504
        element_symbol = (symbol
 
505
                          ? nih_sprintf (NULL, "%s_element", symbol)
 
506
                          : nih_strdup (NULL, "element"));
 
507
        if (! element_symbol)
 
508
                return NULL;
 
509
 
 
510
        if (dbus_type_is_fixed (element_type)) {
 
511
                size_name = nih_sprintf (NULL, "%s_len", name);
 
512
                if (! size_name)
 
513
                        return NULL;
 
514
        } else {
 
515
                size_name = nih_sprintf (NULL, "%s_size", name);
 
516
                if (! size_name)
 
517
                        return NULL;
 
518
        }
 
519
 
 
520
        oom_error_block = nih_strdup (NULL, oom_error_code);
 
521
        if (! oom_error_block)
 
522
                return NULL;
 
523
        if (! indent (&oom_error_block, NULL, 1))
 
524
                return NULL;
 
525
 
 
526
        child_oom_error_code = nih_sprintf (NULL, ("if (%s)\n"
 
527
                                                   "\tnih_free (%s);\n"
 
528
                                                   "%s"),
 
529
                                            name, name, oom_error_code);
 
530
        if (! child_oom_error_code)
 
531
                return NULL;
 
532
 
 
533
        child_oom_error_block = nih_strdup (NULL, child_oom_error_code);
 
534
        if (! child_oom_error_block)
 
535
                return NULL;
 
536
        if (! indent (&child_oom_error_block, NULL, 1))
 
537
                return NULL;
 
538
 
 
539
        type_error_block = nih_strdup (NULL, type_error_code);
 
540
        if (! type_error_block)
 
541
                return NULL;
 
542
        if (! indent (&type_error_block, NULL, 1))
 
543
                return NULL;
 
544
 
 
545
        child_type_error_code = nih_sprintf (NULL, ("if (%s)\n"
 
546
                                                    "\tnih_free (%s);\n"
 
547
                                                    "%s"),
 
548
                                             name, name, type_error_code);
 
549
        if (! child_type_error_code)
 
550
                return NULL;
 
551
 
 
552
        child_type_error_block = nih_strdup (NULL, child_type_error_code);
 
553
        if (! child_type_error_block)
 
554
                return NULL;
 
555
        if (! indent (&child_type_error_block, NULL, 1))
 
556
                return NULL;
 
557
 
 
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"
 
562
                                  "%s"
 
563
                                  "}\n"
 
564
                                  "\n"
 
565
                                  "dbus_message_iter_recurse (&%s, &%s);\n"
 
566
                                  "\n",
 
567
                                  iter_name,
 
568
                                  type_error_block,
 
569
                                  iter_name, array_iter_name))
 
570
                return NULL;
 
571
 
 
572
        array_iter_var = type_var_new (code, "DBusMessageIter",
 
573
                                       array_iter_name);
 
574
        if (! array_iter_var) {
 
575
                nih_free (code);
 
576
                return NULL;
 
577
        }
 
578
 
 
579
        nih_list_add (locals, &array_iter_var->entry);
 
580
 
 
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.
 
584
         */
 
585
        size_var = type_var_new (code, "size_t", size_name);
 
586
        if (! size_var) {
 
587
                nih_free (code);
 
588
                return NULL;
 
589
        }
 
590
 
 
591
        if (! dbus_type_is_fixed (element_type))
 
592
                nih_list_add (locals, &size_var->entry);
 
593
 
 
594
 
 
595
        if (! nih_strcat_sprintf (&code, parent,
 
596
                                  "%s = 0;\n",
 
597
                                  size_name)) {
 
598
                nih_free (code);
 
599
                return NULL;
 
600
        }
 
601
 
 
602
        /* Get the code that will demarshal the individual elements, and
 
603
         * any output and local variables it needs.
 
604
         */
 
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,
 
615
                                   &element_structs);
 
616
        if (! element_block) {
 
617
                nih_free (code);
 
618
                return NULL;
 
619
        }
 
620
 
 
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.
 
625
         *
 
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
 
630
         * NULL pointer.
 
631
         *
 
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.
 
635
         */
 
636
        NIH_LIST_FOREACH_SAFE (&element_outputs, iter) {
 
637
                TypeVar *       output_var = (TypeVar *)iter;
 
638
                char *          ptr;
 
639
                nih_local char *var_type = NULL;
 
640
                const char *    suffix;
 
641
                nih_local char *var_name = NULL;
 
642
                TypeVar *       var;
 
643
                nih_local char *tmp_name = NULL;
 
644
                const char *    var_parent;
 
645
 
 
646
                /* Output variable */
 
647
                var_type = nih_strdup (NULL, output_var->type);
 
648
                if (! var_type) {
 
649
                        nih_free (code);
 
650
                        return NULL;
 
651
                }
 
652
 
 
653
                if (! type_to_pointer (&var_type, NULL)) {
 
654
                        nih_free (code);
 
655
                        return NULL;
 
656
                }
 
657
 
 
658
                nih_assert (! strncmp (output_var->name, element_name,
 
659
                                       strlen (element_name)));
 
660
                suffix = output_var->name + strlen (element_name);
 
661
 
 
662
                var_name = nih_sprintf (NULL, "%s%s", name, suffix);
 
663
                if (! var_name) {
 
664
                        nih_free (code);
 
665
                        return NULL;
 
666
                }
 
667
 
 
668
                var = type_var_new (code, var_type, var_name);
 
669
                if (! var) {
 
670
                        nih_free (code);
 
671
                        return NULL;
 
672
                }
 
673
 
 
674
                nih_list_add (outputs, &var->entry);
 
675
 
 
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.
 
680
                 */
 
681
                tmp_name = nih_sprintf (NULL, "%s_tmp", var_name);
 
682
                if (! tmp_name) {
 
683
                        nih_free (code);
 
684
                        return NULL;
 
685
                }
 
686
 
 
687
                var = type_var_new (element_block, var_type, tmp_name);
 
688
                if (! var) {
 
689
                        nih_free (code);
 
690
                        return NULL;
 
691
                }
 
692
 
 
693
                nih_list_add (&element_locals, &var->entry);
 
694
 
 
695
                /* Code to allocate and reallocate */
 
696
                var_parent = (*suffix ? name : parent_name);
 
697
 
 
698
                if (! nih_strcat_sprintf (&code, parent,
 
699
                                          "%s = NULL;\n",
 
700
                                          var_name)) {
 
701
                        nih_free (code);
 
702
                        return NULL;
 
703
                }
 
704
 
 
705
                ptr = output_var->type + strlen (output_var->type) - 1;
 
706
                if (*ptr != '*') {
 
707
                        if (! nih_strcat_sprintf (&block, NULL,
 
708
                                                  "if (%s + 1 > SIZE_MAX / sizeof (%s)) {\n"
 
709
                                                  "%s"
 
710
                                                  "}\n"
 
711
                                                  "\n"
 
712
                                                  "%s = nih_realloc (%s, %s, sizeof (%s) * (%s + 1));\n"
 
713
                                                  "if (! %s) {\n"
 
714
                                                  "%s"
 
715
                                                  "}\n"
 
716
                                                  "\n"
 
717
                                                  "%s = %s;\n"
 
718
                                                  "%s[%s] = %s;\n"
 
719
                                                  "\n",
 
720
                                                  size_name, output_var->type,
 
721
                                                  child_type_error_block,
 
722
                                                  tmp_name, var_name, var_parent, output_var->type, size_name,
 
723
                                                  tmp_name,
 
724
                                                  child_oom_error_block,
 
725
                                                  var_name, tmp_name,
 
726
                                                  var_name, size_name, output_var->name)) {
 
727
                                nih_free (code);
 
728
                                return NULL;
 
729
                        }
 
730
                } else {
 
731
                        if (! nih_strcat_sprintf (&alloc_block, NULL,
 
732
                                                  "%s = nih_alloc (%s, sizeof (%s));\n"
 
733
                                                  "if (! %s) {\n"
 
734
                                                  "%s"
 
735
                                                  "}\n"
 
736
                                                  "\n"
 
737
                                                  "%s[%s] = NULL;\n"
 
738
                                                  "\n",
 
739
                                                  var_name, var_parent, output_var->type,
 
740
                                                  var_name,
 
741
                                                  (*suffix ? child_oom_error_block : oom_error_block),
 
742
                                                  var_name, size_name)) {
 
743
                                nih_free (code);
 
744
                                return NULL;
 
745
                        }
 
746
 
 
747
                        if (! nih_strcat_sprintf (&block, NULL,
 
748
                                                  "if (%s + 2 > SIZE_MAX / sizeof (%s)) {\n"
 
749
                                                  "%s"
 
750
                                                  "}\n"
 
751
                                                  "\n"
 
752
                                                  "%s = nih_realloc (%s, %s, sizeof (%s) * (%s + 2));\n"
 
753
                                                  "if (! %s) {\n"
 
754
                                                  "%s"
 
755
                                                  "}\n"
 
756
                                                  "\n"
 
757
                                                  "%s = %s;\n"
 
758
                                                  "%s[%s] = %s;\n"
 
759
                                                  "%s[%s + 1] = NULL;\n"
 
760
                                                  "\n",
 
761
                                                  size_name, output_var->type,
 
762
                                                  child_type_error_block,
 
763
                                                  tmp_name, var_name, var_parent, output_var->type, size_name,
 
764
                                                  tmp_name,
 
765
                                                  child_oom_error_block,
 
766
                                                  var_name, tmp_name,
 
767
                                                  var_name, size_name, output_var->name,
 
768
                                                  var_name, size_name)) {
 
769
                                nih_free (code);
 
770
                                return NULL;
 
771
                        }
 
772
                }
 
773
 
 
774
                nih_list_add (&element_locals, &output_var->entry);
 
775
        }
 
776
 
 
777
        if (! nih_strcat_sprintf (&code, parent,
 
778
                                  "\n"
 
779
                                  "%s",
 
780
                                  alloc_block ?: "")) {
 
781
                nih_free (code);
 
782
                return NULL;
 
783
        }
 
784
 
 
785
        if (! nih_strcat_sprintf (&block, parent,
 
786
                                  "%s++;\n",
 
787
                                  size_name)) {
 
788
                nih_free (code);
 
789
                return NULL;
 
790
        }
 
791
 
 
792
        vars_block = type_var_layout (NULL, &element_locals);
 
793
        if (! vars_block) {
 
794
                nih_free (code);
 
795
                return NULL;
 
796
        }
 
797
 
 
798
        NIH_LIST_FOREACH_SAFE (&element_structs, iter) {
 
799
                TypeStruct *structure = (TypeStruct *)iter;
 
800
 
 
801
                nih_ref (structure, code);
 
802
                nih_list_add (structs, &structure->entry);
 
803
        }
 
804
 
 
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",
 
808
                                  array_iter_name)) {
 
809
                nih_free (code);
 
810
                return NULL;
 
811
        }
 
812
 
 
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
 
816
         * not.
 
817
         */
 
818
        if (! indent (&vars_block, NULL, 1)) {
 
819
                nih_free (code);
 
820
                return NULL;
 
821
        }
 
822
 
 
823
        if (! indent (&element_block, NULL, 1)) {
 
824
                nih_free (code);
 
825
                return NULL;
 
826
        }
 
827
 
 
828
        if (! indent (&block, NULL, 1)) {
 
829
                nih_free (code);
 
830
                return NULL;
 
831
        }
 
832
 
 
833
        if (! nih_strcat_sprintf (&code, parent,
 
834
                                  "%s"
 
835
                                  "\n"
 
836
                                  "%s"
 
837
                                  "\n"
 
838
                                  "%s",
 
839
                                  vars_block,
 
840
                                  element_block,
 
841
                                  block)) {
 
842
                nih_free (code);
 
843
                return NULL;
 
844
        }
 
845
 
 
846
        /* Finish off the iteration and move onto the next message item */
 
847
        if (! nih_strcat_sprintf (&code, parent,
 
848
                                  "}\n"
 
849
                                  "\n"
 
850
                                  "dbus_message_iter_next (&%s);\n",
 
851
                                  iter_name)) {
 
852
                nih_free (code);
 
853
                return NULL;
 
854
        }
 
855
 
 
856
        if (dbus_type_is_fixed (element_type))
 
857
                nih_list_add (outputs, &size_var->entry);
 
858
 
 
859
        return code;
 
860
}
 
861
 
 
862
 
 
863
/**
 
864
 * demarshal_struct:
 
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.
 
877
 *
 
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.
 
881
 *
 
882
 * The type should be the current element of the signature iterator @iter.
 
883
 *
 
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.
 
888
 *
 
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.
 
891
 *
 
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
 
896
 * the @locals list.
 
897
 *
 
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.
 
901
 *
 
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
 
905
 * freed.
 
906
 *
 
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".
 
909
 *
 
910
 * Returns: newly allocated string or NULL if insufficient memory.
 
911
 **/
 
912
static char *
 
913
demarshal_struct (const void *       parent,
 
914
                  DBusSignatureIter *iter,
 
915
                  const char *       parent_name,
 
916
                  const char *       iter_name,
 
917
                  const char *       name,
 
918
                  const char *       oom_error_code,
 
919
                  const char *       type_error_code,
 
920
                  NihList *          outputs,
 
921
                  NihList *          locals,
 
922
                  const char *       prefix,
 
923
                  const char *       interface_symbol,
 
924
                  const char *       member_symbol,
 
925
                  const char *       symbol,
 
926
                  NihList *          structs)
 
927
{
 
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;
 
935
        int               dbus_type;
 
936
        const char *      dbus_const;
 
937
        DBusSignatureIter subiter;
 
938
        char *            code = NULL;
 
939
        TypeVar *         struct_iter_var;
 
940
        nih_local char *  c_type = NULL;
 
941
        nih_local char *  alloc_type = NULL;
 
942
        TypeStruct *      structure;
 
943
        size_t            count = 0;
 
944
        TypeVar *         var;
 
945
 
 
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);
 
957
 
 
958
        struct_iter_name = nih_sprintf (NULL, "%s_iter", name);
 
959
        if (! struct_iter_name)
 
960
                return NULL;
 
961
 
 
962
        oom_error_block = nih_strdup (NULL, oom_error_code);
 
963
        if (! oom_error_block)
 
964
                return NULL;
 
965
        if (! indent (&oom_error_block, NULL, 1))
 
966
                return NULL;
 
967
 
 
968
        child_oom_error_code = nih_sprintf (NULL, ("nih_free (%s);\n"
 
969
                                                   "%s"),
 
970
                                            name, oom_error_code);
 
971
        if (! child_oom_error_code)
 
972
                return NULL;
 
973
 
 
974
        child_oom_error_block = nih_strdup (NULL, child_oom_error_code);
 
975
        if (! child_oom_error_block)
 
976
                return NULL;
 
977
        if (! indent (&child_oom_error_block, NULL, 1))
 
978
                return NULL;
 
979
 
 
980
        type_error_block = nih_strdup (NULL, type_error_code);
 
981
        if (! type_error_block)
 
982
                return NULL;
 
983
        if (! indent (&type_error_block, NULL, 1))
 
984
                return NULL;
 
985
 
 
986
        child_type_error_code = nih_sprintf (NULL, ("nih_free (%s);\n"
 
987
                                                    "%s"),
 
988
                                             name, type_error_code);
 
989
        if (! child_type_error_code)
 
990
                return NULL;
 
991
 
 
992
        child_type_error_block = nih_strdup (NULL, child_type_error_code);
 
993
        if (! child_type_error_block)
 
994
                return NULL;
 
995
        if (! indent (&child_type_error_block, NULL, 1))
 
996
                return NULL;
 
997
 
 
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.
 
1002
         */
 
1003
        dbus_type = dbus_signature_iter_get_current_type (iter);
 
1004
        dbus_const = type_const (dbus_type);
 
1005
 
 
1006
        dbus_signature_iter_recurse (iter, &subiter);
 
1007
 
 
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"
 
1011
                                  "%s"
 
1012
                                  "}\n"
 
1013
                                  "\n"
 
1014
                                  "dbus_message_iter_recurse (&%s, &%s);\n"
 
1015
                                  "\n",
 
1016
                                  iter_name, dbus_const,
 
1017
                                  type_error_block,
 
1018
                                  iter_name, struct_iter_name))
 
1019
                return NULL;
 
1020
 
 
1021
        struct_iter_var = type_var_new (code, "DBusMessageIter",
 
1022
                                        struct_iter_name);
 
1023
        if (! struct_iter_var) {
 
1024
                nih_free (code);
 
1025
                return NULL;
 
1026
        }
 
1027
 
 
1028
        nih_list_add (locals, &struct_iter_var->entry);
 
1029
 
 
1030
        /* FIXME there should be a way to override this to a different type
 
1031
         * name by annotation.
 
1032
         */
 
1033
        alloc_type = symbol_typedef (NULL, prefix, interface_symbol, NULL,
 
1034
                                     member_symbol, symbol);
 
1035
        if (! alloc_type) {
 
1036
                nih_free (code);
 
1037
                return NULL;
 
1038
        }
 
1039
 
 
1040
        c_type = nih_strdup (NULL, alloc_type);
 
1041
        if (! c_type) {
 
1042
                nih_free (code);
 
1043
                return NULL;
 
1044
        }
 
1045
 
 
1046
        structure = type_struct_new (code, c_type);
 
1047
        if (! structure) {
 
1048
                nih_free (code);
 
1049
                return NULL;
 
1050
        }
 
1051
 
 
1052
        nih_list_add (structs, &structure->entry);
 
1053
 
 
1054
        if (! type_to_pointer (&c_type, NULL)) {
 
1055
                nih_free (code);
 
1056
                return NULL;
 
1057
        }
 
1058
 
 
1059
        /* Allocate the new structure */
 
1060
        if (! nih_strcat_sprintf (&code, parent,
 
1061
                                  "%s = nih_new (%s, %s);\n"
 
1062
                                  "if (! %s) {\n"
 
1063
                                  "%s"
 
1064
                                  "}\n"
 
1065
                                  "\n",
 
1066
                                  name, parent_name, alloc_type,
 
1067
                                  name,
 
1068
                                  oom_error_block)) {
 
1069
                nih_free (code);
 
1070
                return NULL;
 
1071
        }
 
1072
 
 
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.
 
1076
         */
 
1077
        do {
 
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;
 
1085
 
 
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.
 
1089
                 */
 
1090
                item_member = nih_sprintf (NULL, "item%zu", count);
 
1091
                if (! item_member) {
 
1092
                        nih_free (code);
 
1093
                        return NULL;
 
1094
                }
 
1095
 
 
1096
                item_name = nih_sprintf (NULL, "%s_%s", name, item_member);
 
1097
                if (! item_name) {
 
1098
                        nih_free (code);
 
1099
                        return NULL;
 
1100
                }
 
1101
 
 
1102
                item_symbol = (symbol
 
1103
                               ? nih_sprintf (NULL, "%s_%s", symbol, item_member)
 
1104
                               : nih_strdup (NULL, item_member));
 
1105
                if (! item_symbol) {
 
1106
                        nih_free (code);
 
1107
                        return NULL;
 
1108
                }
 
1109
 
 
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,
 
1121
                                       &item_structs);
 
1122
                if (! item_code) {
 
1123
                        nih_free (code);
 
1124
                        return NULL;
 
1125
                }
 
1126
 
 
1127
                /* Append the item locals onto our locals list, we have
 
1128
                 * to reference these as we go.
 
1129
                 */
 
1130
                NIH_LIST_FOREACH_SAFE (&item_locals, iter) {
 
1131
                        TypeVar *item_local_var = (TypeVar *)iter;
 
1132
 
 
1133
                        nih_list_add (locals, &item_local_var->entry);
 
1134
                        nih_ref (item_local_var, code);
 
1135
                }
 
1136
 
 
1137
                /* Append item demarshalling code block */
 
1138
                if (! nih_strcat_sprintf (&code, parent,
 
1139
                                          "%s"
 
1140
                                          "\n",
 
1141
                                          item_code)) {
 
1142
                        nih_free (code);
 
1143
                        return NULL;
 
1144
                }
 
1145
 
 
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.
 
1150
                 */
 
1151
                NIH_LIST_FOREACH_SAFE (&item_outputs, iter) {
 
1152
                        TypeVar *       output_var = (TypeVar *)iter;
 
1153
                        char *          suffix;
 
1154
                        nih_local char *member_name = NULL;
 
1155
                        TypeVar *       member_var;
 
1156
 
 
1157
                        nih_assert (! strncmp (output_var->name, item_name,
 
1158
                                               strlen (item_name)));
 
1159
                        suffix = output_var->name + strlen (item_name);
 
1160
 
 
1161
                        /* Create the structure member entry */
 
1162
                        member_name = nih_sprintf (NULL, "%s%s",
 
1163
                                                   item_member, suffix);
 
1164
                        if (! member_name) {
 
1165
                                nih_free (code);
 
1166
                                return NULL;
 
1167
                        }
 
1168
 
 
1169
                        member_var = type_var_new (structure,
 
1170
                                                   output_var->type,
 
1171
                                                   member_name);
 
1172
                        if (! member_var) {
 
1173
                                nih_free (code);
 
1174
                                return NULL;
 
1175
                        }
 
1176
 
 
1177
                        nih_list_add (&structure->members, &member_var->entry);
 
1178
 
 
1179
                        /* Add code to copy from local variable */
 
1180
                        if (! nih_strcat_sprintf (&code, parent,
 
1181
                                                  "%s->%s = %s;\n",
 
1182
                                                  name, member_name,
 
1183
                                                  output_var->name)) {
 
1184
                                nih_free (code);
 
1185
                                return NULL;
 
1186
                        }
 
1187
 
 
1188
                        /* Add to locals */
 
1189
                        nih_list_add (locals, &output_var->entry);
 
1190
                        nih_ref (output_var, code);
 
1191
                }
 
1192
 
 
1193
                NIH_LIST_FOREACH_SAFE (&item_structs, iter) {
 
1194
                        TypeStruct *structure = (TypeStruct *)iter;
 
1195
 
 
1196
                        nih_ref (structure, code);
 
1197
                        nih_list_add (structs, &structure->entry);
 
1198
                }
 
1199
 
 
1200
                if (! nih_strcat (&code, parent, "\n")) {
 
1201
                        nih_free (code);
 
1202
                        return NULL;
 
1203
                }
 
1204
 
 
1205
                nih_assert (++count > 0);
 
1206
        } while (dbus_signature_iter_next (&subiter));
 
1207
 
 
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"
 
1211
                                  "%s"
 
1212
                                  "}\n"
 
1213
                                  "\n"
 
1214
                                  "dbus_message_iter_next (&%s);\n",
 
1215
                                  struct_iter_name,
 
1216
                                  child_type_error_block,
 
1217
                                  iter_name)) {
 
1218
                nih_free (code);
 
1219
                return NULL;
 
1220
        }
 
1221
 
 
1222
        /* Append our required output variable */
 
1223
        var = type_var_new (code, c_type, name);
 
1224
        if (! var) {
 
1225
                nih_free (code);
 
1226
                return NULL;
 
1227
        }
 
1228
 
 
1229
        nih_list_add (outputs, &var->entry);
 
1230
 
 
1231
        return code;
 
1232
}