mail[Wesnoth-commits] r44988 - in /trunk/src: ./ editor/ scripting/


Others Months | Index by Date | Thread Index
>>   [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Header


Content

Posted by guillaume . melquiond on July 31, 2010 - 12:52:
Author: silene
Date: Sat Jul 31 12:52:26 2010
New Revision: 44988

URL: http://svn.gna.org/viewcvs/wesnoth?rev=44988&view=rev
Log:
Factored the whole exception handling.
Implemented sticky exceptions that can be rethrown at will.
Used them to ensure that quitting the game, loading a new game, and leaving 
to title screen, work correctly when WML is being executed.

Added:
    trunk/src/exceptions.hpp
Modified:
    trunk/src/editor/editor_map.cpp
    trunk/src/game.cpp
    trunk/src/game_end_exceptions.hpp
    trunk/src/game_errors.hpp
    trunk/src/scripting/lua.cpp
    trunk/src/video.hpp
    trunk/src/wml_exception.cpp
    trunk/src/wml_exception.hpp

Modified: trunk/src/editor/editor_map.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/editor/editor_map.cpp?rev=44988&r1=44987&r2=44988&view=diff
==============================================================================
--- trunk/src/editor/editor_map.cpp (original)
+++ trunk/src/editor/editor_map.cpp Sat Jul 31 12:52:26 2010
@@ -60,7 +60,7 @@
        } catch (incorrect_map_format_exception& e) {
                throw wrap_exc("format", e.msg_, "");
        } catch (twml_exception& e) {
-               throw wrap_exc("wml", e.user_message, "");
+               throw wrap_exc("wml", e.message, "");
        } catch (config::error& e) {
                throw wrap_exc("config", e.message, "");
        }

Added: trunk/src/exceptions.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/exceptions.hpp?rev=44988&view=auto
==============================================================================
--- trunk/src/exceptions.hpp (added)
+++ trunk/src/exceptions.hpp Sat Jul 31 12:52:26 2010
@@ -1,0 +1,79 @@
+/* $Id$ */
+/*
+   Copyright (C) 2010 by Guillaume Melquiond <guillaume.melquiond@xxxxxxxxx>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2
+   or at your option any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY.
+
+   See the COPYING file for more details.
+*/
+#ifndef EXCEPTIONS_HPP_INCLUDED
+#define EXCEPTIONS_HPP_INCLUDED
+
+#include <exception>
+#include <string>
+
+namespace game {
+
+/**
+ * Base class for all the errors encountered by the engine.
+ * It provides a field for storing custom messages related to the actual
+ * error.
+ */
+struct error : std::exception
+{
+       std::string message;
+
+       error() : message() {}
+       error(const std::string &msg) : message(msg) {}
+       ~error() throw() {}
+
+       const char *what() const throw()
+       {
+               return message.c_str();
+       }
+};
+
+/**
+ * Base class for all the exceptions for changing the control flow.
+ * Its message only carries a description of the exception.
+ * It also handles sticky exceptions that are automatically rethrown if
+ * lost; such exceptions cannot have any embedded payload, since it would
+ * still be lost.
+ */
+struct exception : std::exception
+{
+       const char *message;
+
+       /**
+        * Rethrows the current sticky exception, if any.
+        */
+       static void rethrow();
+
+       /**
+        * Marks an exception of name @a sticky as a rethrow candidate.
+        * @note The value should be set to NULL in order to discard the
+        *       sticky exception once it has been handled.
+        */
+       static const char *sticky;
+
+       exception(const char *msg, const char *stick = NULL) : message(msg)
+       {
+               sticky = stick;
+       }
+
+       ~exception() throw() {}
+
+       const char *what() const throw()
+       {
+               return message;
+       }
+};
+
+}
+
+#endif

Modified: trunk/src/game.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/game.cpp?rev=44988&r1=44987&r2=44988&view=diff
==============================================================================
--- trunk/src/game.cpp (original)
+++ trunk/src/game.cpp Sat Jul 31 12:52:26 2010
@@ -132,6 +132,21 @@
        return a["rank"].to_int(1000) < b["rank"].to_int(1000);
 }
 
+char const *game::exception::sticky;
+
+void game::exception::rethrow()
+{
+       if (!sticky) return;
+       if (strcmp(sticky, "quit") == 0) throw CVideo::quit();
+       if (strcmp(sticky, "load game") == 0) throw 
game::load_game_exception();
+       if (strcmp(sticky, "end level") == 0) throw end_level_exception(QUIT);
+       throw game::exception("Unknown exception", "unknown");
+}
+
+std::string game::load_game_exception::game;
+bool game::load_game_exception::show_replay;
+bool game::load_game_exception::cancel_orders;
+
 namespace {
 struct jump_to_campaign_info
 {
@@ -165,7 +180,7 @@
        void reload_changed_game_config();
 
        bool is_loading() const;
-       void clear_loaded_game() {loaded_game_.clear();};
+       void clear_loaded_game() { game::load_game_exception::game.clear(); }
        bool load_game();
        void set_tutorial();
 
@@ -232,10 +247,6 @@
        util::scoped_ptr<game_display> disp_;
 
        game_state state_;
-
-       std::string loaded_game_;
-       bool loaded_game_show_replay_;
-       bool loaded_game_cancel_orders_;
 
        std::string multiplayer_server_;
        bool jump_to_multiplayer_;
@@ -273,9 +284,6 @@
        old_defines_map_(),
        disp_(NULL),
        state_(),
-       loaded_game_(),
-       loaded_game_show_replay_(false),
-       loaded_game_cancel_orders_(false),
        multiplayer_server_(),
        jump_to_multiplayer_(false),
        jump_to_campaign_(false,-1,"","")
@@ -353,10 +361,10 @@
                } else if(val == "--load" || val == "-l") {
                        if(arg_+1 != argc_) {
                                ++arg_;
-                               loaded_game_ = argv_[arg_];
+                               game::load_game_exception::game = argv_[arg_];
                        }
                } else if(val == "--with-replay") {
-                       loaded_game_show_replay_ = true;
+                       game::load_game_exception::show_replay = true;
 
                } else if(val == "--nogui") {
                        no_gui_ = true;
@@ -471,7 +479,7 @@
                        if(arg_+1 != argc_) {
                                if (argv_[arg_ + 1][0] != '-') {
                                        ++arg_;
-                                       loaded_game_ = argv_[arg_];
+                                       game::load_game_exception::game = 
argv_[arg_];
                                }
                        }
 #endif
@@ -660,9 +668,6 @@
                upload_log nolog(false);
                play_game(disp(),state_,game_config(),nolog);
        } catch(game::load_game_exception& e) {
-               loaded_game_ = e.game;
-               loaded_game_show_replay_ = e.show_replay;
-               loaded_game_cancel_orders_ = e.cancel_orders;
                test_mode_ = false;
                return true;
        }
@@ -892,13 +897,8 @@
 
                state_.snapshot = level;
                play_game(disp(), state_, game_config(), log);
-       } catch(game::error& e) {
-               std::cerr << "caught error: '" << e.message << "'\n";
        } catch(game::load_game_exception& e) {
                //the user's trying to load a game, so go into the normal 
title screen loop and load one
-               loaded_game_ = e.game;
-               loaded_game_show_replay_ = e.show_replay;
-               loaded_game_cancel_orders_ = e.cancel_orders;
                return true;
        } catch(twml_exception& e) {
                e.show(disp());
@@ -914,7 +914,7 @@
 
 bool game_controller::is_loading() const
 {
-       return loaded_game_.empty() == false;
+       return !game::load_game_exception::game.empty();
 }
 
 bool game_controller::load_game()
@@ -922,7 +922,7 @@
        savegame::loadgame load(disp(), game_config(), state_);
 
        try {
-               load.load_game(loaded_game_, loaded_game_show_replay_, 
loaded_game_cancel_orders_);
+               load.load_game(game::load_game_exception::game, 
game::load_game_exception::show_replay, 
game::load_game_exception::cancel_orders);
 
                cache_.clear_defines();
                game_config::scoped_preproc_define 
dificulty_def(state_.classification().difficulty);
@@ -950,7 +950,7 @@
                load.set_gamestate();
 
        } catch(load_game_cancelled_exception&) {
-               loaded_game_ = "";
+               clear_loaded_game();
                return false;
        } catch(config::error& e) {
                if(e.message.empty()) {
@@ -960,6 +960,9 @@
                        gui2::show_error_message(disp().video(), _("The file 
you have tried to load is corrupt: '") + e.message + '\'');
                }
                return false;
+       } catch(twml_exception& e) {
+               e.show(disp());
+               return false;
        } catch(game::error& e) {
                if(e.message.empty()) {
                        gui2::show_error_message(disp().video(), _("The file 
you have tried to load is corrupt"));
@@ -970,9 +973,6 @@
                return false;
        } catch(io_exception&) {
                gui2::show_error_message(disp().video(), _("File I/O Error 
while reading the game"));
-               return false;
-       } catch(twml_exception& e) {
-               e.show(disp());
                return false;
        }
        recorder = replay(state_.replay_data);
@@ -1225,12 +1225,12 @@
 {
        if(jump_to_editor_){
                jump_to_editor_ = false;
-               if (start_editor(normalize_path(loaded_game_)) ==
+               if 
(start_editor(normalize_path(game::load_game_exception::game)) ==
                    editor::EXIT_QUIT_TO_DESKTOP)
                {
                        return false;
                }
-               loaded_game_ = "";
+               clear_loaded_game();
        }
        return true;
 }
@@ -1410,9 +1410,6 @@
                gui2::show_error_message(disp().video(), std::string(_("The 
game map could not be loaded: ")) + e.msg_);
        } catch(game::load_game_exception& e) {
                //this will make it so next time through the title screen 
loop, this game is loaded
-               loaded_game_ = e.game;
-               loaded_game_show_replay_ = e.show_replay;
-               loaded_game_cancel_orders_ = e.cancel_orders;
        } catch(twml_exception& e) {
                e.show(disp());
        }
@@ -1632,16 +1629,9 @@
                        
about::show_about(disp(),state_.classification().campaign);
                }
 
-               loaded_game_ = "";
-               loaded_game_show_replay_ = false;
-               loaded_game_cancel_orders_ = false;
-       } catch(game::load_game_exception& e) {
-
+               clear_loaded_game();
+       } catch (game::load_game_exception &) {
                //this will make it so next time through the title screen 
loop, this game is loaded
-               loaded_game_ = e.game;
-               loaded_game_show_replay_ = e.show_replay;
-               loaded_game_cancel_orders_ = e.cancel_orders;
-
        } catch(twml_exception& e) {
                e.show(disp());
        }
@@ -1656,16 +1646,9 @@
        try {
                ::play_replay(disp(),state_,game_config(),video_);
 
-               loaded_game_ = "";
-               loaded_game_show_replay_ = false;
-               loaded_game_cancel_orders_ = false;
-       } catch(game::load_game_exception& e) {
-
+               clear_loaded_game();
+       } catch (game::load_game_exception &) {
                //this will make it so next time through the title screen 
loop, this game is loaded
-               loaded_game_ = e.game;
-               loaded_game_show_replay_ = e.show_replay;
-               loaded_game_cancel_orders_ = e.cancel_orders;
-
        } catch(twml_exception& e) {
                e.show(disp());
        }
@@ -2152,7 +2135,9 @@
 
        LOG_CONFIG << "time elapsed: "<<  (SDL_GetTicks() - start_ticks) << " 
ms\n";
 
-       for(;;){
+       for (;;)
+       {
+               game::exception::sticky = NULL;
 
                // reset the TC, since a game can modify it, and it may be 
used
                // by images in add-ons or campaigns dialogs
@@ -2361,14 +2346,14 @@
                //just means the game should quit
        } catch(end_level_exception&) {
                std::cerr << "caught end_level_exception (quitting)\n";
+       } catch(twml_exception& e) {
+               std::cerr << "WML exception:\nUser message: "
+                       << e.message << "\nDev message: " << e.dev_message << 
'\n';
        } catch(game::error &) {
                // A message has already been displayed.
        } catch(std::bad_alloc&) {
                std::cerr << "Ran out of memory. Aborted.\n";
                return ENOMEM;
-       } catch(twml_exception& e) {
-               std::cerr << "WML exception:\nUser message: "
-                       << e.user_message << "\nDev message: " << 
e.dev_message << '\n';
        } catch(game_logic::formula_error& e) {
                std::cerr << "Formula error found in " << e.filename << ":" 
<< e.line
                        << "\nIn formula " << e.formula

Modified: trunk/src/game_end_exceptions.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/game_end_exceptions.hpp?rev=44988&r1=44987&r2=44988&view=diff
==============================================================================
--- trunk/src/game_end_exceptions.hpp (original)
+++ trunk/src/game_end_exceptions.hpp Sat Jul 31 12:52:26 2010
@@ -22,7 +22,7 @@
 #ifndef GAME_END_EXCEPTIONS_HPP_INCLUDED
 #define GAME_END_EXCEPTIONS_HPP_INCLUDED
 
-#include <string>
+#include "exceptions.hpp"
 
 enum LEVEL_RESULT {
        NONE,
@@ -36,18 +36,21 @@
 /**
  * Exception used to signal the end of a player turn.
  */
-struct end_turn_exception
+struct end_turn_exception : game::exception
 {
-       end_turn_exception(unsigned r = 0): redo(r) {}
+       end_turn_exception(unsigned r = 0)
+               : game::exception("End turn"), redo(r) {}
        unsigned redo;
 };
 
 /**
  * Exception used to signal the end of a scenario.
  */
-struct end_level_exception
+struct end_level_exception : game::exception
 {
-       end_level_exception(LEVEL_RESULT res): result(res) {}
+       end_level_exception(LEVEL_RESULT res)
+               : game::exception("End level", res == QUIT ? "end level" : 
NULL)
+               , result(res) {}
        LEVEL_RESULT result;
 };
 

Modified: trunk/src/game_errors.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/game_errors.hpp?rev=44988&r1=44987&r2=44988&view=diff
==============================================================================
--- trunk/src/game_errors.hpp (original)
+++ trunk/src/game_errors.hpp Sat Jul 31 12:52:26 2010
@@ -15,57 +15,59 @@
 #ifndef GAME_ERRORS_HPP_INCLUDED
 #define GAME_ERRORS_HPP_INCLUDED
 
-#include <exception>
-#include <string>
+#include "exceptions.hpp"
 
 namespace game {
-
-struct error : std::exception
-{
-       std::string message;
-
-       error() :
-               message()
-               {}
-       error(const std::string& msg) : message(msg)
-       {}
-       ~error() throw() {}
-
-       const char *what() const throw()
-       {
-               return message.c_str();
-       }
-};
 
 struct mp_server_error : public error {
        mp_server_error(const std::string& msg) : error("MP server error: " + 
msg) {}
 };
-//an exception object used when loading a game fails.
+
+/**
+ * Error used when game loading fails.
+ */
 struct load_game_failed : public error {
        load_game_failed() {}
        load_game_failed(const std::string& msg) : error("load_game_failed: " 
+ msg) {}
 };
 
-//an exception object used when saving a game fails.
+/**
+ * Error used when game saving fails.
+ */
 struct save_game_failed : public error {
        save_game_failed() {}
        save_game_failed(const std::string& msg) : error("save_game_failed: " 
+ msg) {}
 };
 
-//an exception object used for any general game error.
-//e.g. data files are corrupt.
+/**
+ * Error used for any general game error, e.g. data files are corrupt.
+ */
 struct game_error : public error {
        game_error(const std::string& msg) : error("game_error: " + msg) {}
 };
 
-//an exception object used to signal that the user has decided to abort
-//a game, and load another game instead
-struct load_game_exception {
-       load_game_exception(const std::string& game, bool show_replay, bool 
cancel_orders)
-       : game(game), show_replay(show_replay), cancel_orders(cancel_orders) 
{}
-       std::string game;
-       bool show_replay;
-       bool cancel_orders;
+/**
+ * Exception used to signal that the user has decided to abort a game,
+ * and to load another game instead.
+ */
+struct load_game_exception : exception
+{
+       load_game_exception()
+               : exception("Abort the current game and load a new one", 
"load game")
+       {
+       }
+
+       load_game_exception(const std::string &game_, bool show_replay_, bool 
cancel_orders_)
+               : exception("Abort the current game and load a new one", 
"load game")
+       {
+               game = game_;
+               show_replay = show_replay_;
+               cancel_orders = cancel_orders_;
+       }
+
+       static std::string game;
+       static bool show_replay;
+       static bool cancel_orders;
 };
 }
 

Modified: trunk/src/scripting/lua.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/scripting/lua.cpp?rev=44988&r1=44987&r2=44988&view=diff
==============================================================================
--- trunk/src/scripting/lua.cpp (original)
+++ trunk/src/scripting/lua.cpp Sat Jul 31 12:52:26 2010
@@ -413,6 +413,8 @@
 
        // Call the function.
        int res = lua_pcall(L, nArgs, nRets, -2 - nArgs);
+       game::exception::rethrow();
+
        if (res)
        {
                char const *m = lua_tostring(L, -1);

Modified: trunk/src/video.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/video.hpp?rev=44988&r1=44987&r2=44988&view=diff
==============================================================================
--- trunk/src/video.hpp (original)
+++ trunk/src/video.hpp Sat Jul 31 12:52:26 2010
@@ -15,6 +15,7 @@
 #define VIDEO_HPP_INCLUDED
 
 #include "events.hpp"
+#include "exceptions.hpp"
 #include "SDL.h"
 
 #include <boost/utility.hpp>
@@ -66,9 +67,15 @@
 
        bool isFullScreen() const;
 
-       struct error {};
+       struct error : game::error
+       {
+               error() : game::error("Video initialization failed") {}
+       };
 
-       struct quit {};
+       struct quit : game::exception
+       {
+               quit() : game::exception("Exit game", "quit") {}
+       };
 
        //functions to allow changing video modes when 16BPP is emulated
        void setBpp( int bpp );

Modified: trunk/src/wml_exception.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/wml_exception.cpp?rev=44988&r1=44987&r2=44988&view=diff
==============================================================================
--- trunk/src/wml_exception.cpp (original)
+++ trunk/src/wml_exception.cpp Sat Jul 31 12:52:26 2010
@@ -45,7 +45,7 @@
        // The extra spaces between the \n are needed, otherwise the dialog 
doesn't show
        // an empty line.
        sstr << _("An error due to possibly invalid WML occurred\nThe error 
message is :")
-               << "\n" << user_message << "\n \n"
+               << "\n" << message << "\n \n"
                << _("When reporting the bug please include the following 
error message :")
                << "\n" << dev_message;
 

Modified: trunk/src/wml_exception.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/wml_exception.hpp?rev=44988&r1=44987&r2=44988&view=diff
==============================================================================
--- trunk/src/wml_exception.hpp (original)
+++ trunk/src/wml_exception.hpp Sat Jul 31 12:52:26 2010
@@ -21,8 +21,7 @@
 #ifndef WML_EXCEPTION_HPP_INCLUDED
 #define WML_EXCEPTION_HPP_INCLUDED
 
-#include <exception>
-#include <string>
+#include "exceptions.hpp"
 
 class display;
 
@@ -59,17 +58,12 @@
        int line, const char *function, const std::string &message);
 
 /** Helper class, don't construct this directly. */
-struct twml_exception: std::exception
+struct twml_exception: game::error
 {
        twml_exception(const std::string &user_msg, const std::string 
&dev_msg)
-               : user_message(user_msg), dev_message(dev_msg) {}
+               : game::error(user_msg), dev_message(dev_msg) {}
+
        ~twml_exception() throw() {}
-
-       /**
-        *  The message for the user explaining what went wrong. This message 
can
-        *  be translated so the user gets a explanation in his/her native 
tongue.
-        */
-       std::string user_message;
 
        /**
         *  The message for developers telling which problem was triggered, 
this
@@ -83,9 +77,6 @@
         *  @param disp         The display object to show the message on.
         */
        void show(display &disp);
-
-       const char *what() const throw()
-       { return user_message.c_str(); }
 };
 
 /**




Related Messages


Powered by MHonArc, Updated Sat Jul 31 13:20:16 2010