From 60680946bb9970d02b70a8950c6af531fd9cb484 Mon Sep 17 00:00:00 2001 From: "Peter D. Barnes, Jr" Date: Mon, 3 Feb 2020 15:22:41 -0800 Subject: [PATCH] docs: Refactor print-introspected-doxygen --- utils/print-introspected-doxygen.cc | 1103 ++++++++++++++------------- 1 file changed, 579 insertions(+), 524 deletions(-) diff --git a/utils/print-introspected-doxygen.cc b/utils/print-introspected-doxygen.cc index c3e41d768..bbb9191b8 100644 --- a/utils/print-introspected-doxygen.cc +++ b/utils/print-introspected-doxygen.cc @@ -25,6 +25,7 @@ */ #include +#include #include #include #include // CHAR_BIT @@ -47,6 +48,10 @@ NS_LOG_COMPONENT_DEFINE ("PrintIntrospectedDoxygen"); namespace { + /** + * Markup tokens. + * @{ + */ std::string anchor; ///< hyperlink anchor std::string argument; ///< function argument std::string boldStart; ///< start of bold span @@ -84,6 +89,7 @@ namespace std::string templArgExplicit; ///< template argument required std::string templateArgument; ///< template argument std::string variable; ///< variable or class member + /** @} */ } // unnamed namespace @@ -180,10 +186,479 @@ SetMarkup (bool outputText) } // SetMarkup () +/*************************************************************** + * Aggregation and configuration paths + ***************************************************************/ + +/** + * Gather aggregation and configuration path information from registered types. + */ +class StaticInformation +{ +public: + /** + * Record the a -> b aggregation relation. + * + * \param a [in] the source(?) TypeId name + * \param b [in] the destination(?) TypeId name + */ + void RecordAggregationInfo (std::string a, std::string b); + /** + * Gather aggregation and configuration path information for tid + * + * \param tid [in] the TypeId to gather information from + */ + void Gather (TypeId tid); + /** + * Print output in "a -> b" form on std::cout + */ + void Print (void) const; + + /** + * \return the configuration paths for tid + * + * \param tid [in] the TypeId to return information for + */ + std::vector Get (TypeId tid) const; + + /** + * \return the type names we couldn't aggregate. + */ + std::vector GetNoTypeIds (void) const; + +private: + /** + * \return the current configuration path + */ + std::string GetCurrentPath (void) const; + /** + * Gather attribute, configuration path information for tid + * + * \param tid [in] the TypeId to gather information from + */ + void DoGather (TypeId tid); + /** + * Record the current config path for tid. + * + * \param tid [in] the TypeId to record. + */ + void RecordOutput (TypeId tid); + /** + * \return whether the tid has already been processed + * + * \param tid [in] the TypeId to check. + */ + bool HasAlreadyBeenProcessed (TypeId tid) const; + /** + * Configuration path for each TypeId + */ + std::vector > m_output; + /** + * Current configuration path + */ + std::vector m_currentPath; + /** + * List of TypeIds we've already processed + */ + std::vector m_alreadyProcessed; + /** + * List of aggregation relationships. + */ + std::vector > m_aggregates; + /** + * List of type names without TypeIds, because those modules aren't enabled. + * + * This is mutable because GetNoTypeIds sorts and uniquifies this list + * before returning it. + */ + mutable std::vector m_noTids; + +}; // class StaticInformation + + +void +StaticInformation::RecordAggregationInfo (std::string a, std::string b) +{ + NS_LOG_FUNCTION (this << a << b); + TypeId aTid; + bool found = TypeId::LookupByNameFailSafe (a, &aTid); + if (!found) + { + m_noTids.push_back (a); + return; + } + TypeId bTid; + found = TypeId::LookupByNameFailSafe (b, &bTid); + if (!found) + { + m_noTids.push_back (b); + return; + } + + m_aggregates.push_back (std::make_pair (aTid, bTid)); +} + + +void +StaticInformation::Print (void) const +{ + NS_LOG_FUNCTION (this); + for (auto item : m_output) + { + std::cout << item.first.GetName () << " -> " << item.second << std::endl; + } +} + + +std::string +StaticInformation::GetCurrentPath (void) const +{ + NS_LOG_FUNCTION (this); + std::ostringstream oss; + for (auto item : m_currentPath) + { + oss << "/" << item; + } + return oss.str (); +} + + +void +StaticInformation::RecordOutput (TypeId tid) +{ + NS_LOG_FUNCTION (this << tid); + m_output.push_back (std::make_pair (tid, GetCurrentPath ())); +} + + +bool +StaticInformation::HasAlreadyBeenProcessed (TypeId tid) const +{ + NS_LOG_FUNCTION (this << tid); + for (auto it : m_alreadyProcessed) + { + if (it == tid) + { + return true; + } + } + return false; +} + + +std::vector +StaticInformation::Get (TypeId tid) const +{ + NS_LOG_FUNCTION (this << tid); + std::vector paths; + for (auto item : m_output) + { + if (item.first == tid) + { + paths.push_back (item.second); + } + } + return paths; +} + +/** + * Helper to keep only the unique items in a container. + * + * The container is modified in place; the elements end up sorted. + * + * The container must support \c begin(), \c end() and \c erase(), + * which, among the STL containers, limits this to + * \c std::vector, \c std::dequeue and \c std::list. + * + * The container elements must support \c operator< (for \c std::sort) + * and \c operator== (for \c std::unique). + * + * \tparam T \deduced The container type. + * \param t The container. + */ +template +void +Uniquefy (T t) +{ + std::sort (t.begin (), t.end ()); + t.erase (std::unique (t.begin (), t.end ()), t.end ()); +} + +std::vector +StaticInformation::GetNoTypeIds (void) const +{ + NS_LOG_FUNCTION (this); + Uniquefy (m_noTids); + return m_noTids; +} + + +void +StaticInformation::Gather (TypeId tid) +{ + NS_LOG_FUNCTION (this << tid); + DoGather (tid); + Uniquefy (m_output); +} + + +void +StaticInformation::DoGather (TypeId tid) +{ + NS_LOG_FUNCTION (this << tid); + if (HasAlreadyBeenProcessed (tid)) + { + return; + } + RecordOutput (tid); + for (uint32_t i = 0; i < tid.GetAttributeN (); ++i) + { + struct TypeId::AttributeInformation info = tid.GetAttribute(i); + const PointerChecker *ptrChecker = dynamic_cast (PeekPointer (info.checker)); + if (ptrChecker != 0) + { + TypeId pointee = ptrChecker->GetPointeeTypeId (); + + // See if this is a pointer to an Object. + Ptr object = CreateObject (); + TypeId objectTypeId = object->GetTypeId (); + if (objectTypeId == pointee) + { + // Stop the recursion at this attribute if it is a + // pointer to an Object, which create too many spurious + // paths in the list of attribute paths because any + // Object can be in that part of the path. + continue; + } + + m_currentPath.push_back (info.name); + m_alreadyProcessed.push_back (tid); + DoGather (pointee); + m_alreadyProcessed.pop_back (); + m_currentPath.pop_back (); + continue; + } + // attempt to cast to an object vector. + const ObjectPtrContainerChecker *vectorChecker = dynamic_cast (PeekPointer (info.checker)); + if (vectorChecker != 0) + { + TypeId item = vectorChecker->GetItemTypeId (); + m_currentPath.push_back (info.name + "/[i]"); + m_alreadyProcessed.push_back (tid); + DoGather (item); + m_alreadyProcessed.pop_back (); + m_currentPath.pop_back (); + continue; + } + } + for (uint32_t j = 0; j < TypeId::GetRegisteredN (); j++) + { + TypeId child = TypeId::GetRegistered (j); + if (child.IsChildOf (tid)) + { + std::string childName = "$" + child.GetName (); + m_currentPath.push_back (childName); + m_alreadyProcessed.push_back (tid); + DoGather (child); + m_alreadyProcessed.pop_back (); + m_currentPath.pop_back (); + } + } + for (auto item : m_aggregates) + { + if (item.first == tid || item.second == tid) + { + TypeId other; + if (item.first == tid) + { + other = item.second; + } + if (item.second == tid) + { + other = item.first; + } + std::string name = "$" + other.GetName (); + m_currentPath.push_back (name); + m_alreadyProcessed.push_back (tid); + DoGather (other); + m_alreadyProcessed.pop_back (); + m_currentPath.pop_back (); + } + } +} // StaticInformation::DoGather () + + +/// Register aggregation relationships that are not automatically +/// detected by this introspection program. Statements added here +/// result in more configuration paths being added to the doxygen. +/// \return instance of StaticInformation with the registered information +StaticInformation GetTypicalAggregations () +{ + NS_LOG_FUNCTION_NOARGS (); + + static StaticInformation info; + static bool mapped = false; + + if (mapped) + { + return info; + } + + // Short circuit next call + mapped = true; + + // The below statements register typical aggregation relationships + // in ns-3 programs, that otherwise aren't picked up automatically + // by the creation of the above node. To manually list other common + // aggregation relationships that you would like to see show up in + // the list of configuration paths in the doxygen, add additional + // statements below. + info.RecordAggregationInfo ("ns3::Node", "ns3::TcpSocketFactory"); + info.RecordAggregationInfo ("ns3::Node", "ns3::UdpSocketFactory"); + info.RecordAggregationInfo ("ns3::Node", "ns3::PacketSocketFactory"); + info.RecordAggregationInfo ("ns3::Node", "ns3::MobilityModel"); + info.RecordAggregationInfo ("ns3::Node", "ns3::Ipv4L3Protocol"); + info.RecordAggregationInfo ("ns3::Node", "ns3::Ipv4NixVectorRouting"); + info.RecordAggregationInfo ("ns3::Node", "ns3::Icmpv4L4Protocol"); + info.RecordAggregationInfo ("ns3::Node", "ns3::ArpL3Protocol"); + info.RecordAggregationInfo ("ns3::Node", "ns3::Icmpv4L4Protocol"); + info.RecordAggregationInfo ("ns3::Node", "ns3::UdpL4Protocol"); + info.RecordAggregationInfo ("ns3::Node", "ns3::Ipv6L3Protocol"); + info.RecordAggregationInfo ("ns3::Node", "ns3::Icmpv6L4Protocol"); + info.RecordAggregationInfo ("ns3::Node", "ns3::TcpL4Protocol"); + info.RecordAggregationInfo ("ns3::Node", "ns3::RipNg"); + info.RecordAggregationInfo ("ns3::Node", "ns3::GlobalRouter"); + info.RecordAggregationInfo ("ns3::Node", "ns3::aodv::RoutingProtocol"); + info.RecordAggregationInfo ("ns3::Node", "ns3::dsdv::RoutingProtocol"); + info.RecordAggregationInfo ("ns3::Node", "ns3::dsr::DsrRouting"); + info.RecordAggregationInfo ("ns3::Node", "ns3::olsr::RoutingProtocol"); + info.RecordAggregationInfo ("ns3::Node", "ns3::EnergyHarvesterContainer"); + info.RecordAggregationInfo ("ns3::Node", "ns3::EnergySourceContainer"); + + // Create a channel object so that channels appear in the namespace + // paths that will be generated here. + Ptr simpleChannel; + simpleChannel = CreateObject (); + + for (uint32_t i = 0; i < Config::GetRootNamespaceObjectN (); ++i) + { + Ptr object = Config::GetRootNamespaceObject (i); + info.Gather (object->GetInstanceTypeId ()); + } + + return info; + +} // GetTypicalAggregations () + + +/// Map from TypeId name to tid +typedef std::map< std::string, int32_t> NameMap; +typedef NameMap::const_iterator NameMapIterator; ///< NameMap iterator + + +/** + * Create a map from the class names to their index in the vector of + * TypeId's so that the names will end up in alphabetical order. + * + * \param info type names withut type ids + * \returns NameMap + */ +NameMap +GetNameMap (void) +{ + NS_LOG_FUNCTION_NOARGS (); + + static NameMap nameMap; + static bool mapped = false; + + if (mapped) + { + return nameMap; + } + + // Short circuit next call + mapped = true; + + // Get typical aggregation relationships. + StaticInformation info = GetTypicalAggregations (); + + // Registered types + for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++) + { + TypeId tid = TypeId::GetRegistered (i); + if (tid.MustHideFromDocumentation ()) + { + continue; + } + + // Capitalize all of letters in the name so that it sorts + // correctly in the map. + std::string name = tid.GetName (); + std::transform (name.begin (), name.end (), name.begin (), ::toupper); + + // Save this name's index. + nameMap[name] = i; + } + + // Type names without TypeIds + std::vector noTids = info.GetNoTypeIds (); + for (auto item : noTids) + { + nameMap[item] = -1; + } + + return nameMap; +} // GetNameMap () + + /*************************************************************** * Docs for a single TypeId ***************************************************************/ +/** + * Print config paths + * \param os the output stream + * \param info the information + * \param tid the type ID + */ +void +PrintConfigPaths (std::ostream & os, const TypeId tid) +{ + NS_LOG_FUNCTION (tid); + std::vector paths = GetTypicalAggregations ().Get (tid); + + // Config -------------- + if (paths.empty ()) + { + os << "Introspection did not find any typical Config paths." + << breakBoth + << std::endl; + } + else + { + os << headingStart + << "Config Paths" + << headingStop + << std::endl; + os << std::endl; + os << tid.GetName () + << " is accessible through the following paths" + << " with Config::Set and Config::Connect:" + << std::endl; + os << listStart << std::endl; + for (auto path : paths) + { + os << listLineStart + << "\"" << path << "\"" + << listLineStop + << breakTextOnly + << std::endl; + } + os << listStop << std::endl; + } +} // PrintConfigPaths () + + /** * Print direct Attributes for this TypeId. * @@ -456,6 +931,47 @@ void PrintSize (std::ostream & os, const TypeId tid) } // PrintSize () +/** + * Print the doxy block for each TypeId + * + * \param [in,out] os The output stream. +*/ +void +PrintTypeIdBlocks (std::ostream & os) +{ + NS_LOG_FUNCTION_NOARGS (); + + NameMap nameMap = GetNameMap (); + + // Iterate over the map, which will print the class names in + // alphabetical order. + for (auto item : nameMap) + { + // Handle only real TypeIds + if (item.second < 0) + { + continue ; + } + // Get the class's index out of the map; + TypeId tid = TypeId::GetRegistered (item.second); + std::string name = tid.GetName (); + + std::cout << commentStart << std::endl; + + std::cout << classStart << name << std::endl; + std::cout << std::endl; + + PrintConfigPaths (std::cout, tid); + PrintAttributes (std::cout, tid); + PrintTraceSources (std::cout, tid); + PrintSize (std::cout, tid); + + std::cout << commentStop << std::endl; + } // for class documentation + +} // PrintTypeIdBlocks + + /*************************************************************** * Lists of All things ***************************************************************/ @@ -464,6 +980,9 @@ void PrintSize (std::ostream & os, const TypeId tid) * Print the list of all Attributes. * * \param [in,out] os The output stream. + * + * \todo Print this sorted by class (the current version) + * as well as by Attribute name. */ void PrintAllAttributes (std::ostream & os) @@ -477,11 +996,20 @@ PrintAllAttributes (std::ostream & os) << "in the Tutorial and Manual.\n" << std::endl; - for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i) + NameMap nameMap = GetNameMap (); + // Iterate over the map, which will print the class names in + // alphabetical order. + for (auto item: nameMap) { - TypeId tid = TypeId::GetRegistered (i); - if (tid.GetAttributeN () == 0 || - tid.MustHideFromDocumentation ()) + // Handle only real TypeIds + if (item.second < 0) + { + continue ; + } + // Get the class's index out of the map; + TypeId tid = TypeId::GetRegistered (item.second); + + if (tid.GetAttributeN () == 0 ) { continue; } @@ -561,12 +1089,34 @@ PrintAllLogComponents (std::ostream & os) * \todo Switch to a border-less table, so the file links align * See http://www.stack.nl/~dimitri/doxygen/manual/htmlcmds.html */ - os << listStart << std::endl; LogComponent::ComponentList * logs = LogComponent::GetComponentList (); - LogComponent::ComponentList::const_iterator it; - for (it = logs->begin (); it != logs->end (); ++it) + // Find longest log name + std::size_t widthL = std::string ("Log Component").size (); + std::size_t widthR = std::string ("file").size (); + for (auto it : (*logs)) { - std::string file = it->second->File (); + widthL = std::max (widthL, it.first.size ()); + std::string file = it.second->File (); + // Strip leading "../" related to depth in build directory + // since doxygen only sees the path starting with "src/", etc. + while (file.find ("../") == 0) + { + file = file.substr (3); + } + widthR = std::max (widthR, file.size ()); + } + const std::string sep (" | "); + + os << std::setw (widthL) << std::left << "Log Component" << sep + // Header line has to be padded to same length as separator line + << std::setw (widthR) << std::left << "File " << std::endl; + os << ":" << std::string (widthL - 1, '-') << sep + << ":" << std::string (widthR - 1, '-') << std::endl; + + LogComponent::ComponentList::const_iterator it; + for (auto it : (*logs)) + { + std::string file = it.second->File (); // Strip leading "../" related to depth in build directory // since doxygen only sees the path starting with "src/", etc. while (file.find ("../") == 0) @@ -574,12 +1124,9 @@ PrintAllLogComponents (std::ostream & os) file = file.substr (3); } - os << listLineStart - << boldStart << it->first << boldStop << ": " << file - << listLineStop - << std::endl; + os << std::setw (widthL) << std::left << it.first << sep << file << std::endl; } - os << listStop << std::endl; + os << std::right << std::endl; os << commentStop << std::endl; } // PrintAllLogComponents () @@ -588,6 +1135,9 @@ PrintAllLogComponents (std::ostream & os) * Print the list of all Trace sources. * * \param [in,out] os The output stream. + * + * \todo Print this sorted by class (the current version) + * as well as by TraceSource name. */ void PrintAllTraceSources (std::ostream & os) @@ -601,11 +1151,21 @@ PrintAllTraceSources (std::ostream & os) << "in the Tutorial and Manual.\n" << std::endl; - for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i) + NameMap nameMap = GetNameMap (); + + // Iterate over the map, which will print the class names in + // alphabetical order. + for (auto item : nameMap) { - TypeId tid = TypeId::GetRegistered (i); - if (tid.GetTraceSourceN () == 0 || - tid.MustHideFromDocumentation ()) + // Handle only real TypeIds + if (item.second < 0) + { + continue ; + } + // Get the class's index out of the map; + TypeId tid = TypeId::GetRegistered (item.second); + + if (tid.GetTraceSourceN () == 0 ) { continue; } @@ -963,462 +1523,6 @@ PrintAttributeImplementations (std::ostream & os) } // PrintAttributeImplementations () -/*************************************************************** - * Aggregation and configuration paths - ***************************************************************/ - -/** - * Gather aggregation and configuration path information from registered types. - */ -class StaticInformation -{ -public: - /** - * Record the a -> b aggregation relation. - * - * \param a [in] the source(?) TypeId name - * \param b [in] the destination(?) TypeId name - */ - void RecordAggregationInfo (std::string a, std::string b); - /** - * Gather aggregation and configuration path information for tid - * - * \param tid [in] the TypeId to gather information from - */ - void Gather (TypeId tid); - /** - * Print output in "a -> b" form on std::cout - */ - void Print (void) const; - - /** - * \return the configuration paths for tid - * - * \param tid [in] the TypeId to return information for - */ - std::vector Get (TypeId tid) const; - - /** - * \return the type names we couldn't aggregate. - */ - std::vector GetNoTypeIds (void) const; - -private: - /** - * \return the current configuration path - */ - std::string GetCurrentPath (void) const; - /** - * Gather attribute, configuration path information for tid - * - * \param tid [in] the TypeId to gather information from - */ - void DoGather (TypeId tid); - /** - * Record the current config path for tid. - * - * \param tid [in] the TypeId to record. - */ - void RecordOutput (TypeId tid); - /** - * \return whether the tid has already been processed - * - * \param tid [in] the TypeId to check. - */ - bool HasAlreadyBeenProcessed (TypeId tid) const; - /** - * Configuration path for each TypeId - */ - std::vector > m_output; - /** - * Current configuration path - */ - std::vector m_currentPath; - /** - * List of TypeIds we've already processed - */ - std::vector m_alreadyProcessed; - /** - * List of aggregation relationships. - */ - std::vector > m_aggregates; - /** - * List of type names without TypeIds, because those modules aren't enabled. - * - * This is mutable because GetNoTypeIds sorts and uniquifies this list - * before returning it. - */ - mutable std::vector m_noTids; - -}; // class StaticInformation - - -void -StaticInformation::RecordAggregationInfo (std::string a, std::string b) -{ - NS_LOG_FUNCTION (this << a << b); - TypeId aTid; - bool found = TypeId::LookupByNameFailSafe (a, &aTid); - if (!found) - { - m_noTids.push_back (a); - return; - } - TypeId bTid; - found = TypeId::LookupByNameFailSafe (b, &bTid); - if (!found) - { - m_noTids.push_back (b); - return; - } - - m_aggregates.push_back (std::make_pair (aTid, bTid)); -} - - -void -StaticInformation::Print (void) const -{ - NS_LOG_FUNCTION (this); - for (std::vector >::const_iterator i = m_output.begin (); i != m_output.end (); ++i) - { - std::pair item = *i; - std::cout << item.first.GetName () << " -> " << item.second << std::endl; - } -} - - -std::string -StaticInformation::GetCurrentPath (void) const -{ - NS_LOG_FUNCTION (this); - std::ostringstream oss; - for (std::vector::const_iterator i = m_currentPath.begin (); i != m_currentPath.end (); ++i) - { - std::string item = *i; - oss << "/" << item; - } - return oss.str (); -} - - -void -StaticInformation::RecordOutput (TypeId tid) -{ - NS_LOG_FUNCTION (this << tid); - m_output.push_back (std::make_pair (tid, GetCurrentPath ())); -} - - -bool -StaticInformation::HasAlreadyBeenProcessed (TypeId tid) const -{ - NS_LOG_FUNCTION (this << tid); - for (uint32_t i = 0; i < m_alreadyProcessed.size (); ++i) - { - if (m_alreadyProcessed[i] == tid) - { - return true; - } - } - return false; -} - - -std::vector -StaticInformation::Get (TypeId tid) const -{ - NS_LOG_FUNCTION (this << tid); - std::vector paths; - for (uint32_t i = 0; i < m_output.size (); ++i) - { - std::pair tmp = m_output[i]; - if (tmp.first == tid) - { - paths.push_back (tmp.second); - } - } - return paths; -} - -/** - * Helper to keep only the unique items in a container. - * - * The container is modified in place; the elements end up sorted. - * - * The container must support \c begin(), \c end() and \c erase(), - * which, among the STL containers, limits this to - * \c std::vector, \c std::dequeue and \c std::list. - * - * The container elements must support \c operator< (for \c std::sort) - * and \c operator== (for \c std::unique). - * - * \tparam T \deduced The container type. - * \param t The container. - */ -template -void -Uniquefy (T t) -{ - std::sort (t.begin (), t.end ()); - t.erase (std::unique (t.begin (), t.end ()), t.end ()); -} - -std::vector -StaticInformation::GetNoTypeIds (void) const -{ - NS_LOG_FUNCTION (this); - Uniquefy (m_noTids); - return m_noTids; -} - - -void -StaticInformation::Gather (TypeId tid) -{ - NS_LOG_FUNCTION (this << tid); - DoGather (tid); - Uniquefy (m_output); -} - - -void -StaticInformation::DoGather (TypeId tid) -{ - NS_LOG_FUNCTION (this << tid); - if (HasAlreadyBeenProcessed (tid)) - { - return; - } - RecordOutput (tid); - for (uint32_t i = 0; i < tid.GetAttributeN (); ++i) - { - struct TypeId::AttributeInformation info = tid.GetAttribute(i); - const PointerChecker *ptrChecker = dynamic_cast (PeekPointer (info.checker)); - if (ptrChecker != 0) - { - TypeId pointee = ptrChecker->GetPointeeTypeId (); - - // See if this is a pointer to an Object. - Ptr object = CreateObject (); - TypeId objectTypeId = object->GetTypeId (); - if (objectTypeId == pointee) - { - // Stop the recursion at this attribute if it is a - // pointer to an Object, which create too many spurious - // paths in the list of attribute paths because any - // Object can be in that part of the path. - continue; - } - - m_currentPath.push_back (info.name); - m_alreadyProcessed.push_back (tid); - DoGather (pointee); - m_alreadyProcessed.pop_back (); - m_currentPath.pop_back (); - continue; - } - // attempt to cast to an object vector. - const ObjectPtrContainerChecker *vectorChecker = dynamic_cast (PeekPointer (info.checker)); - if (vectorChecker != 0) - { - TypeId item = vectorChecker->GetItemTypeId (); - m_currentPath.push_back (info.name + "/[i]"); - m_alreadyProcessed.push_back (tid); - DoGather (item); - m_alreadyProcessed.pop_back (); - m_currentPath.pop_back (); - continue; - } - } - for (uint32_t j = 0; j < TypeId::GetRegisteredN (); j++) - { - TypeId child = TypeId::GetRegistered (j); - if (child.IsChildOf (tid)) - { - std::string childName = "$" + child.GetName (); - m_currentPath.push_back (childName); - m_alreadyProcessed.push_back (tid); - DoGather (child); - m_alreadyProcessed.pop_back (); - m_currentPath.pop_back (); - } - } - for (uint32_t k = 0; k < m_aggregates.size (); ++k) - { - std::pair tmp = m_aggregates[k]; - if (tmp.first == tid || tmp.second == tid) - { - TypeId other; - if (tmp.first == tid) - { - other = tmp.second; - } - if (tmp.second == tid) - { - other = tmp.first; - } - std::string name = "$" + other.GetName (); - m_currentPath.push_back (name); - m_alreadyProcessed.push_back (tid); - DoGather (other); - m_alreadyProcessed.pop_back (); - m_currentPath.pop_back (); - } - } -} // StaticInformation::DoGather () - - -/// Register aggregation relationships that are not automatically -/// detected by this introspection program. Statements added here -/// result in more configuration paths being added to the doxygen. -/// \return instance of StaticInformation with the registered information -StaticInformation GetTypicalAggregations () -{ - NS_LOG_FUNCTION_NOARGS (); - // The below statements register typical aggregation relationships - // in ns-3 programs, that otherwise aren't picked up automatically - // by the creation of the above node. To manually list other common - // aggregation relationships that you would like to see show up in - // the list of configuration paths in the doxygen, add additional - // statements below. - StaticInformation info; - info.RecordAggregationInfo ("ns3::Node", "ns3::TcpSocketFactory"); - info.RecordAggregationInfo ("ns3::Node", "ns3::UdpSocketFactory"); - info.RecordAggregationInfo ("ns3::Node", "ns3::PacketSocketFactory"); - info.RecordAggregationInfo ("ns3::Node", "ns3::MobilityModel"); - info.RecordAggregationInfo ("ns3::Node", "ns3::Ipv4L3Protocol"); - info.RecordAggregationInfo ("ns3::Node", "ns3::Ipv4NixVectorRouting"); - info.RecordAggregationInfo ("ns3::Node", "ns3::Icmpv4L4Protocol"); - info.RecordAggregationInfo ("ns3::Node", "ns3::ArpL3Protocol"); - info.RecordAggregationInfo ("ns3::Node", "ns3::Icmpv4L4Protocol"); - info.RecordAggregationInfo ("ns3::Node", "ns3::UdpL4Protocol"); - info.RecordAggregationInfo ("ns3::Node", "ns3::Ipv6L3Protocol"); - info.RecordAggregationInfo ("ns3::Node", "ns3::Icmpv6L4Protocol"); - info.RecordAggregationInfo ("ns3::Node", "ns3::TcpL4Protocol"); - info.RecordAggregationInfo ("ns3::Node", "ns3::RipNg"); - info.RecordAggregationInfo ("ns3::Node", "ns3::GlobalRouter"); - info.RecordAggregationInfo ("ns3::Node", "ns3::aodv::RoutingProtocol"); - info.RecordAggregationInfo ("ns3::Node", "ns3::dsdv::RoutingProtocol"); - info.RecordAggregationInfo ("ns3::Node", "ns3::dsr::DsrRouting"); - info.RecordAggregationInfo ("ns3::Node", "ns3::olsr::RoutingProtocol"); - info.RecordAggregationInfo ("ns3::Node", "ns3::EnergyHarvesterContainer"); - info.RecordAggregationInfo ("ns3::Node", "ns3::EnergySourceContainer"); - - // Create a channel object so that channels appear in the namespace - // paths that will be generated here. - Ptr simpleChannel; - simpleChannel = CreateObject (); - - for (uint32_t i = 0; i < Config::GetRootNamespaceObjectN (); ++i) - { - Ptr object = Config::GetRootNamespaceObject (i); - info.Gather (object->GetInstanceTypeId ()); - } - - return info; - -} // GetTypicalAggregations () - - -/// Map from TypeId name to tid -typedef std::map< std::string, int32_t> NameMap; -typedef NameMap::const_iterator NameMapIterator; ///< NameMap iterator - - -/** - * Create a map from the class names to their index in the vector of - * TypeId's so that the names will end up in alphabetical order. - * - * \param info type names withut type ids - * \returns NameMap - */ -NameMap -GetNameMap (const StaticInformation & info) -{ - NS_LOG_FUNCTION_NOARGS (); - NameMap nameMap; - - // Registered types - for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++) - { - TypeId tid = TypeId::GetRegistered (i); - if (tid.MustHideFromDocumentation ()) - { - continue; - } - - // Capitalize all of letters in the name so that it sorts - // correctly in the map. - std::string name = tid.GetName (); - for (uint32_t j = 0; j < name.length (); j++) - { - name[j] = toupper (name[j]); - } - - // Save this name's index. - nameMap[name] = i; - } - - // Type names without TypeIds - std::vector noTids = info.GetNoTypeIds (); - for (std::vector::const_iterator i = noTids.begin (); - i != noTids.end (); - ++i) - { - nameMap[*i] = -1; - } - - return nameMap; -} // GetNameMap () - - -/** - * Print config paths - * \param os the output stream - * \param info the information - * \param tid the type ID - */ -void -PrintConfigPaths (std::ostream & os, const StaticInformation & info, - const TypeId tid) -{ - NS_LOG_FUNCTION (tid); - std::vector paths = info.Get (tid); - - // Config -------------- - if (paths.empty ()) - { - os << "Introspection did not find any typical Config paths." - << breakBoth - << std::endl; - } - else - { - os << headingStart - << "Config Paths" - << headingStop - << std::endl; - os << std::endl; - os << tid.GetName () - << " is accessible through the following paths" - << " with Config::Set and Config::Connect:" - << std::endl; - os << listStart << std::endl; - for (uint32_t k = 0; k < paths.size (); ++k) - { - std::string path = paths[k]; - os << listLineStart - << "\"" << path << "\"" - << listLineStop - << breakTextOnly - << std::endl; - } - os << listStop << std::endl; - } -} // PrintConfigPaths () - - /*************************************************************** * Main ***************************************************************/ @@ -1462,58 +1566,9 @@ int main (int argc, char *argv[]) << "Edit that file instead.\n" << commentStop << std::endl; + + PrintTypeIdBlocks (std::cout); - // Get typical aggregation relationships. - StaticInformation info = GetTypicalAggregations (); - - NameMap nameMap = GetNameMap (info); - - // Iterate over the map, which will print the class names in - // alphabetical order. - for (NameMapIterator nameMapIterator = nameMap.begin (); - nameMapIterator != nameMap.end (); - nameMapIterator++) - { - // Get the class's index out of the map; - std::string name = nameMapIterator->first; - int32_t i = nameMapIterator->second; - TypeId tid; - - if (i >= 0) - { - tid = TypeId::GetRegistered (i); - if (tid.MustHideFromDocumentation ()) - { - continue; - } - name = tid.GetName (); - } - - std::cout << commentStart << std::endl; - - std::cout << classStart << name << std::endl; - std::cout << std::endl; - - if (i >= 0) - { - PrintConfigPaths (std::cout, info, tid); - PrintAttributes (std::cout, tid); - PrintTraceSources (std::cout, tid); - PrintSize (std::cout, tid); - } - else - { - std::cout << "Introspection could not find Config paths for " << name - << " in this build because the parent module" - << " was not included in the waf configuration." - << breakBoth - << std::endl; - } - - std::cout << commentStop << std::endl; - } // class documentation - - PrintAllAttributes (std::cout); PrintAllGlobals (std::cout); PrintAllLogComponents (std::cout);