1 /* GObject introspection: Metadata creation
3 * Copyright (C) 2005 Matthias Clasen
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.
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.
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.
24 #include "gidlmodule.h"
26 #include "gmetadata.h"
28 #define ALIGN_VALUE(this, boundary) \
29 (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
33 g_idl_module_new (const gchar
*name
)
37 module
= g_new (GIdlModule
, 1);
39 module
->name
= g_strdup (name
);
40 module
->entries
= NULL
;
46 g_idl_module_free (GIdlModule
*module
)
50 g_free (module
->name
);
52 for (e
= module
->entries
; e
; e
= e
->next
)
53 g_idl_node_free ((GIdlNode
*)e
->data
);
55 g_list_free (module
->entries
);
61 g_idl_module_build_metadata (GIdlModule
*module
,
73 guint32 n_local_entries
;
74 guint32 size
, offset
, offset2
, old_offset
;
79 header_size
= ALIGN_VALUE (sizeof (Header
), 4);
80 n_local_entries
= g_list_length (module
->entries
);
84 strings
= g_hash_table_new (g_str_hash
, g_str_equal
);
85 types
= g_hash_table_new (g_str_hash
, g_str_equal
);
86 n_entries
= g_list_length (module
->entries
);
88 g_message ("%d entries (%d local)\n", n_entries
, n_local_entries
);
90 dir_size
= n_entries
* 12;
91 size
= header_size
+ dir_size
;
93 size
+= ALIGN_VALUE (strlen (module
->name
) + 1, 4);
95 for (e
= module
->entries
; e
; e
= e
->next
)
97 GIdlNode
*node
= e
->data
;
99 size
+= g_idl_node_get_full_size (node
);
102 g_message ("allocating %d bytes (%d header, %d directory, %d entries)\n",
103 size
, header_size
, dir_size
, size
- header_size
- dir_size
);
105 data
= g_malloc0 (size
);
108 header
= (Header
*)data
;
109 memcpy (header
, G_IDL_MAGIC
, 16);
110 header
->major_version
= 1;
111 header
->minor_version
= 0;
112 header
->reserved
= 0;
113 header
->n_entries
= n_entries
;
114 header
->n_local_entries
= n_local_entries
;
115 header
->n_annotations
= 0;
116 header
->annotations
= 0; /* filled in later */
117 header
->size
= 0; /* filled in later */
118 header
->namespace = write_string (module
->name
, strings
, data
, &header_size
);
119 header
->directory
= ALIGN_VALUE (header_size
, 4);
120 header
->entry_blob_size
= 12;
121 header
->function_blob_size
= 16;
122 header
->callback_blob_size
= 12;
123 header
->signal_blob_size
= 12;
124 header
->vfunc_blob_size
= 16;
125 header
->arg_blob_size
= 12;
126 header
->property_blob_size
= 12;
127 header
->field_blob_size
= 12;
128 header
->value_blob_size
= 12;
129 header
->constant_blob_size
= 20;
130 header
->error_domain_blob_size
= 16;
131 header
->annotation_blob_size
= 12;
132 header
->signature_blob_size
= 8;
133 header
->enum_blob_size
= 20;
134 header
->struct_blob_size
= 20;
135 header
->object_blob_size
= 32;
136 header
->interface_blob_size
= 28;
137 header
->union_blob_size
= 28;
139 /* fill in directory and content */
140 entry
= (DirEntry
*)&data
[header
->directory
];
142 offset2
= header
->directory
+ dir_size
;
144 for (e
= module
->entries
, i
= 0; e
; e
= e
->next
, i
++)
146 GIdlNode
*node
= e
->data
;
148 if (strchr (node
->name
, '.'))
150 g_error ("Names may not contain '.'");
153 /* we picked up implicit xref nodes, start over */
156 g_message ("Found implicit cross references, starting over");
158 g_hash_table_destroy (strings
);
159 g_hash_table_destroy (types
);
170 if (node
->type
== G_IDL_NODE_XREF
)
172 entry
->blob_type
= 0;
173 entry
->local
= FALSE
;
174 entry
->offset
= write_string (((GIdlNodeXRef
*)node
)->namespace, strings
, data
, &offset2
);
175 entry
->name
= write_string (node
->name
, strings
, data
, &offset2
);
180 offset2
= offset
+ g_idl_node_get_size (node
);
182 entry
->blob_type
= node
->type
;
184 entry
->offset
= offset
;
185 entry
->name
= write_string (node
->name
, strings
, data
, &offset2
);
187 g_idl_node_build_metadata (node
, module
, modules
,
188 strings
, types
, data
, &offset
, &offset2
);
190 if (offset2
> old_offset
+ g_idl_node_get_full_size (node
))
191 g_error ("left a hole of %d bytes\n", offset2
- old_offset
- g_idl_node_get_full_size (node
));
198 g_hash_table_destroy (strings
);
199 g_hash_table_destroy (types
);
201 header
->annotations
= offset2
;
203 g_message ("reallocating to %d bytes", offset2
);
205 *metadata
= g_realloc (data
, offset2
);
206 *length
= header
->size
= offset2
;