
Index: ChangeLog from Benoît Perrot <benoit@lrde.epita.fr> shell::Cmd is a minimalist AST, shell::Shell is one of its visitor. * src/shell/cmd.hh: Move execution engine to... * src/shell/shell.hh, src/shell/shell.cc: This class. 2004-07-18 Benoît Perrot <benoit@lrde.epita.fr> Index: src/shell/cmd.hh --- src/shell/cmd.hh (revision 118) +++ src/shell/cmd.hh (working copy) @@ -24,22 +24,8 @@ # define SHELL_CMD_HH # include <list> -# include <map> - # include <string> -# include <sstream> -# include <iostream> - -# include <algorithm> - -# include "common.hh" -# include "modules.hh" -# include "task/task_register.hh" -# include "parse/libparse.hh" -# include "vm/virtual_machine.hh" -# include "shell/shell.hh" - namespace shell { /// Cmd Class. @@ -72,238 +58,41 @@ \{ */ public: /// Construct a Cmd. - Cmd(const cmd_type_type cmd_type, Shell &sh): - cmd_type_(cmd_type), - sh_(sh) - { - } + Cmd(const cmd_type_type cmd_type): + cmd_type_(cmd_type) + {} /// Destroy a Cmd. ~Cmd() {} /** \} */ + /** \name Accessors + \{ */ + public: /// Add an argument void push_arg(const std::string &arg) { list_args_.push_back(arg); } - /// Execute the Cmd. - int execute() - { - switch (cmd_type_) + /// Return the list of arguments + const list_args_type & get_args() const { - case cmd_quit: - return 1; - case cmd_unknown: - e_error(); - break; - case cmd_load: - e_load(); - break; - case cmd_run: - e_run(); - break; - case cmd_continue: - e_continue(); - break; - case cmd_next: - e_next(); - break; - case cmd_dump: - e_dump(); - break; - case cmd_print: - e_print(); - break; - case cmd_display: - e_display(); - break; - case cmd_undisplay: - e_undisplay(); - break; - case cmd_mem: - e_mem(); - break; - case cmd_break: - e_break(); - break; - case cmd_nop_after_branch: - e_nop_after_branch(); - break; - case cmd_null: - break; - case cmd_help: - e_help(); - } - return 0; + return list_args_; } /// Return the Cmd type. - cmd_type_type get_cmd_type() const + cmd_type_type get_type() const { return cmd_type_; } - - /** \name Function to execute. - \{ */ - private: - void e_load() - { - // FIXME: introducing memory leak! - filename = strdup(list_args_.begin()->c_str()); - - //std::cerr << "#DEBUG: _load: filename == " << filename << std::endl; - - parse::tasks::parse(); - inst::tasks::prg_solve(); - sh_.vm_.load_program(* parse::tasks::program); - } - - void e_run() - { - if (!parse::tasks::program) - { - std::cerr << "No program loaded." << std::endl; - return; - } - - if (sh_.vm_.get_status() != vm::VirtualMachine::halt) - sh_.vm_.set_runnable(); - else - { - sh_.vm_.reset(); - sh_.vm_.set_runnable(); - } - sh_.vm_.execute(false); - } - - void e_continue() - { - if (!parse::tasks::program) - { - std::cerr << "No program loaded." << std::endl; - return; - } - - if (sh_.vm_.get_status() != vm::VirtualMachine::halt) - { - sh_.vm_.set_runnable(); - sh_.vm_.execute(false); - } - else - std::cerr << "The program is not being run." << std::endl; - } - - void e_next() - { - if (!parse::tasks::program) - { - std::cerr << "No program loaded." << std::endl; - return; - } - - if (sh_.vm_.get_status() != vm::VirtualMachine::halt) - { - sh_.vm_.set_run_next(); - sh_.vm_.execute(true); - } - else - std::cerr << "The program is not being run." << std::endl; - } - - void e_break() - { - if (!parse::tasks::program) - { - std::cerr << "No program loaded." << std::endl; - return; - } - - //std::cerr <<"#DEBUG: label = " << *label << std::endl; -// sh_.vm_.add_break(*label); - sh_.vm_.add_breakpoint(*list_args_.begin()); - } - - void e_display() - { - sh_.add_display(*list_args_.begin()); - } - - void e_undisplay() - { - sh_.remove_display(*list_args_.begin()); - } - - void e_dump() - { - std::cout << sh_.vm_ << std::endl; - } - - void e_print() - { - std::cout - << *list_args_.begin() << " = " - << sh_.get_register(*list_args_.begin()) << std::endl; - } - - void e_nop_after_branch() - { - parse::tasks::nop_after_branch(); - } - - void e_mem() - { -// const std::string* addr = *(list_args_.begin()); - //std::cout << "addr: " << *addr << " = " << sh_.vm_.get_memory_offset(atoi(addr->c_str())) << std::endl; - } - - void e_error() const - { - std::cerr << "Command error" << std::endl; - } - - void e_help() const - { - std::cout << "run <args>" << std::endl - << "\trun the current loaded file with the specified arguments" - << std::endl - << "load <filename>" << std::endl - << "\tload the specified filename" << std::endl - << "break <label>" << std::endl - << "\tenable a break point on a label" << std::endl - << "quit" << std::endl - << "\tquit the debugging session" << std::endl - << "next" << std::endl - << "\texecute the next asm line" << std::endl - << "continue" << std::endl - << "\tcontinue to the next breakpoint" << std::endl - << "display <register>" << std::endl - << "\tdisplay (and set displayable) a register value" - << std::endl - << "undisplay <register>" << std::endl - << "\tundisplay a register" << std::endl - << "print <register>" << std::endl - << "\tprint a register value" << std::endl - << "dump" << std::endl - << "\tdump all the register value" << std::endl - << "mem <addr>" << std::endl - << "\tprint a the value of a memory region" << std::endl - << "nop-after-branch" << std::endl - << "\tenable Fill delay slot of branch instructions " - << "with NOP" << std::endl; - } - /** \} */ private: /// The command type. cmd_type_type cmd_type_; - /// Link to shell class. - Shell &sh_; - /// List of arguments. list_args_type list_args_; }; Index: src/shell/shell.hh --- src/shell/shell.hh (revision 118) +++ src/shell/shell.hh (working copy) @@ -39,7 +39,7 @@ # include "task/task_register.hh" # include "vm/virtual_machine.hh" - +# include "shell/cmd.hh" namespace shell { @@ -63,15 +63,9 @@ HELP = 213 }; - /** Forward declaration. */ - class Cmd; - /// Shell Class. class Shell { - /// friend class (dirty). - friend class Cmd; - public: /** \name Shortand type definition \{ */ @@ -201,6 +195,29 @@ return TERROR; } + /** \name Execution engine + \{ */ + protected: + void do_load(const Cmd &cmd); + void do_run(); + void do_continue(); + void do_next(); + void do_break(const Cmd &cmd); + + void do_display(const Cmd &cmd); + void do_undisplay(const Cmd &cmd); + void do_dump(); + void do_print(const Cmd &cmd); + void do_mem(); + + void do_nop_after_branch(); + + void do_error() const; + void do_help() const; + + int execute(const Cmd &cmd); + /** \} */ + private: /// virtual machine link. vm::VirtualMachine vm_; Index: src/shell/shell.cc --- src/shell/shell.cc (revision 118) +++ src/shell/shell.cc (working copy) @@ -19,6 +19,8 @@ #include "misc/readline.hh" +#include "parse/libparse.hh" + #include "shell/shell.hh" #include "shell/cmd.hh" @@ -94,10 +96,10 @@ void Shell::run() { - Cmd *command = new Cmd(Cmd::cmd_null, *this); + Cmd *command = new Cmd(Cmd::cmd_null); std::string line; - while ((command->execute() == 0) && misc::readline("(nolimips) ", line)) + while (execute(*command) == 0 && misc::readline("(nolimips) ", line)) { display(); @@ -120,10 +122,10 @@ switch (eat_word(iss)) { case QUIT: - return new Cmd(Cmd::cmd_quit, *this); + return new Cmd(Cmd::cmd_quit); case RUN: { - command = new Cmd(Cmd::cmd_run, *this); + command = new Cmd(Cmd::cmd_run); std::string tmp = get_next_word(iss); while (0 < tmp.length()) { @@ -134,7 +136,7 @@ } case BREAK: { - command = new Cmd(Cmd::cmd_break, *this); + command = new Cmd(Cmd::cmd_break); std::string tmp = get_next_word(iss); if (tmp.empty()) { @@ -151,14 +153,14 @@ break; } case CONTINUE: - return new Cmd(Cmd::cmd_continue, *this); + return new Cmd(Cmd::cmd_continue); case NEXT: - return new Cmd(Cmd::cmd_next, *this); + return new Cmd(Cmd::cmd_next); case DUMP: - return new Cmd(Cmd::cmd_dump, *this); + return new Cmd(Cmd::cmd_dump); case LOAD: { - command = new Cmd(Cmd::cmd_load, *this); + command = new Cmd(Cmd::cmd_load); std::string tmp = get_next_word(iss); if (tmp.empty()) { @@ -170,7 +172,7 @@ } case PRINT: { - command = new Cmd(Cmd::cmd_print, *this); + command = new Cmd(Cmd::cmd_print); std::string tmp = get_next_word(iss); if (tmp.empty()) { @@ -188,7 +190,7 @@ } case DISPLAY: { - command = new Cmd(Cmd::cmd_display, *this); + command = new Cmd(Cmd::cmd_display); std::string tmp = get_next_word(iss); if (tmp.empty()) { @@ -206,7 +208,7 @@ } case UNDISPLAY: { - command = new Cmd(Cmd::cmd_undisplay, *this); + command = new Cmd(Cmd::cmd_undisplay); std::string tmp = get_next_word(iss); if (tmp.empty()) { @@ -224,7 +226,7 @@ } case MEM: { - command = new Cmd(Cmd::cmd_mem, *this); + command = new Cmd(Cmd::cmd_mem); std::string tmp = get_next_word(iss); if (tmp.empty()) { @@ -236,15 +238,228 @@ return command; } case NOP_AFTER_BRANCH: - return new Cmd(Cmd::cmd_nop_after_branch, *this); + return new Cmd(Cmd::cmd_nop_after_branch); case HELP: - return new Cmd(Cmd::cmd_help, *this); + return new Cmd(Cmd::cmd_help); case TERROR: case EOL: break; } - return new Cmd(Cmd::cmd_unknown, *this); + return new Cmd(Cmd::cmd_unknown); + } + + + void + Shell::do_load(const Cmd &cmd) + { + // FIXME: introducing memory leak! + filename = strdup(cmd.get_args().begin()->c_str()); + + //std::cerr << "#DEBUG: _load: filename == " << filename << std::endl; + + parse::tasks::parse(); + inst::tasks::prg_solve(); + vm_.load_program(* parse::tasks::program); + } + + void + Shell::do_run() + { + if (!parse::tasks::program) + { + std::cerr << "No program loaded." << std::endl; + return; + } + + if (vm_.get_status() != vm::VirtualMachine::halt) + vm_.set_runnable(); + else + { + vm_.reset(); + vm_.set_runnable(); + } + vm_.execute(false); + } + + void + Shell::do_continue() + { + if (!parse::tasks::program) + { + std::cerr << "No program loaded." << std::endl; + return; + } + + if (vm_.get_status() != vm::VirtualMachine::halt) + { + vm_.set_runnable(); + vm_.execute(false); + } + else + std::cerr << "The program is not being run." << std::endl; + } + + void + Shell::do_next() + { + if (!parse::tasks::program) + { + std::cerr << "No program loaded." << std::endl; + return; + } + + if (vm_.get_status() != vm::VirtualMachine::halt) + { + vm_.set_run_next(); + vm_.execute(true); + } + else + std::cerr << "The program is not being run." << std::endl; + } + + void + Shell::do_break(const Cmd &cmd) + { + if (!parse::tasks::program) + { + std::cerr << "No program loaded." << std::endl; + return; + } + + //std::cerr <<"#DEBUG: label = " << *label << std::endl; + // sh_.vm_.add_break(*label); + vm_.add_breakpoint(*cmd.get_args().begin()); + } + + void + Shell::do_display(const Cmd &cmd) + { + add_display(*cmd.get_args().begin()); + } + + void + Shell::do_undisplay(const Cmd &cmd) + { + remove_display(*cmd.get_args().begin()); + } + + void + Shell::do_dump() + { + std::cout << vm_ << std::endl; + } + + void + Shell::do_print(const Cmd &cmd) + { + std::cout + << *cmd.get_args().begin() << " = " + << get_register(*cmd.get_args().begin()) << std::endl; + } + + void + Shell::do_nop_after_branch() + { + parse::tasks::nop_after_branch(); + } + + void + Shell::do_mem() + { + // const std::string* addr = *(list_args_.begin()); + //std::cout << "addr: " << *addr << " = " << sh_.vm_.get_memory_offset(atoi(addr->c_str())) << std::endl; + } + + void + Shell::do_error() const + { + std::cerr << "Command error" << std::endl; + } + + void + Shell::do_help() const + { + std::cout + << "run <args>" << std::endl + << "\trun the current loaded file with the specified arguments" + << std::endl + << "load <filename>" << std::endl + << "\tload the specified filename" << std::endl + << "break <label>" << std::endl + << "\tenable a break point on a label" << std::endl + << "quit" << std::endl + << "\tquit the debugging session" << std::endl + << "next" << std::endl + << "\texecute the next asm line" << std::endl + << "continue" << std::endl + << "\tcontinue to the next breakpoint" << std::endl + << "display <register>" << std::endl + << "\tdisplay (and set displayable) a register value" + << std::endl + << "undisplay <register>" << std::endl + << "\tundisplay a register" << std::endl + << "print <register>" << std::endl + << "\tprint a register value" << std::endl + << "dump" << std::endl + << "\tdump all the register value" << std::endl + << "mem <addr>" << std::endl + << "\tprint a the value of a memory region" << std::endl + << "nop-after-branch" << std::endl + << "\tenable Fill delay slot of branch instructions " + << "with NOP" << std::endl; + } + + /// Execute the Cmd. + int + Shell::execute(const Cmd &cmd) + { + switch (cmd.get_type()) + { + case Cmd::cmd_quit: + return 1; + case Cmd::cmd_unknown: + do_error(); + break; + case Cmd::cmd_load: + do_load(cmd); + break; + case Cmd::cmd_run: + do_run(); + break; + case Cmd::cmd_continue: + do_continue(); + break; + case Cmd::cmd_next: + do_next(); + break; + case Cmd::cmd_dump: + do_dump(); + break; + case Cmd::cmd_print: + do_print(cmd); + break; + case Cmd::cmd_display: + do_display(cmd); + break; + case Cmd::cmd_undisplay: + do_undisplay(cmd); + break; + case Cmd::cmd_mem: + do_mem(); + break; + case Cmd::cmd_break: + do_break(cmd); + break; + case Cmd::cmd_nop_after_branch: + do_nop_after_branch(); + break; + case Cmd::cmd_null: + break; + case Cmd::cmd_help: + do_help(); + } + return 0; } } // namespace shell