* src/pmc/multisub.pmc:
[parrot.git] / src / pbc_merge.c
blobf7bf5a51d78ad1049b9e3d2e8c4baccccef2b771
1 /*
2 Copyright (C) 2005-2007, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 pbc_merge - Merge multiple Parrot bytecode (PBC) files into
8 a single PBC file.
10 =head1 SYNOPSIS
12 pbc_merge -o out.pbc input1.pbc input2.pbc ...
14 =head1 DESCRIPTION
16 This program takes two or more PBC files and produces a single
17 merged output PBC file with a single fix-up table and constants
18 table.
20 =head2 Command-Line Options
22 =over 4
24 =item C<-o out.pbc>
26 The name of the PBC file to produce, containing the merged
27 segments from the input PBC files.
29 =back
31 =cut
36 #include "parrot/parrot.h"
37 #include "parrot/embed.h"
38 #include "parrot/oplib/ops.h"
41 /* This struct describes an input file. */
42 typedef struct pbc_merge_input {
43 const char *filename; /* Filename of the input file. */
44 PackFile *pf; /* The loaded packfile. */
45 opcode_t code_start; /* Where the bytecode is located in the merged
46 bytecode. */
47 opcode_t const_start; /* Where the const table is located in the merged
48 one. */
49 } pbc_merge_input;
51 /* HEADERIZER HFILE: none */
53 /* HEADERIZER BEGIN: static */
55 static void help( PARROT_INTERP )
56 __attribute__nonnull__(1);
58 PARROT_WARN_UNUSED_RESULT
59 PARROT_CANNOT_RETURN_NULL
60 static PackFile* pbc_merge_begin( PARROT_INTERP,
61 NOTNULL(pbc_merge_input **inputs),
62 int num_inputs )
63 __attribute__nonnull__(1)
64 __attribute__nonnull__(2);
66 PARROT_WARN_UNUSED_RESULT
67 PARROT_CANNOT_RETURN_NULL
68 static PackFile_ByteCode* pbc_merge_bytecode( PARROT_INTERP,
69 NOTNULL(pbc_merge_input **inputs),
70 int num_inputs,
71 NOTNULL(PackFile *pf) )
72 __attribute__nonnull__(1)
73 __attribute__nonnull__(2)
74 __attribute__nonnull__(4);
76 PARROT_WARN_UNUSED_RESULT
77 PARROT_CANNOT_RETURN_NULL
78 static PackFile_ConstTable* pbc_merge_constants( PARROT_INTERP,
79 NOTNULL(pbc_merge_input **inputs),
80 int num_inputs,
81 NOTNULL(PackFile *pf),
82 NOTNULL(PackFile_ByteCode *bc) )
83 __attribute__nonnull__(1)
84 __attribute__nonnull__(2)
85 __attribute__nonnull__(4)
86 __attribute__nonnull__(5);
88 static void pbc_merge_ctpointers( PARROT_INTERP,
89 NOTNULL(pbc_merge_input **inputs),
90 int num_inputs,
91 NOTNULL(PackFile_ByteCode *bc) )
92 __attribute__nonnull__(1)
93 __attribute__nonnull__(2)
94 __attribute__nonnull__(4);
96 static void pbc_merge_debugs( PARROT_INTERP,
97 NOTNULL(pbc_merge_input **inputs),
98 int num_inputs,
99 NOTNULL(PackFile *pf),
100 NOTNULL(PackFile_ByteCode *bc) )
101 __attribute__nonnull__(1)
102 __attribute__nonnull__(2)
103 __attribute__nonnull__(4)
104 __attribute__nonnull__(5);
106 static void pbc_merge_fixups( PARROT_INTERP,
107 NOTNULL(pbc_merge_input **inputs),
108 int num_inputs,
109 NOTNULL(PackFile *pf),
110 NOTNULL(PackFile_ByteCode *bc) )
111 __attribute__nonnull__(1)
112 __attribute__nonnull__(2)
113 __attribute__nonnull__(4)
114 __attribute__nonnull__(5);
116 PARROT_WARN_UNUSED_RESULT
117 PARROT_CANNOT_RETURN_NULL
118 static PackFile* pbc_merge_loadpbc( PARROT_INTERP,
119 NOTNULL(const char *fullname) )
120 __attribute__nonnull__(1)
121 __attribute__nonnull__(2);
123 static void pbc_merge_pic_index( PARROT_INTERP,
124 NOTNULL(pbc_merge_input **inputs),
125 int num_inputs,
126 NOTNULL(PackFile *pf),
127 NOTNULL(PackFile_ByteCode *bc) )
128 __attribute__nonnull__(1)
129 __attribute__nonnull__(2)
130 __attribute__nonnull__(4)
131 __attribute__nonnull__(5);
133 static void pbc_merge_write( PARROT_INTERP,
134 NOTNULL(PackFile *pf),
135 NOTNULL(const char *filename) )
136 __attribute__nonnull__(1)
137 __attribute__nonnull__(2)
138 __attribute__nonnull__(3);
140 PARROT_MALLOC
141 PARROT_CANNOT_RETURN_NULL
142 static char * str_dup( NOTNULL(const char *old) )
143 __attribute__nonnull__(1);
145 /* HEADERIZER END: static */
149 static void help(Interp *)
151 Print out the user help info.
155 static void
156 help(PARROT_INTERP)
158 printf("pbc_merge - merge multiple parrot bytecode files into one\n");
159 printf("Usage:\n");
160 printf(" pbc_merge -o out.pbc file1.pbc file2.pbc ...\n\n");
161 Parrot_exit(interp, 0);
166 FUNCDOC: str_dup
168 Duplicate a C string
172 PARROT_MALLOC
173 PARROT_CANNOT_RETURN_NULL
174 static char *
175 str_dup(NOTNULL(const char *old))
177 const size_t bytes = strlen(old) + 1;
178 char * const copy = mem_sys_allocate(bytes);
179 memcpy(copy, old, bytes);
180 #ifdef MEMDEBUG
181 debug(interp, 1,"line %d str_dup %s [%x]\n", line, old, copy);
182 #endif
183 return copy;
188 FUNCDOC: pbc_merge_loadpbc
190 This function loads a PBC file and unpacks it. We can't
191 use Parrot_readbc because that is specified to also
192 fixup the segments, which we don't want.
195 PARROT_WARN_UNUSED_RESULT
196 PARROT_CANNOT_RETURN_NULL
197 static PackFile*
198 pbc_merge_loadpbc(PARROT_INTERP, NOTNULL(const char *fullname))
200 INTVAL program_size, wanted;
201 char *program_code;
202 PackFile *pf;
203 FILE * io = NULL;
204 INTVAL is_mapped = 0;
205 size_t chunk_size;
206 char *cursor;
207 INTVAL read_result;
209 /* Check the file exists. */
210 STRING * const fs = string_make(interp, fullname,
211 strlen(fullname), NULL, 0);
212 if (!Parrot_stat_info_intval(interp, fs, STAT_EXISTS)) {
213 PIO_eprintf(interp, "PBC Merge: Can't stat %s, code %i.\n",
214 fullname, errno);
215 Parrot_exit(interp, 1);
218 /* Get program size. */
219 program_size = Parrot_stat_info_intval(interp, fs, STAT_FILESIZE);
221 /* Attempt to open file and handle any errors. */
222 io = fopen(fullname, "rb");
223 if (!io) {
224 PIO_eprintf(interp, "PBC Merge: Can't open %s, code %i.\n",
225 fullname, errno);
226 Parrot_exit(interp, 1);
229 /* Read in program. Nabbed from Parrot_readpbc. */
230 chunk_size = program_size > 0 ? program_size : 1024;
231 program_code = (char *)mem_sys_allocate(chunk_size);
232 wanted = program_size;
233 program_size = 0;
234 cursor = (char *)program_code;
236 while ((read_result = fread(cursor, 1, chunk_size, io)) > 0) {
237 program_size += read_result;
238 if (program_size == wanted)
239 break;
240 chunk_size = 1024;
241 program_code =
242 (char *)mem_sys_realloc(program_code, program_size + chunk_size);
244 if (!program_code) {
245 PIO_eprintf(interp,
246 "PBC Merge: Could not reallocate buffer");
247 Parrot_exit(interp, 1);
250 cursor = (char *)program_code + program_size;
253 if (read_result < 0) {
254 PIO_eprintf(interp,
255 "PBC Merge: Problem reading packfile from PIO.\n");
256 Parrot_exit(interp, 1);
258 fclose(io);
260 /* Now that we have the bytecode, let's unpack it. */
261 pf = PackFile_new(interp, is_mapped);
262 if (!PackFile_unpack(interp,
263 pf, (opcode_t *)program_code, program_size)) {
264 PIO_eprintf(interp, "PBC Merge: Can't unpack packfile %s.\n",
265 fullname);
266 Parrot_exit(interp, 1);
269 /* Return the packfile. */
270 return pf;
276 FUNCDOC: pbc_merge_bytecode
278 This function merges the bytecode from the input packfiles, storing the
279 offsets that each bit of bytecode now exists at.
282 PARROT_WARN_UNUSED_RESULT
283 PARROT_CANNOT_RETURN_NULL
284 static PackFile_ByteCode*
285 pbc_merge_bytecode(PARROT_INTERP, NOTNULL(pbc_merge_input **inputs),
286 int num_inputs, NOTNULL(PackFile *pf))
288 opcode_t *bc = mem_allocate_typed(opcode_t);
289 opcode_t cursor = 0;
290 int i;
292 /* Add a bytecode segment. */
293 PackFile_ByteCode * const bc_seg =
294 (PackFile_ByteCode *)PackFile_Segment_new_seg(interp,
295 &pf->directory, PF_BYTEC_SEG, BYTE_CODE_SEGMENT_NAME, 1);
296 if (bc_seg == NULL) {
297 PIO_eprintf(interp, "PBC Merge: Error creating bytecode segment.");
298 Parrot_exit(interp, 1);
301 /* Loop over input files. */
302 for (i = 0; i < num_inputs; i++) {
303 /* Get the bytecode segment from the input file. */
304 PackFile_ByteCode *in_seg = inputs[i]->pf->cur_cs;
305 if (in_seg == NULL) {
306 PIO_eprintf(interp,
307 "PBC Merge: Cannot locate bytecode segment in %s",
308 inputs[i]->filename);
309 Parrot_exit(interp, 1);
312 /* Re-allocate the current buffer. */
313 bc = (opcode_t *)mem_sys_realloc(bc,
314 (cursor + in_seg->base.size) * sizeof (opcode_t));
315 if (bc == NULL) {
316 PIO_eprintf(interp, "PBC Merge: Cannot reallocate memory\n");
317 Parrot_exit(interp, 1);
320 /* Copy data and store cursor. */
321 memcpy(bc + cursor, in_seg->base.data,
322 in_seg->base.size * sizeof (opcode_t));
323 inputs[i]->code_start = cursor;
325 /* Update cursor. */
326 cursor += in_seg->base.size;
329 /* Stash produced bytecode. */
330 bc_seg->base.data = bc;
331 bc_seg->base.size = cursor;
332 bc_seg->base.name = str_dup("MERGED");
333 return bc_seg;
339 FUNCDOC: pbc_merge_constants
341 This function merges the constants tables from the input PBC files.
344 PARROT_WARN_UNUSED_RESULT
345 PARROT_CANNOT_RETURN_NULL
346 static PackFile_ConstTable*
347 pbc_merge_constants(PARROT_INTERP, NOTNULL(pbc_merge_input **inputs),
348 int num_inputs, NOTNULL(PackFile *pf), NOTNULL(PackFile_ByteCode *bc))
350 PackFile_Constant **constants = mem_allocate_typed(PackFile_Constant *);
351 opcode_t cursor = 0;
352 int i, j;
354 /* Add a constant table segment. */
355 PackFile_ConstTable * const const_seg = (PackFile_ConstTable*)PackFile_Segment_new_seg(
356 interp, &pf->directory, PF_CONST_SEG, CONSTANT_SEGMENT_NAME, 1);
357 if (const_seg == NULL) {
358 PIO_eprintf(interp,
359 "PBC Merge: Error creating constant table segment.");
360 Parrot_exit(interp, 1);
363 /* Loop over input files. */
364 for (i = 0; i < num_inputs; i++) {
365 /* Get the constant table segment from the input file. */
366 PackFile_ConstTable * const in_seg = inputs[i]->pf->cur_cs->const_table;
367 if (in_seg == NULL) {
368 PIO_eprintf(interp,
369 "PBC Merge: Cannot locate constant table segment in %s\n",
370 inputs[i]->filename);
371 Parrot_exit(interp, 1);
374 /* Store cursor as position where constant table starts. */
375 inputs[i]->const_start = cursor;
377 /* Allocate space for the constant list, provided we have some. */
378 if (in_seg->const_count > 0) {
379 constants = (PackFile_Constant **)mem_sys_realloc(constants,
380 (cursor + in_seg->const_count) * sizeof (Parrot_Pointer));
381 if (constants == NULL) {
382 PIO_eprintf(interp, "PBC Merge: Out of memory");
383 Parrot_exit(interp, 1);
387 /* Loop over the constants and copy them to the output PBC. */
388 for (j = 0; j < in_seg->const_count; j++) {
389 /* Get the entry and allocate space for copy. */
390 PackFile_Constant *cur_entry = in_seg->constants[j];
391 PackFile_Constant *copy = mem_allocate_typed(
392 PackFile_Constant);
393 if (copy == NULL) {
394 PIO_eprintf(interp, "PBC Merge: Out of memory");
395 Parrot_exit(interp, 1);
398 STRUCT_COPY(copy, cur_entry);
400 /* If it's a sub PMC, need to deal with offsets. */
401 if (copy->type == PFC_PMC) {
402 switch (copy->u.key->vtable->base_type) {
403 case enum_class_Sub:
404 case enum_class_Closure:
405 case enum_class_Coroutine:
407 Parrot_sub * const sub = PMC_sub(copy->u.key);
408 sub->start_offs += inputs[i]->code_start;
409 sub->end_offs += inputs[i]->code_start;
411 break;
415 /* Slot it into the list. */
416 constants[cursor] = copy;
417 cursor++;
421 /* Stash merged constants table and count and return the new segment. */
422 const_seg->constants = constants;
423 const_seg->const_count = cursor;
424 const_seg->code = bc;
425 bc->const_table = const_seg;
426 return const_seg;
432 FUNCDOC: pbc_merge_fixups
434 This function merges the fixups tables from the input PBC files.
437 static void
438 pbc_merge_fixups(PARROT_INTERP, NOTNULL(pbc_merge_input **inputs),
439 int num_inputs, NOTNULL(PackFile *pf), NOTNULL(PackFile_ByteCode *bc))
441 PackFile_FixupTable *fixup_seg;
442 PackFile_FixupEntry **fixups = mem_allocate_typed(PackFile_FixupEntry *);
443 opcode_t cursor = 0;
444 int i, j;
446 /* Add a fixup table segment. */
447 fixup_seg = (PackFile_FixupTable*)PackFile_Segment_new_seg(
448 interp, &pf->directory, PF_FIXUP_SEG, FIXUP_TABLE_SEGMENT_NAME, 1);
449 if (fixup_seg == NULL) {
450 PIO_eprintf(interp,
451 "PBC Merge: Error creating fixup table segment.");
452 Parrot_exit(interp, 1);
455 /* Loop over input files. */
456 for (i = 0; i < num_inputs; i++) {
457 /* Get the fixup segment from the input file. */
458 PackFile_FixupTable * const in_seg = inputs[i]->pf->cur_cs->fixups;
459 if (in_seg == NULL) {
460 PIO_eprintf(interp,
461 "PBC Merge: Cannot locate fixup segment in %s",
462 inputs[i]->filename);
463 Parrot_exit(interp, 1);
466 /* Allocate space for these fixups, provided we have some. */
467 if (in_seg->fixup_count > 0) {
468 fixups = (PackFile_FixupEntry **)mem_sys_realloc(fixups,
469 (cursor + in_seg->fixup_count) * sizeof (Parrot_Pointer));
470 if (fixups == NULL) {
471 PIO_eprintf(interp, "PBC Merge: Out of memory");
472 Parrot_exit(interp, 1);
476 /* Loop over the fixups and copy them to the output PBC, correcting
477 the offsets into the bytecode. */
478 for (j = 0; j < in_seg->fixup_count; j++) {
479 /* Get the entry and allocate space for copies. */
480 PackFile_FixupEntry *cur_entry = in_seg->fixups[j];
481 PackFile_FixupEntry *copy = mem_allocate_typed(
482 PackFile_FixupEntry);
483 char *name_copy = (char *)mem_sys_allocate(
484 strlen(cur_entry->name) + 1);
485 if (copy == NULL || name_copy == NULL) {
486 PIO_eprintf(interp, "PBC Merge: Out of memory");
487 Parrot_exit(interp, 1);
490 /* Copy type and name. */
491 copy->type = cur_entry->type;
492 strcpy(name_copy, cur_entry->name);
493 copy->name = name_copy;
495 /* Set new offset and bytecode pointer. */
496 switch (copy->type) {
497 case enum_fixup_label:
498 copy->offset = cur_entry->offset + inputs[i]->code_start;
499 break;
500 case enum_fixup_sub:
501 copy->offset = cur_entry->offset + inputs[i]->const_start;
502 break;
503 default:
504 PIO_eprintf(interp, "PBC Merge: Unknown fixup type");
505 Parrot_exit(interp, 1);
508 copy->seg = bc;
510 /* Slot it into the list. */
511 fixups[cursor] = copy;
512 cursor++;
516 /* Stash merged fixup table and count. */
517 fixup_seg->fixups = fixups;
518 fixup_seg->fixup_count = cursor;
524 FUNCDOC: pbc_merge_debugs
526 This function merges the debug segments from the input PBC files.
529 static void
530 pbc_merge_debugs(PARROT_INTERP, NOTNULL(pbc_merge_input **inputs),
531 int num_inputs, NOTNULL(PackFile *pf), NOTNULL(PackFile_ByteCode *bc))
533 PackFile_Debug *debug_seg;
534 opcode_t *lines = mem_allocate_typed(opcode_t);
535 PackFile_DebugMapping **mappings =
536 mem_allocate_typed(PackFile_DebugMapping *);
537 opcode_t num_mappings = 0;
538 opcode_t num_lines = 0;
539 int i, j;
541 /* We need to merge both the mappings and the list of line numbers.
542 The line numbers can just be concatenated. The mappings must have
543 their offsets fixed up. */
544 for (i = 0; i < num_inputs; i++) {
545 PackFile_Debug *in_seg = inputs[i]->pf->cur_cs->debugs;
547 /* Concatenate line numbers. */
548 lines = (opcode_t *)mem_sys_realloc(lines,
549 (num_lines + in_seg->base.size) * sizeof (opcode_t));
550 if (lines == NULL) {
551 PIO_eprintf(interp, "PBC Merge: Cannot reallocate memory\n");
552 Parrot_exit(interp, 1);
554 memcpy(lines + num_lines, in_seg->base.data,
555 in_seg->base.size * sizeof (opcode_t));
557 /* Concatenate mappings. */
558 mappings = (PackFile_DebugMapping **)mem_sys_realloc(mappings,
559 (num_mappings + in_seg->num_mappings) *
560 sizeof (Parrot_Pointer));
561 for (j = 0; j < in_seg->num_mappings; j++) {
562 PackFile_DebugMapping *mapping = mem_allocate_typed(
563 PackFile_DebugMapping);
564 STRUCT_COPY(mapping, in_seg->mappings[j]);
565 mapping->offset += num_lines;
566 if (mapping->mapping_type == PF_DEBUGMAPPINGTYPE_FILENAME)
567 mapping->u.filename += inputs[i]->const_start;
568 mappings[num_mappings + j] = mapping;
571 /* Update counts. */
572 num_lines += in_seg->base.size;
573 num_mappings += in_seg->num_mappings;
576 /* Create merged debug segment. Replace created data and mappings
577 with merged ones we have created. */
578 debug_seg = Parrot_new_debug_seg(interp, bc, num_lines);
579 PackFile_add_segment(interp, &pf->directory, (PackFile_Segment*)debug_seg);
580 free(debug_seg->base.data);
581 debug_seg->base.data = lines;
582 free(debug_seg->mappings);
584 debug_seg->mappings = mappings;
585 debug_seg->num_mappings = num_mappings;
590 FUNCDOC: pbc_merge_pic_index
592 This function merges the pic_index segments from the input PBC files.
596 static void
597 pbc_merge_pic_index(PARROT_INTERP, NOTNULL(pbc_merge_input **inputs),
598 int num_inputs, NOTNULL(PackFile *pf), NOTNULL(PackFile_ByteCode *bc))
600 int i;
601 PackFile_Segment *pic_index;
602 size_t size;
603 opcode_t cursor = 0;
604 opcode_t start = 0;
605 opcode_t last = 0;
607 /* calc needed size */
608 for (i = 0, size = 0; i < num_inputs; i++) {
609 PackFile_Segment * const in_seg = inputs[i]->pf->cur_cs->pic_index;
610 size += in_seg->size;
612 pic_index = PackFile_Segment_new_seg(interp,
613 &pf->directory, PF_UNKNOWN_SEG, "PIC_idx_MERGED", 1);
614 pic_index->data
615 = (opcode_t *)mem_sys_allocate_zeroed(size * sizeof (opcode_t));
616 pic_index->size = size;
618 for (i = 0, size = 0; i < num_inputs; i++) {
619 PackFile_Segment * const in_seg = inputs[i]->pf->cur_cs->pic_index;
620 size_t j;
622 * pic_index is 0 or an ever increasing (by 1) number
624 for (j = 0; j < in_seg->size; j++) {
625 const opcode_t k = in_seg->data[j];
626 if (k) {
627 pic_index->data[cursor] = k + start;
628 last = k;
630 cursor++;
632 start = last;
634 bc->pic_index = pic_index;
639 FUNCDOC: pbc_merge_ctpointers
641 This function corrects the pointers into the constants table found in the
642 bytecode.
645 static void
646 pbc_merge_ctpointers(PARROT_INTERP, NOTNULL(pbc_merge_input **inputs),
647 int num_inputs, NOTNULL(PackFile_ByteCode *bc))
649 opcode_t *op_ptr;
650 opcode_t *ops = bc->base.data;
651 opcode_t cur_op = 0;
652 int cur_input = 0;
653 int cur_arg;
655 /* Loop over the ops in the merged bytecode. */
656 while (cur_op < (opcode_t)bc->base.size) {
657 op_info_t *op;
658 opcode_t op_num;
660 /* Keep track of the current input file. */
661 if (cur_input + 1 < num_inputs &&
662 cur_op >= inputs[cur_input + 1]->code_start)
663 cur_input++;
665 /* Get info about this op and jump over it. */
666 op_num = ops[cur_op];
667 op = &interp->op_info_table[op_num];
668 op_ptr = ops + cur_op;
669 cur_op++;
671 /* Loop over the arguments. */
672 for (cur_arg = 1; cur_arg < op->op_count; cur_arg++) {
673 /* Pick out any indexes into the constant table and correct them. */
674 switch (op->types[cur_arg - 1]) {
675 case PARROT_ARG_NC:
676 case PARROT_ARG_PC:
677 case PARROT_ARG_SC:
678 case PARROT_ARG_KC:
679 ops[cur_op] += inputs[cur_input]->const_start;
680 break;
683 /* Move along the bytecode array. */
684 cur_op++;
687 /* Handle special case variable argument opcodes. */
688 if (op_num == PARROT_OP_set_args_pc ||
689 op_num == PARROT_OP_get_results_pc ||
690 op_num == PARROT_OP_get_params_pc ||
691 op_num == PARROT_OP_set_returns_pc) {
692 /* Get the signature. */
693 const PMC * const sig = bc->const_table->constants[op_ptr[1]]->u.key;
695 /* Loop over the arguments to locate any that need a fixup. */
696 const int sig_items = SIG_ELEMS(sig);
697 for (cur_arg = 0; cur_arg < sig_items; cur_arg++) {
698 switch (SIG_ITEM(sig, cur_arg)) {
699 case PARROT_ARG_NC:
700 case PARROT_ARG_PC:
701 case PARROT_ARG_SC:
702 case PARROT_ARG_KC:
703 ops[cur_op] += inputs[cur_input]->const_start;
704 break;
706 cur_op++;
715 FUNCDOC: pbc_merge_begin
717 This is the function that drives PBC merging process.
720 PARROT_WARN_UNUSED_RESULT
721 PARROT_CANNOT_RETURN_NULL
722 static PackFile*
723 pbc_merge_begin(PARROT_INTERP, NOTNULL(pbc_merge_input **inputs), int num_inputs)
725 PackFile_ByteCode *bc;
727 /* Create a new empty packfile. */
728 PackFile * const merged = PackFile_new(interp, 0);
729 if (merged == NULL) {
730 PIO_eprintf(interp, "PBC Merge: Error creating new packfile.\n");
731 Parrot_exit(interp, 1);
734 /* Merge the various stuff. */
735 bc = pbc_merge_bytecode(interp, inputs, num_inputs, merged);
736 pbc_merge_constants(interp, inputs, num_inputs, merged, bc);
738 pbc_merge_fixups(interp, inputs, num_inputs, merged, bc);
739 pbc_merge_debugs(interp, inputs, num_inputs, merged, bc);
740 pbc_merge_pic_index(interp, inputs, num_inputs, merged, bc);
742 /* Walk bytecode and fix ops that reference the constants table. */
743 pbc_merge_ctpointers(interp, inputs, num_inputs, bc);
745 /* Return merged result. */
746 return merged;
752 FUNCDOC: pbc_merge_write
754 This functions writes out the merged packfile.
757 static void
758 pbc_merge_write(PARROT_INTERP, NOTNULL(PackFile *pf), NOTNULL(const char *filename))
760 FILE *fp;
762 /* Get size of packfile we'll write. */
763 const size_t size = PackFile_pack_size(interp, pf) * sizeof (opcode_t);
765 /* Allocate memory. */
766 opcode_t * const pack = (opcode_t*) mem_sys_allocate(size);
767 if (pack == NULL) {
768 PIO_eprintf(interp, "PBC Merge: Out of memory");
769 Parrot_exit(interp, 1);
772 /* Write and clean up. */
773 PackFile_pack(interp, pf, pack);
774 if ((fp = fopen(filename, "wb")) == 0) {
775 PIO_eprintf(interp, "PBC Merge: Couldn't open %s\n", filename);
776 Parrot_exit(interp, 1);
778 if ((1 != fwrite(pack, size, 1, fp))) {
779 PIO_eprintf(interp, "PBC Merge: Couldn't write %s\n", filename);
780 Parrot_exit(interp, 1);
782 fclose(fp);
783 mem_sys_free(pack);
789 FUNCDOC: main(int argc, char **argv)
791 The main function that grabs console input, reads in the packfiles
792 provided they exist, hands them to another function that runs the
793 merge process and finally writes out the produced packfile.
797 static struct longopt_opt_decl options[] = {
798 { 'o', 'o', OPTION_required_FLAG, { "--output" } }
802 main(int argc, char **argv)
804 int status;
805 pbc_merge_input** input_files;
806 PackFile *merged;
807 int i;
808 const char *output_file = NULL;
809 struct longopt_opt_info opt = LONGOPT_OPT_INFO_INIT;
810 Interp * const interp = Parrot_new(NULL);
812 Parrot_block_DOD(interp);
814 /* Get options, ensuring we have at least one input
815 file and an output file. */
816 if (argc < 4) {
817 help(interp);
819 while ((status = longopt_get(interp, argc, argv, options, &opt)) > 0) {
820 switch (opt.opt_id) {
821 case 'o':
822 if (output_file == NULL)
823 output_file = opt.opt_arg;
824 else
825 help(interp);
826 break;
827 case '?':
828 help(interp);
829 break;
832 if (status == -1 || !output_file) {
833 help(interp);
835 argc -= opt.opt_index; /* Now the number of input files. */
836 argv += opt.opt_index; /* Now at first input filename. */
838 /* Load each packfile that we are to merge and set up an input
839 structure for each of them. */
840 input_files = (pbc_merge_input **)mem_sys_allocate(
841 argc * sizeof (Parrot_Pointer));
843 for (i = 0; i < argc; i++) {
844 /* Allocate a struct. */
845 input_files[i] = mem_allocate_typed(pbc_merge_input);
847 /* Set filename */
848 input_files[i]->filename = *argv;
850 /* Load the packfile and unpack it. */
851 input_files[i]->pf = pbc_merge_loadpbc(interp,
852 input_files[i]->filename);
853 if (input_files[i]->pf == NULL) {
854 PIO_eprintf(interp,
855 "PBC Merge: Unknown error while reading and unpacking %s\n",
856 *argv);
857 Parrot_exit(interp, 1);
860 /* Next file. */
861 argv++;
864 /* Merge. */
865 merged = pbc_merge_begin(interp, input_files, argc);
866 if (merged == NULL) {
867 PIO_eprintf(interp, "PBC Merge: Unknown error during merge\n");
868 Parrot_exit(interp, 1);
871 /* Write merged packfile. */
872 pbc_merge_write(interp, merged, output_file);
874 /* Finally, we're done. */
875 Parrot_exit(interp, 0);
876 return 0;
881 * Local variables:
882 * c-file-style: "parrot"
883 * End:
884 * vim: expandtab shiftwidth=4: