# New Ticket Created by Jürgen Bömmels # Please include the string: [perl #18056] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=18056 >
This patch is the beginning of an effort to make PackFile format extendible. At the moment its combatible with the old bytecode format. Ok, to the details: It appends a 4th segment behind the 3 already defined segments (FIXUP, CONSTANT and BYTECODE) name DIRECTORY. After this directory one ore more uniquely named segments may follow. The directory segments start with the number of segments in the PackFile, followed by a list of directory items. Each item constists of a '\0' terminated c-string (padded to opcode_t-alignment), a flag-word, the size of the corresponding segment and the position of the segment in the packfile. The 4 first segments are nothing special, expect that their name and order is fixed. The implementation uses a glib style inheritance aproach. The base-"class" of all Segments is struct PackFile_Segment which consists of data-members for name, packfile, fileoffset, size and flags and furter the member-functions destroy, packed_size, and pack. The derived "classes" struct PackFile_Directory, PackFile_ConstTable PackFile_FixupTable and PackFile_ByteCode (the later two are ATM just dummy implementations) embed a PackFile_Segment as first elment so the base-class can be get by a pointer cast. Next steps might be: - seperate the packfile.c in diffrent files (maybe move them to a directory/subsystem on its own as suggest by PDD07) one for each segment-type. - document the extension in parrotbyte.pod - lower the restriction on the ordering of the first 4 segments - write an objdump-like tool for manipulating packfiles. (I tried to extend pdump for that, but it segfaults in unmake_COW, a NULL-interpreter from PIO_eprintf) - Teach the assembler to output the new format. (imcc uses AFAIK packout.c and should already work) bye b. -- attachment 1 ------------------------------------------------------ url: http://rt.perl.org/rt2/attach/40325/32605/06f52f/packfile.diff
Index: packfile.c =================================================================== RCS file: /cvs/public/parrot/packfile.c,v retrieving revision 1.57 diff -u -r1.57 packfile.c --- packfile.c 11 Oct 2002 01:46:31 -0000 1.57 +++ packfile.c 22 Oct 2002 00:26:35 -0000 @@ -19,6 +19,46 @@ #define TRACE_PACKFILE 0 +/* +** Static functions +*/ +static void segment_init (struct PackFile_Segment *self, + struct PackFile *pf, + const char* name, + PackFile_Segment_destroy_func_t destroy, + PackFile_Segment_packed_size_func_t packed_size, + PackFile_Segment_pack_func_t size); + +static void default_destroy (struct PackFile_Segment *self); +static size_t default_packed_size (struct PackFile_Segment *self); +static size_t default_pack (struct PackFile_Segment *self, + opcode_t *dest, size_t offset, size_t size); + +static struct PackFile_Directory *directory_new (struct PackFile *pf); +static size_t directory_unpack (struct PackFile *pf, opcode_t *cursor); +static void directory_destroy (struct PackFile_Segment *self); +static size_t directory_packed_size (struct PackFile_Segment *self); +static size_t directory_pack (struct PackFile_Segment *self, + opcode_t *dest, size_t offset, size_t size); + +static struct PackFile_FixupTable *fixup_new (struct PackFile *pf); +static size_t fixup_packed_size (struct PackFile_Segment *self); +static size_t fixup_pack (struct PackFile_Segment * self, + opcode_t *dest, size_t offset, size_t size); + +static struct PackFile_ConstTable *const_new (struct PackFile *pf); +static void const_destroy (struct PackFile_Segment *self); +static size_t const_pack (struct PackFile_Segment *self, + opcode_t *dest, size_t offset, size_t size); + +static struct PackFile_ByteCode *byte_code_new (struct PackFile *pf); +static size_t byte_code_packed_size (struct PackFile_Segment *self); +static size_t byte_code_pack (struct PackFile_Segment *self, + opcode_t *dest, size_t offset, size_t size); + +/* internal definitions */ +#define ROUND_UP(val,size) ((val) + (size) - (val)%(size)) + /****************************************************************************** =head1 PackFile Manipulation Functions @@ -61,8 +101,7 @@ } /* Create fixup table */ - pf->fixup_table = - mem_sys_allocate(sizeof(struct PackFile_FixupTable)); + pf->fixup_table = fixup_new(pf); if (!pf->fixup_table) { PIO_eprintf(NULL, "PackFile_new: Unable to allocate fixup table!\n"); @@ -72,21 +111,22 @@ pf->fixup_table->dummy = 0; /* Create constant table */ - pf->const_table = - mem_sys_allocate(sizeof(struct PackFile_ConstTable)); + pf->const_table = const_new (pf); if (!pf->const_table) { PIO_eprintf(NULL, "PackFile_new: Unable to allocate constant table!\n"); + PackFile_FixupTable_clear (pf->fixup_table); PackFile_destroy(pf); return NULL; } - pf->const_table->const_count = 0; - pf->const_table->constants = NULL; - + + pf->byte_code_segment = byte_code_new (pf); /* Other fields empty for now */ pf->byte_code = NULL; pf->byte_code_size = 0; + pf->directory = NULL; + return pf; } @@ -209,21 +249,8 @@ return; } - if (pf->header) { - mem_sys_free(pf->header); - } - - if (pf->fixup_table) { - mem_sys_free(pf->fixup_table); - } - - if (pf->const_table) { - PackFile_ConstTable_clear(pf->const_table); - mem_sys_free(pf->const_table); - } - - if (pf->byte_code) { - mem_sys_free(pf->byte_code); + if (pf->directory) { + directory_destroy ((struct PackFile_Segment *)pf->directory); } mem_sys_free(pf); @@ -430,10 +457,438 @@ } + /* For the moment append directory */ + if (((size_t)(cursor - packed) * sizeof(opcode_t)) != packed_size) { + self->src = packed; + cursor += directory_unpack (self, cursor) + / sizeof (opcode_t); + } + else { + self->directory = directory_new (self); + } + return ((size_t)(cursor - packed) * sizeof(opcode_t)) == packed_size; } /* +** PackFile_map_segments +** for each segment in the packfile 'pf' the callbackfunction 'callback' +** is called. The pointer 'user_data' is append to each call. +** If a callback returns non-zero the processing of segments is stopped, +** and this value is returned +*/ + +INTVAL +PackFile_map_segments (struct PackFile *pf, + PackFile_map_segments_func_t callback, + void *user_data) +{ + INTVAL ret; + size_t i; + struct PackFile_Directory *dir = pf->directory; + + for (i=0; i < dir->num_segments; i++) { + ret = callback (dir->segments[i], user_data); + if (!ret) return ret; + } + + return 0; +} + +/* +** PackFile_add_segment +** adds the Segment 'seg' to the PackFile 'pf'. +** The PackFile becomes the owner of the segment; that means its +** getting destroyed, when the packfile gets destroyed. +*/ + +INTVAL +PackFile_add_segment (struct PackFile *pf, struct PackFile_Segment *seg) +{ + struct PackFile_Directory *dir = pf->directory; + + dir->segments = mem_sys_realloc (dir->segments, + sizeof (struct PackFile_Segment *) * (dir->num_segments+1)); + dir->segments[dir->num_segments] = seg; + dir->num_segments++; + + return 0; +} + +/* +** PackFile_find_segment +** finds the segment with the name 'name' in the PackFile 'pf' +** The segment is returned, but its still owned by the PackFile. +*/ + +struct PackFile_Segment * +PackFile_find_segment (struct PackFile *pf, const char *name) +{ + struct PackFile_Directory *dir = pf->directory; + size_t i; + + for (i=0; i < dir->num_segments; i++) { + if (strcmp (dir->segments[i]->name, name) == 0) { + return dir->segments[i]; + } + } + + return NULL; +} + +/* +** PackFile_remove_segment_by_name +** finds and removes the segment with name 'name' in the PackFile 'pf' +** The segment is returned an must be destroyed by the user +*/ + +struct PackFile_Segment * +PackFile_remove_segment_by_name (struct PackFile *pf, const char *name) +{ + struct PackFile_Directory *dir = pf->directory; + size_t i; + + for (i=0; i < dir->num_segments; i++) { + struct PackFile_Segment *seg = dir->segments[i]; + if (strcmp (seg->name, name) == 0) { + memmove (dir->segments[i], dir->segments[i+1], + (--dir->num_segments) * sizeof (struct PackFile_Segment *)); + dir->segments = mem_sys_realloc (dir->segments, + sizeof (struct PackFile_Segment *) * dir->num_segments); + return seg; + } + } + + return NULL; +} + + +/*****************************************************************************/ + +/* +** PackFile_Directory Functions +*/ + +/* +**Format of the directory: +* +----------+----------+----------+----------+ +* | number of directory items | +* +----------+----------+----------+----------+ +* +* followed by a sequence of items +* +----------+----------+----------+----------+ +* | "name" | +* | ... '\0' padding bytes | +* +----------+----------+----------+----------+ +* | Section Flags | +* +----------+----------+----------+----------+ +* | Offset in the file | +* +----------+----------+----------+----------+ +* | Size of the segment | +* +----------+----------+----------+----------+ +* +* name is a NUL-terminated c-string encoded in +* plain ASCII. +* Section Flags are currently undefined. +*/ + +static struct PackFile_Directory * +directory_new (struct PackFile *pf) +{ + struct PackFile_Directory *dir; + + dir = mem_sys_allocate (sizeof(struct PackFile_Directory)); + + segment_init (&dir->base, pf, DIRECTORY_SEGMENT_NAME, + directory_destroy, directory_packed_size, directory_pack); + + dir->num_segments = 4; + dir->segments = mem_sys_allocate (sizeof(struct PackFile_Segment *) * 4); + + dir->segments[0] = (struct PackFile_Segment*)pf->fixup_table; + dir->segments[1] = (struct PackFile_Segment*)pf->const_table; + dir->segments[2] = (struct PackFile_Segment*)pf->byte_code_segment; + + dir->segments[3] = (struct PackFile_Segment*)dir; + + return dir; +} + +static size_t +directory_unpack (struct PackFile * self, + opcode_t * dir_begin) +{ + opcode_t dir_len; + opcode_t *cursor = dir_begin; + size_t i; + + struct PackFile_Directory *dir; + + dir_len = PackFile_fetch_op (self, cursor++); + + if (!PackFile_check_segment_size(dir_len, "directory")) { + return 0; + } + + dir = directory_new (self); + + dir->num_segments = PackFile_fetch_op (self, cursor++); + dir->segments = mem_sys_realloc (dir->segments, + sizeof(struct PackFile_Segment *) * dir->num_segments); + + for (i=0; i < dir->num_segments; i++) { + struct PackFile_Segment *seg; + size_t str_len; + size_t tmp; + + if (strcmp ((char*)cursor,DIRECTORY_SEGMENT_NAME) == 0) { + seg = (struct PackFile_Segment *)dir; + } + else { + /* Assign the fixed values */ + switch (i) { + case 0: + seg = &self->fixup_table->base; + break; + + case 1: + seg = &self->const_table->base; + break; + + case 2: + seg = &self->byte_code_segment->base; + break; + + default: + seg = PackFile_Segment_new(self); + break; + } + } + + str_len = strlen ((char *)cursor); + seg->name = mem_sys_allocate (str_len); + strcpy (seg->name, (char *)cursor); + + cursor += ROUND_UP(str_len+1, sizeof(opcode_t)) / sizeof(opcode_t); + + seg->flags = PackFile_fetch_op(self, cursor++); + seg->file_offset = PackFile_fetch_iv(self, cursor++); + seg->byte_count = PackFile_fetch_op(self, cursor++); + + /* check the constraints */ + if (seg == (struct PackFile_Segment *)dir + && FILE_POS(self->src, dir->base.file_offset) != dir_begin) { + fprintf (stderr, "%s: Directory is not selfreferential: (%p != %p)\n", "section", dir_begin, FILE_POS(self->src, dir->base.file_offset)); + } + + tmp = PackFile_fetch_op (self, FILE_POS(self->src, seg->file_offset)); + if (seg->byte_count != tmp) { + fprintf (stderr, "%s: Size in directory (%d) doesn't match size at offset (%d)\n", "section", seg->byte_count, tmp); + } + if (i>0) { + struct PackFile_Segment *last = dir->segments[i-1]; + if (last->file_offset + last->byte_count + sizeof(opcode_t) + != seg->file_offset) { + fprintf (stderr, "%s: sections are not back to back\n", + "section"); + } + } + + /* store the segment */ + dir->segments[i] = seg; + } + + self->directory = dir; + + + return (cursor - dir_begin) * sizeof(opcode_t); +} + +#define PACKFILE_DIR_IN_DESTROY 0x01 + +void +directory_destroy (struct PackFile_Segment *self) +{ + struct PackFile_Directory *dir = (struct PackFile_Directory *)self; + size_t i; + + if (self->flags & PACKFILE_DIR_IN_DESTROY) { + return; + } + + self->flags |= PACKFILE_DIR_IN_DESTROY; + + for (i = 0; i < dir->num_segments; i++) { + PackFile_Segment_destroy (dir->segments[i]); + } + + if (dir->segments) mem_sys_free (dir->segments); + mem_sys_free (self); +} + +size_t +directory_packed_size (struct PackFile_Segment *self) +{ + struct PackFile_Directory *dir = (struct PackFile_Directory *)self; + size_t size = 0; + size_t i; + + /* number of segments */ + size += sizeof (opcode_t); + + for (i = 0; i < dir->num_segments; i++) { + UINTVAL str_len; + /* name */ + str_len = strlen (dir->segments[i]->name); + size += ROUND_UP(str_len + 1, sizeof(opcode_t)); + /* flags */ + size += sizeof(opcode_t); + /* file_offset */ + size += sizeof(opcode_t); + /* size */ + size += sizeof(opcode_t); + } + + return size; +} + +size_t +directory_pack (struct PackFile_Segment *self, + opcode_t *dest, size_t offset, size_t size) +{ + struct PackFile_Directory *dir = (struct PackFile_Directory *)self; + size_t i; + size_t needed_size; + opcode_t *cursor = FILE_POS(dest,offset); + size_t *new_sizes; + size_t *new_offsets; + size_t base_offset =0; + size_t last_offset; + size_t num_segs; + + needed_size = directory_packed_size (self); + + /* number of segments */ + num_segs = dir->num_segments; + *cursor++ = num_segs; + + new_sizes = mem_sys_allocate(2 * sizeof(size_t) * num_segs); + new_offsets = new_sizes + num_segs; + + /* calculate the file offsets */ + last_offset = 0; + for (i = 0; i < num_segs; i++) { + new_sizes[i] = PackFile_Segment_packed_size(dir->segments[i]); + new_offsets[i] = last_offset; + if (dir->segments[i] == self) base_offset = last_offset; + last_offset += new_sizes[i] + sizeof(opcode_t); + } + + if (offset < base_offset + sizeof(opcode_t)) { + fprintf (stderr, DIRECTORY_SEGMENT_NAME ": pack offset not big enough for all previous sections\n"); + } + base_offset = offset - base_offset - sizeof(opcode_t); + + for (i = 0; i < num_segs; i++) { + struct PackFile_Segment *seg = dir->segments[i]; + size_t str_len = strlen (seg->name); + /* name */ + + strcpy ((char *)cursor, seg->name); + cursor += ROUND_UP(str_len + 1, sizeof(opcode_t)) / sizeof(opcode_t); + /* flags */ + *cursor++ = seg->flags; + /* file_offset */ + *cursor++ = base_offset + new_offsets[i]; + /* size */ + *cursor++ = new_sizes[i]; + } + + mem_sys_free (new_sizes); + + return needed_size; +} + +/*****************************************************************************/ + +/* +** PackFile_Segment Functions +*/ + +static void +segment_init (struct PackFile_Segment *self, + struct PackFile *pf, + const char *name, + PackFile_Segment_destroy_func_t destroy, + PackFile_Segment_packed_size_func_t packed_size, + PackFile_Segment_pack_func_t pack) +{ + self->pf = pf; + self->flags = 0; + self->file_offset = 0; + self->byte_count = 0; + + self->name = mem_sys_allocate (strlen (name)); + strcpy (self->name, name); + + self->destroy = destroy; + self->packed_size = packed_size; + self->pack = pack; +} + +/* +** PackFile_Segment_new: +* create a new default section +*/ + +struct PackFile_Segment * +PackFile_Segment_new (struct PackFile *pf) +{ + struct PackFile_Segment *seg; + + seg = mem_sys_allocate (sizeof(struct PackFile_Segment)); + + segment_init (seg, pf, "", default_destroy, default_packed_size, + default_pack); + + return seg; +} + +/* default function implementations */ + +static void +default_destroy (struct PackFile_Segment *self) +{ + if (self->name) mem_sys_free (self->name); + mem_sys_free (self); +} + +static size_t +default_packed_size (struct PackFile_Segment *self) +{ + return self->byte_count; +} + +static size_t +default_pack (struct PackFile_Segment *self, + opcode_t *dest, size_t offset, size_t size) +{ + if (size < self->byte_count) { + fprintf (stderr, "%s: pack segment not enough space", ""); + return 0; + } + + /* copy the orignal data if necessary */ + if (dest != self->pf->src) { + memcpy (dest + offset/sizeof(opcode_t), + self->pf->src + self->file_offset/sizeof(opcode_t), + self->byte_count); + } + + return self->byte_count; +} + +/* =back @@ -457,9 +912,40 @@ return; } + default_destroy (&self->base); + return; } +static size_t +fixup_packed_size (struct PackFile_Segment *self) +{ + return 0; +} +static size_t +fixup_pack (struct PackFile_Segment *self, + opcode_t *dest, size_t offset, size_t size) +{ + return 0; +} + +/* +** PackFile_FixupTable_new +*/ + +struct PackFile_FixupTable * +fixup_new (struct PackFile *pf) +{ + struct PackFile_FixupTable *fixup; + + fixup = mem_sys_allocate(sizeof(struct PackFile_FixupTable)); + + segment_init (&fixup->base, pf, FIXUP_TABLE_SEGMENT_NAME, + (PackFile_Segment_destroy_func_t)PackFile_FixupTable_clear, + fixup_packed_size, fixup_pack); + + return fixup; +} /*************************************** @@ -602,6 +1088,76 @@ return 1; } +static struct PackFile_ConstTable * +const_new (struct PackFile *pf) +{ + struct PackFile_ConstTable *const_table; + + const_table = mem_sys_allocate(sizeof(struct PackFile_ConstTable)); + + segment_init (&const_table->base, pf, CONSTANT_SEGMENT_NAME, + const_destroy, + (PackFile_Segment_packed_size_func_t)PackFile_ConstTable_pack_size, + const_pack); + + const_table->const_count = 0; + const_table->constants = NULL; + + return const_table; +} + +static void +const_destroy (struct PackFile_Segment *self) +{ + struct PackFile_ConstTable *ct = (struct PackFile_ConstTable *)self; + + PackFile_ConstTable_clear (ct); + default_destroy (self); +} + +static size_t +const_pack (struct PackFile_Segment *self, + opcode_t *dest, size_t offset, size_t size) +{ + struct PackFile_ConstTable *ct = (struct PackFile_ConstTable *)self; + + PackFile_ConstTable_pack (self->pf, ct, dest + offset/sizeof(opcode_t)); + + return size; +} + +/* +** ByteCode +*/ + +static struct PackFile_ByteCode * +byte_code_new (struct PackFile *pf) +{ + struct PackFile_ByteCode *byte_code; + + byte_code = mem_sys_allocate(sizeof(struct PackFile_ByteCode)); + + segment_init (&byte_code->base, pf, FIXUP_TABLE_SEGMENT_NAME, + default_destroy, byte_code_packed_size, + byte_code_pack); + + return byte_code; +} + +static size_t +byte_code_packed_size (struct PackFile_Segment *self) +{ + return self->pf->byte_code_size; +} + +static size_t +byte_code_pack (struct PackFile_Segment *self, + opcode_t *dest, size_t offset, size_t size) +{ + memcpy (dest + offset/sizeof(opcode_t), self->pf->byte_code, size); + return size; +} + /* =back @@ -674,8 +1230,6 @@ return; break; } - - mem_sys_free(self); return; } Index: packout.c =================================================================== RCS file: /cvs/public/parrot/packout.c,v retrieving revision 1.12 diff -u -r1.12 packout.c --- packout.c 11 Oct 2002 01:46:31 -0000 1.12 +++ packout.c 22 Oct 2002 00:26:35 -0000 @@ -28,38 +28,24 @@ opcode_t magic_size; opcode_t oct_size; /* opcode_type */ opcode_t segment_length_size; - opcode_t fixup_table_size; - opcode_t const_table_size; + + struct PackFile_Directory *dir = self->directory; + opcode_t other_segments_size; + size_t i; header_size = PACKFILE_HEADER_BYTES; magic_size = sizeof(opcode_t); oct_size = sizeof(opcode_t); segment_length_size = sizeof(opcode_t); -#if TRACE_PACKFILE - PIO_eprintf(NULL, "getting fixup table size...\n"); -#endif - - fixup_table_size = PackFile_FixupTable_pack_size(self->fixup_table); - -#if TRACE_PACKFILE - PIO_eprintf(NULL, " ... it is %ld\n", fixup_table_size); -#endif - -#if TRACE_PACKFILE - PIO_eprintf(NULL, "getting const table size...\n"); -#endif - - const_table_size = PackFile_ConstTable_pack_size(self->const_table); - -#if TRACE_PACKFILE - PIO_eprintf(NULL, " ... it is %ld\n", const_table_size); -#endif - - return header_size + magic_size + oct_size - + segment_length_size + fixup_table_size - + segment_length_size + const_table_size - + segment_length_size + self->byte_code_size; + other_segments_size = 0; + + for (i=0; i < dir->num_segments; i++) { + other_segments_size += PackFile_Segment_packed_size (dir->segments[i]) + + sizeof(opcode_t); + } + + return header_size + magic_size + oct_size + other_segments_size; } @@ -78,6 +64,9 @@ opcode_t const_table_size = PackFile_ConstTable_pack_size(self->const_table); + size_t i; + struct PackFile_Directory *dir = self->directory; + self->header->wordsize = sizeof(opcode_t); self->header->byteorder = PARROT_BIGENDIAN; self->header->minor = PARROT_MINOR_VERSION; @@ -97,26 +86,16 @@ /* Pack the fixup table size, followed by the packed fixup table */ - *cursor++ = fixup_table_size; - - PackFile_FixupTable_pack(self->fixup_table, cursor); - /* Sizes are in bytes */ - cursor += fixup_table_size / sizeof(opcode_t); - - /* Pack the constant table size, followed by the packed constant table */ - - *cursor++ = const_table_size; - - PackFile_ConstTable_pack(self, self->const_table, cursor); - /* Sizes are in bytes */ - cursor += const_table_size / sizeof(opcode_t); - - /* Pack the byte code size, followed by the byte code */ - - *cursor++ = self->byte_code_size; - - if (self->byte_code_size) { - mem_sys_memcopy(cursor, self->byte_code, self->byte_code_size); + for (i = 0; i < dir->num_segments; i++) { + struct PackFile_Segment *seg = dir->segments[i]; + size_t size; + + size = PackFile_Segment_packed_size (seg); + *cursor++ = size; + + cursor += PackFile_Segment_pack (seg, packed, + (cursor-packed)* sizeof(opcode_t), + size) / sizeof (opcode_t); } return; Index: include/parrot/packfile.h =================================================================== RCS file: /cvs/public/parrot/include/parrot/packfile.h,v retrieving revision 1.31 diff -u -r1.31 packfile.h --- include/parrot/packfile.h 19 Aug 2002 23:15:52 -0000 1.31 +++ include/parrot/packfile.h 22 Oct 2002 00:26:35 -0000 @@ -15,6 +15,12 @@ #define PF_NCONST(pf) ((pf)->const_table->const_count) #define PF_CONST(pf,i) ((pf)->const_table->constants[(i)]) +#define DIRECTORY_SEGMENT_NAME "DIRECTORY" +#define FIXUP_TABLE_SEGMENT_NAME "FIXUP" +#define CONSTANT_SEGMENT_NAME "CONSTANT" +#define BYTE_CODE_SEGMENT_NAME "BYTECODE" + +#define FILE_POS(file,offset) ((file) + (offset)/sizeof(opcode_t)) /* ** Structure Definitions: @@ -43,7 +49,42 @@ opcode_t bytecode_ss; }; +/* +** PackFile Segment: +* The base type of every section +* include it as first element of every derivated Segment +*/ + +struct PackFile_Segment; + +typedef void (*PackFile_Segment_destroy_func_t) (struct PackFile_Segment *); +typedef size_t (*PackFile_Segment_packed_size_func_t) (struct PackFile_Segment *); +typedef size_t (*PackFile_Segment_pack_func_t) (struct PackFile_Segment *, + opcode_t *dest, + size_t offset, + size_t max_size); +typedef INTVAL (*PackFile_map_segments_func_t) (struct PackFile_Segment *seg, + void *user_data); + +struct PackFile_Segment { + struct PackFile * pf; + char * name; + UINTVAL flags; + size_t byte_count; /* size in bytes */ + size_t file_offset; + + /* Segment operations */ + PackFile_Segment_destroy_func_t destroy; + PackFile_Segment_packed_size_func_t packed_size; + PackFile_Segment_pack_func_t pack; +}; + +/* +** PackFile_FixupTable: +* not implemented yet +*/ struct PackFile_FixupTable { + struct PackFile_Segment base; opcode_t dummy; }; @@ -60,17 +101,34 @@ PMC *key; }; - struct PackFile_ConstTable { + struct PackFile_Segment base; opcode_t const_count; struct PackFile_Constant **constants; }; +struct PackFile_ByteCode { + struct PackFile_Segment base; + opcode_t * code; +}; + +struct PackFile_Directory { + struct PackFile_Segment base; + size_t num_segments; + struct PackFile_Segment ** segments; +}; struct PackFile { + opcode_t *src; /* FIXME: use PIO */ + struct PackFile_Header * header; + + /* special Segments */ + struct PackFile_Directory * directory; struct PackFile_FixupTable * fixup_table; struct PackFile_ConstTable * const_table; + struct PackFile_ByteCode * byte_code_segment; + size_t byte_code_size; /* size in bytes */ opcode_t * byte_code; INTVAL need_wordsize; @@ -96,6 +154,30 @@ opcode_t PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, opcode_t *packed, size_t packed_size); + +INTVAL PackFile_add_segment (struct PackFile *pf, + struct PackFile_Segment *seg); + +struct PackFile_Segment * PackFile_find_segment (struct PackFile *pf, + const char *name); + +struct PackFile_Segment * +PackFile_remove_segment_by_name (struct PackFile *pf, const char *name); + +INTVAL PackFile_map_segments (struct PackFile *pf, + PackFile_map_segments_func_t callback, + void* usr_data); + +/* +** PackFile_Segment Functions: +*/ + +#define PackFile_Segment_destroy(self) ((self)->destroy(self)) +#define PackFile_Segment_packed_size(self) ((self)->packed_size(self)) +#define PackFile_Segment_pack(self, file, offset, max_size) \ + ((self)->pack(self, file, offset, max_size)) + +struct PackFile_Segment *PackFile_Segment_new(struct PackFile *pf); /* ** PackFile_FixupTable Functions: