| /* ************************************************************** |
| * |
| * bs_ActorClass.cpp |
| * |
| * (C) 1998 Protos Logistik Software GmbH |
| * |
| * The actor class implementation. |
| * |
| * 980826 kb created |
| * |
| *************************************************************** */ |
| |
| #ifdef CHECK_MEM |
| #define WITHOUT_MFCXLib |
| #include "../stdafx.h" |
| #else |
| #define TRACE (void)0 |
| #endif |
| |
| /* ************************************************************* */ |
| |
| // switch off compiler warning: reduced identifier length in debug information |
| #pragma warning(disable : 4786) |
| |
| // *************************************************************** |
| |
| #ifdef _DEBUG |
| #define DEBUG_MAKE_CONSISTENT |
| #endif |
| |
| // *************************************************************** |
| |
| #include <assert.h> |
| |
| #include <ostream> |
| #include <istream> |
| #include <algorithm> |
| #include <limits> |
| using namespace std; |
| |
| |
| #include "bs_ActorClass.h" |
| #include "bs_ActorVisitor.h" |
| #include "bs_StateMachine.h" |
| #include "bs_DataClassObj.h" |
| #include "bs_MemberVisitor.h" |
| #include "bs_ClassVisitor.h" |
| #include "bs_ParallelMdlVisitor.h" |
| #include "bs_GraphSort.h" |
| #include "../bsRoomBase/bs_ErrorHdlr.h" |
| #include "bs_MdlLocation.h" |
| #include "bsFormal/bs_AuxGraph.h" |
| |
| /* ************************************************************* */ |
| |
| #ifdef CHECK_MEM |
| #define new DEBUG_NEW |
| #undef THIS_FILE |
| static char THIS_FILE[] = __FILE__; |
| #endif |
| |
| /* ************************************************************* */ |
| |
| #include "../bsRoomBase/bs_RoomList.cpp" |
| |
| /* ************************************************************* */ |
| |
| // explicit instantiation |
| template class bs_RoomList<bs_ActorClass>; |
| |
| // *************************************************************** |
| |
| // helper class for creating duplicates of actor interface and structure PortRefLists |
| class pr_entry |
| { |
| public: |
| typedef enum |
| { |
| none, |
| iface, |
| structure, |
| common |
| } |
| Owner; |
| |
| pr_entry (void) |
| : _port_ref(NULL), _owner(none), _if_id(-1), _st_id(-1) |
| {} |
| |
| pr_entry (bs_PortRefPtr p, Owner o, int i, int s) |
| : _port_ref(p), _owner(o), _if_id(i), _st_id(s) |
| {} |
| |
| // data |
| bs_PortRefPtr _port_ref; |
| Owner _owner; |
| int _if_id; |
| int _st_id; |
| }; |
| |
| // default: compare interface id |
| bool operator< (const pr_entry& e0, const pr_entry& e1) |
| { |
| return e0._if_id < e1._if_id; |
| } |
| |
| bool operator== (const pr_entry& e0, const pr_entry& e1) |
| { |
| return e0._if_id == e1._if_id; |
| } |
| |
| // special compare: structure id |
| class st_cmp |
| { |
| public: |
| bool operator() (const pr_entry& e0, const pr_entry& e1) |
| { |
| return e0._st_id < e1._st_id; |
| } |
| }; |
| |
| // *************************************************************** |
| |
| /**# implementation bs_ActorClass:: id(C_0902130146) |
| */ |
| |
| // *************************************************************** |
| |
| DEFINE_STREAMABLE(bs_ActorClass,"bs_ModelClass") |
| |
| bs_ActorClass::bs_ActorClass (void) : |
| bs_ModelClass(), |
| _check_bindings(false), |
| _enable_debug_macros(true), |
| _override_enable_debug(false), |
| _allow_override(false), |
| _abstract_class(false), |
| _generated_ids_valid(true) |
| { |
| } |
| |
| bs_ActorClass::bs_ActorClass (const bs_ActorClass& orig, CopyType t) |
| : bs_ModelClass(orig), |
| bs_Cloner<bs_ActorClass>(orig), |
| _interface(orig._interface, t), |
| _structure(orig._structure, t), |
| _behaviour(orig._behaviour, t), |
| _memberfct(orig._memberfct, t), |
| _base_class(GetAppropriatePtr(orig._base_class, t)), |
| _check_bindings(false), |
| _enable_debug_macros(orig._enable_debug_macros), |
| _override_enable_debug(orig._override_enable_debug), |
| _allow_override(orig._allow_override), |
| _perso_version(orig._perso_version), |
| _abstract_class(orig._abstract_class), |
| _generated_ids_valid(orig._generated_ids_valid) |
| { |
| } |
| |
| bs_ActorClass::~bs_ActorClass (void) |
| { |
| } |
| |
| |
| bs_ActorClass::bs_ActorClass (bs_RoomName name) |
| : bs_ModelClass(name), |
| _check_bindings(false), |
| _enable_debug_macros(true), |
| _override_enable_debug(false), |
| _allow_override(false), |
| _abstract_class(false) |
| { |
| CommonConstruct(); |
| } |
| |
| |
| bs_ActorClass::bs_ActorClass (int version, istream& is, bs_ProtocolClassList& pcl, bs_ActorClassList& acl) |
| : bs_ModelClass(), |
| _check_bindings(false), |
| _enable_debug_macros(true), |
| _override_enable_debug(false), |
| _allow_override(false), |
| _abstract_class(false) |
| { |
| ReadStream(version, is, pcl, acl); |
| |
| CommonConstruct(); |
| } |
| |
| |
| void bs_ActorClass::CommonConstruct (void) |
| { |
| // join the namespaces of all lists that produce members in the generated class |
| _interface.GetPortRefList().JoinNamespace(_structure.GetPortRefList()); |
| _interface.GetPortRefList().JoinNamespace(_structure.GetSAPs()); |
| _interface.GetPortRefList().JoinNamespace(_behaviour.GetStateMachine()->GetStateVariables()); |
| } |
| |
| |
| // *************************************************************** |
| |
| void bs_ActorClass::Dump (bs_TMSContext& tmsc) |
| { |
| tmsc.TMS() << "actor class " << GetName(); |
| if (_base_class) |
| tmsc.TMS() << "derived from " << _base_class->GetName(); |
| |
| tmsc.TMS() << " {\n"; |
| tmsc.Indent(); |
| |
| tmsc.TMS() << "interface: {\n"; |
| tmsc.Indent(); |
| _interface.GetPortRefList().Dump(tmsc); |
| tmsc.Unindent(); |
| tmsc.TMS() << "}\n"; |
| |
| tmsc.TMS() << "structure: {\n"; |
| tmsc.Indent(); |
| tmsc.TMS() << "end ports: {\n"; |
| tmsc.Indent(); |
| _structure.GetPortRefList().Dump(tmsc); |
| tmsc.Unindent(); |
| tmsc.TMS() << "}\n"; |
| |
| tmsc.TMS() << "saps: {\n"; |
| tmsc.Indent(); |
| _structure.GetSAPs().Dump(tmsc); |
| tmsc.Unindent(); |
| tmsc.TMS() << "}\n"; |
| |
| tmsc.TMS() << "components: {\n"; |
| tmsc.Indent(); |
| _structure.GetActorRefList().Dump(tmsc); |
| _structure.GetPrtvRefList().Dump(tmsc); |
| tmsc.Unindent(); |
| tmsc.TMS() << "}\n"; |
| |
| tmsc.TMS() << "bindings: {\n"; |
| tmsc.Indent(); |
| _structure.GetBindingContractList().Dump(tmsc); |
| tmsc.Unindent(); |
| tmsc.TMS() << "}\n"; |
| tmsc.Unindent(); |
| tmsc.TMS() << "}\n"; |
| |
| tmsc.TMS() << "behaviour: {\n"; |
| tmsc.Indent(); |
| _behaviour.Dump(tmsc); |
| tmsc.Unindent(); |
| tmsc.TMS() << "}\n"; |
| |
| tmsc.Unindent(); |
| tmsc.TMS() << "};\n"; |
| } |
| |
| void bs_ActorClass::Docu (bs_DocuContext& dc) |
| { |
| if (_base_class) |
| { |
| dc.Docu("derived from" + _base_class->GetName()); |
| dc.Newline(); |
| if (_allow_override) |
| dc.Docu("(allows overrides)"); |
| else |
| dc.Docu("(prohibits overrides)"); |
| dc.Newline(); |
| dc.Newline(); |
| } |
| |
| dc.BeginSection("Interface"); |
| _interface.GetPortRefList().Docu(dc); |
| dc.EndSection(); |
| |
| dc.BeginSection("Structure"); |
| dc.Picture(*this, GetName()+"_structure", "Structure of actor class "+GetName()); |
| _structure.Docu(dc); |
| dc.EndSection(); |
| |
| dc.BeginSection("Behaviour"); |
| dc.Picture(_behaviour, *this, GetName()+"_behaviour", "Hierarchical state machine of actor class "+GetName()); |
| _behaviour.GetStateMachine()->Docu(dc); |
| dc.EndSection(); |
| } |
| |
| |
| // *************************************************************** |
| |
| // bs_StreamObj touch interface |
| |
| bool bs_ActorClass::IsComponentTouched (void) const |
| { |
| if (_interface.IsTouched()) return true; |
| if (_structure.IsTouched()) return true; |
| if (_behaviour.IsTouched()) return true; |
| if (_memberfct.IsTouched()) return true; |
| return false; |
| } |
| |
| time_t bs_ActorClass::GetLastTouchTime (void) const |
| { |
| time_t touched = bs_TouchableObject::GetLastTouchTime(); |
| touched = GetMaxTouchTime(_interface.GetLastTouchTime(), touched); |
| touched = GetMaxTouchTime(_structure.GetLastTouchTime(), touched); |
| touched = GetMaxTouchTime(_behaviour.GetLastTouchTime(), touched); |
| touched = GetMaxTouchTime(_memberfct.GetLastTouchTime(), touched); |
| |
| return touched; |
| } |
| |
| /* ************************************************************* */ |
| |
| // bs_ActorVisitor interface |
| void bs_ActorClass::Accept (bs_ActorClassPtr myself, bs_ActorVisitor& visitor) |
| { |
| visitor.VisitActorClass(myself); |
| |
| bs_ActorRefList& arefs = _structure.GetActorRefList(); |
| bs_ActorRefIterator aref; |
| for(aref=arefs.begin(); aref!=arefs.end(); aref++) |
| { |
| (*aref)->Accept(*aref, visitor); |
| } |
| |
| bs_PrtvRefList& prefs = _structure.GetPrtvRefList(); |
| bs_PrtvRefIterator pref; |
| for(pref=prefs.begin(); pref!=prefs.end(); pref++) |
| { |
| (*pref)->Accept(*pref, visitor); |
| } |
| |
| visitor.VisitActorClassEnd(myself); |
| } |
| |
| /* ************************************************************* */ |
| |
| void bs_ActorClass::Accept (bs_ActorClassPtr myself, bs_MemberVisitor& visitor) |
| { |
| visitor.Visit(myself); |
| |
| // base class |
| if (_base_class) |
| _base_class->Accept(_base_class, visitor); |
| |
| // component actors |
| { |
| bs_ActorRefList& comp = _structure.GetActorRefList(); |
| for (bs_ActorRefIterator c=comp.begin(); c!=comp.end(); c++) |
| { |
| bs_ActorClassPtr ac = (*c)->GetActorClass(); |
| ac->Accept(ac,visitor); |
| } |
| } |
| |
| // component primitives |
| { |
| bs_PrtvRefList& comp = _structure.GetPrtvRefList(); |
| for (bs_PrtvRefIterator c=comp.begin(); c!=comp.end(); c++) |
| { |
| bs_PrtvClassPtr pc = (*c)->GetPrtvClass(); |
| pc->Accept(pc,visitor); |
| } |
| } |
| |
| // SAPClasses |
| { |
| bs_SAPRefList& saps = _structure.GetSAPs(); |
| for (bs_SAPRefIterator c=saps.begin(); c!=saps.end(); c++) |
| { |
| bs_SAPClassPtr sc = (*c)->GetSAPClass(); |
| sc->Accept(sc,visitor); |
| } |
| } |
| |
| // Protocols of PortRefs |
| { |
| bs_PortRefList& comp = _interface.GetPortRefList(); |
| bs_PortRefIterator c; |
| for (c=comp.begin(); c!=comp.end(); ++c) |
| { |
| bs_ProtocolClassPtr pc = (*c)->GetProtocolClass(); |
| pc->Accept(pc,visitor); |
| } |
| } |
| { |
| bs_PortRefList& comp = _structure.GetPortRefList(); |
| bs_PortRefIterator c; |
| for (c=comp.begin(); c!=comp.end(); ++c) |
| { |
| bs_ProtocolClassPtr pc = (*c)->GetProtocolClass(); |
| pc->Accept(pc,visitor); |
| } |
| } |
| |
| // DataMembers |
| { |
| bs_DataMemberList& dml = _behaviour.GetStateMachine()->GetStateVariables(); |
| for (bs_DataMemberIterator c=dml.begin(); c!=dml.end(); ++c) |
| { |
| (*c)->Accept(*c,visitor); |
| } |
| } |
| } |
| |
| /* ************************************************************* */ |
| |
| void bs_ActorClass::Accept (bs_ActorClassPtr myself, bs_ClassVisitor& visitor) |
| { |
| visitor.Visit(myself); |
| } |
| |
| /* ************************************************************* */ |
| |
| void bs_ActorClass::Accept (bs_ActorClassPtr ac1, bs_ActorClassPtr ac2, bs_ParallelMdlVisitor& visitor) |
| { |
| if (ac1) |
| visitor.PushPath(ac1->GetName()); |
| else |
| visitor.PushPath(ac2->GetName()); |
| |
| bool descend = visitor.Visit(ac1, ac2); |
| |
| if (!descend || ac1==NULL || ac2==NULL) |
| { |
| visitor.PopPath(); |
| return; |
| } |
| |
| bs_ActorInterface::Accept(ac1->_interface, ac2->_interface, visitor); |
| bs_ActorStructure::Accept(ac1->_structure, ac2->_structure, visitor); |
| bs_ActorBehaviour::Accept(ac1->_behaviour, ac2->_behaviour, visitor); |
| bs_ActorMemberFct::Accept(ac1->_memberfct, ac2->_memberfct, visitor); |
| |
| visitor.PopPath(); |
| } |
| |
| /* ************************************************************* */ |
| |
| void bs_ActorClass::Handle (bs_InvalidateGeneratedIDsEvent& evt) |
| { |
| if (&*evt.GetActorClass()==this) |
| _generated_ids_valid = false; |
| } |
| |
| void bs_ActorClass::Handle (bs_CmdExecutedEvent& evt) |
| { |
| if (!_generated_ids_valid) |
| { |
| //TRACE("bs_ActorClass[%s]::Handle (bs_CmdExecutedEvent& evt) - setting generated IDs\n", GetName().c_str()); |
| _behaviour.GetStateMachine()->SetGeneratedIds(); |
| _generated_ids_valid = true; |
| } |
| } |
| |
| /* ************************************************************* */ |
| |
| void bs_ActorClass::GetBaseClasses (vector<bs_ActorClassPtr>& bcl) const |
| { |
| if (!_base_class) |
| return; |
| |
| // add direct base class |
| bcl.push_back(_base_class); |
| |
| // recurse |
| _base_class->GetBaseClasses(bcl); |
| } |
| |
| bool bs_ActorClass::ContainsInstanceOf (bs_ActorClassPtr actor) |
| { |
| // check references to component actors |
| bs_ActorRefList& comp = _structure.GetActorRefList(); |
| bs_ActorRefIterator c; |
| for(c=comp.begin(); c!=comp.end(); c++) |
| { |
| bs_ActorClassPtr refd = (*c)->GetActorClass(); |
| |
| // direct reference |
| if (refd==actor) |
| return true; |
| |
| // or recursive reference |
| if (refd->ContainsInstanceOf(actor)) |
| return true; |
| } |
| |
| // no reference |
| return false; |
| } |
| |
| bool bs_ActorClass::IsDerivedFrom (bs_ActorClassPtr base_class) |
| { |
| if (!_base_class) |
| return false; |
| |
| // direct base class |
| if (_base_class==base_class) |
| return true; |
| |
| // or recursive base class |
| if (_base_class->IsDerivedFrom(base_class)) |
| return true; |
| |
| return false; |
| } |
| |
| bool bs_ActorClass::IsDerivedFrom (bs_RoomName base_class) |
| { |
| if (!_base_class) |
| return false; |
| |
| // direct base class |
| if (_base_class->GetName()==base_class) |
| return true; |
| |
| // or recursive base class |
| if (_base_class->IsDerivedFrom(base_class)) |
| return true; |
| |
| return false; |
| } |
| |
| |
| bool bs_ActorClass::IsUsingActorClass (bs_ActorClassPtr ac) |
| { |
| if (!ac) |
| return false; |
| |
| const bs_RoomName& ac_name = ac->GetName(); |
| |
| if (IsDerivedFrom(ac_name)) |
| return true; |
| |
| bs_ActorRefList& arefs = GetStructure().GetActorRefList(); |
| for (bs_ActorRefIterator it=arefs.begin(); it!=arefs.end(); ++it) |
| { |
| if ((*it)->GetActorClass()->GetName()==ac_name) |
| return true; |
| |
| // start recursion |
| if ((*it)->GetActorClass()->IsUsingActorClass(ac)) |
| return true; |
| } |
| return false; |
| } |
| |
| static void AddInheritedStateVars (const bs_DataMemberList& base_dml, bs_DataMemberList& own_dml) |
| { |
| // reset owner flag for inherited items |
| for (bs_DataMemberList::const_iterator dmit=base_dml.begin(); dmit!=base_dml.end(); ++dmit) |
| { |
| own_dml.SetOwnerOf((*dmit)->GetName(), false); |
| } |
| } |
| |
| template<class T> |
| class AddItem |
| { |
| public: |
| virtual bool operator() (bs_RoomPtr<T> item) const { return true; } |
| }; |
| |
| template<class T> |
| class AddPortItem : public AddItem<T> |
| { |
| public: |
| AddPortItem (const bs_RoomList<T>& list) : _list(list) {} |
| |
| virtual bool operator() (bs_RoomPtr<T> item) const |
| { |
| // this is meant for structure ports |
| // they are not mandatory if the port already is in the interface |
| // i.e. an end port in the base class may be a relay port in the derived class |
| bool in_interface = !_list[item->GetName()].IsNull(); |
| if (in_interface) |
| { |
| #ifdef _DEBUG |
| TRACE("structure port %s is in the interface and will not be added to the derived structure\n", |
| item->GetName().c_str() |
| ); |
| #endif |
| } |
| return !in_interface; |
| } |
| |
| private: |
| const bs_RoomList<T>& _list; |
| }; |
| |
| template<class T> |
| static void AddInheritedItems ( |
| const string& ac_name, |
| const string& item_type, |
| const bs_RoomList<T>& base_list, |
| bs_RoomList<T>& own_list, |
| bool signal_errors, |
| const AddItem<T>& add_item |
| ) |
| { |
| // reset owner flag for inherited items |
| for (bs_RoomList<T>::const_iterator it=base_list.begin(); it!=base_list.end(); ++it) |
| { |
| // own_list is not owner, but should contain item with same name |
| bs_RoomPtr<T> own = own_list[(*it)->GetName()]; |
| if (own) |
| { |
| if (own!=*it) |
| { |
| // base and derived classes have items with same name, but there are |
| // two different objects. kill zombie object and discard changes in zombie. |
| (*it).TakeOverPtrsFrom(own); |
| |
| if (signal_errors) |
| { |
| bs_ErrorHdlr::Get()->Handle( |
| bs_ErrorHdlr::error, |
| "Actor class '" + ac_name + "' has inherited " + |
| item_type + " '"+ (*it)->GetName() +"',\n" |
| "which has been decoupled from its base class item!\n\n" + |
| "This has been repaired by Trice's consistency check.\n", |
| __FILE__, |
| __LINE__ |
| ); |
| } |
| } |
| } |
| else if (add_item(*it)) |
| { |
| // own_list doesn't contain inherited item |
| own_list.push_back(*it); |
| |
| if (signal_errors) |
| { |
| bs_ErrorHdlr::Get()->Handle( |
| bs_ErrorHdlr::error, |
| "Actor class '" + ac_name + "' has missing inherited " + |
| item_type + " '" + (*it)->GetName() +"'!\n\n" |
| "It is automatically added by Trice's consistency check.\n", |
| __FILE__, |
| __LINE__ |
| ); |
| } |
| else |
| { |
| string msg = "AddInheritedItems - added " + item_type + " '" + (*it)->GetName() +"'\n"; |
| TRACE(msg.c_str()); |
| } |
| } |
| |
| own_list.SetOwnerOf((*it)->GetName(), false); |
| } |
| } |
| |
| static void AddInheritedBehaviourNotes ( |
| const string& ac_name, |
| bs_StateContext& base_sc, |
| bs_StateContext& own_sc, |
| bool signal_errors |
| ) |
| { |
| bs_StateGraph& base_sg = base_sc.GetStateMachine()->GetStateGraph(); |
| bs_StateGraph& own_sg = own_sc.GetStateMachine()->GetStateGraph(); |
| |
| // handle items on this level |
| AddInheritedItems(ac_name, "note", base_sg.GetNotes(), own_sg.GetNotes(), signal_errors, AddItem<bs_Note>()); |
| |
| // handle sub-graphs recursively |
| bs_StateIterator sit; |
| for(sit=own_sg.GetStates().begin(); sit!=own_sg.GetStates().end(); sit++) |
| { |
| if (! ((*sit)->IsInherited() && (*sit)->HasStateMachine())) |
| continue; |
| |
| bs_StatePtr base_s = (*sit)->GetBaseClassState(); |
| if (base_s==NULL) |
| continue; |
| |
| if (base_sc.OneLevelDown(base_s)) |
| { |
| if (own_sc.OneLevelDown(*sit)) |
| { |
| AddInheritedBehaviourNotes(ac_name, base_sc, own_sc, signal_errors); |
| base_sc.OneLevelUp(); |
| } |
| own_sc.OneLevelUp(); |
| } |
| } |
| } |
| |
| static void AddInheritedStateVarsOld (const bs_DataMemberList& base_dml, bs_DataMemberList& own_dml) |
| { |
| // add derived |
| bs_DataMemberList tmp; |
| for (bs_DataMemberList::const_iterator dmit=base_dml.begin(); dmit!=base_dml.end(); ++dmit) |
| { |
| tmp.push_back(*dmit); |
| } |
| |
| // add own |
| for (dmit=own_dml.begin(); dmit!=own_dml.end(); ++dmit) |
| { |
| tmp.push_back(*dmit); |
| } |
| |
| // copy tmp |
| own_dml.clear(); |
| for (dmit=tmp.begin(); dmit!=tmp.end(); ++dmit) |
| { |
| own_dml.push_back(*dmit); |
| |
| if (base_dml[(*dmit)->GetName()]) |
| own_dml.SetOwnerOf((*dmit)->GetName(), false); |
| } |
| } |
| |
| template<class T> |
| static void AddInheritedItemsOld (const bs_RoomList<T>& base_list, bs_RoomList<T>& own_list) |
| { |
| // make a copy of the base list |
| bs_RoomList<T> tmp(base_list); |
| |
| // set inherited |
| for (bs_RoomList<T>::iterator it=tmp.begin(); it!=tmp.end(); ++it) |
| { |
| tmp.SetOwnerOf((*it)->GetName(), false); |
| } |
| |
| // add own |
| for (it=own_list.begin(); it!=own_list.end(); ++it) |
| { |
| tmp.push_back(*it); |
| } |
| |
| // copy back |
| own_list = tmp; |
| } |
| |
| void bs_ActorClass::AddInheritedAttributes (bool signal_errors) |
| { |
| if (!_base_class) |
| return; |
| |
| if (signal_errors) |
| { |
| bs_StateGraph& base_sg = _base_class->GetBehaviour().GetStateMachine()->GetStateGraph(); |
| _behaviour.GetStateMachine()->GetStateGraph().SetBaseClassPtrs(base_sg); |
| } |
| |
| // NB: we can assume that the direct base class already is complete |
| |
| if (_perso_version>=8) |
| { |
| // state variables |
| AddInheritedItems( |
| GetName(), "data member", |
| _base_class->GetBehaviour().GetStateMachine()->GetStateVariables(), |
| GetBehaviour().GetStateMachine()->GetStateVariables(), |
| signal_errors, |
| AddItem<bs_DataMember>() |
| ); |
| |
| // interface ports |
| AddInheritedItems( |
| GetName(), "interface port", |
| _base_class->GetInterface().GetPortRefList(), |
| GetInterface().GetPortRefList(), |
| signal_errors, |
| AddItem<bs_PortRef>() |
| ); |
| |
| // structure ports |
| AddInheritedItems( |
| GetName(), "end port", |
| _base_class->GetStructure().GetPortRefList(), |
| GetStructure().GetPortRefList(), |
| signal_errors, |
| AddPortItem<bs_PortRef>(_base_class->GetInterface().GetPortRefList()) |
| ); |
| |
| // actor refs |
| AddInheritedItems( |
| GetName(), "actor reference", |
| _base_class->GetStructure().GetActorRefList(), |
| GetStructure().GetActorRefList(), |
| signal_errors, |
| AddItem<bs_ActorRef>() |
| ); |
| |
| // prtv refs |
| AddInheritedItems( |
| GetName(), "primitive reference", |
| _base_class->GetStructure().GetPrtvRefList(), |
| GetStructure().GetPrtvRefList(), |
| signal_errors, |
| AddItem<bs_PrtvRef>() |
| ); |
| |
| // binding contracts |
| AddInheritedItems( |
| GetName(), "binding", |
| _base_class->GetStructure().GetBindingContractList(), |
| GetStructure().GetBindingContractList(), |
| signal_errors, |
| AddItem<bs_BindingContract>() |
| ); |
| |
| // SAPs |
| AddInheritedItems( |
| GetName(), "SAP", |
| _base_class->GetStructure().GetSAPs(), |
| GetStructure().GetSAPs(), |
| signal_errors, |
| AddItem<bs_SAPRef>() |
| ); |
| |
| // structure notes |
| AddInheritedItems( |
| GetName(), "note", |
| _base_class->GetStructure().GetNoteList(), |
| GetStructure().GetNoteList(), |
| signal_errors, |
| AddItem<bs_Note>() |
| ); |
| |
| // behaviour notes |
| bs_StateContext base_sc(_base_class->GetBehaviour().GetStateMachine()); |
| bs_StateContext own_sc(_behaviour.GetStateMachine()); |
| AddInheritedBehaviourNotes(GetName(), base_sc, own_sc, signal_errors); |
| } |
| else |
| { |
| // state variables |
| AddInheritedStateVarsOld( |
| _base_class->GetBehaviour().GetStateMachine()->GetStateVariables(), |
| GetBehaviour().GetStateMachine()->GetStateVariables() |
| ); |
| |
| // interface ports |
| AddInheritedItemsOld( |
| _base_class->GetInterface().GetPortRefList(), |
| GetInterface().GetPortRefList() |
| ); |
| |
| // structure ports |
| AddInheritedItemsOld( |
| _base_class->GetStructure().GetPortRefList(), |
| GetStructure().GetPortRefList() |
| ); |
| |
| // actor refs |
| AddInheritedItemsOld( |
| _base_class->GetStructure().GetActorRefList(), |
| GetStructure().GetActorRefList() |
| ); |
| |
| // prtv refs |
| AddInheritedItemsOld( |
| _base_class->GetStructure().GetPrtvRefList(), |
| GetStructure().GetPrtvRefList() |
| ); |
| |
| // binding contracts |
| AddInheritedItemsOld( |
| _base_class->GetStructure().GetBindingContractList(), |
| GetStructure().GetBindingContractList() |
| ); |
| |
| // SAPs |
| AddInheritedItemsOld( |
| _base_class->GetStructure().GetSAPs(), |
| GetStructure().GetSAPs() |
| ); |
| } |
| |
| // now we are up to date |
| _perso_version = STREAMOBJ_VERSION(bs_ActorClass); |
| } |
| |
| string bs_ActorClass::GetObjID (void) const |
| { |
| return "bs_ActorClass: " + GetName() + GetUniqueObjectIDstr(); |
| } |
| |
| // *************************************************************** |
| |
| void bs_ActorClass::STREAMOBJ_WRITE(bs_ActorClass) (bs_ObjectOStream& oos) |
| { |
| if (_base_class) |
| oos << _base_class->GetName(); |
| else |
| oos << ""; |
| |
| oos << _allow_override; |
| |
| oos << _interface; |
| oos << _structure; |
| oos << _behaviour; |
| oos << _memberfct; |
| |
| oos << _enable_debug_macros; |
| oos << _override_enable_debug; |
| oos << _abstract_class; |
| } |
| |
| |
| void bs_ActorClass::STREAMOBJ_READ(bs_ActorClass) (bs_ObjectIStream& ois, Version version) |
| { |
| _perso_version = version; |
| |
| if (version>=3) |
| ois >> _base_class_name; |
| |
| if (version>=7) |
| ois >> _allow_override; |
| else |
| _allow_override = false; |
| |
| ois >> _interface; |
| ois >> _structure; |
| ois >> _behaviour; |
| |
| if (version>=1) |
| ois >> _memberfct; |
| |
| CommonConstruct(); |
| |
| // check the oldstyle SAPRefList in ActorInterface and move it to ActorStructure |
| bs_SAPRefIterator sap; |
| for(sap=_interface.GetOldstyleSAPs().begin(); sap!=_interface.GetOldstyleSAPs().end(); sap++) |
| { |
| _structure.GetSAPs().push_back(*sap); |
| } |
| _interface.GetOldstyleSAPs().clear(); |
| |
| /* todo: in later versions, checking can be switched off again, |
| currently, we keep it checking until the _real_ reason for |
| spurious bindings has been found.*/ |
| // _check_bindings = (version<2); |
| |
| _check_bindings = true; |
| |
| //if (version==2) |
| { |
| int errors = 0; |
| bs_BindingContractList& bcl = _structure.GetBindingContractList(); |
| for (bs_BindingContractList::iterator it=bcl.begin(); it!=bcl.end(); /* no iterator step here */) |
| { |
| if ((*it)->GetPoint1().GetPortRef()==(*it)->GetPoint2().GetPortRef()) |
| { |
| ++errors; |
| it = bcl.erase(it); |
| } |
| else |
| ++it; |
| } |
| |
| if (errors) |
| { |
| char buf[32]; |
| sprintf(buf, "%d", errors); |
| bs_ErrorHdlr::Get()->Handle( |
| bs_ErrorHdlr::error, |
| "Actor class '" + GetName() + "' had " + buf + " corrupt bindings,\n" |
| "which have been deleted by Trice's consistency check.", |
| __FILE__, |
| __LINE__ |
| ); |
| } |
| } |
| |
| if (version>=4) |
| { |
| ois >> _enable_debug_macros; |
| } |
| if (version>=6) |
| { |
| ois >> _override_enable_debug; |
| } |
| if (version>=5) |
| { |
| ois >> _abstract_class; |
| } |
| |
| RemoveSpuriousTrPoints(); |
| RemoveSpuriousTrSegments(); |
| } |
| |
| void bs_ActorClass::RemoveSpuriousTrPoints (void) |
| { |
| bool removed = false; |
| |
| bs_StateGraph& sg = _behaviour.GetStateMachine()->GetStateGraph(); |
| bs_StateList& sl = sg.GetStates(); |
| for (bs_StateIterator sit=sl.begin(); sit!=sl.end(); ++sit) |
| { |
| if ((*sit)->RemoveSpuriousTrPoints(sg)) |
| removed = true; |
| } |
| |
| if (removed) |
| { |
| bs_ErrorHdlr::Get()->Handle( |
| bs_ErrorHdlr::error, |
| "Actor class '" + GetName() + "' had spurious extending transition points,\n" |
| "which have been deleted by Trice's consistency check.\n\n" |
| "Please check its behaviour for missing transitions!\n", |
| __FILE__, |
| __LINE__ |
| ); |
| } |
| } |
| |
| void bs_ActorClass::RemoveSpuriousTrSegments (void) |
| { |
| int count = _behaviour.GetStateMachine()->GetStateGraph().RemoveSpuriousTrSegments(); |
| |
| if (count>0) |
| { |
| char buf[32]; |
| sprintf(buf, "%d", count); |
| bs_ErrorHdlr::Get()->Handle( |
| bs_ErrorHdlr::error, |
| "Actor class '" + GetName() + "' had " + buf + " corrupt transition segments,\n" |
| "which have been deleted by Trice's consistency check.\n\n" |
| "Please check its behaviour for missing transition segments!\n", |
| __FILE__, |
| __LINE__ |
| ); |
| } |
| } |
| |
| /* |
| static int CheckAndCorrectEndPoint (const bs_BCEndPoint& ep, bs_PortRefList& stp, bs_PortRefList& ifp) |
| { |
| int corrected = 0; |
| |
| if (ep.IsLocal()) |
| { |
| bs_PortRefIterator prit = find(stp.begin(), stp.end(), ep.GetPortRef()); |
| if (prit==stp.end()) |
| prit = find(ifp.begin(), ifp.end(), ep.GetPortRef()); |
| if (prit==ifp.end()) |
| { |
| // pointer not found, try with name |
| prit = stp.FindName(ep.GetPortRef()->GetName()); |
| if (prit==stp.end()) |
| prit = ifp.FindName(ep.GetPortRef()->GetName()); |
| if (prit==ifp.end()) |
| { |
| // cannot correct |
| } |
| else |
| { |
| // correct it |
| ep.SetPortRef(*prit); |
| corrected++; |
| } |
| } |
| } |
| else |
| { |
| // todo: NIY |
| } |
| |
| return corrected; |
| } |
| */ |
| |
| void bs_ActorClass::RemoveSpuriousBindings (void) |
| { |
| // check for BCEndpoints with spurious PortRefs (bug in Trice) |
| // this is checked only for versions in a certain version range (see STREAMOBJ_READ) |
| if (! _check_bindings) |
| return; |
| |
| _check_bindings = false; |
| |
| typedef enum |
| { |
| bc_error |
| } |
| Exception; |
| |
| int errors = 0; |
| |
| bs_PortRefList& ifp = _interface.GetPortRefList(); |
| bs_PortRefList& stp = _structure.GetPortRefList(); |
| |
| bs_BindingContractList& bcl = _structure.GetBindingContractList(); |
| int nbc_before = bcl.size(); // for debugging only |
| int nbc_checked = 0; // for debugging only |
| // int nbep_corrected = 0; // for debugging only |
| for (bs_BindingContractList::iterator it=bcl.begin(); it!=bcl.end(); /* no iterator step here */) |
| { |
| nbc_checked++; |
| |
| try |
| { |
| const bs_BCEndPoint& p1 = (*it)->GetPoint1(); |
| const bs_BCEndPoint& p2 = (*it)->GetPoint2(); |
| |
| // nbep_corrected += CheckAndCorrectEndPoint(p1, stp, ifp); |
| |
| if (p1.IsLocal()) |
| { |
| bs_PortRefIterator prit = find(stp.begin(), stp.end(), p1.GetPortRef()); |
| if (prit==stp.end()) |
| prit = find(ifp.begin(), ifp.end(), p1.GetPortRef()); |
| if (prit==ifp.end()) |
| throw bc_error; |
| if (p2.GetActorRef()) |
| { |
| if (! p2.GetActorRef()->GetActorClass()) |
| throw bc_error; |
| |
| bs_PortRefList& compp = p2.GetActorRef()->GetActorClass()->GetInterface().GetPortRefList(); |
| prit = find(compp.begin(), compp.end(), p2.GetPortRef()); |
| if (prit==compp.end()) |
| throw bc_error; |
| } |
| else |
| { |
| bs_PortRefList& compp = p2.GetPrtvRef()->GetPrtvClass()->GetInterface().GetPortRefList(); |
| prit = find(compp.begin(), compp.end(), p2.GetPortRef()); |
| if (prit==compp.end()) |
| throw bc_error; |
| } |
| } |
| else if (p2.IsLocal()) |
| { |
| bs_PortRefIterator prit = find(stp.begin(), stp.end(), p2.GetPortRef()); |
| if (prit==stp.end()) |
| prit = find(ifp.begin(), ifp.end(), p2.GetPortRef()); |
| if (prit==ifp.end()) |
| throw bc_error; |
| if (p1.GetActorRef()) |
| { |
| if (! p1.GetActorRef()->GetActorClass()) |
| throw bc_error; |
| |
| bs_PortRefList& compp = p1.GetActorRef()->GetActorClass()->GetInterface().GetPortRefList(); |
| prit = find(compp.begin(), compp.end(), p1.GetPortRef()); |
| if (prit==compp.end()) |
| throw bc_error; |
| } |
| else |
| { |
| bs_PortRefList& compp = p1.GetPrtvRef()->GetPrtvClass()->GetInterface().GetPortRefList(); |
| prit = find(compp.begin(), compp.end(), p1.GetPortRef()); |
| if (prit==compp.end()) |
| throw bc_error; |
| } |
| } |
| else |
| { |
| if (p1.GetActorRef()) |
| { |
| if (! p1.GetActorRef()->GetActorClass()) |
| throw bc_error; |
| |
| bs_PortRefList& compp = p1.GetActorRef()->GetActorClass()->GetInterface().GetPortRefList(); |
| bs_PortRefIterator prit = find(compp.begin(), compp.end(), p1.GetPortRef()); |
| if (prit==compp.end()) |
| throw bc_error; |
| if (p2.GetActorRef()) |
| { |
| if (! p2.GetActorRef()->GetActorClass()) |
| throw bc_error; |
| |
| bs_PortRefList& compp = p2.GetActorRef()->GetActorClass()->GetInterface().GetPortRefList(); |
| prit = find(compp.begin(), compp.end(), p2.GetPortRef()); |
| if (prit==compp.end()) |
| throw bc_error; |
| } |
| else |
| { |
| bs_PortRefList& compp = p2.GetPrtvRef()->GetPrtvClass()->GetInterface().GetPortRefList(); |
| prit = find(compp.begin(), compp.end(), p2.GetPortRef()); |
| if (prit==compp.end()) |
| throw bc_error; |
| } |
| } |
| else |
| { |
| bs_PortRefList& compp = p1.GetPrtvRef()->GetPrtvClass()->GetInterface().GetPortRefList(); |
| bs_PortRefIterator prit = find(compp.begin(), compp.end(), p1.GetPortRef()); |
| if (prit==compp.end()) |
| throw bc_error; |
| if (p2.GetActorRef()) |
| { |
| if (! p2.GetActorRef()->GetActorClass()) |
| throw bc_error; |
| |
| bs_PortRefList& compp = p2.GetActorRef()->GetActorClass()->GetInterface().GetPortRefList(); |
| prit = find(compp.begin(), compp.end(), p2.GetPortRef()); |
| if (prit==compp.end()) |
| throw bc_error; |
| } |
| else |
| { |
| bs_PortRefList& compp = p2.GetPrtvRef()->GetPrtvClass()->GetInterface().GetPortRefList(); |
| prit = find(compp.begin(), compp.end(), p2.GetPortRef()); |
| if (prit==compp.end()) |
| throw bc_error; |
| } |
| } |
| } |
| |
| // do an iterator step (otherwise it is increased in the catch() block) |
| it++; |
| } |
| catch (Exception) |
| { |
| errors++; |
| |
| // remove this binding |
| // NB: this will implicitly move the iterator one step forward |
| it = bcl.erase(it); |
| } |
| } |
| |
| int nbc_after = bcl.size(); // for debugging only |
| if (errors) |
| { |
| char buf[32]; |
| sprintf(buf, "%d", errors); |
| bs_ErrorHdlr::Get()->Handle( |
| bs_ErrorHdlr::error, |
| "Actor class '" + GetName() + "' had " + buf + " corrupt bindings,\n" |
| "which have been deleted by Trice's consistency check.\n\n" |
| "Please check its structure for missing bindings!\n", |
| __FILE__, |
| __LINE__ |
| ); |
| } |
| } |
| |
| static void CheckPortBases (string ac_name, bs_PortRefList& prl, bs_PortRefList& base_prl) |
| { |
| bs_PortRefIterator pr; |
| for(pr=prl.begin(); pr!=prl.end(); ++pr) |
| { |
| if (prl.IsOwnerOf((*pr)->GetName())) |
| continue; |
| |
| // we are not owner, base class must have port with same name |
| bs_PortRefPtr base_pr = base_prl[(*pr)->GetName()]; |
| if (base_pr) |
| { |
| if (base_pr!=*pr) |
| { |
| // base class contains port with same name, but there are |
| // two different port objects. |
| // kill zombie PortRef object and discard changes in zombie |
| base_pr.TakeOverPtrsFrom(*pr); |
| |
| bs_ErrorHdlr::Get()->Handle( |
| bs_ErrorHdlr::error, |
| "Actor class '" + ac_name + "' has inherited port " + (*pr)->GetName() +",\n" |
| "which has been decoupled from its base class port! This has been repaired by\n" |
| "Trice's consistency check.\n", |
| __FILE__, |
| __LINE__ |
| ); |
| } |
| } |
| else |
| { |
| // base class doesn't have port with same name, decouple it. |
| prl.SetOwnerOf((*pr)->GetName()); |
| |
| bs_ErrorHdlr::Get()->Handle( |
| bs_ErrorHdlr::error, |
| "Actor class '" + ac_name + "' has inherited port " + (*pr)->GetName() +",\n" |
| "which is unknown in base class! It is automatically set to non-inherited.\n", |
| __FILE__, |
| __LINE__ |
| ); |
| } |
| } |
| } |
| |
| void bs_ActorClass::RemoveSpuriousPorts (void) |
| { |
| if (! _base_class) |
| return; |
| |
| CheckPortBases( |
| GetName(), |
| _interface.GetPortRefList(), |
| _base_class->GetInterface().GetPortRefList() |
| ); |
| CheckPortBases( |
| GetName(), |
| _structure.GetPortRefList(), |
| _base_class->GetStructure().GetPortRefList() |
| ); |
| } |
| |
| void bs_ActorClass::SetBaseClass (bs_ActorClassList& acl) |
| { |
| _base_class = acl[_base_class_name]; |
| } |
| |
| void bs_ActorClass::ReadStream (int version, istream& is, bs_ProtocolClassList& pcl, bs_ActorClassList& acl) |
| { |
| bs_RoomObject::ReadStream(is); |
| |
| _interface.ReadStream(is, pcl); |
| _structure.ReadStream(version, is, pcl, acl); |
| _behaviour.ReadStream(version, is); |
| } |
| |
| |
| |
| bool bs_ActorClass::operator== (const bs_ActorClass& rhs) const |
| { |
| if (((bs_ModelClass)rhs) != *(bs_ModelClass*)this) |
| return false; |
| |
| string bc_name; |
| if (_base_class) |
| bc_name = _base_class->GetName(); |
| string rhs_bc_name; |
| if (rhs._base_class) |
| rhs_bc_name = rhs._base_class->GetName(); |
| |
| if (bc_name!=rhs_bc_name) |
| return false; |
| |
| if (_interface != rhs._interface) |
| return false; |
| |
| if (_structure != rhs._structure) |
| return false; |
| |
| if (_behaviour != rhs._behaviour) |
| return false; |
| |
| if (_memberfct != rhs._memberfct) |
| return false; |
| |
| return true; |
| } |
| |
| |
| void bs_ActorClass::PrepareTakingOver (bs_ActorClassPtr old) |
| { |
| if (this==(bs_ActorClass*)old) |
| return; |
| |
| _interface.PrepareTakingOver(old->GetInterface()); |
| _structure.PrepareTakingOver(old->GetStructure()); |
| _behaviour.GetStateMachine()->PrepareTakingOver(old->_behaviour.GetStateMachine()); |
| } |
| |
| |
| bs_CheckReport bs_ActorClass::CheckConsistency (void) |
| { |
| return _behaviour.CheckConsistency(_base_class ? &_base_class->GetBehaviour() : NULL); |
| } |
| |
| |
| // *************************************************************** |
| |
| bool bs_ActorClassList::MayDeletePortRef (bs_PortRefPtr port_ref) |
| { |
| bs_ActorClassIterator i; |
| for(i=begin(); i!=end(); i++) |
| { |
| if ((*i)->GetStructure().GetBindingContractList().IsBoundOnComponent(port_ref)) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool bs_ActorClassList::IsUsingActorClass (bs_RoomName ac1_name, bs_RoomName ac2_name) |
| { |
| bs_ActorClassPtr ac1 = (*this)[ac1_name]; |
| if (ac1) |
| { |
| bs_ActorClassPtr ac2 = (*this)[ac2_name]; |
| return ac1->IsUsingActorClass(ac2); |
| } |
| else |
| return false; |
| } |
| |
| bool bs_ActorClassList::HasDerivedClass (bs_ActorClassPtr base_ac) |
| { |
| for (bs_ActorClassIterator it=begin(); it!=end(); ++it) |
| { |
| if ((*it)->IsDerivedFrom(base_ac)) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| void bs_ActorClassList::RemoveAllBindingsTo (bs_ActorClassPtr ac) |
| { |
| bs_ActorClassIterator i; |
| for(i=begin(); i!=end(); i++) |
| { |
| bs_ActorRefList& arefs = (*i)->GetStructure().GetActorRefList(); |
| for (bs_ActorRefIterator aref=arefs.begin(); aref!=arefs.end(); ++aref) |
| { |
| if ((*aref)->GetActorClass()==ac) |
| { |
| bs_PortRefList& prl = ac->GetInterface().GetPortRefList(); |
| for (bs_PortRefIterator pref=prl.begin(); pref!=prl.end(); ++pref) |
| { |
| (*i)->GetStructure().GetBindingContractList().RemoveBindingsTo(*pref); |
| } |
| } |
| } |
| } |
| } |
| |
| |
| // *************************************************************** |
| |
| DEFINE_STREAMABLE(bs_ActorClassList,"bs_Namespace") |
| |
| bs_ActorClassList::bs_ActorClassList (void) : |
| bs_RoomList<bs_ActorClass> ("ActorClassListDummyName") |
| { |
| } |
| |
| bs_ActorClassList::bs_ActorClassList (bs_RoomName basename) : |
| bs_RoomList<bs_ActorClass> (basename) |
| { |
| } |
| |
| // helper class used for sorting |
| class GetReferencedActors |
| { |
| public: |
| typedef bs_ActorClassPtr obj; |
| typedef vector<obj> ObjVec; |
| |
| ObjVec operator() (const obj& ac) |
| { |
| ObjVec objs; |
| objs.clear(); |
| |
| ac->GetBaseClasses(objs); |
| |
| bs_ActorRefList& arefs = ac->GetStructure().GetActorRefList(); |
| for (bs_ActorRefIterator ir=arefs.begin(); ir!=arefs.end(); ++ir) |
| { |
| objs.push_back((*ir)->GetActorClass()); |
| } |
| |
| return objs; |
| } |
| }; |
| |
| bs_ActorClassList::bs_ActorClassList (const bs_ActorClassList& orig, CopyType t) |
| : bs_RoomList<bs_ActorClass>(orig, t) |
| { |
| } |
| |
| void bs_ActorClassList::GetDependencySortedVector (vector<bs_ActorClassPtr>& result) const |
| { |
| // (a) make a temporary vector |
| vector<bs_ActorClassPtr> tmp(*this); |
| |
| // (b) sort following dependencies |
| bs_GraphSort(tmp,GetReferencedActors()); |
| |
| // (c) fill result |
| result.clear(); |
| for (reverse_iterator i=tmp.rbegin(); i!=tmp.rend(); i++) |
| { |
| result.push_back(*i); |
| } |
| } |
| |
| void bs_ActorClassList::STREAMOBJ_WRITE(bs_ActorClassList) (bs_ObjectOStream& oos) |
| { |
| for (iterator it=begin(); it!=end(); it++) |
| { |
| (*it)->GetBehaviour().GetStateMachine()->SetGeneratedIds(); |
| } |
| |
| WriteMembersSorted(oos); |
| } |
| |
| void bs_ActorClassList::STREAMOBJ_READ(bs_ActorClassList) (bs_ObjectIStream& ois, Version) |
| { |
| ReadMembers(ois); |
| |
| // loop actor classes and set pointers in actor refs |
| for (iterator it=begin(); it!=end(); ++it) |
| { |
| (*it)->SetBaseClass(*this); |
| |
| bs_ActorRefList& arl = (*it)->GetStructure().GetActorRefList(); |
| for (bs_ActorRefIterator arit=arl.begin(); arit!=arl.end(); ++arit) |
| { |
| (*arit)->SetActorClassPtr(*this); |
| } |
| } |
| |
| // some clean-up |
| for (it=begin(); it!=end(); ++it) |
| { |
| (*it)->RemoveSpuriousBindings(); |
| } |
| } |
| |
| |
| |
| |
| void bs_ActorClassList::ResetUsedFlags (void) |
| { |
| bs_ActorClassIterator i; |
| for(i=begin(); i!=end(); i++) |
| { |
| (*i)->SetUsed(false); |
| } |
| } |
| |
| |
| |
| void bs_ActorClassList::ResetVisitedFlags (void) |
| { |
| bs_ActorClassIterator i; |
| for(i=begin(); i!=end(); i++) |
| { |
| (*i)->ResetVisitedFlag(); |
| } |
| } |
| |
| |
| |
| void bs_ActorClassList::ReadStream (int version, istream& is, bs_ProtocolClassList& pcl) |
| { |
| bool more; |
| |
| // read actor classes (without bindings) |
| is >> more; |
| while (more) |
| { |
| push_back(new bs_ActorClass(version, is, pcl, *this)); |
| is >> more; |
| } |
| |
| |
| // read bindings |
| is >> more; |
| while (more) |
| { |
| bs_RoomName actor_name; actor_name.ReadStream(is); |
| bs_ActorClassPtr actor = (*this)[actor_name]; |
| |
| actor->GetStructure().GetBindingContractList().ReadStream(is, actor); |
| is >> more; |
| } |
| |
| } |
| |
| bs_CheckReport bs_ActorClassList::CheckConsistency (void) |
| { |
| bs_CheckReport rep; |
| |
| vector<bs_ActorClassPtr> tmp; |
| GetDependencySortedVector(tmp); |
| |
| // check in order of dependencies |
| for (vector<bs_ActorClassPtr>::iterator it=tmp.begin(); it!=tmp.end(); it++) |
| { |
| bs_CheckReport actor_rep = (*it)->CheckConsistency(); |
| rep.AddReportSection(actor_rep,"Actor " + (*it)->GetName()); |
| } |
| |
| // check in order of dependencies |
| for (vector<bs_ActorClassPtr>::iterator vit=tmp.begin(); vit!=tmp.end(); vit++) |
| { |
| (*vit)->RemoveSpuriousPorts(); |
| } |
| |
| return rep; |
| } |
| |
| |
| // *************************************************************** |
| |
| void bs_ActorClass::RefreshFormalInfos (bs_ActorClassPtr actor, bool have_license) |
| { |
| bs_StateMachinePtr toplevel_sm = actor->GetBehaviour().GetStateMachine(); |
| bs_StateGraph& graph = toplevel_sm->GetStateGraph(); |
| bs_TrSegmentList& transitions = graph.GetTrSegments(); |
| bs_StateList& states = graph.GetStates(); |
| |
| /* |
| { |
| bs_SourceParser::Signals signals; |
| bs_SourceParser parser(actor->GetStructure().GetPortRefList(), actor->GetStructure().GetSAPs()); |
| bs_TrSegmentIterator ti; |
| for(ti=transitions.begin(); ti!=transitions.end(); ti++) |
| { |
| parser.GetSignals((*ti)->GetActionCode(), signals); |
| } |
| |
| bs_StateIterator si; |
| for(si=states.begin(); si!=states.end(); si++) |
| { |
| parser.GetSignals((*si)->GetEntryAction(), signals); |
| parser.GetSignals((*si)->GetExitAction(), signals); |
| } |
| |
| |
| bs_SourceParser::Signals::iterator s; |
| string txt = "Outgoing signals:\t"; |
| for(s=signals.begin(); s!=signals.end(); s++) |
| { |
| txt += s->GetSignal() + ":" + s->GetPortRef()->GetName() + "\t"; |
| } |
| txt += "\n"; |
| TRACE(txt.c_str()); |
| } |
| */ |
| |
| { |
| FmlFactory factory(toplevel_sm); |
| bs_AuxGraph aux_graph(graph, factory); |
| // bs_SourceParser parser(actor->GetStructure().GetPortRefList(), actor->GetStructure().GetSAPs()); |
| |
| // compute reachability of states, choicepoints and transitions |
| { |
| aux_graph.ComputeReachability(); |
| bs_AuxGraph::Nodes::iterator ni; |
| /* |
| for(si=aux_graph.GetStates().begin(); si!=aux_graph.GetStates().end(); si++) |
| { |
| bs_StatePtr s = si->second.GetState(); |
| if (s!=NULL) |
| { |
| bs_SourceParser::Signals signals; |
| parser.GetSignals(s->GetEntryAction(), signals); |
| parser.GetSignals(s->GetExitAction(), signals); |
| bs_SourceParser::Signals::iterator sig; |
| string txt; |
| for(sig=signals.begin(); sig!=signals.end(); sig++) |
| { |
| if (sig!=signals.begin()) txt += ", "; |
| txt += sig->GetSignal() + ":" + sig->GetPortRef()->GetName(); |
| } |
| s->GetAnalysis()._textual_info = txt; |
| } |
| } |
| */ |
| } |
| |
| // without DEVELOP_FORMAL we will not do more ... |
| if (! have_license) |
| return; |
| |
| // compute outgoing signals for complete graph |
| { |
| /* |
| bs_SourceParser::Signals signals; |
| aux_graph.ComputeOutgoingSignals(actor, signals); |
| |
| bs_SourceParser::Signals::iterator s; |
| string txt = "Outgoing signals:\t"; |
| for(s=signals.begin(); s!=signals.end(); s++) |
| { |
| txt += s->GetSignal() + ":" + s->GetPortRef()->GetName() + "\t"; |
| } |
| txt += "\n"; |
| TRACE(txt.c_str()); |
| */ |
| } |
| |
| // compute outstanding signals for each state |
| if (graph.GetFormalCheckLevel()==bs_StateGraph::fc_full) |
| { |
| //bs_SourceParser::Signals signals; |
| aux_graph.ComputeOutstandingSignals(actor); |
| } |
| } |
| } |
| |
| template<class C> |
| class bs_HasPos |
| { |
| public: |
| bs_HasPos (const bs_ContextCoord& pos) : _pos(pos) {} |
| |
| bool operator () (bs_RoomPtr<C>& obj) |
| { |
| return IsEqual(_pos, obj->GetContextCoord()); |
| } |
| |
| private: |
| static bool IsEqual (double a, double b) |
| { |
| return floor(a*1000)==floor(b*1000); |
| } |
| |
| static bool IsEqual (bs_ContextCoord& a, bs_ContextCoord& b) |
| { |
| return IsEqual(a.X, b.X) && IsEqual(a.Y, b.Y); |
| } |
| |
| private: |
| bs_ContextCoord _pos; |
| }; |
| |
| #undef max |
| |
| template<class C> |
| static int RenameDerivedIff (bs_RoomList<C>& lst, bs_RoomPtr<C>& obj, bs_RoomPtr<C>& base_obj) |
| { |
| if (base_obj->GetName()==obj->GetName()) |
| return 0; |
| |
| // have to rename inherited obj |
| |
| // check for name conflict first |
| if (!lst.IsUniqueName(base_obj->GetName().c_str())) |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: renaming other obj %s", base_obj->GetName().c_str()); |
| #endif |
| |
| string new_name = lst.GetUniqueDefaultName(); |
| if (!lst.ChangeName(base_obj->GetName(), new_name)) |
| { |
| HANDLE_ERROR("RenameDerivedIff - renaming other failed"); |
| } |
| |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" to %s\n", new_name.c_str()); |
| #endif |
| } |
| |
| // alright: here we go |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: renaming %s to %s\n", obj->GetName().c_str(), base_obj->GetName().c_str()); |
| #endif |
| |
| if (!lst.ChangeName(obj->GetName(), base_obj->GetName())) |
| { |
| HANDLE_ERROR("RenameDerivedIff - renaming failed"); |
| } |
| |
| return 1; |
| } |
| |
| template<class C, class Creator, class Matcher> |
| static int MakeDerivedListConsistent (bs_RoomList<C>& lst, bs_RoomList<C>& base_lst, Creator creator, Matcher match) |
| { |
| int fixed = 0; |
| |
| int n_inherited = 0; |
| { |
| for (bs_RoomList<C>::iterator it2=lst.begin(); it2!=lst.end(); ++it2) |
| if ((*it2)->IsInherited()) |
| n_inherited++; |
| } |
| |
| int missing_inherited = base_lst.size()-n_inherited; |
| if (missing_inherited) |
| TRACE(" ### inherited mismatch (%d!=%d)\n", base_lst.size(), n_inherited); |
| |
| for (bs_RoomList<C>::iterator it=base_lst.begin(); it!=base_lst.end(); ++it) |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE("--- %s ---\n", (*it)->GetName().c_str()); |
| #endif |
| |
| // find matching derived class object by position |
| bs_RoomList<C>::iterator it_deriv = lst.end(); |
| double min = numeric_limits<double>::max(); |
| if (true) |
| { |
| // minimal dist^2 |
| for (bs_RoomList<C>::iterator it2=lst.begin(); it2!=lst.end(); ++it2) |
| { |
| if (!match(*it, *it2)) |
| continue; |
| |
| double dist2 = norm2((*it)->GetContextCoord()-(*it2)->GetContextCoord()); |
| if (dist2<min) |
| { |
| min = dist2; |
| it_deriv = it2; |
| if (min==0.0) |
| break; |
| } |
| } |
| #ifdef DEBUG_MAKE_CONSISTENT |
| if (min!=0.0) |
| TRACE(" min dist = %12.8f\n", sqrt(min)); |
| #endif |
| } |
| else |
| { |
| // exactly matching pos with rounding |
| it_deriv = find_if(lst.begin(), lst.end(), bs_HasPos<C>((*it)->GetContextCoord())); |
| } |
| |
| // require better than 1% match |
| if (min>1e-4 || it_deriv==lst.end()) |
| { |
| if (missing_inherited>0) |
| { |
| it_deriv = creator.GetNewObj(); |
| (*it_deriv)->SetInherited(); |
| |
| missing_inherited--; |
| |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: added missing inherited\n"); |
| #endif |
| } |
| else |
| { |
| //HANDLE_ERROR("MakeDerivedListConsistent - inconsistent data structure"); |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" missing inherited\n"); |
| TRACE(" searched pos (%12.8f,%12.8f)\n", (*it)->GetContextCoord().X, (*it)->GetContextCoord().Y); |
| for (bs_RoomList<C>::iterator it2=lst.begin(); it2!=lst.end(); ++it2) |
| { |
| TRACE(" (%12.8f,%12.8f) %s\n", (*it2)->GetContextCoord().X, (*it2)->GetContextCoord().Y, (*it2)->GetName().c_str()); |
| } |
| #endif |
| |
| continue; |
| } |
| } |
| if (!(*it_deriv)->IsInherited()) |
| { |
| // HANDLE_ERROR("MakeDerivedListConsistent - inconsistent data structure"); |
| missing_inherited--; |
| (*it_deriv)->SetInherited(); |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: made inherited\n"); |
| #endif |
| } |
| |
| // ensuring same pos |
| (*it_deriv)->SetContextCoord((*it)->GetContextCoord()); |
| |
| fixed += RenameDerivedIff(lst, *it_deriv, *it); |
| } |
| |
| for (it=lst.begin(); it!=lst.end(); ++it) |
| { |
| if (!(*it)->IsInherited()) |
| continue; |
| |
| bs_RoomPtr<C> base_obj = base_lst[(*it)->GetName()]; |
| if (base_obj.IsNull()) |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: %s: spurious inherited\n", (*it)->GetName().c_str()); |
| #endif |
| |
| (*it)->SetInherited(false); |
| } |
| } |
| |
| n_inherited = 0; |
| { |
| for (bs_RoomList<C>::iterator it2=lst.begin(); it2!=lst.end(); ++it2) |
| if ((*it2)->IsInherited()) |
| n_inherited++; |
| } |
| |
| missing_inherited = base_lst.size()-n_inherited; |
| if (missing_inherited) |
| TRACE(" ### still inherited mismatch (%d!=%d)\n", base_lst.size(), n_inherited); |
| |
| return fixed; |
| } |
| |
| static int CheckInheritanceProperties ( |
| bs_TrSegmentPtr ts, |
| bs_TrPointPtr tp, |
| bs_StateMachinePtr sub_sm, |
| bs_StateMachinePtr base_sm, |
| bs_StateMachinePtr base_sub_sm |
| ) |
| { |
| if (ts->IsInherited()) |
| { |
| int fixed = 0; |
| if (!tp->IsInherited()) |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: setting %s to inherited\n", tp->GetName().c_str()); |
| #endif |
| |
| fixed ++; |
| tp->SetInherited(); |
| } |
| |
| bs_TrSegmentPtr base_ts = ts->GetBaseClassSegment(); |
| if (!base_ts) |
| HANDLE_ERROR("CheckInheritanceProperties - inconsistent data structure"); |
| |
| bs_TrSegmentList& base_tsl = base_sm->GetStateGraph().GetTrSegments(); |
| if (base_tsl.FindItem(base_ts)==base_tsl.end()) |
| HANDLE_ERROR("CheckInheritanceProperties - inconsistent data structure"); |
| |
| bs_TrPointPtr base_tp = base_sub_sm->GetStateGraph().GetTrPoint(base_ts); |
| if (!base_tp) |
| HANDLE_ERROR("CheckInheritanceProperties - inconsistent data structure"); |
| |
| if (tp->GetContextCoord()!=base_tp->GetContextCoord()) |
| { |
| double dist2 = norm2(tp->GetContextCoord()-base_tp->GetContextCoord()); |
| if (dist2>1e-4) |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: setting %s to base tp position\n", tp->GetName().c_str()); |
| #endif |
| |
| fixed ++; |
| tp->SetContextCoord(base_tp->GetContextCoord()); |
| } |
| } |
| return fixed + RenameDerivedIff(sub_sm->GetStateGraph().GetTrPoints(), tp, base_tp); |
| } |
| else |
| { |
| if (tp->IsInherited()) |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: setting %s to non-inherited\n", tp->GetName().c_str()); |
| #endif |
| |
| tp->SetInherited(false); |
| return 1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| static bs_TrPointPtr AddTrPoint ( |
| bs_TrSegmentPtr ts, |
| bs_StatePtr s, |
| bs_StateMachinePtr sub_sm, |
| bs_StateMachinePtr base_sub_sm, |
| bool is_incoming |
| ) |
| { |
| bs_TrPointPtr tp; |
| |
| if (ts->IsInherited()) |
| { |
| bs_TrSegmentPtr base_ts = ts->GetBaseClassSegment(); |
| if (!base_ts) |
| HANDLE_ERROR("AddTrPoint - inconsistent data structure"); |
| |
| bs_TrPointPtr base_tp = base_sub_sm->GetStateGraph().GetTrPoint(base_ts); |
| if (!base_tp) |
| HANDLE_ERROR("AddTrPoint - inconsistent data structure"); |
| |
| tp = sub_sm->GetStateGraph().AddNewTrPoint(ts, is_incoming); |
| tp->SetInherited(); |
| |
| RenameDerivedIff(sub_sm->GetStateGraph().GetTrPoints(), tp, base_tp); |
| } |
| else |
| { |
| tp = sub_sm->GetStateGraph().AddNewTrPoint(ts, is_incoming); |
| |
| int cnt = 0; |
| while (true) |
| { |
| // use system time for unique name |
| string name = tp->GetName(); |
| time_t tm = time(NULL); |
| char buffer[32]; |
| sprintf(buffer, "%d%d", tm, cnt); |
| name += buffer; |
| |
| if (sub_sm->GetStateGraph().GetTrPoints().ChangeName(tp->GetName(), name)) |
| // fine |
| break; |
| |
| if (++cnt>100) |
| { |
| HANDLE_ERROR("AddTrPoint: inconsistent data structure"); |
| break; |
| } |
| } |
| } |
| tp->ComputeContextCoord(s->GetContextCoord()); |
| |
| return tp; |
| } |
| |
| class HasOutside2 |
| { |
| public: |
| HasOutside2(const bs_TrSegment* tseg, bool incoming) : _tseg(tseg), _incoming(incoming) { } |
| |
| bool operator() (const bs_TrPointPtr& item) const |
| { |
| if (item->IsNonExtending()) |
| return false; |
| |
| if (item->IsIncoming()!=_incoming) |
| return false; |
| |
| bs_TrSegmentPtr t = item->GetOutsideTrSegment(); |
| return (_tseg==(const bs_TrSegment*)t); |
| } |
| |
| private: |
| const bs_TrSegment* _tseg; |
| bool _incoming; |
| }; |
| |
| static bs_TrPointPtr GetUniqueTrPoint (bs_StateGraph& sg, bs_TrSegment* outside, bool incoming) |
| { |
| bs_TrPointList::iterator tp = find_if(sg.GetTrPoints().begin(), sg.GetTrPoints().end(), HasOutside2(outside, incoming)); |
| if (tp!=sg.GetTrPoints().end()) |
| { |
| // check uniqueness |
| bs_TrPointList::iterator tp2 = find_if(tp+1, sg.GetTrPoints().end(), HasOutside2(outside, incoming)); |
| while (tp2!=sg.GetTrPoints().end()) |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: destroying %s\n", (*tp2)->GetName().c_str()); |
| #endif |
| tp2 = sg.GetTrPoints().erase(tp2); |
| tp2 = find_if(tp2, sg.GetTrPoints().end(), HasOutside2(outside, incoming)); |
| } |
| |
| return *tp; |
| } |
| |
| return NULL; |
| } |
| |
| static int MakeTrPointConnectivityConsistent ( |
| bs_StatePtr s, |
| bs_StateMachinePtr sm, |
| bs_StateMachinePtr base_sm, |
| bs_StateMachinePtr sub_sm, |
| bs_StateMachinePtr base_sub_sm |
| ) |
| { |
| bs_TrSegmentList& tsl = sm->GetStateGraph().GetTrSegments(); |
| bs_StateGraph& sub_sg = sub_sm->GetStateGraph(); |
| |
| int fixed = 0; |
| |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE("<<< MakeTrPointConnectivityConsistent >>>\n"); |
| #endif |
| |
| // loop outgoing trsegments of s |
| for (bs_TrSegmentIterator it=tsl.GetOutgoing(s); it!=tsl.end(); it=tsl.GetOutgoing(s, it)) |
| { |
| bs_TrPointPtr tp = GetUniqueTrPoint(sub_sg, *it, false); |
| if (tp) |
| { |
| if (!tp->IsOutgoing()) |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: setting %s to outgoing\n", tp->GetName().c_str()); |
| #endif |
| |
| ++fixed; |
| tp->SetOutgoing(*it); |
| } |
| fixed += CheckInheritanceProperties(*it, tp, sub_sm, base_sm, base_sub_sm); |
| } |
| else |
| { |
| // error: add trpoint |
| ++fixed; |
| tp = AddTrPoint(*it, s, sub_sm, base_sub_sm, false); |
| |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: adding %s to outgoing\n", tp->GetName().c_str()); |
| #endif |
| } |
| } |
| |
| // loop incoming trsegments of s |
| for (it=tsl.GetIncoming(s); it!=tsl.end(); it=tsl.GetIncoming(s, it)) |
| { |
| bs_TrPointPtr tp = GetUniqueTrPoint(sub_sg, *it, true); |
| if (tp) |
| { |
| if (!tp->IsIncoming()) |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: setting %s to incoming\n", tp->GetName().c_str()); |
| #endif |
| |
| ++fixed; |
| tp->SetIncoming(*it); |
| } |
| fixed += CheckInheritanceProperties(*it, tp, sub_sm, base_sm, base_sub_sm); |
| } |
| else |
| { |
| // error: add trpoint |
| ++fixed; |
| tp = AddTrPoint(*it, s, sub_sm, base_sub_sm, true); |
| |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE(" *** fix: adding %s to incoming\n", tp->GetName().c_str()); |
| #endif |
| } |
| } |
| |
| return fixed; |
| } |
| |
| class CPCreator |
| { |
| public: |
| CPCreator (bs_StateGraph& sg) : _sg(sg) {} |
| |
| bs_ChoicepointIterator GetNewObj (void) |
| { |
| bs_ChoicepointPtr cp = _sg.AddNewChoicepoint(); |
| return _sg.GetChoicepoints().FindItem(cp); |
| } |
| |
| private: |
| bs_StateGraph& _sg; |
| }; |
| |
| static bool MatchCP (bs_ChoicepointPtr&, bs_ChoicepointPtr&) |
| { |
| return true; |
| } |
| |
| class TrPCreator |
| { |
| public: |
| TrPCreator (bs_StateGraph& sg) : _sg(sg) {} |
| |
| bs_TrPointIterator GetNewObj (void) |
| { |
| bs_TrPointPtr tp = _sg.AddNewTrPoint(NULL, false); |
| return _sg.GetTrPoints().FindItem(tp); |
| } |
| |
| private: |
| bs_StateGraph& _sg; |
| }; |
| |
| static bool MatchTrP (bs_TrPointPtr& tp1, bs_TrPointPtr& tp2) |
| { |
| return tp1->IsNonExtending()==tp2->IsNonExtending(); |
| } |
| |
| static int MakeDerivedObjsConsistent (bs_StateMachinePtr sm, bs_StateMachinePtr base_sm) |
| { |
| int fixed = 0; |
| |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE("====== MakeDerivedObjsConsistent ======\n"); |
| #endif |
| |
| // choicepoints |
| bs_ChoicepointList& cpl = sm->GetStateGraph().GetChoicepoints(); |
| bs_ChoicepointList& base_cpl = base_sm->GetStateGraph().GetChoicepoints(); |
| |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE("~~~~~~ checking choicepoints ~~~~~~\n"); |
| #endif |
| fixed += MakeDerivedListConsistent(cpl, base_cpl, CPCreator(sm->GetStateGraph()), MatchCP); |
| |
| // trpoints |
| bs_TrPointList& tpl = sm->GetStateGraph().GetTrPoints(); |
| bs_TrPointList& base_tpl = base_sm->GetStateGraph().GetTrPoints(); |
| |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE("~~~~~~ checking trpoints ~~~~~~\n"); |
| #endif |
| fixed += MakeDerivedListConsistent(tpl, base_tpl, TrPCreator(sm->GetStateGraph()), MatchTrP); |
| |
| // recurse into base class states |
| bs_StateList& sl = sm->GetStateGraph().GetStates(); |
| bs_StateList& base_sl = base_sm->GetStateGraph().GetStates(); |
| |
| bs_StateContext sc(sm); |
| bs_StateContext base_sc(base_sm); |
| |
| for (bs_StateIterator sit=base_sl.begin(); sit!=base_sl.end(); ++sit) |
| { |
| bs_StatePtr s = sl[(*sit)->GetName()]; |
| if (!s) |
| { |
| HANDLE_ERROR("MakeDerivedObjsConsistent - inconsistent data structure"); |
| continue; |
| } |
| if (!s->IsInherited()) |
| { |
| HANDLE_ERROR("MakeDerivedObjsConsistent - inconsistent data structure"); |
| continue; |
| } |
| if (!s->HasStateMachine()) |
| continue; |
| |
| if (sc.OneLevelDown(s)) |
| { |
| if (base_sc.OneLevelDown(*sit)) |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE("*** state %s ***\n", (*sit)->GetName().c_str()); |
| #endif |
| |
| fixed += MakeTrPointConnectivityConsistent( |
| s, |
| sm, |
| base_sm, |
| sc.GetStateMachine(), |
| base_sc.GetStateMachine() |
| ); |
| fixed += MakeDerivedObjsConsistent(sc.GetStateMachine(), base_sc.GetStateMachine()); |
| |
| base_sc.OneLevelUp(); |
| } |
| else |
| { |
| HANDLE_ERROR("MakeDerivedObjsConsistent - inconsistent data structure"); |
| } |
| |
| sc.OneLevelUp(); |
| } |
| else |
| { |
| HANDLE_ERROR("MakeDerivedObjsConsistent - inconsistent data structure"); |
| } |
| } |
| |
| return fixed; |
| } |
| |
| void bs_ActorClassList::MakeDerivedObjectsConsistent (void) |
| { |
| vector<bs_ActorClassPtr> tmp; |
| GetDependencySortedVector(tmp); |
| |
| // we have to identify inherited choicepoints and trpoints in |
| // derived classes with their base class counterparts and |
| // make their names consistent because some commands rely |
| // on this property of derived classes |
| |
| for (bs_ActorClassIterator it=tmp.begin(); it!=tmp.end(); ++it) |
| { |
| if (!(*it)->IsDerived()) |
| continue; |
| |
| // the base class is already fixed |
| // recusrively descend into state machines |
| bs_StateMachinePtr sm = (*it)->GetBehaviour().GetStateMachine(); |
| bs_StateMachinePtr base_sm = (*it)->GetBaseClass()->GetBehaviour().GetStateMachine(); |
| |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE("### actor class %s ###\n", (*it)->GetName().c_str()); |
| TRACE("*** state TOP ***\n"); |
| #endif |
| |
| int fixed = MakeDerivedObjsConsistent(sm, base_sm); |
| |
| if (fixed) |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE("### %d fixes made \n\n", fixed); |
| #endif |
| |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE("### second run ### \n\n"); |
| #endif |
| |
| int fixed2 = MakeDerivedObjsConsistent(sm, base_sm); |
| if (fixed2) |
| TRACE("### still %d problems ### \n\n", fixed2); |
| |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE("### second run end ### \n\n"); |
| #endif |
| |
| if (fixed2) |
| { |
| string msg = |
| "Actor class '" + (*it)->GetName() + "' had inconsistencies\n" |
| "WHICH COULD NOT BE REOLVED.\n\n" |
| "Please send project file and version number of Trice to support@protos.de!\n"; |
| |
| bs_ErrorHdlr::Get()->Handle( |
| bs_ErrorHdlr::error, |
| msg.c_str(), |
| __FILE__, |
| __LINE__ |
| ); |
| } |
| else |
| { |
| char buf[32]; |
| sprintf(buf, "%d", fixed); |
| string msg = |
| "Actor class '" + (*it)->GetName() + "' had " + buf + " inconsistencies\n" |
| "in derived Choicepoints and/or TrPoints.\n\n" |
| "These problems have been fixed!\n"; |
| |
| bs_ErrorHdlr::Get()->Handle( |
| bs_ErrorHdlr::error, |
| msg.c_str(), |
| __FILE__, |
| __LINE__ |
| ); |
| } |
| } |
| else |
| { |
| #ifdef DEBUG_MAKE_CONSISTENT |
| TRACE("### ok\n\n"); |
| #endif |
| } |
| } |
| } |
| |
| // ************************************************************** |