cmDocumentationFormatterDocbook.cxx 7.4 KB

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