diff --git a/MANIFEST b/MANIFEST index ea2a093..da7e37d 100644 --- a/MANIFEST +++ b/MANIFEST @@ -869,6 +869,7 @@ ext/winxed/compiler.pir [] ext/winxed/driver.pir [] frontend/parrot/main.c [] frontend/parrot_debugger/main.c [] +frontend/pbc_disassemble/main.c [] frontend/pbc_dump/main.c [] frontend/pbc_dump/packdump.c [] frontend/pbc_merge/main.c [] @@ -1286,7 +1287,6 @@ src/packfile/byteorder.h [] src/packfile/object_serialization.c [] src/packfile/output.c [] src/packfile/pf_items.c [] -src/pbc_disassemble.c [] src/platform/aix/asm.s [] src/platform/ansi/dl.c [] src/platform/ansi/exec.c [] diff --git a/config/gen/makefiles/root.in b/config/gen/makefiles/root.in index 947f3a9..fdd0a29 100644 --- a/config/gen/makefiles/root.in +++ b/config/gen/makefiles/root.in @@ -1073,23 +1073,23 @@ $(INSTALLABLEPDB) : frontend/parrot_debugger/main$(O) $(LIBPARROT) src/parrot_co # Parrot Disassembler # -src/pbc_disassemble$(O) : \ +frontend/pbc_disassemble/main$(O) : \ $(PARROT_H_HEADERS) \ $(INC_DIR)/api.h \ $(INC_DIR)/longopt.h \ - src/pbc_disassemble.c \ + frontend/pbc_disassemble/main.c -$(DIS) : src/pbc_disassemble$(O) $(LIBPARROT) +$(DIS) : frontend/pbc_disassemble/main$(O) $(LIBPARROT) $(LINK) @ld_out@$@ \ - src/pbc_disassemble$(O) \ + frontend/pbc_disassemble/main$(O) \ src/longopt$(O) \ $(RPATH_BLIB) $(ALL_PARROT_LIBS) $(LINKFLAGS) #IF(win32): if exist $@.manifest mt.exe -nologo -manifest $@.manifest -outputresource:$@;1 -$(INSTALLABLEDIS) : src/pbc_disassemble$(O) \ +$(INSTALLABLEDIS) : frontend/pbc_disassemble/main$(O) \ src/install_config$(O) $(LIBPARROT) $(LINK) @ld_out@$@ \ - src/pbc_disassemble$(O) \ + frontend/pbc_disassemble/main$(O) \ src/longopt$(O) \ @rpath_lib@ $(ALL_PARROT_LIBS) $(LINKFLAGS) #IF(win32): if exist $@.manifest mt.exe -nologo -manifest $@.manifest -outputresource:$@;1 @@ -2286,7 +2286,7 @@ prog-clean : $(PDUMP) frontend/pbc_dump/main$(O) frontend/pbc_dump/packdump$(O) \ $(PDB) frontend/parrot_debugger/main$(O) \ $(PBC_MERGE) frontend/pbc_merge/main$(O) \ - $(DIS) src/pbc_disassemble$(O) + $(DIS) frontend/pbc_disassemble/main$(O) $(RM_F) \ frontend/parrot/main$(O) \ src/null_config$(O) \ @@ -2323,7 +2323,7 @@ archclean: dynext-clean $(PDUMP) frontend/pbc_dump/main$(O) frontend/pbc_dump/packdump$(O) \ $(PDB) frontend/parrot_debugger/main$(O) \ $(PBC_MERGE) frontend/pbc_merge/main$(O) \ - $(DIS) src/pbc_disassemble$(O) \ + $(DIS) frontend/pbc_disassemble/main$(O) \ $(PARROT_CONFIG) parrot_config$(O) parrot_config.c \ src/parrot_config$(O) parrot_config.pbc \ pbc_to_exe$(EXE) pbc_to_exe$(O) pbc_to_exe.pbc \ diff --git a/frontend/pbc_disassemble/main.c b/frontend/pbc_disassemble/main.c new file mode 100644 index 0000000..a213ccc --- /dev/null +++ b/frontend/pbc_disassemble/main.c @@ -0,0 +1,275 @@ +/* Copyright (C) 2001-2009, Parrot Foundation. */ + +/* + +=head1 NAME + +pbc_disassemble - parrot bytecode disassembler + +=head1 SYNOPSIS + +pbc_disassemble [-bh?] [--bare|--header-only] [-o outfile] [file.pbc] + +=head1 DESCRIPTION + +C translates Parrot bytecode (C) into Parrot assembly +language (C). + +C is the bytecode file to disassemble. If a file is not specified, the +bytecode will be read from C. Additionally, if the C<-o> switch is not +given, the output is displayed to C. + +=head1 OPTIONS + +=over 4 + +=item B<-?>, B<--help> + +Displays usage and help information. + +=item B<-b>, B<--bare> + +Displays bare PASM without the header and left column. + +=item B<-h>, B<--header-only> + +Displays only the constants table header. + +=item B<-o> filename, B<--output> filename + +Writes output to C. + +=back + +=head1 STATIC FUNCTIONS + +=over 4 + +=cut + +*/ + +#include +#include +#include + +#include "parrot/parrot.h" +#include "parrot/api.h" +#include "parrot/longopt.h" + +#define PFOPT_UTILS 1 + +/* NOTE: + * C uses the C function from F, + * which in turn uses the C function from F. + */ + +/* Flags indicating the presence of the -b and -h command-line switches */ +typedef enum { + enum_DIS_BARE = 1, /* -b switch */ + enum_DIS_HEADER = 2 /* -h switch */ +} Parrot_disassemble_options; + +/* Longopts option table */ +static struct longopt_opt_decl options[] = { + { '?', '?', OPTION_optional_FLAG, { "--help" } }, + { 'b', 'b', OPTION_optional_FLAG, { "--bare" } }, + { 'h', 'h', OPTION_optional_FLAG, { "--header-only" } }, + { 'o', 'o', OPTION_required_FLAG, { "--output" } }, + { 0 , 0, OPTION_optional_FLAG, { NULL } } +}; + +static void help(void); +static void show_last_error_and_exit(Parrot_PMC interp); + +/* + +=item C + +Execution entry point. Starts up an interpreter, loads the bytecode from the +command-line, and disassembles it. + +=cut + +*/ + +int +main(int argc, const char *argv[]) +{ + const char *outfile = NULL; + int option = 0, + status = 0, + debug = PFOPT_UTILS; + struct longopt_opt_info opt = LONGOPT_OPT_INFO_INIT; + + Parrot_PMC interp = NULL, + pbc = NULL; + Parrot_String filename = NULL; + Parrot_Init_Args *initargs = NULL; + + /* Parse command-line arguments */ + while ((status = longopt_get(argc, argv, options, &opt)) > 0) { + switch (opt.opt_id) { + case 'h': + option += enum_DIS_HEADER; + break; + case 'b': + option += enum_DIS_BARE; + break; + case 'o': + outfile = opt.opt_arg; + break; + case '?': + /* Fall through */ + default: + help(); + break; + } + } + + /* Check for parse errors */ + if (status == -1) { + help(); + } + + /* Set initialization parameters */ + GET_INIT_STRUCT(initargs); + + /* Create new interpreter and set executable name */ + if (!(Parrot_api_make_interpreter(NULL, 0, initargs, &interp) + && Parrot_api_set_executable_name(interp, argv[0]))) { + + fprintf(stderr, "PARROT VM: Could not initialize new interpreter\n"); + show_last_error_and_exit(interp); + } + + argc -= opt.opt_index; + argv += opt.opt_index; + + /* What to do about this debug flag? */ + /* pf = Parrot_pbc_read(interp, argc ? *argv : "-", debug); */ + + /* Convert native char * to Parrot_String */ + if (!Parrot_api_string_import(interp, argc ? *argv : "-", &filename)) { + fprintf(stderr, "String transformation failed\n"); + show_last_error_and_exit(interp); + } + + /* Disassemble bytecode and destroy interpreter */ + if (!(Parrot_api_load_bytecode_file(interp, filename, &pbc) + && Parrot_api_disassemble_bytecode(interp, pbc, outfile, option) + && Parrot_api_destroy_interpreter(interp))) { + + fprintf(stderr, "Error during disassembly\n"); + show_last_error_and_exit(interp); + } + + return 0; +} + +/* + +=item C + +Prints out the user help information and exits. + +=cut + +*/ + +static void +help(void) +{ + puts("pbc_disassemble - parrot bytecode disassembler\n"); + + puts("Usage:"); + puts("pbc_disassemble [-bh] [file.pbc]"); + puts("pbc_disassemble -o file.pasm file.pbc\n"); + + puts(" -?, --help Displays help information"); + puts(" -b, --bare Displays bare PASM without header and left column"); + puts(" -h, --header-only Dumps only the constants table header"); + puts(" -o, --output \"filename\" Writes output to \"filename\""); + + exit(EXIT_SUCCESS); +} + +/* + +=item C + +Prints out the C's last error and exits. + +=cut + +*/ + +static void +show_last_error_and_exit(Parrot_PMC interp) +{ + Parrot_Int is_error, + exit_code; + Parrot_String errmsg, + backtrace; + Parrot_PMC exception; + + /* Get result of last API function call and exception backtrace */ + if (!(Parrot_api_get_result(interp, &is_error, &exception, &exit_code, &errmsg) + && Parrot_api_get_exception_backtrace(interp, exception, &backtrace))) { + + fprintf(stderr, "PARROT VM: Cannot recover\n"); + exit(EXIT_FAILURE); + } + + /* Check for unhandled exceptions */ + if (is_error) { + char *msg; + + /* Display error message */ + Parrot_api_string_export_ascii(interp, errmsg, &msg); + fprintf(stderr, "%s\n", msg); + Parrot_api_string_free_exported_ascii(interp, msg); + + /* Display exception backtrace */ + Parrot_api_string_export_ascii(interp, backtrace, &msg); + fprintf(stderr, "%s\n", msg); + Parrot_api_string_free_exported_ascii(interp, msg); + } + + exit(exit_code); +} + +/* + +=back + +=head1 SEE ALSO + +F and F. + +=head1 HISTORY + +Initial version by Daniel Grunblatt on 2002.5.26. + +Florian Ragwitz: Moved POD documentation that's not necessary to know how to +actually run the disassembler to normal C comments (Wed, 16 Nov 2005). + +Reini Urban: Renamed from disassemble to pbc_disassemble (2008-07-03). + Add options: help, -h, -o, --debug, --bare (2009-01-29) + Force option 1 for passing version check (2009-03-07) + +Kevin Polulak (soh_cah_toa): Updated to use embedding API, moved source file + to frontend/pbc_disassemble, and cleaned up + source code and perldoc. (2011-06-19) + +=cut + +*/ + +/* + * Local variables: + * c-file-style: "parrot" + * End: + * vim: expandtab shiftwidth=4 cinoptions='\:2=2' : + */ + diff --git a/src/pbc_disassemble.c b/src/pbc_disassemble.c deleted file mode 100644 index 8f59938..0000000 --- a/src/pbc_disassemble.c +++ /dev/null @@ -1,205 +0,0 @@ -/* -Copyright (C) 2001-2009, Parrot Foundation. - -=head1 NAME - -pbc_disassemble - Parrot disassembler - -=head1 SYNOPSIS - - pbc_disassemble [-bdh?] [-o outfile] [file.pbc] - -=head1 DESCRIPTION - -This uses the C function from F, -which in turn uses the C function from -F. - -Without non-option arguments it reads the pbc from STDIN. - -=head2 Functions - -=over 4 - -=cut - -*/ - -#include -#include -#include -#include "parrot/parrot.h" -#include "parrot/longopt.h" - -#define PFOPT_UTILS 1 - -typedef enum { - enum_DIS_BARE = 1, - enum_DIS_HEADER = 2 -} Parrot_disassemble_options; - -static void show_last_error_and_exit(Parrot_PMC interp); - -/* - -=item C - -Print out the user help info. - -=cut - -*/ - -static void help(void) -{ - printf("pbc_disassemble - dump or convert parrot bytecode (PBC) files\n"); - printf("usage:\n"); - printf("pbc_disassemble [-bh] [--bare|--header-only] [file.pbc]\n"); - printf("pbc_disassemble -o converted.pasm file.pbc\n\n"); - printf(" -b\t\t ... bare .pasm without header and left column\n"); - printf(" -h\t\t ... dump Constant-table header only\n"); - printf(" -o filename\t ... output to filename\n"); - exit(EXIT_SUCCESS); -} - -static struct longopt_opt_decl options[] = { - { 'h', 'h', OPTION_optional_FLAG, { "--header-only" } }, - { '?', '?', OPTION_optional_FLAG, { "--help" } }, - { 'b', 'b', OPTION_optional_FLAG, { "--bare" } }, - { 'o', 'o', OPTION_required_FLAG, { "--output" } }, - { 0 , 0, OPTION_optional_FLAG, { NULL } } -}; - -/* - -=item C - -The run-loop. Starts up an interpreter, loads the bytecode from the -command-line and disassembles it. - -=cut - -*/ - -int -main(int argc, const char *argv[]) -{ - Parrot_PMC interp; - Parrot_PMC pbc; - Parrot_String filename; - const char *outfile = NULL; - int option = 0; - int debug = PFOPT_UTILS; - struct longopt_opt_info opt = LONGOPT_OPT_INFO_INIT; - int status; - Parrot_Init_Args *initargs; - GET_INIT_STRUCT(initargs); - - if (!(Parrot_api_make_interpreter(NULL, 0, initargs, &interp) && - Parrot_api_set_executable_name(interp, argv[0]))) { - fprintf(stderr, "PARROT VM: Could not initialize new interpreter"); - show_last_error_and_exit(interp); - } - - while ((status = longopt_get(argc, argv, options, &opt)) > 0) { - switch (opt.opt_id) { - case 'h': - option += enum_DIS_HEADER; - break; - case 'b': - option += enum_DIS_BARE; - break; - case 'o': - outfile = opt.opt_arg; - break; - case '?': - default: - help(); - break; - } - } - if (status == -1) { - help(); - } - argc -= opt.opt_index; - argv += opt.opt_index; - - /* What to do about this debug flag? */ - /* pf = Parrot_pbc_read(interp, argc ? *argv : "-", debug); */ - - Parrot_api_string_import(interp, argc ? *argv : "-", &filename); - if (!(Parrot_api_load_bytecode_file(interp, filename, &pbc) && - Parrot_api_disassemble_bytecode(interp, pbc, outfile, option) && - Parrot_api_destroy_interpreter(interp))) { - fprintf(stderr, "Error during disassembly\n"); - show_last_error_and_exit(interp); - } - exit(EXIT_SUCCESS); -} - -/* - -=item C - -Prints out the C's last error and exits. - -=cut - -*/ - -static void -show_last_error_and_exit(Parrot_PMC interp) -{ - Parrot_String errmsg, backtrace; - Parrot_Int exit_code, is_error; - Parrot_PMC exception; - - if (!(Parrot_api_get_result(interp, &is_error, &exception, &exit_code, &errmsg) && - Parrot_api_get_exception_backtrace(interp, exception, &backtrace))) { - fprintf(stderr, "PARROT VM: Cannot recover\n"); - exit(EXIT_FAILURE); - } - - if (errmsg) { - char * errmsg_raw; - Parrot_api_string_export_ascii(interp, errmsg, &errmsg_raw); - fprintf(stderr, "%s\n", errmsg_raw); - Parrot_api_string_free_exported_ascii(interp, errmsg_raw); - - Parrot_api_string_export_ascii(interp, backtrace, &errmsg_raw); - fprintf(stderr, "%s\n", errmsg_raw); - Parrot_api_string_free_exported_ascii(interp, errmsg_raw); - } - exit(exit_code); -} - -/* - -=back - -=head1 SEE ALSO - -F and F. - -=head1 HISTORY - -Initial version by Daniel Grunblatt on 2002.5.26. - -Florian Ragwitz: Moved POD documentation that's not necessary to know how to -actually run the disassembler to normal C comments (Wed, 16 Nov 2005). - -Reini Urban: Renamed from disassemble to pbc_disassemble (2008-07-03). - Add options: help, -h, -o, --debug, --bare (2009-01-29) - Force option 1 for passing version check (2009-03-07) - -=cut - -*/ - - -/* - * Local variables: - * c-file-style: "parrot" - * End: - * vim: expandtab shiftwidth=4 cinoptions='\:2=2' : - */ diff --git a/t/tools/pbc_disassemble.t b/t/tools/pbc_disassemble.t index b383c3f..2246506 100644 --- a/t/tools/pbc_disassemble.t +++ b/t/tools/pbc_disassemble.t @@ -48,11 +48,13 @@ BEGIN { } my $helpregex = <