A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
print-introspected-doxygen.cc
1 #include <iostream>
2 #include <algorithm>
3 #include <map>
4 #include "ns3/object.h"
5 #include "ns3/pointer.h"
6 #include "ns3/object-vector.h"
7 #include "ns3/config.h"
8 #include "ns3/log.h"
9 #include "ns3/global-value.h"
10 #include "ns3/string.h"
11 #include "ns3/node-container.h"
12 #include "ns3/csma-channel.h"
13 
14 using namespace ns3;
15 
16 NS_LOG_COMPONENT_DEFINE ("PrintIntrospectedDoxygen");
17 
18 namespace
19 {
20  std::string anchor;
21  std::string boldStart;
22  std::string boldStop;
23  std::string breakBoth;
24  std::string breakHtmlOnly;
25  std::string breakTextOnly;
26  std::string brief;
27  std::string commentStart;
28  std::string commentStop;
35  std::string flagSpanStart;
36  std::string flagSpanStop;
37  std::string functionStart;
38  std::string functionStop;
39  std::string headingStart;
40  std::string headingStop;
41  std::string indentHtmlOnly;
42  std::string ingroupConstructs;
43  std::string listStart;
44  std::string listStop;
45  std::string listLineStart;
46  std::string listLineStop;
47  std::string reference;
48  std::string temporaryCharacter;
49 
50 } // anonymous namespace
51 
52 void
53 PrintAttributes (TypeId tid, std::ostream &os)
54 {
55  os << listStart << std::endl;
56  for (uint32_t j = 0; j < tid.GetAttributeN (); j++)
57  {
58  struct TypeId::AttributeInformation info = tid.GetAttribute(j);
59  os << listLineStart << boldStart << info.name << boldStop << ": "
60  << info.help << std::endl;
61  os << " " << listStart << std::endl
62  << " " << listLineStart << "Set with class: " << reference << info.checker->GetValueTypeName () << listLineStop << std::endl;
63  if (info.checker->HasUnderlyingTypeInformation ())
64  {
65  os << " " << listLineStart << "Underlying type: ";
66  if ( (info.checker->GetValueTypeName () != "ns3::EnumValue")
67  && (info.checker->GetUnderlyingTypeInformation () != "std::string")
68  )
69  {
70  os << reference;
71  }
72  os << info.checker->GetUnderlyingTypeInformation () << listLineStop << std::endl;
73  }
74  if (info.flags & TypeId::ATTR_CONSTRUCT && info.accessor->HasSetter ())
75  {
76  os << " " << listLineStart << "Initial value: " << info.initialValue->SerializeToString (info.checker) << listLineStop << std::endl;
77  }
78  os << " " << listLineStart << "Flags: ";
79  if (info.flags & TypeId::ATTR_CONSTRUCT && info.accessor->HasSetter ())
80  {
81  os << flagSpanStart << "construct " << flagSpanStop;
82  }
83  if (info.flags & TypeId::ATTR_SET && info.accessor->HasSetter ())
84  {
85  os << flagSpanStart << "write " << flagSpanStop;
86  }
87  if (info.flags & TypeId::ATTR_GET && info.accessor->HasGetter ())
88  {
89  os << flagSpanStart << "read " << flagSpanStop;
90  }
91  os << listLineStop << std::endl;
92  os << " " << listStop << " " << std::endl;
93 
94  }
95  os << listStop << std::endl;
96 }
97 
98 void
99 PrintTraceSources (TypeId tid, std::ostream &os)
100 {
101  os << listStart << std::endl;
102  for (uint32_t i = 0; i < tid.GetTraceSourceN (); ++i)
103  {
104  struct TypeId::TraceSourceInformation info = tid.GetTraceSource (i);
105  os << listLineStart << boldStart << info.name << boldStop << ": "
106  << info.help
107  << std::endl;
108  os << listLineStop << std::endl;
109  }
110  os << listStop << std::endl;
111 }
112 
113 
118 {
119 public:
126  void RecordAggregationInfo (std::string a, std::string b);
132  void Gather (TypeId tid);
136  void Print (void) const;
137 
143  std::vector<std::string> Get (TypeId tid);
144 
145 private:
149  std::string GetCurrentPath (void) const;
155  void DoGather (TypeId tid);
161  void RecordOutput (TypeId tid);
167  bool HasAlreadyBeenProcessed (TypeId tid) const;
175  void find_and_replace (std::string &source, const std::string find, std::string replace );
179  std::vector<std::pair<TypeId,std::string> > m_output;
183  std::vector<std::string> m_currentPath;
187  std::vector<TypeId> m_alreadyProcessed;
191  std::vector<std::pair<TypeId,TypeId> > m_aggregates;
192 };
193 
194 void
195 StaticInformation::RecordAggregationInfo (std::string a, std::string b)
196 {
197  m_aggregates.push_back (std::make_pair (TypeId::LookupByName (a), TypeId::LookupByName (b)));
198 }
199 
200 void
202 {
203  for (std::vector<std::pair<TypeId,std::string> >::const_iterator i = m_output.begin (); i != m_output.end (); ++i)
204  {
205  std::pair<TypeId,std::string> item = *i;
206  std::cout << item.first.GetName () << " -> " << item.second << std::endl;
207  }
208 }
209 
210 std::string
212 {
213  std::ostringstream oss;
214  for (std::vector<std::string>::const_iterator i = m_currentPath.begin (); i != m_currentPath.end (); ++i)
215  {
216  std::string item = *i;
217  oss << "/" << item;
218  }
219  return oss.str ();
220 }
221 
222 void
224 {
225  m_output.push_back (std::make_pair (tid, GetCurrentPath ()));
226 }
227 
228 bool
230 {
231  for (uint32_t i = 0; i < m_alreadyProcessed.size (); ++i)
232  {
233  if (m_alreadyProcessed[i] == tid)
234  {
235  return true;
236  }
237  }
238  return false;
239 }
240 
241 std::vector<std::string>
243 {
244  std::vector<std::string> paths;
245  for (uint32_t i = 0; i < m_output.size (); ++i)
246  {
247  std::pair<TypeId,std::string> tmp = m_output[i];
248  if (tmp.first == tid)
249  {
250  paths.push_back (tmp.second);
251  }
252  }
253  return paths;
254 }
255 
256 void
258 {
259  DoGather (tid);
260 
261  std::sort (m_output.begin (), m_output.end ());
262  m_output.erase (std::unique (m_output.begin (), m_output.end ()), m_output.end ());
263 }
264 
265 void
267 {
268  NS_LOG_FUNCTION (this);
269  if (HasAlreadyBeenProcessed (tid))
270  {
271  return;
272  }
273  RecordOutput (tid);
274  for (uint32_t i = 0; i < tid.GetAttributeN (); ++i)
275  {
276  struct TypeId::AttributeInformation info = tid.GetAttribute(i);
277  const PointerChecker *ptrChecker = dynamic_cast<const PointerChecker *> (PeekPointer (info.checker));
278  if (ptrChecker != 0)
279  {
280  TypeId pointee = ptrChecker->GetPointeeTypeId ();
281 
282  // See if this is a pointer to an Object.
283  Ptr<Object> object = CreateObject<Object> ();
284  TypeId objectTypeId = object->GetTypeId ();
285  if (objectTypeId == pointee)
286  {
287  // Stop the recursion at this attribute if it is a
288  // pointer to an Object, which create too many spurious
289  // paths in the list of attribute paths because any
290  // Object can be in that part of the path.
291  continue;
292  }
293 
294  m_currentPath.push_back (info.name);
295  m_alreadyProcessed.push_back (tid);
296  DoGather (pointee);
297  m_alreadyProcessed.pop_back ();
298  m_currentPath.pop_back ();
299  continue;
300  }
301  // attempt to cast to an object vector.
302  const ObjectPtrContainerChecker *vectorChecker = dynamic_cast<const ObjectPtrContainerChecker *> (PeekPointer (info.checker));
303  if (vectorChecker != 0)
304  {
305  TypeId item = vectorChecker->GetItemTypeId ();
306  m_currentPath.push_back (info.name + "/[i]");
307  m_alreadyProcessed.push_back (tid);
308  DoGather (item);
309  m_alreadyProcessed.pop_back ();
310  m_currentPath.pop_back ();
311  continue;
312  }
313  }
314  for (uint32_t j = 0; j < TypeId::GetRegisteredN (); j++)
315  {
316  TypeId child = TypeId::GetRegistered (j);
317  if (child.IsChildOf (tid))
318  {
319  //please take a look at the following note for an explanation
320  std::string childName = "$" + temporaryCharacter + child.GetName ();
321  std::string replaceWith = "::" + temporaryCharacter;
322  find_and_replace(childName,"::",replaceWith);
323  m_currentPath.push_back (childName);
324  m_alreadyProcessed.push_back (tid);
325  DoGather (child);
326  m_alreadyProcessed.pop_back ();
327  m_currentPath.pop_back ();
328  }
329  }
330  for (uint32_t k = 0; k < m_aggregates.size (); ++k)
331  {
332  std::pair<TypeId,TypeId> tmp = m_aggregates[k];
333  if (tmp.first == tid || tmp.second == tid)
334  {
335  TypeId other;
336  if (tmp.first == tid)
337  {
338  other = tmp.second;
339  }
340  if (tmp.second == tid)
341  {
342  other = tmp.first;
343  }
355  std::string name = "$" + temporaryCharacter + other.GetName ();
356  //finding and replacing :: by ::% (for Doxygen version only).
357  std::string replaceWith = "::" + temporaryCharacter;
358  find_and_replace(name,"::",replaceWith);
359  m_currentPath.push_back (name);
360  m_alreadyProcessed.push_back (tid);
361  DoGather (other);
362  m_alreadyProcessed.pop_back ();
363  m_currentPath.pop_back ();
364  }
365  }
366 }
367 
368 void
369 StaticInformation::find_and_replace( std::string &source, const std::string find, std::string replace )
370 {
371  size_t j;
372  j = source.find (find);
373  while (j != std::string::npos )
374  {
375  source.replace (j, find.length (),replace);
376  j = source.find (find,j+1);
377  }
378 }
379 
380 void
381 PrintHelp (const char *program_name)
382 {
383  std::cout << "Usage: " << program_name << " [options]" << std::endl
384  << std::endl
385  << "Options:" << std::endl
386  << " --help : print these options" << std::endl
387  << " --output-text : format output as plain text" << std::endl;
388 }
389 
390 int main (int argc, char *argv[])
391 {
392  bool outputText = false;
393  char *programName = argv[0];
394 
395  argv++;
396 
397  while (*argv != 0)
398  {
399  char *arg = *argv;
400 
401  if (strcmp (arg, "--help") == 0)
402  {
403  PrintHelp (programName);
404  return 0;
405  }
406  else if (strcmp(arg, "--output-text") == 0)
407  {
408  outputText = true;
409  }
410  else
411  {
412  // un-recognized command-line argument
413  PrintHelp (programName);
414  return 0;
415  }
416  argv++;
417  }
418 
419  if (outputText)
420  {
421  anchor = "";
422  boldStart = "";
423  boldStop = "";
424  breakBoth = "\n";
425  breakHtmlOnly = "";
426  breakTextOnly = "\n";
427  brief = "";
428  commentStart = "===============================================================\n";
429  commentStop = "";
436  flagSpanStart = "";
437  flagSpanStop = "";
438  functionStart = "";
439  functionStop = "\n\n";
440  headingStart = "";
441  headingStop = "";
442  indentHtmlOnly = "";
443  ingroupConstructs = "";
444  listStart = "";
445  listStop = "";
446  listLineStart = " * ";
447  listLineStop = "";
448  reference = "";
449  temporaryCharacter = "";
450  }
451  else
452  {
453  anchor = "\\anchor ";
454  boldStart = "<b>";
455  boldStop = "</b>";
456  breakBoth = "<br>";
457  breakHtmlOnly = "<br>";
458  breakTextOnly = "";
459  brief = "\\brief ";
460  commentStart = "/*!";
461  commentStop = "*/";
462  defgroupAttributeListStart = "\\defgroup AttributeList ";
464  defgroupGlobalValueListStart = "\\defgroup GlobalValueList ";
466  defgroupTraceSourceListStart = "\\defgroup TraceSourceList ";
468  flagSpanStart = "<span class=\"mlabel\">";
469  flagSpanStop = "</span>";
470  functionStart = "\\class ";
471  functionStop = "";
472  headingStart = "<h3>";
473  headingStop = "</h3>";
474  indentHtmlOnly = " ";
475  ingroupConstructs = "\\ingroup constructs\n";
476  listStart = "<ul>";
477  listStop = "</ul>";
478  listLineStart = "<li>";
479  listLineStop = "</li>";
480  reference = "\\ref ";
481  temporaryCharacter = "%";
482  }
483 
484  NodeContainer c; c.Create (1);
485 
486  // The below statements register typical aggregation relationships
487  // in ns-3 programs, that otherwise aren't picked up automatically
488  // by the creation of the above node. To manually list other common
489  // aggregation relationships that you would like to see show up in
490  // the list of configuration paths in the doxygen, add additional
491  // statements below.
492  StaticInformation info;
493  info.RecordAggregationInfo ("ns3::Node", "ns3::TcpSocketFactory");
494  info.RecordAggregationInfo ("ns3::Node", "ns3::UdpSocketFactory");
495  info.RecordAggregationInfo ("ns3::Node", "ns3::PacketSocketFactory");
496  info.RecordAggregationInfo ("ns3::Node", "ns3::olsr::RoutingProtocol");
497  info.RecordAggregationInfo ("ns3::Node", "ns3::MobilityModel");
498  info.RecordAggregationInfo ("ns3::Node", "ns3::Ipv4L3Protocol");
499  info.RecordAggregationInfo ("ns3::Node", "ns3::ArpL3Protocol");
500  info.RecordAggregationInfo ("ns3::Node", "ns3::Icmpv4L4Protocol");
501  info.RecordAggregationInfo ("ns3::Node", "ns3::UdpL4Protocol");
502  info.RecordAggregationInfo ("ns3::Node", "ns3::Ipv6L3Protocol");
503  info.RecordAggregationInfo ("ns3::Node", "ns3::Icmpv6L4Protocol");
504  info.RecordAggregationInfo ("ns3::Node", "ns3::TcpL4Protocol");
505 
506  // Create a channel object so that channels appear in the namespace
507  // paths that will be generated here.
508  Ptr<CsmaChannel> csma;
509  csma = CreateObject<CsmaChannel> ();
510 
511  for (uint32_t i = 0; i < Config::GetRootNamespaceObjectN (); ++i)
512  {
514  info.Gather (object->GetInstanceTypeId ());
515  }
516 
517  std::map< std::string, uint32_t> nameMap;
518  std::map< std::string, uint32_t>::const_iterator nameMapIterator;
519 
520  // Create a map from the class names to their index in the vector of
521  // TypeId's so that the names will end up in alphabetical order.
522  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++)
523  {
524  TypeId tid = TypeId::GetRegistered (i);
525  if (tid.MustHideFromDocumentation ())
526  {
527  continue;
528  }
529 
530  // Capitalize all of letters in the name so that it sorts
531  // correctly in the map.
532  std::string name = tid.GetName ();
533  for (uint32_t j = 0; j < name.length (); j++)
534  {
535  name[j] = toupper (name[j]);
536  }
537 
538  // Save this name's index.
539  nameMap[name] = i;
540  }
541 
542  // Iterate over the map, which will print the class names in
543  // alphabetical order.
544  for (nameMapIterator = nameMap.begin ();
545  nameMapIterator != nameMap.end ();
546  nameMapIterator++)
547  {
548  // Get the class's index out of the map;
549  uint32_t i = nameMapIterator->second;
550 
551  std::cout << commentStart << std::endl;
552  TypeId tid = TypeId::GetRegistered (i);
553  if (tid.MustHideFromDocumentation ())
554  {
555  continue;
556  }
557  std::cout << functionStart << tid.GetName () << std::endl;
558  std::cout << std::endl;
559  std::vector<std::string> paths = info.Get (tid);
560 
561  // Config --------------
562  if (paths.empty ())
563  {
564  std::cout << "Doxygen introspection did not find any typical Config paths."
565  << breakBoth << std::endl;
566  }
567  else
568  {
569  std::cout << headingStart
570  << "Config Paths"
571  << headingStop << std::endl;
572  std::cout << std::endl;
573  std::cout << tid.GetName ()
574  << " is accessible through the following paths"
575  << " with Config::Set and Config::Connect:"
576  << std::endl;
577  std::cout << listStart << std::endl;
578  for (uint32_t k = 0; k < paths.size (); ++k)
579  {
580  std::string path = paths[k];
581  std::cout << listLineStart << path
582  << listLineStop << breakTextOnly << std::endl;
583  }
584  std::cout << listStop << std::endl;
585  } // Config
586 
587  // Attributes ----------
588  if (tid.GetAttributeN () == 0)
589  {
590  std::cout << "No Attributes are defined for this type."
591  << breakBoth << std::endl;
592  }
593  else
594  {
595  std::cout << headingStart << "Attributes"
596  << headingStop << std::endl;
597  PrintAttributes (tid, std::cout);
598 
599  TypeId tmp = tid.GetParent ();
600  while (tmp.GetParent () != tmp)
601  {
602  if (tmp.GetAttributeN () != 0)
603  {
604  std::cout << headingStart
605  << "Attributes defined in parent class "
606  << tmp.GetName ()
607  << headingStop << std::endl;
608  PrintAttributes (tmp, std::cout);
609  }
610  tmp = tmp.GetParent ();
611  }
612  } // Attributes
613 
614  // Tracing -------------
615  if (tid.GetTraceSourceN () == 0)
616  {
617  std::cout << "No TraceSources are defined for this type."
618  << breakBoth << std::endl;
619  }
620  else
621  {
622  std::cout << headingStart << "TraceSources"
623  << headingStop << std::endl;
624  PrintTraceSources (tid, std::cout);
625  }
626  {
627  TypeId tmp = tid.GetParent ();
628  while (tmp.GetParent () != tmp)
629  {
630  if (tmp.GetTraceSourceN () != 0)
631  {
632  std::cout << headingStart
633  << "TraceSources defined in parent class "
634  << tmp.GetName ()
635  << headingStop << std::endl;
636  PrintTraceSources (tmp, std::cout);
637  }
638  tmp = tmp.GetParent ();
639  }
640  }
641  std::cout << commentStop << std::endl;
642  } // class documentation
643 
644 
645  std::cout << commentStart << std::endl
647  << defgroupTraceSourceListStart << "The list of all trace sources."
648  << defgroupTraceSourceListStop << std::endl;
649  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
650  {
651  TypeId tid = TypeId::GetRegistered (i);
652  if (tid.GetTraceSourceN () == 0 ||
654  {
655  continue;
656  }
657  std::cout << boldStart << tid.GetName ()
658  << boldStop << breakHtmlOnly << std::endl
659  << listStart << std::endl;
660  for (uint32_t j = 0; j < tid.GetTraceSourceN (); ++j)
661  {
662  struct TypeId::TraceSourceInformation info = tid.GetTraceSource(j);
663  std::cout << listLineStart << info.name << ": " << info.help
664  << listLineStop << std::endl;
665  }
666  std::cout << listStop << std::endl;
667  }
668  std::cout << commentStop << std::endl;
669 
670  std::cout << commentStart << std::endl
672  << defgroupAttributeListStart << "The list of all attributes."
673  << defgroupAttributeListStop << std::endl;
674  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
675  {
676  TypeId tid = TypeId::GetRegistered (i);
677  if (tid.GetAttributeN () == 0 ||
679  {
680  continue;
681  }
682  std::cout << boldStart << tid.GetName ()
683  << boldStop << breakHtmlOnly << std::endl
684  << listStart << std::endl;
685  for (uint32_t j = 0; j < tid.GetAttributeN (); ++j)
686  {
687  struct TypeId::AttributeInformation info = tid.GetAttribute(j);
688  std::cout << listLineStart << info.name << ": " << info.help
689  << listLineStop << std::endl;
690  }
691  std::cout << listStop << std::endl;
692  }
693  std::cout << commentStop << std::endl;
694 
695 
696 
697  std::cout << commentStart << std::endl
699  << defgroupGlobalValueListStart << "The list of all global values."
700  << defgroupGlobalValueListStop << std::endl
701  << listStart << std::endl;
702  for (GlobalValue::Iterator i = GlobalValue::Begin ();
703  i != GlobalValue::End ();
704  ++i)
705  {
706  StringValue val;
707  (*i)->GetValue (val);
708  std::cout << indentHtmlOnly
709  << listLineStart
710  << boldStart
711  << anchor
712  << "GlobalValue" << (*i)->GetName () << " " << (*i)->GetName ()
713  << boldStop
714  << ": " << (*i)->GetHelp () << "(" << val.Get () << ")"
715  << listLineStop << std::endl;
716  }
717  std::cout << listStop << std::endl
718  << commentStop << std::endl;
719 
720 
721  return 0;
722 }
uint32_t GetAttributeN(void) const
Definition: type-id.cc:592
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
virtual TypeId GetInstanceTypeId(void) const
Definition: object.cc:76
std::vector< std::pair< TypeId, std::string > > m_output
void find_and_replace(std::string &source, const std::string find, std::string replace)
hold variables of type string
Definition: string.h:19
std::string defgroupAttributeListStop
end of AttributeList group
std::string defgroupTraceSourceListStart
start of TraceSourceList group
std::string defgroupGlobalValueListStop
end of GlobalValueList group
std::string headingStart
start of section heading (h3)
std::string flagSpanStart
start of Attribute flag value
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
TypeId GetParent(void) const
Definition: type-id.cc:485
std::vector< std::string > Get(TypeId tid)
Ptr< Object > GetRootNamespaceObject(uint32_t i)
Definition: config.cc:763
std::string breakTextOnly
linebreak for text output only
virtual bool HasUnderlyingTypeInformation(void) const =0
bool MustHideFromDocumentation(void) const
Definition: type-id.cc:584
std::string defgroupGlobalValueListStart
start of GlobalValueList group
std::string defgroupTraceSourceListStop
end of TraceSourceList group
static uint32_t GetRegisteredN(void)
Definition: type-id.cc:436
bool HasAlreadyBeenProcessed(TypeId tid) const
static Iterator Begin(void)
virtual std::string GetValueTypeName(void) const =0
uint32_t GetTraceSourceN(void) const
Definition: type-id.cc:613
static TypeId GetRegistered(uint32_t i)
Definition: type-id.cc:442
std::string breakHtmlOnly
linebreak for html output only
keep track of a set of node pointers.
std::string GetName(void) const
Definition: type-id.cc:518
std::vector< TypeId > m_alreadyProcessed
static Iterator End(void)
std::vector< std::string > m_currentPath
uint32_t GetRootNamespaceObjectN(void)
Definition: config.cc:757
bool IsChildOf(TypeId other) const
Definition: type-id.cc:499
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
std::string defgroupAttributeListStart
start of AttributeList group
struct TypeId::TraceSourceInformation GetTraceSource(uint32_t i) const
Definition: type-id.cc:619
struct TypeId::AttributeInformation GetAttribute(uint32_t i) const
Definition: type-id.cc:599
std::vector< std::pair< TypeId, TypeId > > m_aggregates
virtual std::string GetUnderlyingTypeInformation(void) const =0
std::string flagSpanStop
end of Attribute flag value
a unique identifier for an interface.
Definition: type-id.h:44
static TypeId LookupByName(std::string name)
Definition: type-id.cc:415
std::string GetCurrentPath(void) const
void RecordAggregationInfo(std::string a, std::string b)