[t][cage] Remove PGE-dependence from t/op/inf_nan.t since it is part of 'make coretest'
[parrot.git] / src / pbc_dump.c
blob2b1bbf5b53f743d3549c1cb6a525169010b0c229
1 /*
2 Copyright (C) 2001-2009, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 pbc_dump - Dump or convert Parrot bytecode (PBC) files
9 =head1 SYNOPSIS
11 pbc_dump [-tdh] [--terse|--disassemble|--header-only] file.pbc
13 pbc_dump -o converted.pbc file.pbc
15 =head1 DESCRIPTION
17 A program to dump pack files to human readable form.
19 =head2 Command-Line Options
21 =over 4
23 =item C<-d>
25 Disassemble bytecode segments.
27 =item C<-h>
29 Dump the bytecode header only.
31 =item C<-t>
33 Terse output.
35 =item C<-D> C--debug> 1-7
37 Display detailed packfile reader debugging information if
38 F<include/parrot/packfile.h> enables TRACE_PACKFILE.
40 1 print general debug info
41 2 print alignment info
42 4 print values
44 =item C<-o converted.pbc>
46 Repacks a PBC file into the platform's native binary format for better
47 efficiency on reading non-native PBCs.
49 =back
51 =head2 Functions
53 =over 4
55 =cut
59 #include "parrot/parrot.h"
60 #include "parrot/embed.h"
61 #include "parrot/oplib/ops.h"
65 =item C<static void
66 const_dump(PARROT_INTERP, const PackFile_Segment *segp)>
68 Dump the constant table.
70 =cut
74 static void
75 const_dump(PARROT_INTERP, const PackFile_Segment *segp)
77 Parrot_io_printf(interp, "%Ss => [\n", segp->name);
78 PackFile_ConstTable_dump(interp, (const PackFile_ConstTable *)segp);
79 Parrot_io_printf(interp, "],\n");
84 =item C<static void
85 fixup_dump(PARROT_INTERP, const PackFile_Segment *segp)>
87 Dump the fixup table.
89 =cut
93 static void
94 fixup_dump(PARROT_INTERP, const PackFile_Segment *segp)
96 Parrot_io_printf(interp, "%Ss => [\n", segp->name);
97 PackFile_Fixup_dump(interp, (const PackFile_FixupTable *)segp);
98 Parrot_io_printf(interp, "],\n");
103 =item C<static void
104 disas_dump(PARROT_INTERP, const PackFile_Segment *self)>
106 Disassemble and dump.
108 =cut
112 static void
113 disas_dump(PARROT_INTERP, const PackFile_Segment *self)
115 opcode_t *pc;
116 size_t i, n;
117 Parrot_io_printf(interp, "%Ss => [ # %d ops at offs 0x%x\n",
118 self->name, (int)self->size, (int)self->file_offset + 4);
119 pc = self->data;
120 while (pc < self->data + self->size) {
121 /* trace_op_dump(interp, self->pf->src, pc); */
122 Parrot_io_printf(interp, " %04x: ", (int) (pc - self->data));
123 n = (size_t)interp->op_info_table[*pc].op_count;
124 for (i = 0; i < 6; i++)
125 if (i < n)
126 Parrot_io_printf(interp, "%08lx ", (unsigned long) pc[i]);
127 else
128 Parrot_io_printf(interp, " ");
129 Parrot_io_printf(interp, "%s\n",
130 interp->op_info_table[*pc].full_name);
131 ADD_OP_VAR_PART(interp, interp->code, pc, n);
132 pc += n;
134 Parrot_io_printf(interp, "]\n");
139 =item C<static void
140 PackFile_header_dump(PARROT_INTERP, PackFile *pf)>
142 Dump the header.
144 =cut
148 static void
149 PackFile_header_dump(PARROT_INTERP, PackFile *pf)
151 Parrot_io_printf(interp, "HEADER => [\n");
152 Parrot_io_printf(interp, "\twordsize = %d", pf->header->wordsize);
153 Parrot_io_printf(interp, "\t(interpreter's wordsize/INTVAL = %d/%d)\n",
154 sizeof (opcode_t), sizeof (INTVAL));
155 Parrot_io_printf(interp, "\tbyteorder = %d", pf->header->byteorder);
156 Parrot_io_printf(interp, "\t(interpreter's byteorder = %d)\n",
157 PARROT_BIGENDIAN);
158 Parrot_io_printf(interp, "\tfloattype = %d", pf->header->floattype);
159 Parrot_io_printf(interp, "\t(interpreter's NUMVAL_SIZE = %d)\n", NUMVAL_SIZE);
160 Parrot_io_printf(interp, "\tparrot-version %d.%d.%d, bytecode-version %d.%d\n",
161 pf->header->major, pf->header->minor, pf->header->patch,
162 pf->header->bc_major, pf->header->bc_minor);
163 Parrot_io_printf(interp, "\tUUID: type = %d, size = %d",
164 pf->header->uuid_type, pf->header->uuid_size);
165 if (pf->header->uuid_size)
166 Parrot_io_printf(interp, ", '%s'\n", pf->header->uuid_data);
167 else
168 Parrot_io_printf(interp, "\n");
169 Parrot_io_printf(interp, "\t%s endianize, %s opcode, %s numval transform\n",
170 pf->need_endianize ? "**need**" : "no",
171 pf->need_wordsize ? "**need**" : "no",
172 pf->fetch_nv ? "**need**" : "no");
173 Parrot_io_printf(interp, "\tdirformat = %d\n", pf->header->dir_format);
174 Parrot_io_printf(interp, "]\n");
179 =item C<static void help(void)>
181 Print out the user help info.
183 =cut
187 static void help(void)
189 printf("pbc_dump - dump or convert parrot bytecode (PBC) files\n");
190 printf("usage:\n");
191 printf("pbc_dump [-tdh] [--terse|--disassemble|--header-only] file.pbc\n");
192 printf("pbc_dump -o converted.pbc file.pbc\n\n");
193 printf("\t-d ... disassemble bytecode segments\n");
194 printf("\t-h ... dump header only\n");
195 printf("\t-t ... terse output\n");
196 #if TRACE_PACKFILE
197 printf("\t-D<1-7> --debug debug output\n");
198 printf("\t 1 general info\n");
199 printf("\t 2 alignment\n");
200 printf("\t 4 values\n");
201 #endif
202 printf("\t-o converted.pbc ... repacks a PBC file into "
203 "the platform's native\n");
204 printf("\t binary format for better efficiency on reading "
205 "non native PBCs\n");
206 exit(EXIT_SUCCESS);
209 static struct longopt_opt_decl opt_options[] = {
210 { 'h', 'h', OPTION_optional_FLAG, { "--header-only" } },
211 { '?', '?', OPTION_optional_FLAG, { "--help" } },
212 { 't', 't', OPTION_optional_FLAG, { "--terse" } },
213 { 'd', 'd', OPTION_optional_FLAG, { "--disassemble" } },
214 #if TRACE_PACKFILE
215 { 'D', 'D', OPTION_required_FLAG, { "--debug" } },
216 #endif
217 { 'o', 'o', OPTION_required_FLAG, { "--output" } }
222 =item C<int main(int argc, const char **argv)>
224 The run loop. Process the command-line arguments and dump accordingly.
226 =cut
231 main(int argc, const char **argv)
233 PackFile *pf;
234 Interp *interp;
235 int terse = 0;
236 int disas = 0;
237 int convert = 0;
238 int options = PFOPT_UTILS;
239 const char *file = NULL;
240 struct longopt_opt_info opt = LONGOPT_OPT_INFO_INIT;
241 int status;
243 if (argc < 2) {
244 help();
246 interp = Parrot_new(NULL);
247 /* init and set top of stack */
248 Parrot_init_stacktop(interp, &status);
249 while ((status = longopt_get(interp,
250 argc, argv, opt_options, &opt)) > 0) {
251 switch (opt.opt_id) {
252 case 'h':
253 options += PFOPT_HEADERONLY;
254 break;
255 case 't':
256 terse = 1;
257 break;
258 case 'd':
259 disas = 1;
260 break;
261 #if TRACE_PACKFILE
262 case 'D':
263 options += atoi(opt.opt_arg) << 2;
264 break;
265 #endif
266 case 'o':
267 file = opt.opt_arg;
268 convert = 1;
269 break;
270 case '?':
271 default:
272 help();
273 break;
276 if (status == -1) {
277 help();
279 argc -= opt.opt_index;
280 argv += opt.opt_index;
283 pf = Parrot_pbc_read(interp, *argv, options);
285 if (!pf) {
286 printf("Can't read PBC\n");
287 return 1;
289 Parrot_pbc_load(interp, pf);
290 if (convert) {
291 size_t size;
292 opcode_t *pack;
293 FILE *fp;
295 size = PackFile_pack_size(interp,
296 interp->code->base.pf) * sizeof (opcode_t);
297 pack = (opcode_t*) mem_sys_allocate(size);
298 if (!pack) {
299 printf("out of mem\n");
300 exit(EXIT_FAILURE);
302 PackFile_pack(interp, interp->code->base.pf, pack);
303 if (STREQ(file, "-"))
304 fp = stdout;
305 else if ((fp = fopen(file, "wb")) == 0) {
306 printf("Couldn't open %s\n", file);
307 exit(EXIT_FAILURE);
310 if ((1 != fwrite(pack, size, 1, fp))) {
311 printf("Couldn't write %s\n", file);
312 exit(EXIT_FAILURE);
314 fclose(fp);
315 mem_sys_free(pack);
316 Parrot_exit(interp, 0);
319 PackFile_header_dump(interp, pf);
320 if (options & PFOPT_HEADERONLY) {
321 Parrot_exit(interp, 0);
323 /* install a dumper function */
324 if (!terse) {
325 pf->PackFuncs[PF_CONST_SEG].dump = const_dump;
326 pf->PackFuncs[PF_FIXUP_SEG].dump = fixup_dump;
328 if (disas)
329 pf->PackFuncs[PF_BYTEC_SEG].dump = disas_dump;
330 /* do a directory dump, which dumps segs then */
331 PackFile_Segment_dump(interp, &pf->directory.base);
333 Parrot_exit(interp, 0);
338 =back
340 =head1 SEE ALSO
342 F<src/packdump.c>.
344 =cut
349 * Local variables:
350 * c-file-style: "parrot"
351 * End:
352 * vim: expandtab shiftwidth=4: