2 Copyright (C) 2001-2006, The Perl Foundation.
3 This program is free software. It is subject to the same license as
9 src/packout.c - Functions for writing out packfiles
21 #include "parrot/parrot.h"
22 #include "parrot/packfile.h"
25 /***************************************
26 Determine the size of the buffer needed in order to pack the PackFile into a
27 contiguous region of memory.
28 ***************************************/
30 #define TRACE_PACKFILE_PMC 0
32 /* XXX This should be in an external file */
33 extern struct PackFile_Directory
*directory_new(Interp
*, struct PackFile
*pf
);
38 PackFile_pack_size(Interp*, struct PackFile *self)>
47 PackFile_pack_size(Interp
*interp
, struct PackFile
*self
)
50 struct PackFile_Directory
* const dir
= &self
->directory
;
52 size
= PACKFILE_HEADER_BYTES
/ sizeof (opcode_t
);
54 size
+= 4; /* magic + opcode type + directory type + pad */
56 dir
->base
.file_offset
= size
;
57 size
+= PackFile_Segment_packed_size(interp
,
58 (struct PackFile_Segment
*) dir
);
66 PackFile_pack(Interp*, struct PackFile *self, opcode_t *cursor)>
68 Pack the PackFile into a contiguous region of memory.
70 Note that the memory block had better have at least the amount of memory
71 indicated by C<PackFile_pack_size()>.
73 This means that you MUST call C<PackFile_pack_size()> before
76 Other pack routines are in F<src/packfile.c>.
83 PackFile_pack(Interp
*interp
, struct PackFile
*self
, opcode_t
*cursor
)
88 struct PackFile_Directory
* const dir
= &self
->directory
;
89 struct PackFile_Segment
*seg
;
94 mem_sys_memcopy(cursor
, self
->header
, PACKFILE_HEADER_BYTES
);
95 cursor
+= PACKFILE_HEADER_BYTES
/ sizeof (opcode_t
);
96 *cursor
++ = PARROT_MAGIC
; /* Pack the magic */
97 *cursor
++ = OPCODE_TYPE_PERL
; /* Pack opcode type */
98 *cursor
++ = PF_DIR_FORMAT
; /* dir format */
99 *cursor
++ = 0; /* pad */
101 /* pack the directory */
102 seg
= (struct PackFile_Segment
*) dir
;
104 size
= seg
->op_count
;
105 ret
= PackFile_Segment_pack(interp
, seg
, cursor
);
106 if ((size_t)(ret
- cursor
) != size
) {
107 fprintf(stderr
, "PackFile_pack segment '%s' used size %d "
108 "but reported %d\n", seg
->name
, (int)(ret
-cursor
), (int)size
);
115 PackFile_ConstTable_pack_size(struct PackFile_Segment *seg)>
117 Determine the size of the buffer needed in order to pack the PackFile
118 constant table into a contiguous region of memory.
125 PackFile_ConstTable_pack_size(Interp
*interp
, struct PackFile_Segment
*seg
)
128 struct PackFile_ConstTable
* const self
= (struct PackFile_ConstTable
*) seg
;
129 size_t size
= 1; /* const_count */
131 for (i
= 0; i
< self
->const_count
; i
++)
132 size
+= PackFile_Constant_pack_size(interp
, self
->constants
[i
]);
138 =item C<opcode_t *PackFile_ConstTable_pack(Interp *,
139 struct PackFile_Segment *seg,
142 Pack the PackFile ConstTable into a contiguous region of memory.
144 Note that the memory block had better have at least the amount of memory
145 indicated by C<PackFile_pack_size()>.
147 This means that you MUST call C<PackFile_pack_size()> before
148 C<PackFile_ConstTable_pack()>
155 PackFile_ConstTable_pack(Interp
*interp
,
156 struct PackFile_Segment
*seg
, opcode_t
*cursor
)
158 struct PackFile_ConstTable
* const self
= (struct PackFile_ConstTable
*)seg
;
161 *cursor
++ = self
->const_count
;
163 for (i
= 0; i
< self
->const_count
; i
++) {
164 cursor
= PackFile_Constant_pack(interp
, self
, self
->constants
[i
], cursor
);
173 find_in_const(Interp *interp, PMC *key, int type)>
175 This is really ugly, we don't know where our C<PARROT_ARG_SC> key
176 constant is in constant table, so we have to search for it.
183 PackFile_find_in_const(Interp
*interp
, struct PackFile_ConstTable
*ct
, PMC
*key
, int type
)
186 for (i
= 0; i
< ct
->const_count
; i
++)
187 if (type
== PFC_STRING
&& ct
->constants
[i
]->u
.string
==
190 else if (type
== PFC_NUMBER
&& ct
->constants
[i
]->u
.number
==
193 PIO_eprintf(NULL
, "find_in_const: couldn't find const for key\n");
194 Parrot_exit(interp
, 1);
201 PackFile_Constant_pack(Interp*, struct PackFile_ConstTable * const_table,
202 struct PackFile_Constant *self, opcode_t *cursor)>
204 Pack a PackFile Constant into a contiguous region of memory.
206 Note that the memory block had better have at least the amount of memory
207 indicated by C<PackFile_pack_size()>.
209 This means that you MUST call C<PackFile_pack_size()> before
210 C<PackFile_Constant_pack()>
212 The data is zero-padded to an opcode_t-boundary, so pad bytes may be added.
213 (Note this padding is not yet implemented for FLOATVALs.)
220 PackFile_Constant_pack(Interp
* interp
, struct PackFile_ConstTable
* const_table
,
221 struct PackFile_Constant
*self
, opcode_t
*cursor
)
228 *cursor
++ = self
->type
;
230 switch (self
->type
) {
233 cursor
= PF_store_number(cursor
, &self
->u
.number
);
237 cursor
= PF_store_string(cursor
, self
->u
.string
);
241 key
= self
->u
.key
; /* the (Sub) PMC */
242 image
= Parrot_freeze(interp
, key
);
243 cursor
= PF_store_string(cursor
, image
);
247 for (i
= 0, key
= self
->u
.key
; key
; key
= PMC_data(key
), i
++)
249 /* number of key components */
251 /* and now type / value per component */
252 for (key
= self
->u
.key
; key
; key
= PMC_data(key
)) {
253 opcode_t type
= PObj_get_FLAGS(key
);
255 if ((type
& (KEY_start_slice_FLAG
|KEY_inf_slice_FLAG
)) ==
256 (KEY_start_slice_FLAG
|KEY_inf_slice_FLAG
))
257 slice_bits
|= PF_VT_END_INF
;
258 if ((type
& (KEY_end_slice_FLAG
|KEY_inf_slice_FLAG
)) ==
259 (KEY_end_slice_FLAG
|KEY_inf_slice_FLAG
))
260 slice_bits
|= PF_VT_START_ZERO
;
261 if (type
& KEY_start_slice_FLAG
)
262 slice_bits
|= PF_VT_START_SLICE
;
263 if (type
& KEY_end_slice_FLAG
)
264 slice_bits
|= PF_VT_END_SLICE
;
266 type
&= KEY_type_FLAGS
;
268 case KEY_integer_FLAG
:
269 *cursor
++ = PARROT_ARG_IC
| slice_bits
;
270 *cursor
++ = PMC_int_val(key
);
272 case KEY_number_FLAG
:
273 *cursor
++ = PARROT_ARG_NC
| slice_bits
;
275 *cursor
++ = PackFile_find_in_const(interp
, const_table
, key
, PFC_NUMBER
);
277 case KEY_string_FLAG
:
278 *cursor
++ = PARROT_ARG_SC
| slice_bits
;
280 *cursor
++ = PackFile_find_in_const(interp
, const_table
, key
, PFC_STRING
);
283 case KEY_integer_FLAG
| KEY_register_FLAG
:
284 *cursor
++ = PARROT_ARG_I
| slice_bits
;
285 *cursor
++ = PMC_int_val(key
);
287 case KEY_number_FLAG
| KEY_register_FLAG
:
288 *cursor
++ = PARROT_ARG_N
| slice_bits
;
289 *cursor
++ = PMC_int_val(key
);
291 case KEY_string_FLAG
| KEY_register_FLAG
:
292 *cursor
++ = PARROT_ARG_S
| slice_bits
;
293 *cursor
++ = PMC_int_val(key
);
295 case KEY_pmc_FLAG
| KEY_register_FLAG
:
296 *cursor
++ = PARROT_ARG_P
| slice_bits
;
297 *cursor
++ = PMC_int_val(key
);
300 PIO_eprintf(NULL
, "PackFile_Constant_pack: "
301 "unsupported constant type\n");
302 Parrot_exit(interp
, 1);
309 PIO_eprintf(NULL
, "PackFile_Constant_pack: unsupported constant\n");
310 Parrot_exit(interp
, 1);
322 Rework by Melvin; new bytecode format, make bytecode portable. (Do
323 endian conversion and wordsize transforms on the fly.)
325 leo: rewrite to use new directory-based format.
334 * c-file-style: "parrot"
336 * vim: expandtab shiftwidth=4: