Add Nepali translation
[platform/upstream/at-spi2-core.git] / dbind / dbind-any.c
1 /*
2  * Copyright 2008-2011 Novell, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /* type driven marshalling */
21 #include <stdio.h>
22 #include <glib.h>
23
24 #include "config.h"
25 #include "dbind-any.h"
26
27 #undef DEBUG
28
29 /*  Align a value upward to a boundary, expressed as a number of bytes.
30  *  E.g. align to an 8-byte boundary with argument of 8.
31  *
32  *   (this + boundary - 1)
33  *          &
34  *    ~(boundary - 1)
35  */
36 #define ALIGN_VALUE(this, boundary) \
37   (( ((gulong)(this)) + (((gulong)(boundary)) -1)) & (~(((gulong)(boundary))-1)))
38
39 #define ALIGN_ADDRESS(this, boundary) \
40   ((gpointer)ALIGN_VALUE(this, boundary))
41
42 #define PTR_PLUS(ptr, offset) \
43         ((gpointer) (((guchar *)(ptr)) + (offset)))
44
45 #define DBIND_POD_CASES \
46          DBUS_TYPE_BYTE: \
47     case DBUS_TYPE_INT16: \
48     case DBUS_TYPE_UINT16: \
49     case DBUS_TYPE_INT32: \
50     case DBUS_TYPE_UINT32: \
51     case DBUS_TYPE_BOOLEAN: \
52     case DBUS_TYPE_INT64: \
53     case DBUS_TYPE_UINT64: \
54     case DBUS_TYPE_DOUBLE
55
56 /*---------------------------------------------------------------------------*/
57
58 static void
59 warn_braces ()
60 {
61     fprintf (stderr, "Error: dbus flags structures & dicts with braces rather than "
62              " an explicit type member of 'struct'\n");
63 }
64
65 /*---------------------------------------------------------------------------*/
66
67 static unsigned int
68 dbind_find_c_alignment_r (const char **type)
69 {
70     unsigned int retval = 1;
71
72     char t = **type;
73     (*type)++;
74
75 #ifdef DEBUG
76     fprintf (stderr, "\tfind align for %c (0x%x)\n", t, t);
77 #endif
78
79         switch (t) {
80     case DBUS_TYPE_BYTE:
81         return ALIGNOF_CHAR;
82     case DBUS_TYPE_BOOLEAN:
83         return ALIGNOF_DBUS_BOOL_T;
84     case DBUS_TYPE_INT16:
85     case DBUS_TYPE_UINT16:
86         return ALIGNOF_DBUS_INT16_T;
87     case DBUS_TYPE_INT32:
88     case DBUS_TYPE_UINT32:
89         return ALIGNOF_DBUS_INT32_T;
90     case DBUS_TYPE_INT64:
91     case DBUS_TYPE_UINT64:
92         return ALIGNOF_DBUS_INT64_T;
93     case DBUS_TYPE_DOUBLE:
94         return ALIGNOF_DOUBLE;
95     /* ptr types */
96     case DBUS_TYPE_STRING:
97     case DBUS_TYPE_OBJECT_PATH:
98     case DBUS_TYPE_SIGNATURE:
99     case DBUS_TYPE_ARRAY:
100         return ALIGNOF_DBIND_POINTER;
101     case DBUS_STRUCT_BEGIN_CHAR:
102       /* TODO: I think this would break with a nested struct */
103 #if ALIGNOF_DBIND_STRUCT > 1
104                 retval = MAX (retval, ALIGNOF_DBIND_STRUCT);
105 #endif
106         while (**type != DBUS_STRUCT_END_CHAR) {
107             int elem_align = dbind_find_c_alignment_r (type);
108                         retval = MAX (retval, elem_align);
109         }
110         (*type)++;
111         return retval;
112     case DBUS_DICT_ENTRY_BEGIN_CHAR:
113 #if ALIGNOF_DBIND_STRUCT > 1
114                 retval = MAX (retval, ALIGNOF_DBIND_STRUCT);
115 #endif
116         while (**type != DBUS_DICT_ENTRY_END_CHAR) {
117             int elem_align = dbind_find_c_alignment_r (type);
118                         retval = MAX (retval, elem_align);
119         }
120         (*type)++;
121         return retval;
122     case DBUS_TYPE_STRUCT:
123     case DBUS_TYPE_DICT_ENTRY:
124         warn_braces ();
125         return ALIGNOF_DBIND_POINTER;
126     case '\0':
127         g_assert_not_reached();
128         break;
129     default:
130                 return 1;
131   }
132 }
133
134 /*---------------------------------------------------------------------------*/
135
136 /* gather immediate allocation information for this type */
137 static size_t
138 dbind_gather_alloc_info_r (const char **type)
139 {
140   char t = **type;
141   (*type)++;
142   if (t == DBUS_TYPE_ARRAY)
143     {
144       switch (**type)
145         {
146           case DBUS_STRUCT_BEGIN_CHAR:
147               while (**type != DBUS_STRUCT_END_CHAR && **type != '\0') (*type)++;
148               if (**type != '\0') (*type)++;
149               break;
150           case DBUS_DICT_ENTRY_BEGIN_CHAR:
151               while (**type != DBUS_DICT_ENTRY_END_CHAR && **type != '\0') (*type)++;
152               if (**type != '\0') (*type)++;
153               break;
154           case '\0':
155               break;
156           default:
157               (*type)++;
158               break;
159         }
160     }
161
162   switch (t) {
163     case DBUS_TYPE_BYTE:
164         return sizeof (char);
165     case DBUS_TYPE_BOOLEAN:
166         return sizeof (dbus_bool_t);
167     case DBUS_TYPE_INT16:
168     case DBUS_TYPE_UINT16:
169         return sizeof (dbus_int16_t);
170     case DBUS_TYPE_INT32:
171     case DBUS_TYPE_UINT32:
172         return sizeof (dbus_int32_t);
173     case DBUS_TYPE_INT64:
174     case DBUS_TYPE_UINT64:
175         return sizeof (dbus_int64_t);
176     case DBUS_TYPE_DOUBLE:
177         return sizeof (double);
178     /* ptr types */
179     case DBUS_TYPE_STRING:
180     case DBUS_TYPE_OBJECT_PATH:
181     case DBUS_TYPE_SIGNATURE:
182     case DBUS_TYPE_ARRAY:
183         return sizeof (void *);
184     case DBUS_STRUCT_BEGIN_CHAR: {
185                 int sum = 0, stralign;
186
187         stralign = dbind_find_c_alignment (*type - 1);
188
189         while (**type != DBUS_STRUCT_END_CHAR) {
190                         sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type));
191                         sum += dbind_gather_alloc_info_r (type);
192         }
193                 sum = ALIGN_VALUE (sum, stralign);
194
195         g_assert (**type == DBUS_STRUCT_END_CHAR);
196         (*type)++;
197
198                 return sum;
199     }
200     case DBUS_DICT_ENTRY_BEGIN_CHAR: {
201                 int sum = 0, stralign;
202
203         stralign = dbind_find_c_alignment (*type - 1);
204
205         while (**type != DBUS_DICT_ENTRY_END_CHAR) {
206                         sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type));
207                         sum += dbind_gather_alloc_info_r (type);
208         }
209                 sum = ALIGN_VALUE (sum, stralign);
210
211         g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
212         (*type)++;
213
214                 return sum;
215     }
216     case DBUS_TYPE_STRUCT:
217     case DBUS_TYPE_DICT_ENTRY:
218         warn_braces ();
219     default:
220         return 0;
221   }
222 }
223
224 static size_t
225 dbind_gather_alloc_info (const char *type)
226 {
227   return dbind_gather_alloc_info_r (&type);
228 }
229
230 /*---------------------------------------------------------------------------*/
231
232 static void
233 dbind_any_free_r (const char **type, void **data)
234 {
235 #ifdef DEBUG
236     fprintf (stderr, "any free '%c' to %p\n", **type, *data);
237 #endif
238
239     switch (**type) {
240     case DBIND_POD_CASES:
241         *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
242         (*type)++;
243         break;
244     case DBUS_TYPE_STRING:
245     case DBUS_TYPE_OBJECT_PATH:
246     case DBUS_TYPE_SIGNATURE:
247 #ifdef DEBUG
248         fprintf (stderr, "string free %p\n", **(void ***)data);
249 #endif
250         g_free (**(void ***)data);
251         *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
252         (*type)++;
253         break;
254     case DBUS_TYPE_ARRAY: {
255         int i;
256         GArray *vals = **(void ***)data;
257         size_t elem_size, elem_align;
258         const char *saved_child_type;
259
260         (*type)++;
261         saved_child_type = *type;
262
263         elem_size = dbind_gather_alloc_info (*type);
264         elem_align = dbind_find_c_alignment_r (type); 
265
266         for (i = 0; i < vals->len; i++) {
267             void *ptr = vals->data + elem_size * i;
268             *type = saved_child_type; /* rewind type info */
269             ptr = ALIGN_ADDRESS (ptr, elem_align);
270             dbind_any_free_r (type, &ptr);
271         }
272         g_array_free (vals, TRUE);
273         break;
274     }
275     case DBUS_STRUCT_BEGIN_CHAR: {
276                 gconstpointer data0 = *data;
277                 int offset = 0, stralign;
278
279         stralign = dbind_find_c_alignment (*type);
280         (*type)++;
281
282         offset = 0 ;
283         while (**type != DBUS_STRUCT_END_CHAR) {
284             const char *subt = *type;
285                         offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
286                         *data = PTR_PLUS (data0, offset);
287             dbind_any_free_r (type, data);
288             offset += dbind_gather_alloc_info (subt);
289         }
290
291                 offset = ALIGN_VALUE (offset, stralign);
292                 *data = PTR_PLUS (data0, offset);
293
294         g_assert (**type == DBUS_STRUCT_END_CHAR);
295         (*type)++;
296
297         break;
298     }
299     case DBUS_DICT_ENTRY_BEGIN_CHAR: {
300                 gconstpointer data0 = *data;
301                 int offset = 0, stralign;
302
303         stralign = dbind_find_c_alignment (*type);
304         (*type)++;
305
306         offset = 0 ;
307         while (**type != DBUS_DICT_ENTRY_END_CHAR) {
308             const char *subt = *type;
309                         offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
310                         *data = PTR_PLUS (data0, offset);
311             dbind_any_free_r (type, data);
312             offset += dbind_gather_alloc_info (subt);
313         }
314
315                 offset = ALIGN_VALUE (offset, stralign);
316                 *data = PTR_PLUS (data0, offset);
317
318         g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
319         (*type)++;
320
321         break;
322     }
323     case DBUS_TYPE_STRUCT:
324     case DBUS_TYPE_DICT_ENTRY:
325         warn_braces ();
326         break;
327     }
328 }
329
330 /*---------------------------------------------------------------------------*/
331
332 void
333 dbind_any_marshal (DBusMessageIter *iter,
334                    const char           **type,
335                    void           **data)
336 {
337     size_t len;
338
339 #ifdef DEBUG
340     fprintf (stderr, "any marshal '%c' to %p\n", **type, *data);
341 #endif
342
343     switch (**type) {
344     case DBIND_POD_CASES:
345     case DBUS_TYPE_STRING:
346     case DBUS_TYPE_OBJECT_PATH:
347     case DBUS_TYPE_SIGNATURE:
348         len = dbind_gather_alloc_info (*type);
349         dbus_message_iter_append_basic (iter, **type, *data);
350         *data = ((guchar *)*data) + len;
351         (*type)++;
352         break;
353     case DBUS_TYPE_ARRAY: {
354         int i;
355         GArray *vals = **(void ***)data;
356         size_t elem_size, elem_align;
357         DBusMessageIter sub;
358         const char *saved_child_type;
359         char *child_type_string;
360
361         (*type)++;
362         saved_child_type = *type;
363
364         elem_size = dbind_gather_alloc_info (*type);
365         elem_align = dbind_find_c_alignment_r (type); 
366
367         /* wow this part of the API sucks too ... */
368         child_type_string = g_strndup (saved_child_type, *type - saved_child_type);
369         /* fprintf (stderr, "array child type '%s'\n", child_type_string); */
370         dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY,
371                                           child_type_string, &sub);
372         for (i = 0; i < vals->len; i++) {
373             void *ptr = vals->data + elem_size * i;
374             *type = saved_child_type; /* rewind type info */
375             ptr = ALIGN_ADDRESS (ptr, elem_align);
376             dbind_any_marshal (&sub, type, &ptr);
377         }
378
379         dbus_message_iter_close_container (iter, &sub);
380         g_free (child_type_string);
381         break;
382     }
383     case DBUS_STRUCT_BEGIN_CHAR: {
384                 gconstpointer data0 = *data;
385                 int offset = 0, stralign;
386         DBusMessageIter sub;
387
388         stralign = dbind_find_c_alignment (*type);
389
390         (*type)++;
391
392         dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, &sub);
393
394         offset = 0 ;
395         while (**type != DBUS_STRUCT_END_CHAR) {
396             const char *subt = *type;
397                         offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
398                         *data = PTR_PLUS (data0, offset);
399             dbind_any_marshal (&sub, type, data);
400             offset += dbind_gather_alloc_info (subt);
401         }
402
403                 offset = ALIGN_VALUE (offset, stralign);
404                 *data = PTR_PLUS (data0, offset);
405
406         dbus_message_iter_close_container (iter, &sub);
407
408         g_assert (**type == DBUS_STRUCT_END_CHAR);
409         (*type)++;
410
411         break;
412     }
413     case DBUS_DICT_ENTRY_BEGIN_CHAR: {
414                 gconstpointer data0 = *data;
415                 int offset = 0, stralign;
416         DBusMessageIter sub;
417
418         stralign = dbind_find_c_alignment (*type);
419
420         (*type)++;
421
422         dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub);
423
424         offset = 0 ;
425         while (**type != DBUS_DICT_ENTRY_END_CHAR) {
426             const char *subt = *type;
427                         offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
428                         *data = PTR_PLUS (data0, offset);
429             dbind_any_marshal (&sub, type, data);
430             offset += dbind_gather_alloc_info (subt);
431         }
432
433                 offset = ALIGN_VALUE (offset, stralign);
434                 *data = PTR_PLUS (data0, offset);
435
436         dbus_message_iter_close_container (iter, &sub);
437
438         g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
439         (*type)++;
440
441         break;
442     }
443     case DBUS_TYPE_STRUCT:
444     case DBUS_TYPE_DICT_ENTRY:
445         warn_braces ();
446         break;
447     }
448 }
449
450 /*---------------------------------------------------------------------------*/
451
452 void
453 dbind_any_marshal_va (DBusMessageIter *iter,
454                       const char           **arg_types,
455                       va_list          args)
456 {
457     const char *p = *arg_types;
458
459     /* Guard against null arg types 
460        Fix for - http://bugs.freedesktop.org/show_bug.cgi?id=23027
461      */
462     if (p == NULL)
463         p = "";
464
465     {
466         /* special case base-types since we need to walk the stack worse-luck */
467         for (;*p != '\0' && *p != '=';) {
468             int intarg;
469             void *ptrarg;
470             double doublearg;
471             dbus_int64_t int64arg;
472             void *arg = NULL;
473
474             switch (*p) {
475             case DBUS_TYPE_BYTE:
476             case DBUS_TYPE_BOOLEAN:
477             case DBUS_TYPE_INT16:
478             case DBUS_TYPE_UINT16:
479             case DBUS_TYPE_INT32:
480             case DBUS_TYPE_UINT32:
481                 intarg = va_arg (args, int);
482                 arg = &intarg;
483                 break;
484             case DBUS_TYPE_INT64:
485             case DBUS_TYPE_UINT64:
486                 int64arg = va_arg (args, dbus_int64_t);
487                 arg = &int64arg;
488                 break;
489             case DBUS_TYPE_DOUBLE:
490                 doublearg = va_arg (args, double);
491                 arg = &doublearg;
492                 break;
493             /* ptr types */
494             case DBUS_TYPE_STRING:
495             case DBUS_TYPE_OBJECT_PATH:
496             case DBUS_TYPE_SIGNATURE:
497             case DBUS_TYPE_ARRAY:
498             case DBUS_TYPE_DICT_ENTRY:
499                 ptrarg = va_arg (args, void *);
500                 arg = &ptrarg;
501                 break;
502             case DBUS_STRUCT_BEGIN_CHAR:
503                 ptrarg = va_arg (args, void *);
504                 arg = ptrarg;
505                 break;
506             case DBUS_DICT_ENTRY_BEGIN_CHAR:
507                 ptrarg = va_arg (args, void *);
508                 arg = ptrarg;
509                 break;
510
511             case DBUS_TYPE_VARIANT:
512                 fprintf (stderr, "No variant support yet - very toolkit specific\n");
513                 ptrarg = va_arg (args, void *);
514                 arg = &ptrarg;
515                 break;
516             default:
517                 fprintf (stderr, "Unknown / invalid arg type %c\n", *p);
518                 break;
519             }
520             if (arg != NULL)
521                 dbind_any_marshal (iter, &p, &arg);
522             }
523         if (*arg_types)
524           *arg_types = p;
525     }
526 }
527
528 /*---------------------------------------------------------------------------*/
529
530 void
531 dbind_any_demarshal (DBusMessageIter *iter,
532                      const char           **type,
533                      void           **data)
534 {
535     size_t len;
536
537 #ifdef DEBUG
538     fprintf (stderr, "any demarshal '%c' to %p\n", **type, *data);
539 #endif
540
541     switch (**type) {
542     case DBIND_POD_CASES:
543         len = dbind_gather_alloc_info (*type);
544         dbus_message_iter_get_basic (iter, *data);
545         *data = ((guchar *)*data) + len;
546         (*type)++;
547         break;
548     case DBUS_TYPE_STRING:
549     case DBUS_TYPE_OBJECT_PATH:
550     case DBUS_TYPE_SIGNATURE:
551         len = dbind_gather_alloc_info (*type);
552         dbus_message_iter_get_basic (iter, *data);
553 #ifdef DEBUG
554         fprintf (stderr, "dup string '%s' (%p)\n", **(void ***)data, **(void ***)data);
555 #endif
556         **(void ***)data = g_strdup (**(void ***)data);
557         *data = ((guchar *)*data) + len;
558         (*type)++;
559         break;
560     case DBUS_TYPE_ARRAY: {
561         GArray *vals;
562         DBusMessageIter child;
563         size_t elem_size, elem_align;
564         const char *stored_child_type;
565         int i;
566
567         (*type)++;
568         stored_child_type = *type;
569
570         elem_size = dbind_gather_alloc_info (*type);
571         elem_align = dbind_find_c_alignment_r (type);
572         vals = g_array_new (FALSE, FALSE, elem_size);
573         (**(void ***)data) = vals;
574         *data = ((guchar *)*data) + sizeof (void *);
575
576         i = 0;
577         dbus_message_iter_recurse (iter, &child);
578         while (dbus_message_iter_get_arg_type (&child) != DBUS_TYPE_INVALID) {
579             void *ptr;
580             const char *subt = stored_child_type;
581             g_array_set_size (vals, i + 1);
582             ptr = vals->data + elem_size * i;
583             ptr = ALIGN_ADDRESS (ptr, elem_align);
584             dbind_any_demarshal (&child, &subt, &ptr);
585             i++;
586         };
587         break;
588     }
589     case DBUS_STRUCT_BEGIN_CHAR: {
590                 gconstpointer data0 = *data;
591                 int offset = 0, stralign;
592         DBusMessageIter child;
593
594         stralign = dbind_find_c_alignment (*type);
595
596         (*type)++;
597
598         dbus_message_iter_recurse (iter, &child);
599
600         while (**type != DBUS_STRUCT_END_CHAR) {
601             const char *subt = *type;
602                         offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
603                         *data = PTR_PLUS (data0, offset);
604             dbind_any_demarshal (&child, type, data);
605             offset += dbind_gather_alloc_info (subt);
606         }
607
608                 offset = ALIGN_VALUE (offset, stralign);
609                 *data = PTR_PLUS (data0, offset);
610
611         g_assert (**type == DBUS_STRUCT_END_CHAR);
612         (*type)++;
613
614         break;
615     }
616     case DBUS_DICT_ENTRY_BEGIN_CHAR: {
617                 gconstpointer data0 = *data;
618                 int offset = 0, stralign;
619         DBusMessageIter child;
620
621         stralign = dbind_find_c_alignment (*type);
622
623         (*type)++;
624
625         dbus_message_iter_recurse (iter, &child);
626
627         while (**type != DBUS_DICT_ENTRY_END_CHAR) {
628             const char *subt = *type;
629                         offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
630                         *data = PTR_PLUS (data0, offset);
631             dbind_any_demarshal (&child, type, data);
632             offset += dbind_gather_alloc_info (subt);
633         }
634
635                 offset = ALIGN_VALUE (offset, stralign);
636                 *data = PTR_PLUS (data0, offset);
637
638         g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
639         (*type)++;
640
641         break;
642     case DBUS_TYPE_VARIANT:
643         /* skip; unimplemented for now */
644         (*type)++;
645         break;
646     }
647     case DBUS_TYPE_STRUCT:
648     case DBUS_TYPE_DICT_ENTRY:
649         warn_braces ();
650         break;
651     }
652     dbus_message_iter_next (iter);
653 }
654
655 static const char *
656 pass_complex_arg (const char *p, char begin, char end)
657 {
658   int level = 1;
659
660   p++;
661   while (*p && level > 0)
662   {
663     if (*p == begin)
664       level++;
665     else if (*p == end)
666       level--;
667     p++;
668   }
669   if (*p == end)
670     p++;
671   return p;
672 }
673
674 static const char *
675 pass_arg (const char *p)
676 {
677   switch (*p)
678   {
679   case '(':
680     return pass_complex_arg (p, '(', ')');
681   case '{':
682     return pass_complex_arg (p, '{', '}');
683   case 'a':
684     return pass_arg (p+1);
685   default:
686     return p + 1;
687   }
688 }
689
690 /*---------------------------------------------------------------------------*/
691
692 void
693 dbind_any_demarshal_va (DBusMessageIter *iter,
694                         const char           **arg_types,
695                         va_list          args)
696 {
697     const char *p = *arg_types;
698
699         /* Pass in args */
700     for (;*p != '\0' && *p != '=';) {
701         int intarg;
702         void *ptrarg;
703         double doublearg;
704         dbus_int64_t int64arg;
705         void *arg = NULL;
706
707         switch (*p) {
708         case DBUS_TYPE_BYTE:
709         case DBUS_TYPE_BOOLEAN:
710         case DBUS_TYPE_INT16:
711         case DBUS_TYPE_UINT16:
712         case DBUS_TYPE_INT32:
713         case DBUS_TYPE_UINT32:
714             intarg = va_arg (args, int);
715             break;
716         case DBUS_TYPE_INT64:
717         case DBUS_TYPE_UINT64:
718             int64arg = va_arg (args, dbus_int64_t);
719             break;
720         case DBUS_TYPE_DOUBLE:
721             doublearg = va_arg (args, double);
722             break;
723         /* ptr types */
724         case DBUS_TYPE_STRING:
725         case DBUS_TYPE_OBJECT_PATH:
726         case DBUS_TYPE_SIGNATURE:
727         case DBUS_TYPE_ARRAY:
728         case DBUS_TYPE_DICT_ENTRY:
729             ptrarg = va_arg (args, void *);
730             break;
731         case DBUS_STRUCT_BEGIN_CHAR:
732             ptrarg = va_arg (args, void *);
733             break;
734         case DBUS_DICT_ENTRY_BEGIN_CHAR:
735             ptrarg = va_arg (args, void *);
736             break;
737
738         case DBUS_TYPE_VARIANT:
739             fprintf (stderr, "No variant support yet - very toolkit specific\n");
740             ptrarg = va_arg (args, void *);
741             break;
742         default:
743             fprintf (stderr, "Unknown / invalid arg type %c\n", *p);
744             break;
745         }
746       p = pass_arg (p);
747     }
748
749     if (p [0] == '=' && p[1] == '>')
750       p += 2;
751
752     for (;*p != '\0';) {
753         void *arg = va_arg (args, void *);
754         dbind_any_demarshal (iter, &p, &arg);
755     }
756 }
757
758 /*---------------------------------------------------------------------------*/
759
760 /* nice deep free ... */
761 void
762 dbind_any_free (const char *type,
763                 void *ptr)
764 {
765     dbind_any_free_r (&type, &ptr);
766 }
767
768 /* should this be the default normalization ? */
769 void
770 dbind_any_free_ptr (const char *type, void *ptr)
771 {
772     dbind_any_free (type, &ptr);
773 }
774
775 /*---------------------------------------------------------------------------*/
776
777 unsigned int
778 dbind_find_c_alignment (const char *type)
779 {
780     return dbind_find_c_alignment_r (&type);
781 }
782
783 /*END------------------------------------------------------------------------*/