remove deprecation notice for TT #449
[parrot.git] / src / packout.c
blob5d659c58df1012d099f78c68b642d8a858854e11
1 /*
2 Copyright (C) 2001-2010, Parrot Foundation.
3 This program is free software. It is subject to the same license as
4 Parrot itself.
5 $Id$
7 =head1 NAME
9 src/packout.c - Functions for writing out packfiles
11 =head1 DESCRIPTION
13 This file implements various functions for creating and writing packfiles.
15 =head2 Functions
17 =over 4
19 =cut
23 #include "parrot/parrot.h"
24 #include "parrot/packfile.h"
25 #include "pmc/pmc_key.h"
27 /* HEADERIZER HFILE: include/parrot/packfile.h */
31 =item C<opcode_t PackFile_pack_size(PARROT_INTERP, PackFile *self)>
33 Determine the size of the buffer needed in order to pack the PackFile
34 into a contiguous region of memory.
36 Must be run before C<PackFile_pack()>, so it will allocate an adequate
37 buffer.
39 =cut
43 PARROT_EXPORT
44 opcode_t
45 PackFile_pack_size(PARROT_INTERP, ARGMOD(PackFile *self))
47 ASSERT_ARGS(PackFile_pack_size)
48 size_t size;
49 size_t header_size = 0;
50 PackFile_Directory * const dir = &self->directory;
52 header_size = PACKFILE_HEADER_BYTES;
53 header_size += self->header->uuid_size;
54 header_size +=
55 header_size % 16
56 ? 16 - header_size % 16
57 : 0;
59 size = header_size / sizeof (opcode_t);
61 size += 4; /* directory type + 3 padding zeros */
63 dir->base.file_offset = size;
64 size += PackFile_Segment_packed_size(interp, (PackFile_Segment *) dir);
66 return size;
71 =item C<void PackFile_pack(PARROT_INTERP, PackFile *self, opcode_t *cursor)>
73 Pack the PackFile into a contiguous region of memory.
75 Note that the memory block had better have at least the amount of memory
76 indicated by C<PackFile_pack_size()>.
78 This means that you MUST call C<PackFile_pack_size()> before
79 C<PackFile_pack()>
81 Other pack routines are in F<src/packfile.c>.
83 =cut
87 PARROT_EXPORT
88 void
89 PackFile_pack(PARROT_INTERP, ARGMOD(PackFile *self), ARGOUT(opcode_t *cursor))
91 ASSERT_ARGS(PackFile_pack)
92 opcode_t *ret;
94 size_t size;
95 PackFile_Directory * const dir = &self->directory;
96 PackFile_Segment *seg;
97 int padding_size;
98 char *byte_cursor = (char*)cursor;
100 self->src = cursor;
102 /* Pack the fixed part of the header */
103 mem_sys_memcopy(cursor, self->header, PACKFILE_HEADER_BYTES);
104 byte_cursor += PACKFILE_HEADER_BYTES;
106 /* Pack the UUID. */
107 if (self->header->uuid_size > 0)
108 mem_sys_memcopy(byte_cursor, self->header->uuid_data,
109 self->header->uuid_size);
111 /* Padding. */
112 padding_size = 16 - (PACKFILE_HEADER_BYTES + self->header->uuid_size) % 16;
113 if (padding_size < 16) {
114 int i;
115 for (i = 0; i < padding_size; ++i)
116 *byte_cursor++ = 0;
118 else {
119 padding_size = 0;
122 /* Set cursor. */
123 cursor += (PACKFILE_HEADER_BYTES + self->header->uuid_size + padding_size)
124 / sizeof (opcode_t);
126 /* Directory format and padding. */
127 *cursor++ = PF_DIR_FORMAT;
128 *cursor++ = 0;
129 *cursor++ = 0;
130 *cursor++ = 0;
132 /* pack the directory */
133 seg = (PackFile_Segment *) dir;
135 /* dir size */
136 size = seg->op_count;
137 ret = PackFile_Segment_pack(interp, seg, cursor);
138 if ((size_t)(ret - cursor) != size) {
139 Parrot_io_eprintf(interp, "PackFile_pack segment '%Ss' used size %d "
140 "but reported %d\n", seg->name, (int)(ret-cursor), (int)size);
146 =item C<size_t PackFile_ConstTable_pack_size(PARROT_INTERP, PackFile_Segment
147 *seg)>
149 Determine the size of the buffer needed in order to pack the PackFile
150 constant table into a contiguous region of memory.
152 =cut
156 PARROT_EXPORT
157 size_t
158 PackFile_ConstTable_pack_size(PARROT_INTERP, ARGIN(PackFile_Segment *seg))
160 ASSERT_ARGS(PackFile_ConstTable_pack_size)
161 opcode_t i;
162 PackFile_ConstTable* const self = (PackFile_ConstTable *) seg;
163 const opcode_t n_constants = self->const_count;
164 size_t size = 1; /* const_count */
166 for (i = 0; i < n_constants; ++i) {
167 /* only constants up to the current one will be valid on unpack */
168 self->const_count = i;
169 size += PackFile_Constant_pack_size(interp, self->constants[i], self);
172 self->const_count = i;
174 return size;
179 =item C<opcode_t * PackFile_ConstTable_pack(PARROT_INTERP, PackFile_Segment
180 *seg, opcode_t *cursor)>
182 Pack the PackFile ConstTable into a contiguous region of memory.
184 Note that the memory block had better have at least the amount of memory
185 indicated by C<PackFile_pack_size()>.
187 This means that you MUST call C<PackFile_pack_size()> before
188 C<PackFile_ConstTable_pack()>
190 =cut
194 PARROT_EXPORT
195 PARROT_WARN_UNUSED_RESULT
196 PARROT_CANNOT_RETURN_NULL
197 opcode_t *
198 PackFile_ConstTable_pack(PARROT_INTERP,
199 ARGIN(PackFile_Segment *seg), ARGMOD(opcode_t *cursor))
201 ASSERT_ARGS(PackFile_ConstTable_pack)
202 PackFile_ConstTable * const self = (PackFile_ConstTable *)seg;
203 const opcode_t n_constants = self->const_count;
204 opcode_t i;
206 *cursor++ = self->const_count;
208 for (i = 0; i < n_constants; ++i) {
209 /* only constants up to the current one will be valid on unpack */
210 self->const_count = i;
211 cursor = PackFile_Constant_pack(interp, self, self->constants[i], cursor);
214 self->const_count = n_constants;
216 return cursor;
221 =item C<int PackFile_find_in_const(PARROT_INTERP, const PackFile_ConstTable *ct,
222 PMC *key, int type)>
224 This is really ugly, we don't know where our C<PARROT_ARG_SC> key
225 constant is in constant table, so we have to search for it.
227 =cut
231 PARROT_EXPORT
233 PackFile_find_in_const(PARROT_INTERP,
234 ARGIN(const PackFile_ConstTable *ct), ARGIN(PMC *key), int type)
236 ASSERT_ARGS(PackFile_find_in_const)
237 int i = PackFile_ConstTable_rlookup(interp, ct, key, type);
239 if (i < 0) {
240 Parrot_io_eprintf(NULL, "find_in_const: couldn't find const for key\n");
241 Parrot_exit(interp, 1);
244 return i;
249 =item C<int PackFile_ConstTable_rlookup(PARROT_INTERP, const PackFile_ConstTable
250 *ct, PMC *key, int type)>
252 Reverse lookup a constant in the constant table.
254 TODO: use a hash to make these O(1) for strings
256 =cut
260 PARROT_EXPORT
262 PackFile_ConstTable_rlookup(PARROT_INTERP,
263 ARGIN(const PackFile_ConstTable *ct), ARGIN(PMC *key), int type)
265 ASSERT_ARGS(PackFile_ConstTable_rlookup)
266 int i, strings;
267 FLOATVAL key_num;
268 STRING *key_str;
269 PMC *string_list;
271 PARROT_ASSERT(type == PFC_STRING || type == PFC_NUMBER);
273 GETATTR_Key_str_key(interp, key, key_str);
274 GETATTR_Key_num_key(interp, key, key_num);
276 if (type == PFC_STRING && !PMC_IS_NULL(ct->string_hash)) {
277 if (VTABLE_exists_keyed_str(interp, ct->string_hash, key_str)) {
278 i = VTABLE_get_integer_keyed_str(interp, ct->string_hash, key_str);
279 if (i < ct->const_count) /* only consider constants that have already occured */
280 return i;
282 return -1;
285 for (i = 0; i < ct->const_count; ++i) {
286 PackFile_Constant *constant = ct->constants[i];
288 switch (type) {
289 case PFC_STRING:
290 if (constant->type == PFC_STRING) {
291 STRING * const sc = constant->u.string;
292 if (Parrot_str_equal(interp, key_str, sc)
293 && Parrot_charset_number_of_str(interp, key_str)
294 == Parrot_charset_number_of_str(interp, sc)
295 && Parrot_encoding_number_of_str(interp, key_str)
296 == Parrot_encoding_number_of_str(interp, sc)) {
297 return i;
300 break;
302 case PFC_NUMBER:
303 if (constant->type == PFC_NUMBER)
304 if (constant->u.number == key_num)
305 return i;
306 break;
308 default:
309 PANIC(interp, "Universe imploded. Did you divide by zero?");
313 /* not found */
314 return -1;
319 =item C<opcode_t * PackFile_Constant_pack(PARROT_INTERP, const
320 PackFile_ConstTable *const_table, const PackFile_Constant *self, opcode_t
321 *cursor)>
323 Pack a PackFile Constant into a contiguous region of memory.
325 Note that the memory block had better have at least the amount of memory
326 indicated by C<PackFile_pack_size()>.
328 This means that you MUST call C<PackFile_pack_size()> before
329 C<PackFile_Constant_pack()>
331 The data is zero-padded to an opcode_t-boundary, so pad bytes may be added.
332 (Note this padding is not yet implemented for FLOATVALs.)
334 =cut
338 PARROT_EXPORT
339 PARROT_CANNOT_RETURN_NULL
340 PARROT_WARN_UNUSED_RESULT
341 opcode_t *
342 PackFile_Constant_pack(PARROT_INTERP,
343 ARGIN(const PackFile_ConstTable *const_table),
344 ARGIN(const PackFile_Constant *self), ARGOUT(opcode_t *cursor))
346 ASSERT_ARGS(PackFile_Constant_pack)
347 PMC *key;
348 size_t i;
349 STRING *image;
351 *cursor++ = self->type;
353 switch (self->type) {
355 case PFC_NUMBER:
356 cursor = PF_store_number(cursor, &self->u.number);
357 break;
359 case PFC_STRING:
360 cursor = PF_store_string(cursor, self->u.string);
361 break;
363 case PFC_PMC:
364 key = self->u.key; /* the (Sub) PMC */
365 image = Parrot_freeze_pbc(interp, key, const_table);
366 cursor = PF_store_string(cursor, image);
367 break;
369 case PFC_KEY:
370 for (i = 0, key = self->u.key; key; ++i){
371 GETATTR_Key_next_key(interp, key, key);
374 /* number of key components */
375 *cursor++ = i;
376 /* and now type / value per component */
377 for (key = self->u.key; key;) {
378 const opcode_t type = PObj_get_FLAGS(key);
380 switch (type & KEY_type_FLAGS) {
381 case KEY_integer_FLAG:
382 *cursor++ = PARROT_ARG_IC;
383 GETATTR_Key_int_key(interp, key, *cursor++);
384 break;
385 case KEY_number_FLAG:
386 *cursor++ = PARROT_ARG_NC;
387 /* Argh */
388 *cursor++ = PackFile_find_in_const(interp, const_table, key, PFC_NUMBER);
389 break;
390 case KEY_string_FLAG:
391 *cursor++ = PARROT_ARG_SC;
392 /* Argh */
393 *cursor++ = PackFile_find_in_const(interp, const_table, key, PFC_STRING);
394 break;
396 case KEY_integer_FLAG | KEY_register_FLAG:
397 *cursor++ = PARROT_ARG_I;
398 GETATTR_Key_int_key(interp, key, *cursor++);
399 break;
400 case KEY_number_FLAG | KEY_register_FLAG:
401 *cursor++ = PARROT_ARG_N;
402 GETATTR_Key_int_key(interp, key, *cursor++);
403 break;
404 case KEY_string_FLAG | KEY_register_FLAG:
405 *cursor++ = PARROT_ARG_S;
406 GETATTR_Key_int_key(interp, key, *cursor++);
407 break;
408 case KEY_pmc_FLAG | KEY_register_FLAG:
409 *cursor++ = PARROT_ARG_P;
410 GETATTR_Key_int_key(interp, key, *cursor++);
411 break;
412 default:
413 Parrot_io_eprintf(NULL, "PackFile_Constant_pack: "
414 "unsupported constant type\n");
415 Parrot_exit(interp, 1);
417 GETATTR_Key_next_key(interp, key, key);
420 break;
422 default:
423 Parrot_io_eprintf(NULL, "PackFile_Constant_pack: unsupported constant\n");
424 Parrot_exit(interp, 1);
425 break;
427 return cursor;
432 =back
434 =head1 HISTORY
436 Rework by Melvin; new bytecode format, make bytecode portable. (Do
437 endian conversion and wordsize transforms on the fly.)
439 leo: rewrite to use new directory-based format.
441 =cut
447 * Local variables:
448 * c-file-style: "parrot"
449 * End:
450 * vim: expandtab shiftwidth=4: