diff --git a/Makefile.am b/Makefile.am index 6a9f99c..f3f53d5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -167,6 +167,7 @@ src_backend_libbackend_la_SOURCES = \ src/backend/holt_graph.cc \ src/backend/invalid_plugin_exception.cc \ src/backend/key_file.cc \ + src/backend/malformed_policy_exception.cc \ src/backend/module.cc \ src/backend/null_policy_exception.cc \ src/backend/plugin_manager.cc \ @@ -210,6 +211,7 @@ pkginclude_HEADERS += \ src/backend/holt_graph.hh \ src/backend/invalid_plugin_exception.hh \ src/backend/key_file.hh \ + src/backend/malformed_policy_exception.hh \ src/backend/module.hh \ src/backend/null_policy_exception.hh \ src/backend/policy_parameters.hh \ diff --git a/plugins/pyloader/src/python_cpu_policy.cc b/plugins/pyloader/src/python_cpu_policy.cc index 51b6337..8d5e851 100644 --- a/plugins/pyloader/src/python_cpu_policy.cc +++ b/plugins/pyloader/src/python_cpu_policy.cc @@ -32,7 +32,7 @@ using namespace std; // WARNING : this class needs extensive and above all // *strong* exception checking / handling! -PythonCPUPolicy::PythonCPUPolicy(const char* name) +PythonCPUPolicy::PythonCPUPolicy(const char* name) throw(MalformedPolicyException) : _upolicy_dict(NULL), _adapter(NULL), _name(name) { PyObject* pLoadmeStr = PyString_FromString(name); @@ -42,8 +42,7 @@ PythonCPUPolicy::PythonCPUPolicy(const char* name) if( !pUserCPUPolicyModule ) { PyErr_Print(); // Error in import - // FIXME : don't exit abruptly, but fall back gracefully - exit(-1); + throw MalformedPolicyException("this message should be the stuff printed by PyErr_Print"); } // Dictionary with defined ``symbols'' for .pyc file diff --git a/plugins/pyloader/src/python_cpu_policy.hh b/plugins/pyloader/src/python_cpu_policy.hh index 95e1728..0c76374 100644 --- a/plugins/pyloader/src/python_cpu_policy.hh +++ b/plugins/pyloader/src/python_cpu_policy.hh @@ -30,12 +30,12 @@ #include "cpu_policy.hh" #include "user_interrupt_exception.hh" +#include "malformed_policy_exception.hh" namespace sgpem { class PythonCPUPolicy; class PythonCPUPolicyManager; - class UserInterruptException; /** \brief A specialization of abstract class Policy @@ -45,7 +45,7 @@ namespace sgpem class SG_DLLEXPORT PythonCPUPolicy : public CPUPolicy { public: - PythonCPUPolicy(const char* name); + PythonCPUPolicy(const char* name) throw(MalformedPolicyException); virtual ~PythonCPUPolicy(); /** diff --git a/plugins/pyloader/src/python_cpu_policy_manager.cc b/plugins/pyloader/src/python_cpu_policy_manager.cc index 5480f3a..e131b8d 100644 --- a/plugins/pyloader/src/python_cpu_policy_manager.cc +++ b/plugins/pyloader/src/python_cpu_policy_manager.cc @@ -122,23 +122,30 @@ PythonCPUPolicyManager::collect_policies() for(Glib::DirIterator file_it = dir.begin(); file_it != dir.end(); ++file_it) { - cout << "\tChecking if " << *file_it << " is a Python script... "; + cout << "\tChecking if " << *file_it << " is a valid Python script... "; Glib::PatternSpec dot_py("*.py"); if(dot_py.match(*file_it)) { - cout << "yes\n"; - + cout << "yes" << endl; + //strip extension std::string policy_name = (*file_it).substr(0, (*file_it).size() - 3); - PythonCPUPolicy *pypolicy = new PythonCPUPolicy(policy_name.c_str()); + try + { + PythonCPUPolicy *pypolicy = new PythonCPUPolicy(policy_name.c_str()); - _policies.push_back(pypolicy); + _policies.push_back(pypolicy); + } + catch(MalformedPolicyException e) + { + // TODO do something here someday + } } else - cout << "no\n"; + cout << "no" << endl; } } } diff --git a/src/backend/malformed_policy_exception.cc b/src/backend/malformed_policy_exception.cc new file mode 100644 index 0000000..2ed5369 --- /dev/null +++ b/src/backend/malformed_policy_exception.cc @@ -0,0 +1,32 @@ +// src/backend/malformed_policy_exception.cc - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// This file is part of SGPEMv2. +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// SGPEMv2 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SGPEMv2; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// Warning! This exception will be thrown across different libraries. +// It could be necessary to do dynamic type-checking when +// catching it (with typeinfo). + +#include "malformed_policy_exception.hh" +using namespace sgpem; + +MalformedPolicyException::MalformedPolicyException(const char* msg) + : std::runtime_error(msg) +{} + +MalformedPolicyException::~MalformedPolicyException() throw() {} diff --git a/src/backend/malformed_policy_exception.hh b/src/backend/malformed_policy_exception.hh new file mode 100644 index 0000000..36e5fec --- /dev/null +++ b/src/backend/malformed_policy_exception.hh @@ -0,0 +1,46 @@ +// src/backend/malformed_policy_exception.hh - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// This file is part of SGPEMv2. +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// SGPEMv2 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SGPEMv2; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// Warning! This exception will be thrown across different libraries. +// It could be necessary to do dynamic type-checking when +// catching it (with typeinfo). + +#ifndef MALFORMED_POLICY_EXCEPTION +#define MALFORMED_POLICY_EXCEPTION 1 + +#include "config.h" + +#include + +namespace sgpem +{ + class MalformedPolicyException; + + class SG_DLLEXPORT MalformedPolicyException : public std::runtime_error + { + public: + MalformedPolicyException(const char* msg = ""); + virtual ~MalformedPolicyException() throw (); + + private: + }; +} //~ namespace sgpem + +#endif diff --git a/src/text_simulation.cc b/src/text_simulation.cc index 1f52c6f..694ca6a 100644 --- a/src/text_simulation.cc +++ b/src/text_simulation.cc @@ -91,7 +91,8 @@ namespace sgpem } -TextSimulation::TextSimulation() +TextSimulation::TextSimulation() : + _saved(true) { } @@ -116,6 +117,35 @@ TextSimulation::check_arguments_num(const Tokens& arguments, unsigned int num) return true; } +bool +TextSimulation::unsaved_ask_confirm() const +{ + if(!_saved) + { + p_stderr(_("WARNING: Simulation was not recently saved. " + "If you continue some changes to the simulation might be lost.\n")); + + for(bool bad_arg = true; bad_arg;) + { + p_stdout(_("Continue? [y/n] ")); + + ustring buf = readline(); + + Tokens tokens = tokenize(buf); + + if(tokens.size() == 1 && tokens[0].size() == 1) + { + if(tokens[0].lowercase() == _("n")) + return false; + else if(tokens[0].lowercase() == _("y")) + bad_arg = false; + } + } + } + + return true; +} + template void TextSimulation::show(const Container& entities) @@ -459,7 +489,7 @@ TextSimulation::on_help(const Tokens& arguments) if(command.size() == 0) p_stdout(_("Avaiable commands:\nRUN\nSTOP\nPAUSE\n" "CONFIGURE-CPU-POLICY\nHELP\nGET\nSET\nSHOW\nADD\n" - "REMOVE\nQUIT\n\n" + "REMOVE\nSAVE\nLOAD\nQUIT\n\n" "HELP followed by a command name shows help about it.\n" "ex. `HELP RUN` shows help about the command RUN\n")); else if(command == "RUN") @@ -520,6 +550,12 @@ TextSimulation::on_help(const Tokens& arguments) "numeric ids follow the same logic of the previous commands\n" "`REMOVE subrequest ` where the " "numeric ids follow the same logic of the previous commands\n")); + else if(command == "SAVE") + p_stderr(_("-- SAVE COMMAND --\nSaves the simulation.\n\n" + "Syntax: SAVE \n")); + else if(command == "LOAD") + p_stderr(_("-- LOAD COMMAND --\nLoads the simulation.\n\n" + "Syntax: LOAD \n")); else if(command == "QUIT") p_stderr(_("-- QUIT COMMAND --\nGently closes the program.\n")); else @@ -531,6 +567,9 @@ TextSimulation::on_quit(const Tokens& arguments) { check_arguments_num(arguments, 0); + if(!unsaved_ask_confirm()) + return; + p_stdout(_("\n\n*** Thank you for using SGPEM by Sirius Cybernetics Corporation ***\n\n")); // Is this ok? Really? Oh, sure, if it we always did it in this way, it is surely a Good Thing! @@ -1303,11 +1342,53 @@ TextSimulation::on_save(const Tokens& arguments) vector serializers = SerializersGatekeeper::get_instance().get_registered(); + // FIXME using the first serializer available, this + // will need to be changed when multiple serializers will + // be made available Serializer& serializer = *serializers.at(0); const History& history = Simulation::get_instance().get_history(); serializer.save_snapshot(filename, history); + + _saved = true; + } + catch(out_of_range e) + { + p_stderr(_("ERROR: No registered serializer available\n")); + } + catch(SerializerError e) + { + string msg = _("ERROR: "); + + p_stderr(msg + e.what() + "\n"); + } +} + +void +TextSimulation::on_load(const Tokens& arguments) +{ + if(!check_arguments_num(arguments, 1)) + return; + + ustring filename = arguments[0]; + + if(!unsaved_ask_confirm()) + return; + + try + { + vector serializers = + SerializersGatekeeper::get_instance().get_registered(); + + // FIXME using the first serializer available, this + // will need to be changed when multiple serializers will + // be made available + Serializer& serializer = *serializers.at(0); + + History& history = Simulation::get_instance().get_history(); + + serializer.restore_snapshot(filename, history); } catch(out_of_range e) { @@ -1361,8 +1442,9 @@ TextSimulation::parse_command(TextSimulation& sim, const ustring& str) command_handlers["ADD"] = &TextSimulation::on_add; command_handlers["REMOVE"] = &TextSimulation::on_remove; command_handlers["SAVE"] = &TextSimulation::on_save; + command_handlers["LOAD"] = &TextSimulation::on_load; command_handlers["QUIT"] = &TextSimulation::on_quit; - + Tokens arguments = tokenize(str); if(arguments.size() == 0) @@ -1379,6 +1461,9 @@ TextSimulation::parse_command(TextSimulation& sim, const ustring& str) arguments.erase(arguments.begin()); (sim.*(command_handlers[key]))(arguments); + + if(key == "ADD" || key == "REMOVE") + sim._saved = false; } static ostream& diff --git a/src/text_simulation.hh b/src/text_simulation.hh index 9730592..80999b2 100644 --- a/src/text_simulation.hh +++ b/src/text_simulation.hh @@ -74,6 +74,7 @@ namespace sgpem virtual void update(const History& changed_history); bool check_arguments_num(const Tokens& arguments, unsigned int num); + bool unsaved_ask_confirm() const; template void show(const Container& entities); template @@ -107,12 +108,15 @@ namespace sgpem void on_remove_request(const Tokens& arguments); void on_remove_subrequest(const Tokens& arguments); void on_save(const Tokens& arguments); + void on_load(const Tokens& arguments); // FIXME This is a temporary replacement for the // to-be written I/O layer static void p_stdout(const Glib::ustring& str); static void p_stderr(const Glib::ustring& str); static Glib::ustring readline(); + + bool _saved; }; }