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