* t/op/lexicals-2.t (added), MANIFEST:
[parrot.git] / src / packout.c
blobdb4684e265df7f3d7fac26fea6c6bb7279c9d35d
1 /*
2 Copyright (C) 2001-2007, The Perl 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 =head2 Functions
15 =over 4
17 =cut
21 #include "parrot/parrot.h"
22 #include "parrot/packfile.h"
24 /* HEADERIZER HFILE: include/parrot/packfile.h */
28 =item C<opcode_t PackFile_pack_size>
30 Determine the size of the buffer needed in order to pack the PackFile
31 into a contiguous region of memory.
33 Must be run before C<PackFile_pack()>, so it will allocate an adequate
34 buffer.
36 =cut
40 PARROT_API
41 opcode_t
42 PackFile_pack_size(PARROT_INTERP, ARGMOD(PackFile *self))
44 size_t size;
45 size_t header_size = 0;
46 PackFile_Directory * const dir = &self->directory;
48 header_size = PACKFILE_HEADER_BYTES;
49 header_size += self->header->uuid_size;
50 header_size +=
51 header_size % 16
52 ? 16 - header_size % 16
53 : 0;
55 size = header_size / sizeof (opcode_t);
57 size += 4; /* directory type + 3 padding zeros */
59 dir->base.file_offset = size;
60 size += PackFile_Segment_packed_size(interp, (PackFile_Segment *) dir);
62 return size;
67 =item C<void PackFile_pack>
69 Pack the PackFile into a contiguous region of memory.
71 Note that the memory block had better have at least the amount of memory
72 indicated by C<PackFile_pack_size()>.
74 This means that you MUST call C<PackFile_pack_size()> before
75 C<PackFile_pack()>
77 Other pack routines are in F<src/packfile.c>.
79 =cut
83 PARROT_API
84 void
85 PackFile_pack(PARROT_INTERP, ARGMOD(PackFile *self), ARGOUT(opcode_t *cursor))
87 opcode_t *ret;
89 size_t size;
90 PackFile_Directory * const dir = &self->directory;
91 PackFile_Segment *seg;
92 int padding_size;
93 char *byte_cursor = (char*)cursor;
95 self->src = cursor;
97 /* Pack the fixed part of the header */
98 mem_sys_memcopy(cursor, self->header, PACKFILE_HEADER_BYTES);
99 byte_cursor += PACKFILE_HEADER_BYTES;
101 /* Pack the UUID. */
102 if (self->header->uuid_size > 0)
103 mem_sys_memcopy(byte_cursor, self->header->uuid_data,
104 self->header->uuid_size);
106 /* Padding. */
107 padding_size = 16 - (PACKFILE_HEADER_BYTES + self->header->uuid_size) % 16;
108 if (padding_size < 16) {
109 int i;
110 for (i = 0; i < padding_size; i++)
111 *byte_cursor++ = 0;
113 else {
114 padding_size = 0;
117 /* Set cursor. */
118 cursor += (PACKFILE_HEADER_BYTES + self->header->uuid_size + padding_size)
119 / sizeof (opcode_t);
121 /* Directory format and padding. */
122 *cursor++ = PF_DIR_FORMAT;
123 *cursor++ = 0;
124 *cursor++ = 0;
125 *cursor++ = 0;
127 /* pack the directory */
128 seg = (PackFile_Segment *) dir;
130 /* dir size */
131 size = seg->op_count;
132 ret = PackFile_Segment_pack(interp, seg, cursor);
133 if ((size_t)(ret - cursor) != size) {
134 fprintf(stderr, "PackFile_pack segment '%s' used size %d "
135 "but reported %d\n", seg->name, (int)(ret-cursor), (int)size);
141 =item C<size_t PackFile_ConstTable_pack_size>
143 Determine the size of the buffer needed in order to pack the PackFile
144 constant table into a contiguous region of memory.
146 =cut
150 PARROT_API
151 size_t
152 PackFile_ConstTable_pack_size(PARROT_INTERP, ARGIN(PackFile_Segment *seg))
154 opcode_t i;
155 const PackFile_ConstTable* const self = (const PackFile_ConstTable *) seg;
156 size_t size = 1; /* const_count */
158 for (i = 0; i < self->const_count; i++)
159 size += PackFile_Constant_pack_size(interp, self->constants[i]);
160 return size;
165 =item C<opcode_t * PackFile_ConstTable_pack>
167 Pack the PackFile ConstTable into a contiguous region of memory.
169 Note that the memory block had better have at least the amount of memory
170 indicated by C<PackFile_pack_size()>.
172 This means that you MUST call C<PackFile_pack_size()> before
173 C<PackFile_ConstTable_pack()>
175 =cut
179 PARROT_API
180 PARROT_WARN_UNUSED_RESULT
181 PARROT_CANNOT_RETURN_NULL
182 opcode_t *
183 PackFile_ConstTable_pack(PARROT_INTERP,
184 ARGIN(PackFile_Segment *seg), ARGMOD(opcode_t *cursor))
186 const PackFile_ConstTable * const self = (const PackFile_ConstTable *)seg;
187 opcode_t i;
189 *cursor++ = self->const_count;
191 for (i = 0; i < self->const_count; i++)
192 cursor = PackFile_Constant_pack(interp, self, self->constants[i], cursor);
194 return cursor;
199 =item C<int PackFile_find_in_const>
201 This is really ugly, we don't know where our C<PARROT_ARG_SC> key
202 constant is in constant table, so we have to search for it.
204 =cut
208 PARROT_API
210 PackFile_find_in_const(PARROT_INTERP,
211 ARGIN(const PackFile_ConstTable *ct), ARGIN(const PMC *key), int type)
213 int i;
214 for (i = 0; i < ct->const_count; i++)
215 if (type == PFC_STRING && ct->constants[i]->u.string ==
216 PMC_str_val(key))
217 return i;
218 else if (type == PFC_NUMBER && ct->constants[i]->u.number ==
219 PMC_num_val(key))
220 return i;
221 PIO_eprintf(NULL, "find_in_const: couldn't find const for key\n");
222 Parrot_exit(interp, 1);
227 =item C<opcode_t * PackFile_Constant_pack>
229 Pack a PackFile Constant into a contiguous region of memory.
231 Note that the memory block had better have at least the amount of memory
232 indicated by C<PackFile_pack_size()>.
234 This means that you MUST call C<PackFile_pack_size()> before
235 C<PackFile_Constant_pack()>
237 The data is zero-padded to an opcode_t-boundary, so pad bytes may be added.
238 (Note this padding is not yet implemented for FLOATVALs.)
240 =cut
244 PARROT_API
245 PARROT_CANNOT_RETURN_NULL
246 PARROT_WARN_UNUSED_RESULT
247 opcode_t *
248 PackFile_Constant_pack(PARROT_INTERP,
249 ARGIN(const PackFile_ConstTable *const_table),
250 ARGIN(const PackFile_Constant *self), ARGOUT(opcode_t *cursor))
252 PMC *key;
253 size_t i;
254 opcode_t slice_bits;
255 STRING *image;
257 *cursor++ = self->type;
259 switch (self->type) {
261 case PFC_NUMBER:
262 cursor = PF_store_number(cursor, &self->u.number);
263 break;
265 case PFC_STRING:
266 cursor = PF_store_string(cursor, self->u.string);
267 break;
269 case PFC_PMC:
270 key = self->u.key; /* the (Sub) PMC */
271 image = Parrot_freeze(interp, key);
272 cursor = PF_store_string(cursor, image);
273 break;
275 case PFC_KEY:
276 for (i = 0, key = self->u.key; key; key = (PMC *)PMC_data(key), i++)
278 /* number of key components */
279 *cursor++ = i;
280 /* and now type / value per component */
281 for (key = self->u.key; key; key = (PMC *)PMC_data(key)) {
282 const opcode_t type = PObj_get_FLAGS(key);
283 slice_bits = 0;
284 if ((type & (KEY_start_slice_FLAG|KEY_inf_slice_FLAG)) ==
285 (KEY_start_slice_FLAG|KEY_inf_slice_FLAG))
286 slice_bits |= PF_VT_END_INF;
287 if ((type & (KEY_end_slice_FLAG|KEY_inf_slice_FLAG)) ==
288 (KEY_end_slice_FLAG|KEY_inf_slice_FLAG))
289 slice_bits |= PF_VT_START_ZERO;
290 if (type & KEY_start_slice_FLAG)
291 slice_bits |= PF_VT_START_SLICE;
292 if (type & KEY_end_slice_FLAG)
293 slice_bits |= PF_VT_END_SLICE;
295 switch (type & KEY_type_FLAGS) {
296 case KEY_integer_FLAG:
297 *cursor++ = PARROT_ARG_IC | slice_bits;
298 *cursor++ = PMC_int_val(key);
299 break;
300 case KEY_number_FLAG:
301 *cursor++ = PARROT_ARG_NC | slice_bits;
302 /* Argh */
303 *cursor++ = PackFile_find_in_const(interp, const_table, key, PFC_NUMBER);
304 break;
305 case KEY_string_FLAG:
306 *cursor++ = PARROT_ARG_SC | slice_bits;
307 /* Argh */
308 *cursor++ = PackFile_find_in_const(interp, const_table, key, PFC_STRING);
309 break;
311 case KEY_integer_FLAG | KEY_register_FLAG:
312 *cursor++ = PARROT_ARG_I | slice_bits;
313 *cursor++ = PMC_int_val(key);
314 break;
315 case KEY_number_FLAG | KEY_register_FLAG:
316 *cursor++ = PARROT_ARG_N | slice_bits;
317 *cursor++ = PMC_int_val(key);
318 break;
319 case KEY_string_FLAG | KEY_register_FLAG:
320 *cursor++ = PARROT_ARG_S | slice_bits;
321 *cursor++ = PMC_int_val(key);
322 break;
323 case KEY_pmc_FLAG | KEY_register_FLAG:
324 *cursor++ = PARROT_ARG_P | slice_bits;
325 *cursor++ = PMC_int_val(key);
326 break;
327 default:
328 PIO_eprintf(NULL, "PackFile_Constant_pack: "
329 "unsupported constant type\n");
330 Parrot_exit(interp, 1);
334 break;
336 default:
337 PIO_eprintf(NULL, "PackFile_Constant_pack: unsupported constant\n");
338 Parrot_exit(interp, 1);
339 break;
341 return cursor;
346 =back
348 =head1 HISTORY
350 Rework by Melvin; new bytecode format, make bytecode portable. (Do
351 endian conversion and wordsize transforms on the fly.)
353 leo: rewrite to use new directory-based format.
355 =cut
361 * Local variables:
362 * c-file-style: "parrot"
363 * End:
364 * vim: expandtab shiftwidth=4: