cmDocumentation.cxx 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  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 "cmDocumentation.h"
  14. #include "cmSystemTools.h"
  15. //----------------------------------------------------------------------------
  16. static const cmDocumentationEntry cmDocumentationStandardOptions[] =
  17. {
  18. {"--copyright [file]", "Print the CMake copyright and exit.",
  19. "If a file is specified, the copyright is written into it."},
  20. {"--help [command]", "Print usage information and exit.",
  21. "Usage describes the basic command line interface and its options. "
  22. "If a listfile command is specified, help for that specific command is "
  23. "printed."},
  24. {"--help-full [file]", "Print full help and exit.",
  25. "Full help displays most of the documentation provided by the UNIX "
  26. "man page. It is provided for use on non-UNIX platforms, but is "
  27. "also convenient if the man page is not installed. If a file is "
  28. "specified, the help is written into it."},
  29. {"--help-html [file]", "Print full help in HTML format.",
  30. "This option is used by CMake authors to help produce web pages. "
  31. "If a file is specified, the help is written into it."},
  32. {"--help-man [file]", "Print a UNIX man page and exit.",
  33. "This option is used by the cmake build to generate the UNIX man page. "
  34. "If a file is specified, the help is written into it."},
  35. {"--version [file]", "Show program name/version banner and exit.",
  36. "If a file is specified, the version is written into it."},
  37. {0,0,0}
  38. };
  39. //----------------------------------------------------------------------------
  40. static const cmDocumentationEntry cmDocumentationCommandsHeader[] =
  41. {
  42. {0,
  43. "The following commands are available in CMakeLists.txt code:", 0},
  44. {0,0,0}
  45. };
  46. //----------------------------------------------------------------------------
  47. static const cmDocumentationEntry cmDocumentationGeneratorsHeader[] =
  48. {
  49. {0,
  50. "The following generators are available on this platform:", 0},
  51. {0,0,0}
  52. };
  53. //----------------------------------------------------------------------------
  54. const cmDocumentationEntry cmDocumentationMailingList[] =
  55. {
  56. {0,
  57. "For help and discussion about using cmake, a mailing list is provided "
  58. "at [email protected]. Please first read the full documentation at "
  59. "http://www.cmake.org before posting questions to the list.", 0},
  60. {0,0,0}
  61. };
  62. //----------------------------------------------------------------------------
  63. const cmDocumentationEntry cmDocumentationAuthor[] =
  64. {
  65. {0,
  66. "This manual page was generated by the \"--help-man\" option.", 0},
  67. {0,0,0}
  68. };
  69. //----------------------------------------------------------------------------
  70. const cmDocumentationEntry cmDocumentationCopyright[] =
  71. {
  72. {0,
  73. "Copyright (c) 2002 Kitware, Inc., Insight Consortium. "
  74. "All rights reserved.", 0},
  75. {0,
  76. "Redistribution and use in source and binary forms, with or without "
  77. "modification, are permitted provided that the following conditions are "
  78. "met:", 0},
  79. {"",
  80. "Redistributions of source code must retain the above copyright notice, "
  81. "this list of conditions and the following disclaimer.", 0},
  82. {"",
  83. "Redistributions in binary form must reproduce the above copyright "
  84. "notice, this list of conditions and the following disclaimer in the "
  85. "documentation and/or other materials provided with the distribution.",
  86. 0},
  87. {"",
  88. "The names of Kitware, Inc., the Insight Consortium, or the names of "
  89. "any consortium members, or of any contributors, may not be used to "
  90. "endorse or promote products derived from this software without "
  91. "specific prior written permission.", 0},
  92. {"",
  93. "Modified source versions must be plainly marked as such, and must "
  94. "not be misrepresented as being the original software.", 0},
  95. {0,
  96. "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "
  97. "``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT "
  98. "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR "
  99. "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR "
  100. "CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, "
  101. "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, "
  102. "PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR "
  103. "PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF "
  104. "LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING "
  105. "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS "
  106. "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", 0},
  107. {0, 0, 0}
  108. };
  109. //----------------------------------------------------------------------------
  110. cmDocumentation::cmDocumentation()
  111. {
  112. this->CurrentForm = TextForm;
  113. this->TextIndent = "";
  114. this->TextWidth = 77;
  115. }
  116. //----------------------------------------------------------------------------
  117. void cmDocumentation::PrintCopyright(std::ostream& os)
  118. {
  119. os << "CMake version " CMake_VERSION_FULL "\n";
  120. for(const cmDocumentationEntry* op = cmDocumentationCopyright;
  121. op->brief; ++op)
  122. {
  123. if(op->name)
  124. {
  125. os << " * ";
  126. this->TextIndent = " ";
  127. this->PrintColumn(os, op->brief);
  128. }
  129. else
  130. {
  131. this->TextIndent = "";
  132. this->PrintColumn(os, op->brief);
  133. }
  134. os << "\n";
  135. }
  136. }
  137. //----------------------------------------------------------------------------
  138. void cmDocumentation::PrintVersion(std::ostream& os)
  139. {
  140. os << this->GetNameString() << " version " CMake_VERSION_FULL "\n";
  141. }
  142. //----------------------------------------------------------------------------
  143. void cmDocumentation::AddSection(const char* name,
  144. const cmDocumentationEntry* d)
  145. {
  146. this->Names.push_back(name);
  147. this->Sections.push_back(d);
  148. }
  149. //----------------------------------------------------------------------------
  150. void cmDocumentation::ClearSections()
  151. {
  152. this->Names.erase(this->Names.begin(), this->Names.end());
  153. this->Sections.erase(this->Sections.begin(), this->Sections.end());
  154. }
  155. //----------------------------------------------------------------------------
  156. void cmDocumentation::PrintDocumentation(Type ht, std::ostream& os)
  157. {
  158. switch (ht)
  159. {
  160. case cmDocumentation::Usage: this->PrintDocumentationUsage(os); break;
  161. case cmDocumentation::Full: this->PrintDocumentationFull(os); break;
  162. case cmDocumentation::HTML: this->PrintDocumentationHTML(os); break;
  163. case cmDocumentation::Man: this->PrintDocumentationMan(os); break;
  164. case cmDocumentation::Copyright: this->PrintCopyright(os); break;
  165. case cmDocumentation::Version: this->PrintVersion(os); break;
  166. default: break;
  167. }
  168. }
  169. //----------------------------------------------------------------------------
  170. bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os)
  171. {
  172. bool result = true;
  173. // Loop over requested documentation types.
  174. for(RequestedMapType::const_iterator i = this->RequestedMap.begin();
  175. i != this->RequestedMap.end(); ++i)
  176. {
  177. // Special case for printing help for a single command.
  178. if(i->first == cmDocumentation::Usage && i->second.length() > 0 &&
  179. !this->CommandsSection.empty())
  180. {
  181. // Check if the argument to the usage request was a command.
  182. for(cmDocumentationEntry* entry = &this->CommandsSection[0];
  183. entry->brief; ++entry)
  184. {
  185. if(entry->name && (strcmp(entry->name, i->second.c_str()) == 0))
  186. {
  187. this->PrintDocumentationCommand(os, entry);
  188. return true;
  189. }
  190. }
  191. // Argument was not a command. Complain.
  192. os << "Help argument \"" << i->second.c_str()
  193. << "\" is not a CMake command. "
  194. << "Use --help-full to see all commands.\n";
  195. return false;
  196. }
  197. // If a file name was given, use it. Otherwise, default to the
  198. // given stream.
  199. std::ofstream* fout = 0;
  200. std::ostream* s = &os;
  201. if(i->second.length() > 0)
  202. {
  203. fout = new std::ofstream(i->second.c_str(), std::ios::out);
  204. if(fout)
  205. {
  206. s = fout;
  207. }
  208. else
  209. {
  210. result = false;
  211. }
  212. }
  213. // Print this documentation type to the stream.
  214. this->PrintDocumentation(i->first, *s);
  215. // Check for error.
  216. if(!*s)
  217. {
  218. result = false;
  219. }
  220. // Close the file if we wrote one.
  221. if(fout)
  222. {
  223. delete fout;
  224. }
  225. }
  226. return result;
  227. }
  228. //----------------------------------------------------------------------------
  229. bool cmDocumentation::CheckOptions(int argc, const char* const* argv)
  230. {
  231. // Providing zero arguments gives usage information.
  232. if(argc == 1)
  233. {
  234. this->RequestedMap[cmDocumentation::Usage] = "";
  235. return true;
  236. }
  237. // Search for supported help options.
  238. bool result = false;
  239. for(int i=1; i < argc; ++i)
  240. {
  241. // Check if this is a supported help option.
  242. Type type = cmDocumentation::None;
  243. if((strcmp(argv[i], "-help") == 0) ||
  244. (strcmp(argv[i], "--help") == 0) ||
  245. (strcmp(argv[i], "/?") == 0) ||
  246. (strcmp(argv[i], "-usage") == 0) ||
  247. (strcmp(argv[i], "-h") == 0) ||
  248. (strcmp(argv[i], "-H") == 0))
  249. {
  250. type = cmDocumentation::Usage;
  251. }
  252. else if(strcmp(argv[i], "--help-full") == 0)
  253. {
  254. type = cmDocumentation::Full;
  255. }
  256. else if(strcmp(argv[i], "--help-html") == 0)
  257. {
  258. type = cmDocumentation::HTML;
  259. }
  260. else if(strcmp(argv[i], "--help-man") == 0)
  261. {
  262. type = cmDocumentation::Man;
  263. }
  264. else if(strcmp(argv[i], "--copyright") == 0)
  265. {
  266. type = cmDocumentation::Copyright;
  267. }
  268. else if((strcmp(argv[i], "--version") == 0) ||
  269. (strcmp(argv[i], "-version") == 0) ||
  270. (strcmp(argv[i], "/V") == 0))
  271. {
  272. type = cmDocumentation::Version;
  273. }
  274. if(type)
  275. {
  276. // This is a help option. See if there is a file name given.
  277. result = true;
  278. if((i+1 < argc) && (argv[i+1][0] != '-') &&
  279. (strcmp(argv[i+1], "/V") != 0) && (strcmp(argv[i+1], "/?") != 0))
  280. {
  281. this->RequestedMap[type] = argv[i+1];
  282. i = i+1;
  283. }
  284. else
  285. {
  286. this->RequestedMap[type] = "";
  287. }
  288. }
  289. }
  290. return result;
  291. }
  292. //----------------------------------------------------------------------------
  293. void cmDocumentation::Print(Form f, std::ostream& os)
  294. {
  295. this->CurrentForm = f;
  296. for(unsigned int i=0; i < this->Sections.size(); ++i)
  297. {
  298. this->PrintSection(os, this->Sections[i], this->Names[i]);
  299. }
  300. }
  301. //----------------------------------------------------------------------------
  302. void cmDocumentation::SetName(const char* name)
  303. {
  304. this->NameString = name?name:"";
  305. }
  306. //----------------------------------------------------------------------------
  307. void cmDocumentation::SetNameSection(const cmDocumentationEntry* section)
  308. {
  309. this->SetSection(0, section, 0, this->NameSection);
  310. }
  311. //----------------------------------------------------------------------------
  312. void cmDocumentation::SetUsageSection(const cmDocumentationEntry* section)
  313. {
  314. this->SetSection(0, section, 0, this->UsageSection);
  315. }
  316. //----------------------------------------------------------------------------
  317. void cmDocumentation::SetDescriptionSection(const cmDocumentationEntry* section)
  318. {
  319. this->SetSection(0, section, 0, this->DescriptionSection);
  320. }
  321. //----------------------------------------------------------------------------
  322. void cmDocumentation::SetOptionsSection(const cmDocumentationEntry* section)
  323. {
  324. this->SetSection(0, section, cmDocumentationStandardOptions,
  325. this->OptionsSection);
  326. }
  327. //----------------------------------------------------------------------------
  328. void cmDocumentation::SetCommandsSection(const cmDocumentationEntry* section)
  329. {
  330. this->SetSection(cmDocumentationCommandsHeader, section, 0,
  331. this->CommandsSection);
  332. }
  333. //----------------------------------------------------------------------------
  334. void cmDocumentation::SetGeneratorsSection(const cmDocumentationEntry* section)
  335. {
  336. this->SetSection(cmDocumentationGeneratorsHeader, section, 0,
  337. this->GeneratorsSection);
  338. }
  339. //----------------------------------------------------------------------------
  340. void cmDocumentation::SetSeeAlsoList(const cmDocumentationEntry* also)
  341. {
  342. this->SeeAlsoString = ".B ";
  343. for(const cmDocumentationEntry* i = also; i->brief; ++i)
  344. {
  345. this->SeeAlsoString += i->brief;
  346. this->SeeAlsoString += (i+1)->brief? "(1), ":"(1)";
  347. }
  348. cmDocumentationEntry e = {0, 0, 0};
  349. e.brief = this->SeeAlsoString.c_str();
  350. this->SeeAlsoSection.push_back(e);
  351. e.brief = 0;
  352. this->SeeAlsoSection.push_back(e);
  353. }
  354. //----------------------------------------------------------------------------
  355. void cmDocumentation::PrintSection(std::ostream& os,
  356. const cmDocumentationEntry* section,
  357. const char* name)
  358. {
  359. switch (this->CurrentForm)
  360. {
  361. case TextForm: this->PrintSectionText(os, section, name); break;
  362. case HTMLForm: this->PrintSectionHTML(os, section, name); break;
  363. case ManForm: this->PrintSectionMan(os, section, name); break;
  364. case UsageForm: this->PrintSectionUsage(os, section, name); break;
  365. }
  366. }
  367. //----------------------------------------------------------------------------
  368. void cmDocumentation::PrintSectionText(std::ostream& os,
  369. const cmDocumentationEntry* section,
  370. const char* name)
  371. {
  372. if(name)
  373. {
  374. os <<
  375. "---------------------------------------"
  376. "---------------------------------------\n";
  377. os << name << "\n\n";
  378. }
  379. if(!section) { return; }
  380. for(const cmDocumentationEntry* op = section; op->brief; ++op)
  381. {
  382. if(op->name)
  383. {
  384. if(op->name[0])
  385. {
  386. os << " " << op->name << "\n";
  387. }
  388. this->TextIndent = " ";
  389. this->PrintFormatted(os, op->brief);
  390. if(op->full)
  391. {
  392. os << "\n";
  393. this->PrintFormatted(os, op->full);
  394. }
  395. }
  396. else
  397. {
  398. this->TextIndent = "";
  399. this->PrintFormatted(os, op->brief);
  400. }
  401. os << "\n";
  402. }
  403. }
  404. //----------------------------------------------------------------------------
  405. void cmDocumentation::PrintSectionHTML(std::ostream& os,
  406. const cmDocumentationEntry* section,
  407. const char* name)
  408. {
  409. if(name)
  410. {
  411. os << "<h2>" << name << "</h2>\n";
  412. }
  413. if(!section) { return; }
  414. for(const cmDocumentationEntry* op = section; op->brief;)
  415. {
  416. if(op->name)
  417. {
  418. os << "<ul>\n";
  419. for(;op->name;++op)
  420. {
  421. os << " <li>\n";
  422. if(op->name[0])
  423. {
  424. os << " <b><code>";
  425. this->PrintHTMLEscapes(os, op->name);
  426. os << "</code></b>: ";
  427. }
  428. this->PrintHTMLEscapes(os, op->brief);
  429. if(op->full)
  430. {
  431. os << "<br>\n ";
  432. this->PrintFormatted(os, op->full);
  433. }
  434. os << "\n";
  435. os << " </li>\n";
  436. }
  437. os << "</ul>\n";
  438. }
  439. else
  440. {
  441. this->PrintFormatted(os, op->brief);
  442. os << "\n";
  443. ++op;
  444. }
  445. }
  446. }
  447. //----------------------------------------------------------------------------
  448. void cmDocumentation::PrintSectionMan(std::ostream& os,
  449. const cmDocumentationEntry* section,
  450. const char* name)
  451. {
  452. if(name)
  453. {
  454. os << ".SH " << name << "\n";
  455. }
  456. if(!section) { return; }
  457. for(const cmDocumentationEntry* op = section; op->brief; ++op)
  458. {
  459. if(op->name)
  460. {
  461. os << ".TP\n"
  462. << ".B " << (op->name[0]?op->name:"*") << "\n";
  463. this->PrintFormatted(os, op->brief);
  464. this->PrintFormatted(os, op->full);
  465. }
  466. else
  467. {
  468. os << ".PP\n";
  469. this->PrintFormatted(os, op->brief);
  470. }
  471. }
  472. }
  473. //----------------------------------------------------------------------------
  474. void cmDocumentation::PrintSectionUsage(std::ostream& os,
  475. const cmDocumentationEntry* section,
  476. const char* name)
  477. {
  478. if(name)
  479. {
  480. os << name << "\n";
  481. }
  482. if(!section) { return; }
  483. for(const cmDocumentationEntry* op = section; op->brief; ++op)
  484. {
  485. if(op->name)
  486. {
  487. os << " " << op->name;
  488. this->TextIndent = " ";
  489. int align = static_cast<int>(strlen(this->TextIndent))-4;
  490. for(int i = static_cast<int>(strlen(op->name)); i < align; ++i)
  491. {
  492. os << " ";
  493. }
  494. os << "= ";
  495. this->PrintColumn(os, op->brief);
  496. os << "\n";
  497. }
  498. else
  499. {
  500. os << "\n";
  501. this->TextIndent = "";
  502. this->PrintFormatted(os, op->brief);
  503. }
  504. }
  505. os << "\n";
  506. }
  507. //----------------------------------------------------------------------------
  508. void cmDocumentation::PrintFormatted(std::ostream& os, const char* text)
  509. {
  510. if(!text)
  511. {
  512. return;
  513. }
  514. const char* ptr = text;
  515. while(*ptr)
  516. {
  517. // Any ptrs starting in a space are treated as preformatted text.
  518. std::string preformatted;
  519. while(*ptr == ' ')
  520. {
  521. for(char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr)
  522. {
  523. preformatted.append(1, ch);
  524. }
  525. if(*ptr)
  526. {
  527. ++ptr;
  528. preformatted.append(1, '\n');
  529. }
  530. }
  531. if(preformatted.length())
  532. {
  533. this->PrintPreformatted(os, preformatted.c_str());
  534. }
  535. // Other ptrs are treated as paragraphs.
  536. std::string paragraph;
  537. for(char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr)
  538. {
  539. paragraph.append(1, ch);
  540. }
  541. if(*ptr)
  542. {
  543. ++ptr;
  544. paragraph.append(1, '\n');
  545. }
  546. if(paragraph.length())
  547. {
  548. this->PrintParagraph(os, paragraph.c_str());
  549. }
  550. }
  551. }
  552. //----------------------------------------------------------------------------
  553. void cmDocumentation::PrintPreformatted(std::ostream& os, const char* text)
  554. {
  555. switch (this->CurrentForm)
  556. {
  557. case TextForm: this->PrintPreformattedText(os, text); break;
  558. case HTMLForm: this->PrintPreformattedHTML(os, text); break;
  559. case ManForm: this->PrintPreformattedMan(os, text); break;
  560. case UsageForm: this->PrintPreformattedText(os, text); break;
  561. }
  562. }
  563. //----------------------------------------------------------------------------
  564. void cmDocumentation::PrintParagraph(std::ostream& os, const char* text)
  565. {
  566. switch (this->CurrentForm)
  567. {
  568. case TextForm: this->PrintParagraphText(os, text); break;
  569. case HTMLForm: this->PrintParagraphHTML(os, text); break;
  570. case ManForm: this->PrintParagraphMan(os, text); break;
  571. case UsageForm: this->PrintParagraphText(os, text); break;
  572. }
  573. }
  574. //----------------------------------------------------------------------------
  575. void cmDocumentation::PrintPreformattedText(std::ostream& os, const char* text)
  576. {
  577. bool newline = true;
  578. for(const char* ptr = text; *ptr; ++ptr)
  579. {
  580. if(newline)
  581. {
  582. os << this->TextIndent;
  583. newline = false;
  584. }
  585. os << *ptr;
  586. if(*ptr == '\n')
  587. {
  588. newline = true;
  589. }
  590. }
  591. os << "\n";
  592. }
  593. //----------------------------------------------------------------------------
  594. void cmDocumentation::PrintParagraphText(std::ostream& os, const char* text)
  595. {
  596. os << this->TextIndent;
  597. this->PrintColumn(os, text);
  598. os << "\n";
  599. }
  600. //----------------------------------------------------------------------------
  601. void cmDocumentation::PrintPreformattedHTML(std::ostream& os, const char* text)
  602. {
  603. os << "<pre>";
  604. this->PrintHTMLEscapes(os, text);
  605. os << "</pre>\n ";
  606. }
  607. //----------------------------------------------------------------------------
  608. void cmDocumentation::PrintParagraphHTML(std::ostream& os, const char* text)
  609. {
  610. os << "<p>";
  611. this->PrintHTMLEscapes(os, text);
  612. }
  613. //----------------------------------------------------------------------------
  614. void cmDocumentation::PrintPreformattedMan(std::ostream& os, const char* text)
  615. {
  616. os << text << "\n";
  617. }
  618. //----------------------------------------------------------------------------
  619. void cmDocumentation::PrintParagraphMan(std::ostream& os, const char* text)
  620. {
  621. os << text << "\n\n";
  622. }
  623. //----------------------------------------------------------------------------
  624. void cmDocumentation::PrintColumn(std::ostream& os, const char* text)
  625. {
  626. // Print text arranged in an indented column of fixed witdh.
  627. const char* l = text;
  628. int column = 0;
  629. bool newSentence = false;
  630. bool firstLine = true;
  631. int width = this->TextWidth - static_cast<int>(strlen(this->TextIndent));
  632. // Loop until the end of the text.
  633. while(*l)
  634. {
  635. // Parse the next word.
  636. const char* r = l;
  637. while(*r && (*r != '\n') && (*r != ' ')) { ++r; }
  638. // Does it fit on this line?
  639. if(r-l < (width-column-(newSentence?1:0)))
  640. {
  641. // Word fits on this line.
  642. if(r > l)
  643. {
  644. if(column)
  645. {
  646. // Not first word on line. Separate from the previous word
  647. // by a space, or two if this is a new sentence.
  648. if(newSentence)
  649. {
  650. os << " ";
  651. column += 2;
  652. }
  653. else
  654. {
  655. os << " ";
  656. column += 1;
  657. }
  658. }
  659. else
  660. {
  661. // First word on line. Print indentation unless this is the
  662. // first line.
  663. os << (firstLine?"":this->TextIndent);
  664. }
  665. // Print the word.
  666. os.write(l, static_cast<long>(r-l));
  667. newSentence = (*(r-1) == '.');
  668. }
  669. if(*r == '\n')
  670. {
  671. // Text provided a newline. Start a new line.
  672. os << "\n";
  673. ++r;
  674. column = 0;
  675. firstLine = false;
  676. }
  677. else
  678. {
  679. // No provided newline. Continue this line.
  680. column += static_cast<long>(r-l);
  681. }
  682. }
  683. else
  684. {
  685. // Word does not fit on this line. Start a new line.
  686. os << "\n";
  687. firstLine = false;
  688. if(r > l)
  689. {
  690. os << this->TextIndent;
  691. os.write(l, static_cast<long>(r-l));
  692. column = static_cast<long>(r-l);
  693. newSentence = (*(r-1) == '.');
  694. }
  695. }
  696. // Move to beginning of next word. Skip over whitespace.
  697. l = r;
  698. while(*l && (*l == ' ')) { ++l; }
  699. }
  700. }
  701. //----------------------------------------------------------------------------
  702. void cmDocumentation::PrintHTMLEscapes(std::ostream& os, const char* text)
  703. {
  704. static cmDocumentationEntry escapes[] =
  705. {
  706. {"<", "&lt;", 0},
  707. {">", "&gt;", 0},
  708. {"&", "&amp;", 0},
  709. {"\n", "<br>", 0},
  710. {0,0,0}
  711. };
  712. for(const char* p = text; *p; ++p)
  713. {
  714. bool found = false;
  715. for(const cmDocumentationEntry* op = escapes; !found && op->name; ++op)
  716. {
  717. if(op->name[0] == *p)
  718. {
  719. os << op->brief;
  720. found = true;
  721. }
  722. }
  723. if(!found)
  724. {
  725. os << *p;
  726. }
  727. }
  728. }
  729. //----------------------------------------------------------------------------
  730. void cmDocumentation::PrintDocumentationUsage(std::ostream& os)
  731. {
  732. this->CreateUsageDocumentation();
  733. this->Print(UsageForm, os);
  734. }
  735. //----------------------------------------------------------------------------
  736. void cmDocumentation::PrintDocumentationFull(std::ostream& os)
  737. {
  738. this->CreateFullDocumentation();
  739. this->Print(TextForm, os);
  740. }
  741. //----------------------------------------------------------------------------
  742. void cmDocumentation::PrintDocumentationHTML(std::ostream& os)
  743. {
  744. this->CreateFullDocumentation();
  745. os << "<html><body>\n";
  746. this->Print(HTMLForm, os);
  747. os << "</body></html>\n";
  748. }
  749. //----------------------------------------------------------------------------
  750. void cmDocumentation::PrintDocumentationMan(std::ostream& os)
  751. {
  752. this->CreateManDocumentation();
  753. os << ".TH " << this->GetNameString() << " 1 \""
  754. << cmSystemTools::GetCurrentDateTime("%B %d, %Y").c_str()
  755. << "\" \"" << this->GetNameString() << " " CMake_VERSION_FULL "\"\n";
  756. this->Print(ManForm, os);
  757. }
  758. //----------------------------------------------------------------------------
  759. void cmDocumentation::PrintDocumentationCommand(std::ostream& os,
  760. cmDocumentationEntry* entry)
  761. {
  762. cmDocumentationEntry singleCommandSection[3] =
  763. {
  764. {entry->name, entry->brief, entry->full},
  765. {0,0,0}
  766. };
  767. this->ClearSections();
  768. this->AddSection(0, &singleCommandSection[0]);
  769. this->Print(TextForm, os);
  770. }
  771. //----------------------------------------------------------------------------
  772. void cmDocumentation::CreateUsageDocumentation()
  773. {
  774. this->ClearSections();
  775. if(!this->UsageSection.empty())
  776. {
  777. this->AddSection("Usage", &this->UsageSection[0]);
  778. }
  779. if(!this->OptionsSection.empty())
  780. {
  781. this->AddSection("Command-Line Options", &this->OptionsSection[0]);
  782. }
  783. if(!this->GeneratorsSection.empty())
  784. {
  785. this->AddSection("Generators", &this->GeneratorsSection[0]);
  786. }
  787. }
  788. //----------------------------------------------------------------------------
  789. void cmDocumentation::CreateFullDocumentation()
  790. {
  791. this->ClearSections();
  792. if(!this->NameSection.empty())
  793. {
  794. this->AddSection("Name", &this->NameSection[0]);
  795. }
  796. if(!this->UsageSection.empty())
  797. {
  798. this->AddSection("Usage", &this->UsageSection[0]);
  799. }
  800. if(!this->DescriptionSection.empty())
  801. {
  802. this->AddSection(0, &this->DescriptionSection[0]);
  803. }
  804. if(!this->OptionsSection.empty())
  805. {
  806. this->AddSection("Command-Line Options", &this->OptionsSection[0]);
  807. }
  808. if(!this->GeneratorsSection.empty())
  809. {
  810. this->AddSection("Generators", &this->GeneratorsSection[0]);
  811. }
  812. if(!this->CommandsSection.empty())
  813. {
  814. this->AddSection("Listfile Commands", &this->CommandsSection[0]);
  815. }
  816. this->AddSection("Copyright", cmDocumentationCopyright);
  817. this->AddSection("Mailing List", cmDocumentationMailingList);
  818. }
  819. //----------------------------------------------------------------------------
  820. void cmDocumentation::CreateManDocumentation()
  821. {
  822. this->ClearSections();
  823. if(!this->NameSection.empty())
  824. {
  825. this->AddSection("NAME", &this->NameSection[0]);
  826. }
  827. if(!this->UsageSection.empty())
  828. {
  829. this->AddSection("SYNOPSIS", &this->UsageSection[0]);
  830. }
  831. if(!this->DescriptionSection.empty())
  832. {
  833. this->AddSection("DESCRIPTION", &this->DescriptionSection[0]);
  834. }
  835. if(!this->OptionsSection.empty())
  836. {
  837. this->AddSection("OPTIONS", &this->OptionsSection[0]);
  838. }
  839. if(!this->GeneratorsSection.empty())
  840. {
  841. this->AddSection("GENERATORS", &this->GeneratorsSection[0]);
  842. }
  843. if(!this->CommandsSection.empty())
  844. {
  845. this->AddSection("COMMANDS", &this->CommandsSection[0]);
  846. }
  847. this->AddSection("COPYRIGHT", cmDocumentationCopyright);
  848. this->AddSection("MAILING LIST", cmDocumentationMailingList);
  849. if(!this->SeeAlsoSection.empty())
  850. {
  851. this->AddSection("SEE ALSO", &this->SeeAlsoSection[0]);
  852. }
  853. this->AddSection("AUTHOR", cmDocumentationAuthor);
  854. }
  855. //----------------------------------------------------------------------------
  856. void cmDocumentation::SetSection(const cmDocumentationEntry* header,
  857. const cmDocumentationEntry* section,
  858. const cmDocumentationEntry* footer,
  859. std::vector<cmDocumentationEntry>& vec)
  860. {
  861. vec.erase(vec.begin(), vec.end());
  862. if(header)
  863. {
  864. for(const cmDocumentationEntry* op = header; op->brief; ++op)
  865. {
  866. vec.push_back(*op);
  867. }
  868. }
  869. if(section)
  870. {
  871. for(const cmDocumentationEntry* op = section; op->brief; ++op)
  872. {
  873. vec.push_back(*op);
  874. }
  875. }
  876. if(footer)
  877. {
  878. for(const cmDocumentationEntry* op = footer; op->brief; ++op)
  879. {
  880. vec.push_back(*op);
  881. }
  882. }
  883. cmDocumentationEntry empty = {0,0,0};
  884. vec.push_back(empty);
  885. }
  886. //----------------------------------------------------------------------------
  887. const char* cmDocumentation::GetNameString()
  888. {
  889. if(this->NameString.length() > 0)
  890. {
  891. return this->NameString.c_str();
  892. }
  893. else
  894. {
  895. return "CMake";
  896. }
  897. }