Add union.test.
[platform/upstream/gobject-introspection.git] / src / gidlnode.c
1 /* GObject introspection: Metadata creation
2  *
3  * Copyright (C) 2005 Matthias Clasen
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <stdio.h>
22 #include <string.h>
23
24 #include "gidlmodule.h"
25 #include "gidlnode.h"
26 #include "gmetadata.h"
27
28 static gulong string_count = 0;
29 static gulong unique_string_count = 0;
30 static gulong string_size = 0;
31 static gulong unique_string_size = 0;
32 static gulong types_count = 0;
33 static gulong unique_types_count = 0;
34
35 void
36 init_stats (void)
37 {
38   string_count = 0;
39   unique_string_count = 0;
40   string_size = 0;
41   unique_string_size = 0;
42   types_count = 0;
43   unique_types_count = 0;
44 }
45
46 void
47 dump_stats (void)
48 {
49   g_message ("%d strings (%d before sharing), %d bytes (%d before sharing)",
50              unique_string_count, string_count, unique_string_size, string_size);
51   g_message ("%d types (%d before sharing)", unique_types_count, types_count);
52 }
53
54
55 #define ALIGN_VALUE(this, boundary) \
56   (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
57
58
59 GIdlNode *
60 g_idl_node_new (GIdlNodeTypeId type)
61 {
62   GIdlNode *node = NULL;
63
64   switch (type)
65     {
66    case G_IDL_NODE_FUNCTION:
67       node = g_malloc0 (sizeof (GIdlNodeFunction));
68       break;
69
70    case G_IDL_NODE_PARAM:
71       node = g_malloc0 (sizeof (GIdlNodeParam));
72       break;
73
74    case G_IDL_NODE_TYPE:
75       node = g_malloc0 (sizeof (GIdlNodeType));
76       break;
77
78     case G_IDL_NODE_OBJECT:
79     case G_IDL_NODE_INTERFACE:
80       node = g_malloc0 (sizeof (GIdlNodeInterface));
81       break;
82
83     case G_IDL_NODE_SIGNAL:
84       node = g_malloc0 (sizeof (GIdlNodeSignal));
85       break;
86
87     case G_IDL_NODE_PROPERTY:
88       node = g_malloc0 (sizeof (GIdlNodeProperty));
89       break;
90
91     case G_IDL_NODE_VFUNC:
92       node = g_malloc0 (sizeof (GIdlNodeFunction));
93       break;
94
95     case G_IDL_NODE_FIELD:
96       node = g_malloc0 (sizeof (GIdlNodeField));
97       break;
98
99     case G_IDL_NODE_ENUM:
100     case G_IDL_NODE_FLAGS:
101       node = g_malloc0 (sizeof (GIdlNodeEnum));
102       break;
103
104     case G_IDL_NODE_BOXED:
105       node = g_malloc0 (sizeof (GIdlNodeBoxed));
106       break;
107
108     case G_IDL_NODE_STRUCT:
109       node = g_malloc0 (sizeof (GIdlNodeStruct));
110       break;
111
112     case G_IDL_NODE_VALUE:
113       node = g_malloc0 (sizeof (GIdlNodeValue));
114       break;
115
116     case G_IDL_NODE_CONSTANT:
117       node = g_malloc0 (sizeof (GIdlNodeConstant));
118       break;
119
120     case G_IDL_NODE_ERROR_DOMAIN:
121       node = g_malloc0 (sizeof (GIdlNodeErrorDomain));
122       break;
123
124     case G_IDL_NODE_XREF:
125       node = g_malloc0 (sizeof (GIdlNodeXRef));
126       break;
127
128     case G_IDL_NODE_UNION:
129       node = g_malloc0 (sizeof (GIdlNodeUnion));
130       break;
131
132     default:
133       g_error ("Unhandled node type %d\n", type);
134       break;
135     }
136
137   node->type = type;
138
139   return node;
140 }
141
142 void
143 g_idl_node_free (GIdlNode *node)
144 {
145   GList *l;
146
147   if (node == NULL)
148     return;
149
150   switch (node->type)
151     {
152     case G_IDL_NODE_FUNCTION:
153     case G_IDL_NODE_CALLBACK:
154       {
155         GIdlNodeFunction *function = (GIdlNodeFunction *)node;
156         
157         g_free (node->name);
158         g_free (function->symbol);
159         g_idl_node_free ((GIdlNode *)function->result);
160         for (l = function->parameters; l; l = l->next)
161           g_idl_node_free ((GIdlNode *)l->data);
162         g_list_free (function->parameters);
163       }
164       break;
165
166     case G_IDL_NODE_TYPE:
167       {
168         GIdlNodeType *type = (GIdlNodeType *)node;
169         
170         g_free (node->name);
171         g_idl_node_free ((GIdlNode *)type->parameter_type1);
172         g_idl_node_free ((GIdlNode *)type->parameter_type2);
173
174         g_free (type->interface);
175         g_strfreev (type->errors);
176
177       }
178       break;
179
180     case G_IDL_NODE_PARAM:
181       {
182         GIdlNodeParam *param = (GIdlNodeParam *)node;
183         
184         g_free (node->name);
185         g_idl_node_free ((GIdlNode *)param->type);
186       }
187       break;
188
189     case G_IDL_NODE_PROPERTY:
190       {
191         GIdlNodeProperty *property = (GIdlNodeProperty *)node;
192         
193         g_free (node->name);
194         g_idl_node_free ((GIdlNode *)property->type);
195       }
196       break;
197
198     case G_IDL_NODE_SIGNAL:
199       {
200         GIdlNodeSignal *signal = (GIdlNodeSignal *)node;
201         
202         g_free (node->name);
203         for (l = signal->parameters; l; l = l->next)
204           g_idl_node_free ((GIdlNode *)l->data);
205         g_list_free (signal->parameters);
206         g_idl_node_free ((GIdlNode *)signal->result);
207       }
208       break;
209
210     case G_IDL_NODE_VFUNC:
211       {
212         GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)node;
213         
214         g_free (node->name);
215         for (l = vfunc->parameters; l; l = l->next)
216           g_idl_node_free ((GIdlNode *)l->data);
217         g_list_free (vfunc->parameters);
218         g_idl_node_free ((GIdlNode *)vfunc->result);
219       }
220       break;
221
222     case G_IDL_NODE_FIELD:
223       {
224         GIdlNodeField *field = (GIdlNodeField *)node;
225         
226         g_free (node->name);
227         g_idl_node_free ((GIdlNode *)field->type);
228       }
229       break;
230
231     case G_IDL_NODE_OBJECT:
232     case G_IDL_NODE_INTERFACE:
233       {
234         GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
235         
236         g_free (node->name);
237         g_free (iface->gtype_name);
238         g_free (iface->gtype_init);
239         
240         g_free (iface->parent);
241
242         for (l = iface->interfaces; l; l = l->next)
243           g_free ((GIdlNode *)l->data);
244         g_list_free (iface->interfaces);
245
246         for (l = iface->members; l; l = l->next)
247           g_idl_node_free ((GIdlNode *)l->data);
248         g_list_free (iface->members);
249
250       }
251       break;
252  
253     case G_IDL_NODE_VALUE:
254       {
255         GIdlNodeValue *value = (GIdlNodeValue *)node;
256         
257         g_free (node->name);
258       }
259       break;
260
261     case G_IDL_NODE_ENUM:
262     case G_IDL_NODE_FLAGS:
263       {
264         GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
265         
266         g_free (node->name);
267         g_free (enum_->gtype_name);
268         g_free (enum_->gtype_init);
269
270         for (l = enum_->values; l; l = l->next)
271           g_idl_node_free ((GIdlNode *)l->data);
272         g_list_free (enum_->values);
273       }
274       break;
275
276     case G_IDL_NODE_BOXED:
277       {
278         GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
279         
280         g_free (node->name);
281         g_free (boxed->gtype_name);
282         g_free (boxed->gtype_init);
283
284         for (l = boxed->members; l; l = l->next)
285           g_idl_node_free ((GIdlNode *)l->data);
286         g_list_free (boxed->members);
287       }
288       break;
289
290     case G_IDL_NODE_STRUCT:
291       {
292         GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node;
293
294         g_free (node->name);
295         for (l = struct_->members; l; l = l->next)
296           g_idl_node_free ((GIdlNode *)l->data);
297         g_list_free (struct_->members);
298       }
299       break;
300
301     case G_IDL_NODE_CONSTANT:
302       {
303         GIdlNodeConstant *constant = (GIdlNodeConstant *)node;
304         
305         g_free (node->name);
306         g_free (constant->value);
307         g_idl_node_free ((GIdlNode *)constant->type);
308       }
309       break;
310
311     case G_IDL_NODE_ERROR_DOMAIN:
312       {
313         GIdlNodeErrorDomain *domain = (GIdlNodeErrorDomain *)node;
314         
315         g_free (node->name);
316         g_free (domain->getquark);
317         g_free (domain->codes);
318       }
319       break;
320
321     case G_IDL_NODE_XREF:
322       {
323         GIdlNodeXRef *xref = (GIdlNodeXRef *)node;
324         
325         g_free (node->name);
326         g_free (xref->namespace);
327       }
328       break;
329
330     case G_IDL_NODE_UNION:
331       {
332         GIdlNodeUnion *union_ = (GIdlNodeUnion *)node;
333         
334         g_free (node->name);
335         g_free (union_->gtype_name);
336         g_free (union_->gtype_init);
337
338         g_idl_node_free ((GIdlNode *)union_->discriminator_type);
339         for (l = union_->members; l; l = l->next)
340           g_idl_node_free ((GIdlNode *)l->data);
341         for (l = union_->discriminators; l; l = l->next)
342           g_idl_node_free ((GIdlNode *)l->data);
343       }
344       break;
345
346     default:
347       g_error ("Unhandled node type %d\n", node->type);
348       break;
349     } 
350
351   g_free (node);
352 }
353
354 /* returns the fixed size of the blob */
355 guint32
356 g_idl_node_get_size (GIdlNode *node)
357 {
358   GList *l;
359   gint size, n;
360
361   switch (node->type)
362     {
363     case G_IDL_NODE_CALLBACK:
364       size = 12; 
365       break;
366
367     case G_IDL_NODE_FUNCTION:
368       size = 16; 
369       break;
370
371     case G_IDL_NODE_PARAM:
372       size = 12;
373       break;
374
375     case G_IDL_NODE_TYPE:
376       size = 4;
377       break;
378
379     case G_IDL_NODE_OBJECT:
380       {
381         GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
382
383         n = g_list_length (iface->interfaces);
384         size = 32 + 2 * (n + (n % 2));
385
386         for (l = iface->members; l; l = l->next)
387           size += g_idl_node_get_size ((GIdlNode *)l->data);
388       }
389       break;
390
391     case G_IDL_NODE_INTERFACE:
392       {
393         GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
394
395         n = g_list_length (iface->prerequisites);
396         size = 28 + 2 * (n + (n % 2));
397
398         for (l = iface->members; l; l = l->next)
399           size += g_idl_node_get_size ((GIdlNode *)l->data);
400       }
401       break;
402
403     case G_IDL_NODE_ENUM:
404     case G_IDL_NODE_FLAGS:
405       {
406         GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
407         
408         n = g_list_length (enum_->values);
409         size = 20 + n * 16;
410       }
411       break;
412
413     case G_IDL_NODE_VALUE:
414       size = 12;
415       break;
416
417     case G_IDL_NODE_STRUCT:
418       {
419         GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node;
420
421         size = 20;
422         for (l = struct_->members; l; l = l->next)
423           size += g_idl_node_get_size ((GIdlNode *)l->data);
424       }
425       break;
426
427     case G_IDL_NODE_BOXED:
428       {
429         GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
430
431         size = 20;
432         for (l = boxed->members; l; l = l->next)
433           size += g_idl_node_get_size ((GIdlNode *)l->data);
434       }
435       break;
436
437     case G_IDL_NODE_PROPERTY:
438       size = 12;
439       break;
440
441     case G_IDL_NODE_SIGNAL:
442       size = 12;
443       break;
444
445     case G_IDL_NODE_VFUNC:
446       size = 16;
447       break;
448
449     case G_IDL_NODE_FIELD:
450       size = 12;
451       break;
452
453     case G_IDL_NODE_CONSTANT:
454       size = 20;
455       break;
456
457     case G_IDL_NODE_ERROR_DOMAIN:
458       size = 16;
459       break;
460
461     case G_IDL_NODE_XREF:
462       size = 0;
463       break;
464
465     case G_IDL_NODE_UNION:
466       {
467         GIdlNodeUnion *union_ = (GIdlNodeUnion *)node;
468
469         size = 28;
470         for (l = union_->members; l; l = l->next)
471           size += g_idl_node_get_size ((GIdlNode *)l->data);
472         for (l = union_->discriminators; l; l = l->next)
473           size += g_idl_node_get_size ((GIdlNode *)l->data);
474       }
475       break;
476
477     default: 
478       g_error ("Unhandled node type %d\n", node->type);
479       size = 0;
480     }
481
482   g_debug ("node %d type %d size %d", node, node->type, size);
483
484   return size;
485 }
486
487 /* returns the full size of the blob including variable-size parts */
488 guint32
489 g_idl_node_get_full_size (GIdlNode *node)
490 {
491   GList *l;
492   gint size, n;
493
494   g_assert (node != NULL);
495
496   switch (node->type)
497     {
498     case G_IDL_NODE_CALLBACK:
499       {
500         GIdlNodeFunction *function = (GIdlNodeFunction *)node;
501         size = 12; 
502         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
503         for (l = function->parameters; l; l = l->next)
504           size += g_idl_node_get_full_size ((GIdlNode *)l->data);
505         size += g_idl_node_get_full_size ((GIdlNode *)function->result);
506       }
507       break;
508
509     case G_IDL_NODE_FUNCTION:
510       {
511         GIdlNodeFunction *function = (GIdlNodeFunction *)node;
512         size = 16;
513         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
514         size += ALIGN_VALUE (strlen (function->symbol) + 1, 4);
515         for (l = function->parameters; l; l = l->next)
516           size += g_idl_node_get_full_size ((GIdlNode *)l->data);
517         size += g_idl_node_get_full_size ((GIdlNode *)function->result);
518       }
519       break;
520
521     case G_IDL_NODE_PARAM:
522       {
523         GIdlNodeParam *param = (GIdlNodeParam *)node;
524         
525         size = 12;
526         if (node->name)
527           size += ALIGN_VALUE (strlen (node->name) + 1, 4);
528         size += g_idl_node_get_full_size ((GIdlNode *)param->type);     
529       }
530       break;
531
532     case G_IDL_NODE_TYPE:
533       {
534         GIdlNodeType *type = (GIdlNodeType *)node;
535         if (type->tag < 20) 
536           size = 4;
537         else
538           {
539             switch (type->tag)
540               {
541               case 20:
542                 size = 4 + 4 + g_idl_node_get_full_size ((GIdlNode *)type->parameter_type1);
543                 break;
544               case 21:
545                 size = 4 + 4;
546                 break;
547               case 22:
548               case 23:
549                 size = 4 + 4 + g_idl_node_get_full_size ((GIdlNode *)type->parameter_type1);
550                 break;
551               case 24:
552                 size = 4 + 4 + 4
553                   + g_idl_node_get_full_size ((GIdlNode *)type->parameter_type1)
554                   + g_idl_node_get_full_size ((GIdlNode *)type->parameter_type2);
555                 break;
556               case 25:
557                 {
558                   gint n = g_strv_length (type->errors);
559                   size = 4 + 4 + 2 * (n + n % 2);
560                 }
561                 break;
562               default:
563                 g_error ("Unknown type tag %d\n", type->tag);
564                 break;
565               }
566           }
567       }
568       break;
569
570     case G_IDL_NODE_OBJECT:
571       {
572         GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
573
574         n = g_list_length (iface->interfaces);
575         size = 32;
576         if (iface->parent)
577           size += ALIGN_VALUE (strlen (iface->parent) + 1, 4);
578         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
579         size += ALIGN_VALUE (strlen (iface->gtype_name) + 1, 4);
580         size += ALIGN_VALUE (strlen (iface->gtype_init) + 1, 4);
581         size += 2 * (n + (n % 2));
582
583         for (l = iface->members; l; l = l->next)
584           size += g_idl_node_get_full_size ((GIdlNode *)l->data);
585       }
586       break;
587
588     case G_IDL_NODE_INTERFACE:
589       {
590         GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
591
592         n = g_list_length (iface->prerequisites);
593         size = 28;
594         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
595         size += ALIGN_VALUE (strlen (iface->gtype_name) + 1, 4);
596         size += ALIGN_VALUE (strlen (iface->gtype_init) + 1, 4);
597         size += 2 * (n + (n % 2));
598
599         for (l = iface->members; l; l = l->next)
600           size += g_idl_node_get_full_size ((GIdlNode *)l->data);
601       }
602       break;
603
604     case G_IDL_NODE_ENUM:
605     case G_IDL_NODE_FLAGS:
606       {
607         GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
608         
609         size = 20;
610         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
611         if (enum_->gtype_name)
612           {
613             size += ALIGN_VALUE (strlen (enum_->gtype_name) + 1, 4);
614             size += ALIGN_VALUE (strlen (enum_->gtype_init) + 1, 4);
615           }
616
617         for (l = enum_->values; l; l = l->next)
618           size += g_idl_node_get_full_size ((GIdlNode *)l->data);       
619       }
620       break;
621
622     case G_IDL_NODE_VALUE:
623       {
624         GIdlNodeValue *value = (GIdlNodeValue *)node;
625         
626         size = 12;
627         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
628       }
629       break;
630
631     case G_IDL_NODE_STRUCT:
632       {
633         GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node;
634
635         size = 20;
636         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
637         for (l = struct_->members; l; l = l->next)
638           size += g_idl_node_get_full_size ((GIdlNode *)l->data);
639       }
640       break;
641
642     case G_IDL_NODE_BOXED:
643       {
644         GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
645
646         size = 20;
647         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
648         if (boxed->gtype_name)
649           {
650             size += ALIGN_VALUE (strlen (boxed->gtype_name) + 1, 4);
651             size += ALIGN_VALUE (strlen (boxed->gtype_init) + 1, 4);
652           }
653         for (l = boxed->members; l; l = l->next)
654           size += g_idl_node_get_full_size ((GIdlNode *)l->data);
655       }
656       break;
657
658     case G_IDL_NODE_PROPERTY:
659       {
660         GIdlNodeProperty *prop = (GIdlNodeProperty *)node;
661         
662         size = 12;
663         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
664         size += g_idl_node_get_full_size ((GIdlNode *)prop->type);      
665       }
666       break;
667
668     case G_IDL_NODE_SIGNAL:
669       {
670         GIdlNodeSignal *signal = (GIdlNodeSignal *)node;
671
672         size = 12;
673         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
674         for (l = signal->parameters; l; l = l->next)
675           size += g_idl_node_get_full_size ((GIdlNode *)l->data);
676         size += g_idl_node_get_full_size ((GIdlNode *)signal->result);
677       }
678       break;
679
680     case G_IDL_NODE_VFUNC:
681       {
682         GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)node;
683
684         size = 16;
685         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
686         for (l = vfunc->parameters; l; l = l->next)
687           size += g_idl_node_get_full_size ((GIdlNode *)l->data);
688         size += g_idl_node_get_full_size ((GIdlNode *)vfunc->result);
689       }
690       break;
691
692     case G_IDL_NODE_FIELD:
693       {
694         GIdlNodeField *field = (GIdlNodeField *)node;
695
696         size = 12;
697         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
698         size += g_idl_node_get_full_size ((GIdlNode *)field->type);     
699       }
700       break;
701
702     case G_IDL_NODE_CONSTANT:
703       {
704         GIdlNodeConstant *constant = (GIdlNodeConstant *)node;
705
706         size = 20;
707         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
708         /* FIXME non-string values */
709         size += ALIGN_VALUE (strlen (constant->value) + 1, 4);
710         size += g_idl_node_get_full_size ((GIdlNode *)constant->type);  
711       }
712       break;
713
714     case G_IDL_NODE_ERROR_DOMAIN:
715       {
716         GIdlNodeErrorDomain *domain = (GIdlNodeErrorDomain *)node;
717
718         size = 16;
719         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
720         size += ALIGN_VALUE (strlen (domain->getquark) + 1, 4);
721       }
722       break;
723
724     case G_IDL_NODE_XREF:
725       {
726         GIdlNodeXRef *xref = (GIdlNodeXRef *)node;
727         
728         size = 0;
729         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
730         size += ALIGN_VALUE (strlen (xref->namespace) + 1, 4);
731       }
732       break;
733
734     case G_IDL_NODE_UNION:
735       {
736         GIdlNodeUnion *union_ = (GIdlNodeUnion *)node;
737
738         size = 28;
739         size += ALIGN_VALUE (strlen (node->name) + 1, 4);
740         for (l = union_->members; l; l = l->next)
741           size += g_idl_node_get_full_size ((GIdlNode *)l->data);
742         for (l = union_->discriminators; l; l = l->next)
743           size += g_idl_node_get_full_size ((GIdlNode *)l->data);
744       }
745       break;
746
747     default: 
748       g_error ("Unknown type tag %d\n", node->type);
749       size = 0;
750     }
751
752   g_debug ("node %d type %d full size %d", node, node->type, size);
753
754   return size;
755 }
756
757 static gint64
758 parse_int_value (const gchar *str)
759 {
760   return strtoll (str, NULL, 0);
761 }
762
763 static guint64
764 parse_uint_value (const gchar *str)
765 {
766   return strtoull (str, NULL, 0);
767 }
768
769 static gdouble
770 parse_float_value (const gchar *str)
771 {
772   return strtod (str, NULL);
773 }
774
775 static gboolean
776 parse_boolean_value (const gchar *str)
777 {
778   if (strcmp (str, "TRUE") == 0)
779     return TRUE;
780   
781   if (strcmp (str, "FALSE") == 0)
782     return FALSE;
783
784   return parse_int_value (str) ? TRUE : FALSE;
785 }
786
787 static GIdlNode *
788 find_entry_node (GIdlModule  *module,
789                  GList       *modules,
790                  const gchar *name,
791                  guint16     *idx)
792
793 {
794   GList *l;
795   gint i;
796   gchar **names;
797   gint n_names;
798   GIdlNode *result = NULL;
799
800   names = g_strsplit (name, ".", 0);
801   n_names = g_strv_length (names);
802   if (n_names > 2)
803     g_error ("Too many name parts");
804   
805   for (l = module->entries, i = 0; l; l = l->next, i++)
806     {
807       GIdlNode *node = (GIdlNode *)l->data;
808       
809       if (n_names > 1)
810         {
811           if (node->type != G_IDL_NODE_XREF)
812             continue;
813           
814           if (((GIdlNodeXRef *)node)->namespace == NULL ||
815               strcmp (((GIdlNodeXRef *)node)->namespace, names[0]) != 0)
816             continue;
817         }
818          
819       if (strcmp (node->name, names[n_names - 1]) == 0)
820         {
821           if (idx)
822             *idx = i;
823           
824           result = node;
825           goto out;
826         }
827     }
828
829   if (n_names > 1)
830     {
831       GIdlNode *node = g_idl_node_new (G_IDL_NODE_XREF);
832
833       ((GIdlNodeXRef *)node)->namespace = g_strdup (names[0]);
834       node->name = g_strdup (names[1]);
835   
836       module->entries = g_list_append (module->entries, node);
837   
838       if (idx)
839         *idx = g_list_length (module->entries) - 1;
840
841       result = node;
842
843       goto out;
844     }
845
846   g_warning ("Entry %s not found", name);
847
848  out:
849
850   g_strfreev (names);
851
852   return result;
853 }
854
855 static guint16
856 find_entry (GIdlModule  *module,
857             GList       *modules,
858             const gchar *name)
859 {
860   guint16 idx = 0;
861
862   find_entry_node (module, modules, name, &idx);
863
864   return idx;
865 }
866
867 static void
868 serialize_type (GIdlModule   *module, 
869                 GList        *modules,
870                 GIdlNodeType *node, 
871                 GString      *str)
872 {
873   gint i;
874   
875   const gchar* basic[] = {
876     "void", 
877     "gboolean", 
878     "gint8", 
879     "guint8", 
880     "gint16", 
881     "guint16", 
882     "gint32", 
883     "guint32", 
884     "gint64", 
885     "guint64", 
886     "gfloat", 
887     "gdouble", 
888     "gchar", 
889     "GString", 
890     "gint", 
891     "guint", 
892     "glong", 
893     "gulong"
894   };
895
896   if (node->tag < 20)
897     {
898       g_string_append_printf (str, "%s%s", 
899                               basic[node->tag], node->is_pointer ? "*" : "");
900     }
901   else if (node->tag == 20)
902     {
903       serialize_type (module, modules, node->parameter_type1, str);
904       g_string_append (str, "[");
905
906       if (node->has_length)
907         g_string_append_printf (str, "length=%d", node->length);
908       
909       if (node->zero_terminated)
910         g_string_append_printf (str, "%szero-terminated=1", 
911                                 node->has_length ? "," : "");
912       
913       g_string_append (str, "]");
914     }
915   else if (node->tag == 21)
916     {
917       GIdlNode *iface;
918       gchar *name;
919
920       iface = find_entry_node (module, modules, node->interface, NULL);
921       if (iface)
922         name = iface->name;
923       else
924         {
925           g_warning ("Interface for type reference %s not found", node->interface);
926           name = node->interface;
927         }
928
929       g_string_append_printf (str, "%s%s", name, node->is_pointer ? "*" : "");
930     }
931   else if (node->tag == 22)
932     {
933       g_string_append (str, "GList<");
934       serialize_type (module, modules, node->parameter_type1, str);
935       g_string_append (str, ">"); 
936     }
937   else if (node->tag == 23)
938     {
939       g_string_append (str, "GSList<");
940       serialize_type (module, modules, node->parameter_type1, str);
941       g_string_append (str, ">"); 
942     }
943   else if (node->tag == 24)
944     {
945       g_string_append (str, "GHashTable<");
946       serialize_type (module, modules, node->parameter_type1, str);
947       g_string_append (str, ","); 
948       serialize_type (module, modules, node->parameter_type2, str);
949       g_string_append (str, ">"); 
950     }
951   else if (node->tag == 25) 
952     {
953       g_string_append (str, "GError<");
954       for (i = 0; node->errors[i]; i++)
955         {
956           if (i > 0)
957             g_string_append (str, ",");
958           g_string_append (str, node->errors[i]);
959         }
960       g_string_append (str, ">"); 
961     }
962 }
963
964 void
965 g_idl_node_build_metadata (GIdlNode   *node,
966                            GIdlModule *module,
967                            GList      *modules,
968                            GHashTable *strings,
969                            GHashTable *types,
970                            guchar     *data,
971                            guint32    *offset,
972                            guint32    *offset2)
973 {
974   GList *l;
975   guint32 old_offset = *offset;
976   guint32 old_offset2 = *offset2;
977
978   switch (node->type)
979     {
980     case G_IDL_NODE_TYPE:
981       {
982         GIdlNodeType *type = (GIdlNodeType *)node;
983         SimpleTypeBlob *blob = (SimpleTypeBlob *)&data[*offset];
984
985         *offset += 4;
986         
987         if (type->tag < 20)
988           {
989             blob->reserved = 0;
990             blob->reserved2 = 0;
991             blob->pointer = type->is_pointer;
992             blob->reserved3 = 0;
993             blob->tag = type->tag;
994           }
995         else 
996           {
997             GString *str;
998             gchar *s;
999             gpointer value;
1000             
1001             str = g_string_new (0);
1002             serialize_type (module, modules, type, str);
1003             s = g_string_free (str, FALSE);
1004             
1005             types_count += 1;
1006             value = g_hash_table_lookup (types, s);
1007             if (value)
1008               {
1009                 blob->offset = GPOINTER_TO_INT (value);
1010                 g_free (s);
1011               }
1012             else
1013               {
1014                 unique_types_count += 1;
1015                 g_hash_table_insert (types, s, GINT_TO_POINTER(*offset2));
1016                                      
1017                 blob->offset = *offset2;
1018                 switch (type->tag)
1019                   {
1020                   case 20:
1021                     {
1022                       ArrayTypeBlob *array = (ArrayTypeBlob *)&data[*offset2];
1023                       guint32 pos;
1024                       
1025                       array->pointer = 1;
1026                       array->reserved = 0;
1027                       array->tag = type->tag;
1028                       array->zero_terminated = type->zero_terminated;
1029                       array->has_length = type->has_length;
1030                       array->reserved2 = 0;
1031                       array->length = type->length;
1032                       
1033                       pos = *offset2 + 4;
1034                       *offset2 += 8;
1035                       
1036                       g_idl_node_build_metadata ((GIdlNode *)type->parameter_type1, 
1037                                                  module, modules, strings, types, 
1038                                                  data, &pos, offset2);
1039                     }
1040                     break;
1041                     
1042                   case 21:
1043                     {
1044                       InterfaceTypeBlob *iface = (InterfaceTypeBlob *)&data[*offset2];
1045                       *offset2 += 4;
1046                       
1047                       iface->pointer = 1;
1048                       iface->reserved = 0;
1049                       iface->tag = type->tag;
1050                       iface->reserved2 = 0;
1051                       iface->interface = find_entry (module, modules, type->interface);
1052                     }
1053                     break;
1054                     
1055                   case 22:
1056                   case 23:
1057                     {
1058                       ParamTypeBlob *param = (ParamTypeBlob *)&data[*offset2];
1059                       guint32 pos;
1060                       
1061                       param->pointer = 1;
1062                       param->reserved = 0;
1063                       param->tag = type->tag;
1064                       param->reserved2 = 0;
1065                       param->n_types = 1;
1066                       
1067                       pos = *offset2 + 4;
1068                       *offset2 += 8;
1069                       
1070                       g_idl_node_build_metadata ((GIdlNode *)type->parameter_type1, 
1071                                                  module, modules, strings, types,
1072                                                  data, &pos, offset2);
1073                     }
1074                     break;
1075                     
1076                   case 24:
1077                     {
1078                       ParamTypeBlob *param = (ParamTypeBlob *)&data[*offset2];
1079                       guint32 pos;
1080                       
1081                       param->pointer = 1;
1082                       param->reserved = 0;
1083                       param->tag = type->tag;
1084                       param->reserved2 = 0;
1085                       param->n_types = 2;
1086                       
1087                       pos = *offset2 + 4;
1088                       *offset2 += 12;
1089                       
1090                       g_idl_node_build_metadata ((GIdlNode *)type->parameter_type1, 
1091                                                  module, modules, strings, types, 
1092                                                  data, &pos, offset2);
1093                       g_idl_node_build_metadata ((GIdlNode *)type->parameter_type2, 
1094                                                  module, modules, strings, types, 
1095                                                  data, &pos, offset2);
1096                     }
1097                     break;
1098                     
1099                   case 25:
1100                     {
1101                       ErrorTypeBlob *blob = (ErrorTypeBlob *)&data[*offset2];
1102                       gint i, domain;
1103                       
1104                       blob->pointer = 1;
1105                       blob->reserved = 0;
1106                       blob->tag = type->tag;
1107                       blob->reserved2 = 0;
1108                       blob->n_domains = g_strv_length (type->errors);
1109                       
1110                       *offset2 = ALIGN_VALUE (*offset2 + 4 + 2 * blob->n_domains, 4);
1111                       for (i = 0; type->errors[i]; i++)
1112                         blob->domains[i] = find_entry (module, modules, type->errors[i]);
1113                     }
1114                     break;
1115                     
1116                   default:
1117                     g_error ("Unknown type tag %d\n", type->tag);
1118                     break;
1119                   }
1120               }
1121           }
1122       }
1123       break;
1124
1125     case G_IDL_NODE_FIELD:
1126       {
1127         GIdlNodeField *field = (GIdlNodeField *)node;
1128         FieldBlob *blob;
1129
1130         blob = (FieldBlob *)&data[*offset];
1131         *offset += 8;
1132
1133         blob->name = write_string (node->name, strings, data, offset2);
1134         blob->readable = field->readable;
1135         blob->writable = field->writable;
1136         blob->reserved = 0;
1137         blob->bits = 0;
1138         blob->struct_offset = 0;
1139
1140         g_idl_node_build_metadata ((GIdlNode *)field->type, 
1141                                    module, modules, strings, types,
1142                                    data, offset, offset2);
1143       }
1144       break;
1145
1146     case G_IDL_NODE_PROPERTY:
1147       {
1148         GIdlNodeProperty *prop = (GIdlNodeProperty *)node;
1149         PropertyBlob *blob = (PropertyBlob *)&data[*offset];
1150         *offset += 8;
1151
1152         blob->name = write_string (node->name, strings, data, offset2);
1153         blob->deprecated = prop->deprecated;
1154         blob->readable = prop->readable;
1155         blob->writable = prop->writable;
1156         blob->construct = prop->construct;
1157         blob->construct_only = prop->construct_only;
1158         blob->reserved = 0;
1159
1160         g_idl_node_build_metadata ((GIdlNode *)prop->type, 
1161                                    module, modules, strings, types,
1162                                    data, offset, offset2);
1163       }
1164       break;
1165
1166     case G_IDL_NODE_FUNCTION:
1167       {
1168         FunctionBlob *blob = (FunctionBlob *)&data[*offset];
1169         SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
1170         GIdlNodeFunction *function = (GIdlNodeFunction *)node;
1171         guint32 signature, res;
1172         gint n;
1173
1174         signature = *offset2;
1175         n = g_list_length (function->parameters);
1176
1177         *offset += 16;
1178         *offset2 += 8 + n * 12;
1179
1180         blob->blob_type = BLOB_TYPE_FUNCTION;
1181         blob->deprecated = function->deprecated;
1182         blob->setter = function->is_setter;
1183         blob->getter = function->is_getter;
1184         blob->constructor = function->is_constructor;
1185         blob->wraps_vfunc = function->wraps_vfunc;
1186         blob->reserved = 0;
1187         blob->index = 0;
1188         blob->name = write_string (node->name, strings, data, offset2);
1189         blob->symbol = write_string (function->symbol, strings, data, offset2);
1190         blob->signature = signature;
1191         
1192         g_idl_node_build_metadata ((GIdlNode *)function->result->type, 
1193                                    module, modules, strings, types,
1194                                    data, &signature, offset2);
1195
1196         blob2->may_return_null = function->result->null_ok;
1197         blob2->caller_owns_return_value = function->result->transfer;
1198         blob2->caller_owns_return_container = function->result->shallow_transfer;
1199         blob2->reserved = 0;
1200         blob2->n_arguments = n;
1201
1202         signature += 4;
1203         
1204         for (l = function->parameters; l; l = l->next)
1205           {
1206             GIdlNode *param = (GIdlNode *)l->data;
1207
1208             g_idl_node_build_metadata (param, 
1209                                        module, modules, strings, types,
1210                                        data, &signature, offset2);
1211           }
1212       }
1213       break;
1214
1215     case G_IDL_NODE_CALLBACK:
1216       {
1217         CallbackBlob *blob = (CallbackBlob *)&data[*offset];
1218         SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
1219         GIdlNodeFunction *function = (GIdlNodeFunction *)node;
1220         guint32 signature, res;
1221         gint n;
1222
1223         signature = *offset2;
1224         n = g_list_length (function->parameters);
1225
1226         *offset += 12;
1227         *offset2 += 8 + n * 12;
1228
1229         blob->blob_type = BLOB_TYPE_CALLBACK;
1230         blob->deprecated = function->deprecated;
1231         blob->reserved = 0;
1232         blob->name = write_string (node->name, strings, data, offset2);
1233         blob->signature = signature;
1234         
1235         g_idl_node_build_metadata ((GIdlNode *)function->result->type, 
1236                                    module, modules, strings, types,
1237                                    data, &signature, offset2);
1238
1239         blob2->may_return_null = function->result->null_ok;
1240         blob2->caller_owns_return_value = function->result->transfer;
1241         blob2->caller_owns_return_container = function->result->shallow_transfer;
1242         blob2->reserved = 0;
1243         blob2->n_arguments = n;
1244
1245         signature += 4;
1246         
1247         for (l = function->parameters; l; l = l->next)
1248           {
1249             GIdlNode *param = (GIdlNode *)l->data;
1250
1251             g_idl_node_build_metadata (param, 
1252                                        module, modules, strings, types,
1253                                        data, &signature, offset2);
1254           }
1255       }
1256       break;
1257
1258     case G_IDL_NODE_SIGNAL:
1259       {
1260         SignalBlob *blob = (SignalBlob *)&data[*offset];
1261         SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
1262         GIdlNodeSignal *signal = (GIdlNodeSignal *)node;
1263         guint32 signature, res;
1264         gint n;
1265
1266         signature = *offset2;
1267         n = g_list_length (signal->parameters);
1268
1269         *offset += 12;
1270         *offset2 += 8 + n * 12;
1271
1272         blob->deprecated = signal->deprecated;
1273         blob->run_first = signal->run_first;
1274         blob->run_last = signal->run_last;
1275         blob->run_cleanup = signal->run_cleanup;
1276         blob->no_recurse = signal->no_recurse;
1277         blob->detailed = signal->detailed;
1278         blob->action = signal->action;
1279         blob->no_hooks = signal->no_hooks;
1280         blob->has_class_closure = 0; /* FIXME */
1281         blob->true_stops_emit = 0; /* FIXME */
1282         blob->reserved = 0;
1283         blob->class_closure = 0; /* FIXME */
1284         blob->name = write_string (node->name, strings, data, offset2);
1285         blob->signature = signature;
1286         
1287         g_idl_node_build_metadata ((GIdlNode *)signal->result->type, 
1288                                    module, modules, strings, types,
1289                                    data, &signature, offset2);
1290
1291         blob2->may_return_null = signal->result->null_ok;
1292         blob2->caller_owns_return_value = signal->result->transfer;
1293         blob2->caller_owns_return_container = signal->result->shallow_transfer;
1294         blob2->reserved = 0;
1295         blob2->n_arguments = n;
1296
1297         signature += 4;
1298         
1299         for (l = signal->parameters; l; l = l->next)
1300           {
1301             GIdlNode *param = (GIdlNode *)l->data;
1302
1303             g_idl_node_build_metadata (param, module, modules, strings, types,
1304                                        data, &signature, offset2);
1305           }
1306       }
1307       break;
1308
1309     case G_IDL_NODE_VFUNC:
1310       {
1311         VFuncBlob *blob = (VFuncBlob *)&data[*offset];
1312         SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
1313         GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)node;
1314         guint32 signature, res;
1315         gint n;
1316
1317         signature = *offset2;
1318         n = g_list_length (vfunc->parameters);
1319
1320         *offset += 16;
1321         *offset2 += 8 + n * 12;
1322
1323         blob->name = write_string (node->name, strings, data, offset2);
1324         blob->must_chain_up = 0; /* FIXME */
1325         blob->must_be_implemented = 0; /* FIXME */
1326         blob->must_not_be_implemented = 0; /* FIXME */
1327         blob->class_closure = 0; /* FIXME */
1328         blob->reserved = 0;
1329
1330         blob->struct_offset = 0; /* FIXME */
1331         blob->reserved2 = 0;
1332         blob->signature = signature;
1333         
1334         g_idl_node_build_metadata ((GIdlNode *)vfunc->result->type, 
1335                                    module, modules, strings, types,
1336                                    data, &signature, offset2);
1337
1338         blob2->may_return_null = vfunc->result->null_ok;
1339         blob2->caller_owns_return_value = vfunc->result->transfer;
1340         blob2->caller_owns_return_container = vfunc->result->shallow_transfer;
1341         blob2->reserved = 0;
1342         blob2->n_arguments = n;
1343
1344         signature += 4;
1345         
1346         for (l = vfunc->parameters; l; l = l->next)
1347           {
1348             GIdlNode *param = (GIdlNode *)l->data;
1349
1350             g_idl_node_build_metadata (param, module, modules, strings, 
1351                                        types, data, &signature, offset2);
1352           }
1353       }
1354       break;
1355
1356     case G_IDL_NODE_PARAM:
1357       {
1358         ArgBlob *blob = (ArgBlob *)&data[*offset];
1359         GIdlNodeParam *param = (GIdlNodeParam *)node;
1360         guint32 res;
1361
1362         *offset += 8;
1363
1364         blob->name = write_string (node->name, strings, data, offset2);
1365         blob->in = param->in;
1366         blob->out = param->out;
1367         blob->dipper = param->dipper;
1368         blob->null_ok = param->null_ok;
1369         blob->optional = param->optional;
1370         blob->transfer_ownership = param->transfer;
1371         blob->transfer_container_ownership = param->shallow_transfer;
1372         blob->return_value = param->retval;
1373         blob->reserved = 0;
1374
1375         g_idl_node_build_metadata ((GIdlNode *)param->type, module, modules, 
1376                                    strings, types, data, offset, offset2);
1377       }
1378       break;
1379
1380     case G_IDL_NODE_STRUCT:
1381       {
1382         StructBlob *blob = (StructBlob *)&data[*offset];
1383         GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node;
1384         guint32 pos;
1385         
1386         blob->blob_type = BLOB_TYPE_STRUCT;
1387         blob->deprecated = struct_->deprecated;
1388         blob->unregistered = TRUE;
1389         blob->reserved = 0;
1390         blob->name = write_string (node->name, strings, data, offset2);
1391         blob->gtype_name = 0;
1392         blob->gtype_init = 0;
1393
1394         blob->n_fields = 0;
1395         blob->n_methods = 0;
1396
1397         *offset += 20; 
1398         for (l = struct_->members; l; l = l->next)
1399           {
1400             GIdlNode *member = (GIdlNode *)l->data;
1401
1402             if (member->type == G_IDL_NODE_FIELD)
1403               {
1404                 blob->n_fields++;
1405                 g_idl_node_build_metadata (member, module, modules, strings, 
1406                                            types, data, offset, offset2);
1407               }
1408           }
1409
1410         for (l = struct_->members; l; l = l->next)
1411           {
1412             GIdlNode *member = (GIdlNode *)l->data;
1413             
1414             if (member->type == G_IDL_NODE_FUNCTION)
1415               {
1416                 blob->n_methods++;
1417                 g_idl_node_build_metadata (member, module, modules, strings, 
1418                                            types, data, offset, offset2);
1419               }
1420           }
1421       }
1422       break;
1423
1424     case G_IDL_NODE_BOXED:
1425       {
1426         StructBlob *blob = (StructBlob *)&data[*offset];
1427         GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
1428
1429         blob->blob_type = BLOB_TYPE_BOXED;
1430         blob->deprecated = boxed->deprecated;
1431         blob->unregistered = FALSE;
1432         blob->reserved = 0;
1433         blob->name = write_string (node->name, strings, data, offset2);
1434         blob->gtype_name = write_string (boxed->gtype_name, strings, data, offset2);
1435         blob->gtype_init = write_string (boxed->gtype_init, strings, data, offset2);
1436
1437         blob->n_fields = 0;
1438         blob->n_methods = 0;
1439
1440         *offset += 20; 
1441         for (l = boxed->members; l; l = l->next)
1442           {
1443             GIdlNode *member = (GIdlNode *)l->data;
1444
1445             if (member->type == G_IDL_NODE_FIELD)
1446               {
1447                 blob->n_fields++;
1448                 g_idl_node_build_metadata (member, module, modules, strings, 
1449                                            types, data, offset, offset2);
1450               }
1451           }
1452
1453         for (l = boxed->members; l; l = l->next)
1454           {
1455             GIdlNode *member = (GIdlNode *)l->data;
1456
1457             if (member->type == G_IDL_NODE_FUNCTION)
1458               {
1459                 blob->n_methods++;
1460                 g_idl_node_build_metadata (member, module, modules, strings, 
1461                                            types, data, offset, offset2);
1462               }
1463           }
1464       }
1465       break;
1466
1467     case G_IDL_NODE_UNION:
1468       {
1469         UnionBlob *blob = (UnionBlob *)&data[*offset];
1470         GIdlNodeUnion *union_ = (GIdlNodeUnion *)node;
1471
1472         blob->blob_type = BLOB_TYPE_UNION;
1473         blob->deprecated = union_->deprecated;
1474         blob->reserved = 0;
1475         blob->name = write_string (node->name, strings, data, offset2);
1476         if (union_->gtype_name)
1477           {
1478             blob->unregistered = FALSE;
1479             blob->gtype_name = write_string (union_->gtype_name, strings, data, offset2);
1480             blob->gtype_init = write_string (union_->gtype_init, strings, data, offset2);
1481           }
1482         else
1483           {
1484             blob->unregistered = TRUE;
1485             blob->gtype_name = 0;
1486             blob->gtype_init = 0;
1487           }
1488
1489         blob->n_fields = 0;
1490         blob->n_functions = 0;
1491
1492         blob->discriminator_offset = union_->discriminator_offset;
1493
1494         if (union_->discriminator_type)
1495           {
1496             *offset += 24;
1497             blob->discriminated = TRUE;
1498             g_idl_node_build_metadata ((GIdlNode *)union_->discriminator_type, 
1499                                        module, modules, strings, types,
1500                                        data, offset, offset2);
1501           }
1502         else 
1503           {
1504             *offset += 28;
1505             blob->discriminated = FALSE;
1506             blob->discriminator_type.offset = 0;
1507           }
1508         
1509         
1510         for (l = union_->members; l; l = l->next)
1511           {
1512             GIdlNode *member = (GIdlNode *)l->data;
1513
1514             if (member->type == G_IDL_NODE_FIELD)
1515               {
1516                 blob->n_fields++;
1517                 g_idl_node_build_metadata (member, module, modules, strings, 
1518                                            types, data, offset, offset2);
1519               }
1520           }
1521
1522         for (l = union_->members; l; l = l->next)
1523           {
1524             GIdlNode *member = (GIdlNode *)l->data;
1525
1526             if (member->type == G_IDL_NODE_FUNCTION)
1527               {
1528                 blob->n_functions++;
1529                 g_idl_node_build_metadata (member, module, modules, strings, 
1530                                            types, data, offset, offset2);
1531               }
1532           }
1533
1534         if (union_->discriminator_type)
1535           {
1536             for (l = union_->discriminators; l; l = l->next)
1537               {
1538                 GIdlNode *member = (GIdlNode *)l->data;
1539                 
1540                 g_idl_node_build_metadata (member, module, modules, strings, 
1541                                            types, data, offset, offset2);
1542               }
1543           }
1544       }
1545       break;
1546
1547     case G_IDL_NODE_ENUM:
1548     case G_IDL_NODE_FLAGS:
1549       {
1550         EnumBlob *blob = (EnumBlob *)&data[*offset];
1551         GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
1552
1553         *offset += 20; 
1554         
1555         if (node->type == G_IDL_NODE_ENUM)
1556           blob->blob_type = BLOB_TYPE_ENUM;
1557         else
1558           blob->blob_type = BLOB_TYPE_FLAGS;
1559           
1560         blob->deprecated = enum_->deprecated;
1561         blob->reserved = 0;
1562         blob->name = write_string (node->name, strings, data, offset2);
1563         if (enum_->gtype_name)
1564           {
1565             blob->unregistered = FALSE;
1566             blob->gtype_name = write_string (enum_->gtype_name, strings, data, offset2);
1567             blob->gtype_init = write_string (enum_->gtype_init, strings, data, offset2);
1568           }
1569         else
1570           {
1571             blob->unregistered = TRUE;
1572             blob->gtype_name = 0;
1573             blob->gtype_init = 0;
1574           }
1575
1576         blob->n_values = 0;
1577         blob->reserved2 = 0;
1578
1579         for (l = enum_->values; l; l = l->next)
1580           {
1581             GIdlNode *value = (GIdlNode *)l->data;
1582
1583             blob->n_values++;
1584             g_idl_node_build_metadata (value, module, modules, strings, types,
1585                                        data, offset, offset2);
1586           }
1587       }
1588       break;
1589       
1590     case G_IDL_NODE_OBJECT:
1591       {
1592         ObjectBlob *blob = (ObjectBlob *)&data[*offset];
1593         GIdlNodeInterface *object = (GIdlNodeInterface *)node;
1594         gint parent;
1595
1596         blob->blob_type = BLOB_TYPE_OBJECT;
1597         blob->deprecated = object->deprecated;
1598         blob->reserved = 0;
1599         blob->name = write_string (node->name, strings, data, offset2);
1600         blob->gtype_name = write_string (object->gtype_name, strings, data, offset2);
1601         blob->gtype_init = write_string (object->gtype_init, strings, data, offset2);
1602         if (object->parent)
1603           blob->parent = find_entry (module, modules, object->parent);
1604         else
1605           blob->parent = 0;
1606
1607         blob->n_interfaces = 0;
1608         blob->n_fields = 0;
1609         blob->n_properties = 0;
1610         blob->n_methods = 0;
1611         blob->n_signals = 0;
1612         blob->n_vfuncs = 0;
1613         blob->n_constants = 0;
1614         
1615         *offset += 32;
1616         for (l = object->interfaces; l; l = l->next)
1617           {
1618             blob->n_interfaces++;
1619             *(guint16*)&data[*offset] = find_entry (module, modules, (gchar *)l->data);
1620             *offset += 2;
1621           }
1622         
1623         *offset = ALIGN_VALUE (*offset, 4);
1624         for (l = object->members; l; l = l->next)
1625           {
1626             GIdlNode *member = (GIdlNode *)l->data;
1627
1628             if (member->type == G_IDL_NODE_FIELD)
1629               {
1630                 blob->n_fields++;
1631                 g_idl_node_build_metadata (member, module, modules, strings, 
1632                                            types, data, offset, offset2);
1633               }
1634           }
1635
1636         *offset = ALIGN_VALUE (*offset, 4);
1637         for (l = object->members; l; l = l->next)
1638           {
1639             GIdlNode *member = (GIdlNode *)l->data;
1640
1641             if (member->type == G_IDL_NODE_PROPERTY)
1642               {
1643                 blob->n_properties++;
1644                 g_idl_node_build_metadata (member, module, modules, strings, 
1645                                            types, data, offset, offset2);
1646               }
1647           }
1648
1649         *offset = ALIGN_VALUE (*offset, 4);
1650         for (l = object->members; l; l = l->next)
1651           {
1652             GIdlNode *member = (GIdlNode *)l->data;
1653
1654             if (member->type == G_IDL_NODE_FUNCTION)
1655               {
1656                 blob->n_methods++;
1657                 g_idl_node_build_metadata (member, module, modules, strings, 
1658                                            types, data, offset, offset2);
1659               }
1660           }
1661
1662         *offset = ALIGN_VALUE (*offset, 4);
1663         for (l = object->members; l; l = l->next)
1664           {
1665             GIdlNode *member = (GIdlNode *)l->data;
1666
1667             if (member->type == G_IDL_NODE_SIGNAL)
1668               {
1669                 blob->n_signals++;
1670                 g_idl_node_build_metadata (member, module, modules, strings, 
1671                                            types, data, offset, offset2);
1672               }
1673           }
1674
1675         *offset = ALIGN_VALUE (*offset, 4);
1676         for (l = object->members; l; l = l->next)
1677           {
1678             GIdlNode *member = (GIdlNode *)l->data;
1679
1680             if (member->type == G_IDL_NODE_VFUNC)
1681               {
1682                 blob->n_vfuncs++;
1683                 g_idl_node_build_metadata (member, module, modules, strings, 
1684                                            types, data, offset, offset2);
1685               }
1686           }
1687
1688         *offset = ALIGN_VALUE (*offset, 4);
1689         for (l = object->members; l; l = l->next)
1690           {
1691             GIdlNode *member = (GIdlNode *)l->data;
1692
1693             if (member->type == G_IDL_NODE_CONSTANT)
1694               {
1695                 blob->n_constants++;
1696                 g_idl_node_build_metadata (member, module, modules, strings, 
1697                                            types, data, offset, offset2);
1698               }
1699           }
1700       }
1701       break;
1702
1703     case G_IDL_NODE_INTERFACE:
1704       {
1705         InterfaceBlob *blob = (InterfaceBlob *)&data[*offset];
1706         GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
1707
1708         blob->blob_type = BLOB_TYPE_INTERFACE;
1709         blob->deprecated = iface->deprecated;
1710         blob->reserved = 0;
1711         blob->name = write_string (node->name, strings, data, offset2);
1712         blob->gtype_name = write_string (iface->gtype_name, strings, data, offset2);
1713         blob->gtype_init = write_string (iface->gtype_init, strings, data, offset2);
1714         blob->n_prerequisites = 0;
1715         blob->n_properties = 0;
1716         blob->n_methods = 0;
1717         blob->n_signals = 0;
1718         blob->n_vfuncs = 0;
1719         blob->n_constants = 0;
1720         
1721         *offset += 28;
1722         for (l = iface->prerequisites; l; l = l->next)
1723           {
1724             blob->n_prerequisites++;
1725             *(guint16*)&data[*offset] = find_entry (module, modules, (gchar *)l->data);
1726             *offset += 2;
1727           }
1728         
1729         *offset = ALIGN_VALUE (*offset, 4);
1730         for (l = iface->members; l; l = l->next)
1731           {
1732             GIdlNode *member = (GIdlNode *)l->data;
1733
1734             if (member->type == G_IDL_NODE_PROPERTY)
1735               {
1736                 blob->n_properties++;
1737                 g_idl_node_build_metadata (member, module, modules, strings, 
1738                                            types, data, offset, offset2);
1739               }
1740           }
1741
1742         *offset = ALIGN_VALUE (*offset, 4);
1743         for (l = iface->members; l; l = l->next)
1744           {
1745             GIdlNode *member = (GIdlNode *)l->data;
1746
1747             if (member->type == G_IDL_NODE_FUNCTION)
1748               {
1749                 blob->n_methods++;
1750                 g_idl_node_build_metadata (member, module, modules, strings, 
1751                                            types, data, offset, offset2);
1752               }
1753           }
1754
1755         *offset = ALIGN_VALUE (*offset, 4);
1756         for (l = iface->members; l; l = l->next)
1757           {
1758             GIdlNode *member = (GIdlNode *)l->data;
1759
1760             if (member->type == G_IDL_NODE_SIGNAL)
1761               {
1762                 blob->n_signals++;
1763                 g_idl_node_build_metadata (member, module, modules, strings, 
1764                                            types, data, offset, offset2);
1765               }
1766           }
1767
1768         *offset = ALIGN_VALUE (*offset, 4);
1769         for (l = iface->members; l; l = l->next)
1770           {
1771             GIdlNode *member = (GIdlNode *)l->data;
1772
1773             if (member->type == G_IDL_NODE_VFUNC)
1774               {
1775                 blob->n_vfuncs++;
1776                 g_idl_node_build_metadata (member, module, modules, strings, 
1777                                            types, data, offset, offset2);
1778               }
1779           }
1780
1781         *offset = ALIGN_VALUE (*offset, 4);
1782         for (l = iface->members; l; l = l->next)
1783           {
1784             GIdlNode *member = (GIdlNode *)l->data;
1785
1786             if (member->type == G_IDL_NODE_CONSTANT)
1787               {
1788                 blob->n_constants++;
1789                 g_idl_node_build_metadata (member, module, modules, strings, 
1790                                            types, data, offset, offset2);
1791               }
1792           }
1793       }
1794       break;
1795
1796
1797     case G_IDL_NODE_VALUE:
1798       {
1799         GIdlNodeValue *value = (GIdlNodeValue *)node;
1800         ValueBlob *blob = (ValueBlob *)&data[*offset];
1801         *offset += 12;
1802
1803         blob->deprecated = value->deprecated;
1804         blob->reserved = 0;
1805         blob->name = write_string (node->name, strings, data, offset2);
1806         blob->value = value->value;
1807       }
1808       break;
1809
1810     case G_IDL_NODE_ERROR_DOMAIN:
1811       {
1812         GIdlNodeErrorDomain *domain = (GIdlNodeErrorDomain *)node;
1813         ErrorDomainBlob *blob = (ErrorDomainBlob *)&data[*offset];
1814         *offset += 16;
1815
1816         blob->blob_type = BLOB_TYPE_ERROR_DOMAIN;
1817         blob->deprecated = domain->deprecated;
1818         blob->reserved = 0;
1819         blob->name = write_string (node->name, strings, data, offset2);
1820         blob->get_quark = write_string (domain->getquark, strings, data, offset2);
1821         blob->error_codes = find_entry (module, modules, domain->codes);
1822         blob->reserved2 = 0;
1823       }
1824       break;
1825
1826     case G_IDL_NODE_CONSTANT:
1827       {
1828         GIdlNodeConstant *constant = (GIdlNodeConstant *)node;
1829         ConstantBlob *blob = (ConstantBlob *)&data[*offset];
1830         guint32 pos;
1831
1832         pos = *offset + 8;
1833         *offset += 20;
1834
1835         blob->blob_type = BLOB_TYPE_CONSTANT;
1836         blob->deprecated = constant->deprecated;
1837         blob->reserved = 0;
1838         blob->name = write_string (node->name, strings, data, offset2);
1839
1840         blob->offset = *offset2;
1841         switch (constant->type->tag)
1842           {
1843           case 1:
1844             blob->size = 4;
1845             *(gboolean*)&data[blob->offset] = parse_boolean_value (constant->value);
1846             break;
1847             case 2:
1848             blob->size = 1;
1849               *(gint8*)&data[blob->offset] = (gint8) parse_int_value (constant->value);
1850             break;
1851           case 3:
1852             blob->size = 1;
1853             *(guint8*)&data[blob->offset] = (guint8) parse_uint_value (constant->value);
1854             break;
1855           case 4:
1856             blob->size = 2;
1857             *(gint16*)&data[blob->offset] = (gint16) parse_int_value (constant->value);
1858             break;
1859           case 5:
1860             blob->size = 2;
1861             *(guint16*)&data[blob->offset] = (guint16) parse_uint_value (constant->value);
1862             break;
1863           case 6:
1864             blob->size = 4;
1865             *(gint32*)&data[blob->offset] = (gint32) parse_int_value (constant->value);
1866             break;
1867           case 7:
1868             blob->size = 4;
1869             *(guint32*)&data[blob->offset] = (guint32) parse_uint_value (constant->value);
1870             break;
1871           case 8:
1872             blob->size = 8;
1873             *(gint32*)&data[blob->offset] = (gint64) parse_int_value (constant->value);
1874             break;
1875           case 9:
1876             blob->size = 8;
1877             *(guint32*)&data[blob->offset] = (guint64) parse_uint_value (constant->value);
1878             break;
1879           case 10:
1880             blob->size = sizeof (gfloat);
1881             *(gfloat*)&data[blob->offset] = (gfloat) parse_float_value (constant->value);
1882             break;
1883           case 11:
1884             blob->size = sizeof (gdouble);
1885             *(gdouble*)&data[blob->offset] = (gdouble) parse_float_value (constant->value);
1886             break;
1887           case 12:
1888             blob->size = strlen (constant->value) + 1;
1889             memcpy (&data[blob->offset], constant->value, blob->size);
1890             break;
1891           case 14:
1892             blob->size = sizeof (gint);
1893             *(gint*)&data[blob->offset] = (gint) parse_int_value (constant->value);
1894             break;
1895           case 15:
1896             blob->size = sizeof (guint);
1897             *(gint*)&data[blob->offset] = (guint) parse_uint_value (constant->value);
1898             break;
1899           case 16:
1900             blob->size = sizeof (glong);
1901             *(glong*)&data[blob->offset] = (glong) parse_int_value (constant->value);
1902             break;
1903           case 17:
1904             blob->size = sizeof (gulong);
1905             *(gulong*)&data[blob->offset] = (gulong) parse_uint_value (constant->value);
1906             break;
1907           }
1908         *offset2 += ALIGN_VALUE (blob->size, 4);
1909         
1910         g_idl_node_build_metadata ((GIdlNode *)constant->type, module, modules, 
1911                                    strings, types, data, &pos, offset2);
1912       }
1913       break;
1914     }
1915   
1916   g_debug ("node %p type %d, offset %d -> %d, offset2 %d -> %d",
1917            node, node->type, old_offset, *offset, old_offset2, *offset2);
1918
1919   if (*offset2 - old_offset2 + *offset - old_offset > g_idl_node_get_full_size (node))
1920     g_error ("exceeding space reservation !!");
1921 }
1922
1923 /* if str is already in the pool, return previous location, otherwise write str
1924  * to the metadata at offset, put it in the pool and update offset. If the 
1925  * metadata is not large enough to hold the string, reallocate it.
1926  */
1927 guint32 
1928 write_string (const gchar *str,
1929               GHashTable  *strings, 
1930               guchar      *data,
1931               guint32     *offset)
1932 {
1933   gpointer value;
1934   guint32 start;
1935
1936   string_count += 1;
1937   string_size += strlen (str);
1938
1939   value = g_hash_table_lookup (strings, str);
1940   
1941   if (value)
1942     return GPOINTER_TO_INT (value);
1943
1944   unique_string_count += 1;
1945   unique_string_size += strlen (str);
1946
1947   g_hash_table_insert (strings, (gpointer)str, GINT_TO_POINTER (*offset));
1948
1949   start = *offset;
1950   *offset = ALIGN_VALUE (start + strlen (str) + 1, 4);
1951
1952   strcpy ((gchar*)&data[start], str);
1953   
1954   return start;
1955 }
1956