cmDocumentationFormatterDocbook.cxx 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmDocumentationFormatterDocbook.h"
  11. #include "cmDocumentationSection.h"
  12. //----------------------------------------------------------------------------
  13. // this function is a copy of the one in the HTML formatter
  14. // the three functions below are slightly modified copies
  15. static bool cmDocumentationIsHyperlinkCharDocbook(char c)
  16. {
  17. // This is not a complete list but works for CMake documentation.
  18. return ((c >= 'A' && c <= 'Z') ||
  19. (c >= 'a' && c <= 'z') ||
  20. (c >= '0' && c <= '9') ||
  21. c == '-' || c == '.' || c == '/' || c == '~' || c == '@' ||
  22. c == ':' || c == '_' || c == '&' || c == '?' || c == '=');
  23. }
  24. //----------------------------------------------------------------------------
  25. static void cmDocumentationPrintDocbookChar(std::ostream& os, char c)
  26. {
  27. // Use an escape sequence if necessary.
  28. switch(c)
  29. {
  30. case '<':
  31. os << "&lt;";
  32. break;
  33. case '>':
  34. os << "&gt;";
  35. break;
  36. case '&':
  37. os << "&amp;";
  38. break;
  39. default:
  40. os << c;
  41. }
  42. }
  43. //----------------------------------------------------------------------------
  44. const char* cmDocumentationPrintDocbookLink(std::ostream& os,const char* begin)
  45. {
  46. // Look for the end of the link.
  47. const char* end = begin;
  48. while(cmDocumentationIsHyperlinkCharDocbook(*end))
  49. {
  50. ++end;
  51. }
  52. // Print the hyperlink itself.
  53. os << "<ulink url=\"";
  54. for(const char* c = begin; c != end; ++c)
  55. {
  56. cmDocumentationPrintDocbookChar(os, *c);
  57. }
  58. os << "\" />";
  59. return end;
  60. }
  61. //----------------------------------------------------------------------------
  62. void cmDocumentationPrintDocbookEscapes(std::ostream& os, const char* text)
  63. {
  64. // Hyperlink prefixes.
  65. static const char* hyperlinks[] = {"http://", "ftp://", "mailto:", 0};
  66. // Print each character.
  67. for(const char* p = text; *p;)
  68. {
  69. // Handle hyperlinks specially to make them active.
  70. bool found_hyperlink = false;
  71. for(const char** h = hyperlinks; !found_hyperlink && *h; ++h)
  72. {
  73. if(strncmp(p, *h, strlen(*h)) == 0)
  74. {
  75. p = cmDocumentationPrintDocbookLink(os, p);
  76. found_hyperlink = true;
  77. }
  78. }
  79. // Print other characters normally.
  80. if(!found_hyperlink)
  81. {
  82. cmDocumentationPrintDocbookChar(os, *p++);
  83. }
  84. }
  85. }
  86. cmDocumentationFormatterDocbook::cmDocumentationFormatterDocbook()
  87. :cmDocumentationFormatter()
  88. {
  89. }
  90. void cmDocumentationFormatterDocbook
  91. ::PrintSection(std::ostream& os,
  92. const cmDocumentationSection &section,
  93. const char* name)
  94. {
  95. if(name)
  96. {
  97. std::string id = "section_";
  98. id += name;
  99. if (this->EmittedLinkIds.find(id) == this->EmittedLinkIds.end())
  100. {
  101. this->EmittedLinkIds.insert(id);
  102. os << "<sect1 id=\"section_" << name << "\">\n"
  103. "<title>\n" << name << "</title>\n";
  104. }
  105. else
  106. {
  107. static unsigned int i=0;
  108. i++;
  109. os << "<sect1 id=\"section_" << name << i << "\">\n"
  110. "<title>\n" << name << "</title>\n";
  111. }
  112. }
  113. std::string prefix = this->ComputeSectionLinkPrefix(name);
  114. const std::vector<cmDocumentationEntry> &entries =
  115. section.GetEntries();
  116. if (!entries.empty())
  117. {
  118. os << "<itemizedlist>\n";
  119. for(std::vector<cmDocumentationEntry>::const_iterator op
  120. = entries.begin(); op != entries.end(); ++ op )
  121. {
  122. if(op->Name.size())
  123. {
  124. os << " <listitem><link linkend=\"" << prefix << "_";
  125. cmDocumentationPrintDocbookEscapes(os, op->Name.c_str());
  126. os << "\"><emphasis><literal>";
  127. cmDocumentationPrintDocbookEscapes(os, op->Name.c_str());
  128. os << "</literal></emphasis></link></listitem>\n";
  129. }
  130. }
  131. os << "</itemizedlist>\n" ;
  132. }
  133. for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
  134. op != entries.end();)
  135. {
  136. if(op->Name.size())
  137. {
  138. for(;op != entries.end() && op->Name.size(); ++op)
  139. {
  140. if(op->Name.size())
  141. {
  142. os << " <para id=\"" << prefix << "_";
  143. cmDocumentationPrintDocbookEscapes(os, op->Name.c_str());
  144. // make sure that each id exists only once. Since it seems
  145. // not easily possible to determine which link refers to which id,
  146. // we have at least to make sure that the duplicated id's get a
  147. // different name (by appending an increasing number), Alex
  148. std::string id = prefix;
  149. id += "_";
  150. id += op->Name;
  151. if (this->EmittedLinkIds.find(id) == this->EmittedLinkIds.end())
  152. {
  153. this->EmittedLinkIds.insert(id);
  154. }
  155. else
  156. {
  157. static unsigned int i=0;
  158. i++;
  159. os << i;
  160. }
  161. // continue as normal...
  162. os << "\"><sect2><title>";
  163. cmDocumentationPrintDocbookEscapes(os, op->Name.c_str());
  164. os << "</title></sect2> ";
  165. }
  166. cmDocumentationPrintDocbookEscapes(os, op->Brief.c_str());
  167. if(op->Name.size())
  168. {
  169. os << "</para>\n";
  170. }
  171. if(op->Full.size())
  172. {
  173. // a line break seems to be simply a line break with docbook
  174. os << "\n ";
  175. this->PrintFormatted(os, op->Full.c_str());
  176. }
  177. os << "\n";
  178. }
  179. }
  180. else
  181. {
  182. this->PrintFormatted(os, op->Brief.c_str());
  183. os << "\n";
  184. ++op;
  185. }
  186. }
  187. if(name)
  188. {
  189. os << "</sect1>\n";
  190. }
  191. }
  192. void cmDocumentationFormatterDocbook::PrintPreformatted(std::ostream& os,
  193. const char* text)
  194. {
  195. os << "<literallayout>";
  196. cmDocumentationPrintDocbookEscapes(os, text);
  197. os << "</literallayout>\n ";
  198. }
  199. void cmDocumentationFormatterDocbook::PrintParagraph(std::ostream& os,
  200. const char* text)
  201. {
  202. os << "<para>";
  203. cmDocumentationPrintDocbookEscapes(os, text);
  204. os << "</para>";
  205. }
  206. //----------------------------------------------------------------------------
  207. void cmDocumentationFormatterDocbook::PrintHeader(const char* docname,
  208. const char* appname,
  209. std::ostream& os)
  210. {
  211. // this one is used to ensure that we don't create multiple link targets
  212. // with the same name. We can clear it here since we are at the
  213. // start of a document here.
  214. this->EmittedLinkIds.clear();
  215. os << "<?xml version=\"1.0\" ?>\n"
  216. "<!DOCTYPE article PUBLIC \"-//OASIS//DTD DocBook V4.2//EN\" "
  217. "\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\" [\n"
  218. "<!ENTITY % addindex \"IGNORE\">\n"
  219. "<!ENTITY % English \"INCLUDE\"> ]>\n"
  220. "<article>\n"
  221. "<articleinfo>\n"
  222. "<title>" << docname << " - " << appname << "</title>\n"
  223. "</articleinfo>\n";
  224. }
  225. //----------------------------------------------------------------------------
  226. void cmDocumentationFormatterDocbook::PrintFooter(std::ostream& os)
  227. {
  228. os << "</article>\n";
  229. }