Author: sapient
Date: Tue Jun 10 10:51:23 2008
New Revision: 27080

URL: http://svn.gna.org/viewcvs/wesnoth?rev=27080&view=rev
Log:
-a real fix for [insert_tag] infinite recursion (for example, inside spawned 
events.)
-attempt to fix the unit_map problem with duplicate ID's (but apparently not 
successful)

Modified:
    trunk/data/scenario-test.cfg
    trunk/src/unit_map.cpp
    trunk/src/variable.cpp
    trunk/src/variable.hpp

Modified: trunk/data/scenario-test.cfg
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/data/scenario-test.cfg?rev=27080&r1=27079&r2=27080&view=diff
==============================================================================
--- trunk/data/scenario-test.cfg (original)
+++ trunk/data/scenario-test.cfg Tue Jun 10 10:51:23 2008
@@ -994,7 +994,7 @@
   [/set_variable]
   [message]
    id=statue
-   message="dynamic " + {TYPE} + " event ${VAR}|!"
+   message="dynamic " + {TYPE} + " event $|{VAR}|!"
    [option]
     message="Continue!"
    [/option]

Modified: trunk/src/unit_map.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/unit_map.cpp?rev=27080&r1=27079&r2=27080&view=diff
==============================================================================
--- trunk/src/unit_map.cpp (original)
+++ trunk/src/unit_map.cpp Tue Jun 10 10:51:23 2008
@@ -46,7 +46,7 @@
        for (umap::const_iterator i = that.map_.begin(); i != that.map_.end(); 
i++) {
                if (i->second.first) {
                        add(i->second.second);
-               } 
+               }
        }
        return *this;
 }
@@ -69,27 +69,27 @@
 }
 
 unit_map::unit_iterator unit_map::unit_iterator::operator++() {
-       
-       assert(i_ != map_->map_.end());
-       
-       ++i_;
-       while (i_ != map_->map_.end() && !valid()) { 
-               ++i_; 
-       }
-       
+
+       assert(i_ != map_->map_.end());
+
+       ++i_;
+       while (i_ != map_->map_.end() && !valid()) {
+               ++i_;
+       }
+
        return *this;
 }
-       
+
 unit_map::unit_iterator unit_map::unit_iterator::operator++(int){
-       
-       assert(i_ != map_->map_.end());
-       
+
+       assert(i_ != map_->map_.end());
+
        umap::iterator iter(i_);
        ++i_;
-       while (i_ != map_->map_.end() && !valid()) { 
-               ++i_; 
-       }
-       
+       while (i_ != map_->map_.end() && !valid()) {
+               ++i_;
+       }
+
        return unit_iterator(iter, map_);
 }
 
@@ -107,46 +107,46 @@
 }
 
 unit_map::const_unit_iterator unit_map::const_unit_iterator::operator++() {
-       
-       assert(i_ != map_->map_.end());
-       
-       ++i_;
-       while (i_ != map_->map_.end() && !valid()) { 
-               ++i_; 
-       }
-       
+
+       assert(i_ != map_->map_.end());
+
+       ++i_;
+       while (i_ != map_->map_.end() && !valid()) {
+               ++i_;
+       }
+
        return *this;
 }
 
 unit_map::const_unit_iterator unit_map::const_unit_iterator::operator--() {
-       
+
        umap::const_iterator begin = map_->begin().i_;
-       
+
        assert(i_ != begin);
-       
-       --i_;   
-       while (i_ != begin && !valid()) { 
-               --i_; 
-       }
-       
+
+       --i_;
+       while (i_ != begin && !valid()) {
+               --i_;
+       }
+
        return *this;
 }
-       
+
 unit_map::const_unit_iterator unit_map::const_unit_iterator::operator++(int){
-       
-       assert(i_ != map_->map_.end());
-       
+
+       assert(i_ != map_->map_.end());
+
        umap::const_iterator iter(i_);
        ++i_;
-       while (i_ != map_->map_.end() && !valid()) { 
-               ++i_; 
-       }
-       
+       while (i_ != map_->map_.end() && !valid()) {
+               ++i_;
+       }
+
        return const_unit_iterator(iter, map_);
 }
 
-unit_map::unit_xy_iterator::unit_xy_iterator(const unit_iterator &i) : 
counter(i.map_), i_(i.i_), map_(i.map_) { 
-       if (i.valid()) loc_ = i->first; 
+unit_map::unit_xy_iterator::unit_xy_iterator(const unit_iterator &i) : 
counter(i.map_), i_(i.i_), map_(i.map_) {
+       if (i.valid()) loc_ = i->first;
 }
 
 
@@ -163,49 +163,49 @@
 }
 
 unit_map::unit_xy_iterator unit_map::unit_xy_iterator::operator++() {
-       
-       assert(i_ != map_->map_.end());
-       
-       ++i_;   
-       while (i_ != map_->map_.end() && !valid()) { 
-               ++i_; 
-       }
-       
+
+       assert(i_ != map_->map_.end());
+
+       ++i_;
+       while (i_ != map_->map_.end() && !valid()) {
+               ++i_;
+       }
+
        if (i_ != map_->map_.end()) {
                loc_ = i_->second.second->first;
        }
-       
+
        return *this;
 }
-       
+
 unit_map::unit_xy_iterator unit_map::unit_xy_iterator::operator++(int){
-       
-       assert(i_ != map_->map_.end());
-       
+
+       assert(i_ != map_->map_.end());
+
        umap::iterator iter(i_);
        gamemap::location pre_loc = loc_;
        ++i_;
-       while (i_ != map_->map_.end() && !valid()) { 
-               ++i_; 
-       }
-       
+       while (i_ != map_->map_.end() && !valid()) {
+               ++i_;
+       }
+
        if (i_ != map_->map_.end()) {
                loc_ = i_->second.second->first;
        }
-       
+
        return unit_xy_iterator(iter, map_, pre_loc);
 }
 
-bool unit_map::unit_xy_iterator::valid() const { 
-       return i_ != map_->map_.end() && i_->second.first && loc_ == 
i_->second.second->first; 
-}
-
-unit_map::const_unit_xy_iterator::const_unit_xy_iterator(const unit_iterator 
&i) : counter(i.map_), i_(i.i_), map_(i.map_) { 
-       if (i.valid()) loc_ = i->first; 
-}
-
-unit_map::const_unit_xy_iterator::const_unit_xy_iterator(const 
const_unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_)  { 
-       if (i.valid()) loc_ = i->first; 
+bool unit_map::unit_xy_iterator::valid() const {
+       return i_ != map_->map_.end() && i_->second.first && loc_ == 
i_->second.second->first;
+}
+
+unit_map::const_unit_xy_iterator::const_unit_xy_iterator(const unit_iterator 
&i) : counter(i.map_), i_(i.i_), map_(i.map_) {
+       if (i.valid()) loc_ = i->first;
+}
+
+unit_map::const_unit_xy_iterator::const_unit_xy_iterator(const 
const_unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_)  {
+       if (i.valid()) loc_ = i->first;
 }
 
 const std::pair<gamemap::location,unit>* 
unit_map::const_unit_xy_iterator::operator->() const {
@@ -219,54 +219,54 @@
 }
 
 unit_map::const_unit_xy_iterator 
unit_map::const_unit_xy_iterator::operator++() {
-       
-       assert(i_ != map_->map_.end());
-       
-       ++i_;
-       while (i_ != map_->map_.end() && !valid()) { 
-               ++i_; 
-       }
-       
+
+       assert(i_ != map_->map_.end());
+
+       ++i_;
+       while (i_ != map_->map_.end() && !valid()) {
+               ++i_;
+       }
+
        if (i_ != map_->map_.end()) {
                loc_ = i_->second.second->first;
        }
-       
+
        return *this;
 }
-       
+
 unit_map::const_unit_xy_iterator 
unit_map::const_unit_xy_iterator::operator++(int){
-       
-       assert(i_ != map_->map_.end());
-       
+
+       assert(i_ != map_->map_.end());
+
        gamemap::location pre_loc = loc_;
-       
-       umap::const_iterator iter(i_);  
-       ++i_;
-       while (i_ != map_->map_.end() && !valid()) { 
-               ++i_; 
-       }
-       
+
+       umap::const_iterator iter(i_);
+       ++i_;
+       while (i_ != map_->map_.end() && !valid()) {
+               ++i_;
+       }
+
        if (i_ != map_->map_.end()) {
                loc_ = i_->second.second->first;
        }
-       
+
        return const_unit_xy_iterator(iter, map_, pre_loc);
 }
 
-bool unit_map::const_unit_xy_iterator::valid() const { 
-       return i_ != map_->map_.end() && i_->second.first && loc_ == 
i_->second.second->first; 
+bool unit_map::const_unit_xy_iterator::valid() const {
+       return i_ != map_->map_.end() && i_->second.first && loc_ == 
i_->second.second->first;
 }
 
 
 unit_map::xy_accessor::xy_accessor(const unit_iterator &i) : counter(i.map_), 
i_(i.i_), map_(i.map_) {
-       if (i.valid()) loc_ = i->first; 
+       if (i.valid()) loc_ = i->first;
 }
 
 unit_map::xy_accessor::xy_accessor(const unit_xy_iterator &i) : 
counter(i.map_), i_(i.i_), map_(i.map_) {
-       if (i.valid()) loc_ = i->first; 
-}
-       
-               
+       if (i.valid()) loc_ = i->first;
+}
+
+
 std::pair<gamemap::location,unit>* unit_map::xy_accessor::operator->() {
        if (!valid()) { assert(0); }
        return i_->second.second;
@@ -276,40 +276,40 @@
        if (!valid()) { assert(0); }
        return *i_->second.second;
 }
-               
-               
+
+
 bool unit_map::xy_accessor::valid() {
        if (i_->second.first && i_->second.second->first == loc_) {
                return true;
        }
-       
+
        unit_iterator u_iter = map_->find(loc_);
-       
+
        if (u_iter.valid()) {
                i_ = u_iter.i_;
                loc_ = i_->second.second->first;
                return true;
        }
-       
-       return false;   
+
+       return false;
 }
 
 unit_map::const_xy_accessor::const_xy_accessor(const const_unit_iterator &i) : 
counter(i.map_), i_(i.i_), map_(i.map_) {
-       if (i.valid()) loc_ = i->first; 
+       if (i.valid()) loc_ = i->first;
 }
 
 unit_map::const_xy_accessor::const_xy_accessor(const unit_iterator &i) : 
counter(i.map_), i_(i.i_), map_(i.map_) {
-       if (i.valid()) loc_ = i->first; 
+       if (i.valid()) loc_ = i->first;
 }
 
 unit_map::const_xy_accessor::const_xy_accessor(const const_unit_xy_iterator 
&i) : counter(i.map_), i_(i.i_), map_(i.map_) {
-       if (i.valid()) loc_ = i->first; 
+       if (i.valid()) loc_ = i->first;
 }
 
 unit_map::const_xy_accessor::const_xy_accessor(const unit_xy_iterator &i) : 
counter(i.map_), i_(i.i_), map_(i.map_) {
-       if (i.valid()) loc_ = i->first; 
-}      
-               
+       if (i.valid()) loc_ = i->first;
+}
+
 const std::pair<gamemap::location,unit>* 
unit_map::const_xy_accessor::operator->() {
        if (!valid()) { assert(0); }
        return i_->second.second;
@@ -319,22 +319,22 @@
        if (!valid()) { assert(0); }
        return *i_->second.second;
 }
-               
-               
+
+
 bool unit_map::const_xy_accessor::valid() {
        if (i_->second.first && i_->second.second->first == loc_) {
                return true;
        }
-       
+
        const_unit_iterator u_iter = map_->find(loc_);
-       
+
        if (u_iter.valid()) {
                i_ = u_iter.i_;
                loc_ = i_->second.second->first;
                return true;
        }
-       
-       return false;   
+
+       return false;
 }
 
 
@@ -343,7 +343,7 @@
        if (i == lmap_.end()) {
                return unit_iterator(map_.end(), this);
        }
- 
+
        umap::iterator iter = map_.find(i->second);
 
        assert(iter->second.first);
@@ -356,9 +356,9 @@
        if (iter == lmap_.end()) {
                return const_unit_iterator(map_.end(), this);
        }
-       
+
        umap::const_iterator i = map_.find(iter->second);
-       
+
        assert(i->second.first);
        return const_unit_iterator(i , this);
 }
@@ -368,27 +368,27 @@
        if (iter == map_.end() || !iter->second.first) {
                return unit_iterator(map_.end(), this);
        }
-       return unit_iterator(iter, this);       
+       return unit_iterator(iter, this);
 }
 
 unit_map::const_unit_iterator unit_map::find(const std::string &id) const {
        umap::const_iterator iter = map_.find(id);
        if (iter == map_.end() || !iter->second.first) {
                return const_unit_iterator(map_.end(), this);
-       }               
-       return const_unit_iterator(iter, this); 
-}
-
-unit_map::unit_iterator unit_map::begin() {            
+       }
+       return const_unit_iterator(iter, this);
+}
+
+unit_map::unit_iterator unit_map::begin() {
                // clean if there are more invalid than valid, this block just 
needs to go somewhere that is likely to be
                // called when num_iters_ == 0. This seems as good a place as 
any.
                if (num_invalid_ > lmap_.size() && num_iters_ == 0) {
                        clean_invalid();
                }
-               
+
                umap::iterator i = map_.begin();
-               while (i != map_.end() && !i->second.first) { 
-                       ++i; 
+               while (i != map_.end() && !i->second.first) {
+                       ++i;
                }
                return unit_iterator(i, this);
 }
@@ -401,22 +401,22 @@
 
        if (iter == map_.end()) {
                map_[unit_id] = std::pair<bool, std::pair<gamemap::location, 
unit>*>(true, p);
-       } else {        
+       } else if(!iter->second.first) {
+               iter->second.second = p;
+               validate(iter);
+       } else if(iter->second.second->first == p->first) {
+               replace(p);
+               return;
+       } else {
                // if iter->second.first, then this is a duplicate 
underlying_id, or the map is already in an undefined
                // state due to a different duplicate id entry. This is not 
allowed. By storing it with a different id it
                // will not be accessible with find(std::string).
-               if (iter->second.first) {
-                       std::stringstream id;
-                       id << unit_id << "-duplicate-" << get_random();
-                       unit_id = id.str();
-                       
-                       map_[unit_id] = std::pair<bool, 
std::pair<gamemap::location, unit>*>(true, p);
-                       WRN_NG << "unit_map::add -- duplicate id in unit map: " 
<< p->second.underlying_id() << "\n";
-               } else {
-                       iter->second.second = p;
-                       validate(iter);
-               }
-       
+               std::stringstream id;
+               id << unit_id << "-duplicate-" << get_random();
+               unit_id = id.str();
+
+               map_[unit_id] = std::pair<bool, std::pair<gamemap::location, 
unit>*>(true, p);
+               WRN_NG << "unit_map::add -- duplicate id in unit map: " << 
p->second.underlying_id() << "\n";
        }
 
        std::pair<lmap::iterator,bool> res = 
lmap_.insert(std::pair<gamemap::location,std::string>(p->first, unit_id));
@@ -435,7 +435,7 @@
        for (umap::iterator i = map_.begin(); i != map_.end(); ++i) {
                if (i->second.first) delete(i->second.second);
        }
-               
+
        lmap_.clear();
        map_.clear();
 }
@@ -447,11 +447,11 @@
                return NULL;
 
        umap::iterator iter = map_.find(i->second);
-       std::pair<gamemap::location,unit> *res = iter->second.second;   
-       
+       std::pair<gamemap::location,unit> *res = iter->second.second;
+
        invalidate(iter);
-       lmap_.erase(i); 
-       
+       lmap_.erase(i);
+
        return res;
 }
 
@@ -460,21 +460,21 @@
        lmap::iterator i = lmap_.find(loc);
        if (i == lmap_.end())
                return 0;
-                       
+
        umap::iterator iter = map_.find(i->second);
 
        invalidate(iter);
-       
+
        delete iter->second.second;
        lmap_.erase(i);
-       
+
        return 1;
 }
 
 void unit_map::erase(xy_accessor pos)
 {
        assert(pos.valid());
-       
+
        if (erase(pos->first) != 1)
                assert(0);
 }
@@ -486,7 +486,7 @@
 
 void unit_map::clean_invalid() {
        size_t num_cleaned = 0;
-       
+
        umap::iterator iter;
        for (iter = map_.begin(); iter != map_.end(); ++iter) {
                if (!iter->second.first) {
@@ -494,9 +494,9 @@
                        num_cleaned++;
                }
        }
-       
+
        num_invalid_ -= num_cleaned;
-       
+
        LOG_NG << "unit_map::clean_invalid - removed " << num_cleaned << " 
invalid map entries.\n";
 }
-                       
+

Modified: trunk/src/variable.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/variable.cpp?rev=27080&r1=27079&r2=27080&view=diff
==============================================================================
--- trunk/src/variable.cpp (original)
+++ trunk/src/variable.cpp Tue Jun 10 10:51:23 2008
@@ -33,11 +33,14 @@
 
 namespace
 {
-       /** 
+       /**
         * @todo FIXME: the variable repository should be
         * a class of variable.hpp, and not the game_state.
         */
        game_state* repos = NULL;
+
+       // keeps track of insert_tag variables used by get_parsed_config
+       std::set<std::string> vconfig_recursion;
 
        // map to track temp storage of inserted tags on the heap
        std::map<config const *, int> config_cache;
@@ -212,27 +215,35 @@
                        vconfig insert_cfg(child->second);
                        const t_string& name = insert_cfg["name"];
                        const t_string& vname = insert_cfg["variable"];
-                       if(!recursion_.insert(vname).second) {
-                               ERR_NG << "vconfig::get_parsed_config() 
infinite recursion detected, aborting"
-                                       << std::endl;
-                               res.add_child("insert_tag", 
insert_cfg.get_config());
-                               return res;
-                       }
-                       variable_info vinfo(vname, false, 
variable_info::TYPE_CONTAINER);
-                       if(!vinfo.is_valid) {
-                               res.add_child(name); //add empty tag
-                       } else if(vinfo.explicit_index) {
-                               res.add_child(name, 
vconfig(&(vinfo.as_container())).get_parsed_config());
-                       } else {
-                               variable_info::array_range range = 
vinfo.as_array();
-                               if(range.first == range.second) {
+                       if(!vconfig_recursion.insert(vname).second) {
+                               throw 
recursion_error("vconfig::get_parsed_config() infinite recursion detected, 
aborting");
+                       }
+                       try {
+                               variable_info vinfo(vname, false, 
variable_info::TYPE_CONTAINER);
+                               if(!vinfo.is_valid) {
                                        res.add_child(name); //add empty tag
+                               } else if(vinfo.explicit_index) {
+                                       res.add_child(name, 
vconfig(&(vinfo.as_container())).get_parsed_config());
+                               } else {
+                                       variable_info::array_range range = 
vinfo.as_array();
+                                       if(range.first == range.second) {
+                                               res.add_child(name); //add 
empty tag
+                                       }
+                                       while(range.first != range.second) {
+                                               res.add_child(name, 
vconfig(*range.first++).get_parsed_config());
+                                       }
                                }
-                               while(range.first != range.second) {
-                                       res.add_child(name, 
vconfig(*range.first++).get_parsed_config());
+                               vconfig_recursion.erase(vname);
+                       } catch(recursion_error &err) {
+                               vconfig_recursion.erase(vname);
+                               WRN_NG << err.message << std::endl;
+                               if(vconfig_recursion.empty()) {
+                                       res.add_child("insert_tag", 
insert_cfg.get_config());
+                               } else {
+                                       // throw to the top [insert_tag] which 
started the recursion
+                                       throw err;
                                }
                        }
-                       recursion_.erase(vname);
                } else {
                        res.add_child(child_key, 
vconfig((*child).second).get_parsed_config());
                }

Modified: trunk/src/variable.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/variable.hpp?rev=27080&r1=27079&r2=27080&view=diff
==============================================================================
--- trunk/src/variable.hpp (original)
+++ trunk/src/variable.hpp Tue Jun 10 10:51:23 2008
@@ -85,6 +85,10 @@
                unsigned index_offset_;
        };
 
+       struct recursion_error : public config::error {
+               recursion_error(const std::string& msg) : error(msg) {}
+       };
+
        /** In-order iteration over all children. */
        all_children_iterator ordered_begin() const;
        all_children_iterator ordered_end() const;
@@ -92,7 +96,6 @@
 private:
        const config* cfg_;
        const config* cache_key_;
-       mutable std::set<std::string> recursion_;
 };
 
 namespace variable


_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits

Reply via email to