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