📄 cdlcore.hxx
字号:
class ContainerSupport { public: ContainerSupport(CdlInterpreter interp_arg, CdlContainer container) { interp = interp_arg; saved_container = interp->push_container(container); } ~ContainerSupport() { interp->pop_container(saved_container); } private: ContainerSupport(); CdlInterpreter interp; CdlContainer saved_container; }; class NodeSupport { public: NodeSupport(CdlInterpreter interp_arg, CdlNode node) { interp = interp_arg; saved_node = interp->push_node(node); } ~NodeSupport() { interp->pop_node(saved_node); } private: NodeSupport(); CdlInterpreter interp; CdlNode saved_node; }; class CommandSupport { public: CommandSupport(CdlInterpreter interp_arg, std::vector<CdlInterpreterCommandEntry>& commands) { interp = interp_arg; saved_commands = interp->push_commands(commands); } CommandSupport(CdlInterpreter interp_arg, CdlInterpreterCommandEntry* commands) { unsigned int i; for (i = 0; 0 != commands[i].command; i++) { new_commands.push_back(commands[i]); } interp = interp_arg; saved_commands = interp->push_commands(new_commands); } ~CommandSupport() { interp->pop_commands(saved_commands); } private: CommandSupport(); CdlInterpreter interp; std::vector<CdlInterpreterCommandEntry>* saved_commands; std::vector<CdlInterpreterCommandEntry> new_commands; }; // Similar utility classes for variables and assoc data. class VariableSupport { public: VariableSupport(CdlInterpreter interp_arg, std::string varname_arg, std::string data) { interp = interp_arg; varname = varname_arg; interp->set_variable(varname, data); } ~VariableSupport() { interp->unset_variable(varname); } private: VariableSupport(); CdlInterpreter interp; std::string varname; }; class AssocSupport { public: AssocSupport(CdlInterpreter interp_arg, const char* name_arg, ClientData data, Tcl_InterpDeleteProc* del_proc = 0) { interp = interp_arg; name = name_arg; interp->set_assoc_data(name, data, del_proc); } ~AssocSupport() { interp->delete_assoc_data(name); } private: AssocSupport(); CdlInterpreter interp; const char* name; }; // Some command implementations may want to access other Tcl library // routines such as Tcl_SplitList(). This requires convenient access // to the underlying Tcl interpreter. Tcl_Interp* get_tcl_interpreter() const; // For use by the assertion macros. bool check_this(cyg_assert_class_zeal = cyg_quick) const; private: // This is the Tcl command proc that gets registered for all // CdlInterpreterCommand instances. static int tcl_command_proc(ClientData, Tcl_Interp*, int, char*[]); // This key is used to access the CdlInterpreter assoc data. static char* cdlinterpreter_assoc_data_key; // Do not allow static instances of a Cdl interpreter. There are too // many possible failure conditions. Cdl interpreters can only be // created dynamically via make(), which will invoke this. CdlInterpreterBody(Tcl_Interp*); // Default constructor, copy constructor and assignment are illegal CdlInterpreterBody(); CdlInterpreterBody(const CdlInterpreterBody&); CdlInterpreterBody& operator=(const CdlInterpreterBody&); Tcl_Interp* tcl_interp; // The underlying Tcl interpreter bool owns_interp; // Was the Tcl interpreter created by the library? std::vector<CdlInterpreter> slaves; // All slave interpreters CdlInterpreter parent; // Or else the parent CdlToplevel toplevel; // Data that gets used during the parsing process CdlTransaction transaction; CdlLoadable loadable; CdlContainer container; CdlNode node; std::string context; CdlDiagnosticFnPtr error_fn_ptr; CdlDiagnosticFnPtr warning_fn_ptr; bool cdl_result; std::vector<CdlInterpreterCommandEntry>* current_commands; // for push() and pop() enum { CdlInterpreterBody_Invalid = 0, CdlInterpreterBody_Magic = 0x0be67689 } cdlinterpreterbody_cookie;};//}}}//{{{ CdlReference/Referrer classes // ---------------------------------------------------------------------------// CDL objects are organised primarily in a tree hierarchy. For// example a package contains components, components contain options,// and so on. The tree hierarchy tends to change rather infrequently,// so it makes sense to have a quick way of navigating between// entities without continuously having to do hash-table lookups. In// addition it is very desirable to make the connectivity// bidirectional: if a "requires" property in option A references// option B then it would be useful to have a link back to A from B;// that way, if the value of B changes it is a lot easier to keep// things up to date.//// Terminology: the entity which contains the reference, e.g. a// "requires" property, is the source. The relevant property is the// "source property". The entity pointed at is the destination.//// Unfortunately there may be connections between CDL entities outside// the tree hierarchy. In particular any property can contain one or// more references to packages, components, options, wizards, or// whatever. Often these references will be to options etc. within the// same package, but some references will go to other packages. There// may even be references to other configurations: for example a board// may contain both an ordinary processor and a DSP; these two need// their own configurations; however a package running on the DSP may// need to interact with a package running on the processor, and vice// versa.//// Also, a reference may occur inside an object that is not in the// hierarchy. For example CDL expressions may get evaluated inside Tcl// code rather than as part of a property. Such expressions may still// contain references to entities in the current configuration.//// References may not be resolved. When reading in a CDL script there// may be forward references. A reference may involve another package// that has not yet been loaded, which is a conflict.//// Using simple pointers to store these connections is a bad idea. It// makes it a lot harder to figure out what is connected to what, and// it introduces horrible consistency problems when packages get// loaded and unloaded. Instead libCDL provides a CdlReference class.// Whenever a CdlProperty contains a reference to some other CDL// entity there should be a CdlReference object corresponding to this.// The reverse direction is handled via a CdlReferrer object.//// A CdlReference object can be either bound or unbound. By default it// is unbound, containing only a string. It can then be bound via a// member function, examined, and unbound again as required. Creating// a binding automatically creates a CdlReferrer entry in the target// object, thus avoiding any risk of inconsistencies.//// The CdlReference class should not be used outside the hierarchy,// since every bound reference must have a referrer object pointing// back, and this link back can only be valid within the hierarchy.// Temporary CdlReference objects are useful during the construction// of properties.//// It is possible that a given property (e.g. a complicated "requires"// expression) has multiple references to another entity. Each of// these involves a separate CdlReference/CdlReferrer pair.// ----------------------------------------------------------------------------// The actual CdlReference class.class CdlReference { friend class CdlTest; // CdlReferrer must be a friend so that when a package gets unloaded // it can clean up all references to it. friend class CdlReferrer; public: // The default constructor should not normally be used, instead // a string should be supplied. However there are vectors of // reference objects... CdlReference(); // The main constructor supplies the name of the referenced // entity. The resulting object will be unbound. CdlReference(const std::string); // The copy constructor is legal for unbound objects only. CdlReference(const CdlReference&); // The assignment operator is needed for STL operations. // Again it only makes sense of unbound objects. CdlReference& operator=(const CdlReference&); // The destructor is only valid for unbound objects. All references // should be unbound before an entity can be destroyed. ~CdlReference(); // Access the various fields. void set_destination_name(const std::string); const std::string& get_destination_name() const; CdlNode get_destination() const; // Binding a reference. Obviously this can only be used when the // reference is still unbound. When doing the binding it is // necessary to know: // (1) the object containing the reference. // (2) the specific property that contains the reference. // (3) the object being referred to. // Binding a reference results in a new referrer entry in the // destination. void bind(CdlNode, CdlProperty, CdlNode); // Unbinding a reference. Typically this only happens when the // destination is unloaded. The arguments provide the source and // the source property. void unbind(CdlNode, CdlProperty); // This is used by the ASSERT_CLASS() and ASSERT_THIS() macros. bool check_this(cyg_assert_class_zeal cyg_quick) const; CYGDBG_DECLARE_MEMLEAK_COUNTER(); protected: private: // The data fields. The name is usually filled in by the // constructor. The destination defaults to zero for an unbound // object and gets filled in by the bind() operation. std::string dest_name; CdlNode dest; enum { CdlReference_Invalid = 0, CdlReference_Magic = 0x3f908608 } cdlreference_cookie;};// ----------------------------------------------------------------------------// The CdlNode class (and hence just about everything) contains a// vector of CdlReferrer objects. This keeps track of all entities// that refer to this one, so if the value associated with this// changes it is possible to work out the impact of this on all// entities that rely on this value.//// Arguably this should work in terms of CdlValuable objects rather// than CdlNode objects. However it is convenient to use references// for the connection between e.g. an option and a dialog, where// there is no value involved. The reverse connection is of little// use in this circumstance.//// CdlReferrer objects are rarely accessed directly. Instead they will// be filled in during a CdlReference::bind() operation and erased// during a CdlReference::unbind() operation. The only operations that// should be public allow access to the contained data.class CdlReferrer { friend class CdlTest; // CdlReference::bind() and unbind() have direct access to the // members, since these two functions are really responsible for // creating and destroying referrer objects. friend class CdlReference; public: // The default constructor, copy constructor and assignment // operator are all public to avoid problems with having vectors // of referrer objects. Similarly the destructor is public. // In practice updates actually happen as a consequence of // CdlReference::bind() and CdlReference::unbind().
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -