cmDocumentation.cxx 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265
  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. #include "cmVersion.h"
  16. #include <cmsys/Directory.hxx>
  17. //----------------------------------------------------------------------------
  18. static const cmDocumentationEntry cmDocumentationStandardOptions[] =
  19. {
  20. {"--copyright [file]", "Print the CMake copyright and exit.",
  21. "If a file is specified, the copyright is written into it."},
  22. {"--help", "Print usage information and exit.",
  23. "Usage describes the basic command line interface and its options."},
  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 cmDocumentationModulesHeader[] =
  48. {
  49. {0,
  50. "The following modules are provided with CMake. "
  51. "They can be used with INCLUDE(ModuleName).", 0},
  52. {0,0,0}
  53. };
  54. //----------------------------------------------------------------------------
  55. static const cmDocumentationEntry cmDocumentationGeneratorsHeader[] =
  56. {
  57. {0,
  58. "The following generators are available on this platform:", 0},
  59. {0,0,0}
  60. };
  61. //----------------------------------------------------------------------------
  62. const cmDocumentationEntry cmDocumentationMailingList[] =
  63. {
  64. {0,
  65. "For help and discussion about using cmake, a mailing list is provided "
  66. "at [email protected]. Please first read the full documentation at "
  67. "http://www.cmake.org before posting questions to the list.", 0},
  68. {0,0,0}
  69. };
  70. //----------------------------------------------------------------------------
  71. const cmDocumentationEntry cmDocumentationAuthor[] =
  72. {
  73. {0,
  74. "This manual page was generated by the \"--help-man\" option.", 0},
  75. {0,0,0}
  76. };
  77. //----------------------------------------------------------------------------
  78. const cmDocumentationEntry cmDocumentationCopyright[] =
  79. {
  80. {0,
  81. "Copyright (c) 2002 Kitware, Inc., Insight Consortium. "
  82. "All rights reserved.", 0},
  83. {0,
  84. "Redistribution and use in source and binary forms, with or without "
  85. "modification, are permitted provided that the following conditions are "
  86. "met:", 0},
  87. {"",
  88. "Redistributions of source code must retain the above copyright notice, "
  89. "this list of conditions and the following disclaimer.", 0},
  90. {"",
  91. "Redistributions in binary form must reproduce the above copyright "
  92. "notice, this list of conditions and the following disclaimer in the "
  93. "documentation and/or other materials provided with the distribution.",
  94. 0},
  95. {"",
  96. "The names of Kitware, Inc., the Insight Consortium, or the names of "
  97. "any consortium members, or of any contributors, may not be used to "
  98. "endorse or promote products derived from this software without "
  99. "specific prior written permission.", 0},
  100. {"",
  101. "Modified source versions must be plainly marked as such, and must "
  102. "not be misrepresented as being the original software.", 0},
  103. {0,
  104. "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "
  105. "``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT "
  106. "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR "
  107. "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR "
  108. "CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, "
  109. "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, "
  110. "PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR "
  111. "PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF "
  112. "LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING "
  113. "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS "
  114. "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", 0},
  115. {0, 0, 0}
  116. };
  117. //----------------------------------------------------------------------------
  118. cmDocumentation::cmDocumentation()
  119. {
  120. this->CurrentForm = TextForm;
  121. this->TextIndent = "";
  122. this->TextWidth = 77;
  123. }
  124. //----------------------------------------------------------------------------
  125. cmDocumentation::~cmDocumentation()
  126. {
  127. for(std::vector< char* >::iterator i = this->ModuleStrings.begin();
  128. i != this->ModuleStrings.end(); ++i)
  129. {
  130. delete [] *i;
  131. }
  132. }
  133. //----------------------------------------------------------------------------
  134. bool cmDocumentation::PrintCopyright(std::ostream& os)
  135. {
  136. for(const cmDocumentationEntry* op = cmDocumentationCopyright;
  137. op->brief; ++op)
  138. {
  139. if(op->name)
  140. {
  141. os << " * ";
  142. this->TextIndent = " ";
  143. this->PrintColumn(os, op->brief);
  144. }
  145. else
  146. {
  147. this->TextIndent = "";
  148. this->PrintColumn(os, op->brief);
  149. }
  150. os << "\n";
  151. }
  152. return true;
  153. }
  154. //----------------------------------------------------------------------------
  155. bool cmDocumentation::PrintVersion(std::ostream& os)
  156. {
  157. os << this->GetNameString() << " version "
  158. << cmVersion::GetCMakeVersion() << "\n";
  159. return true;
  160. }
  161. //----------------------------------------------------------------------------
  162. void cmDocumentation::AddSection(const char* name,
  163. const cmDocumentationEntry* d)
  164. {
  165. this->Names.push_back(name);
  166. this->Sections.push_back(d);
  167. }
  168. //----------------------------------------------------------------------------
  169. void cmDocumentation::ClearSections()
  170. {
  171. this->Names.erase(this->Names.begin(), this->Names.end());
  172. this->Sections.erase(this->Sections.begin(), this->Sections.end());
  173. }
  174. //----------------------------------------------------------------------------
  175. bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os)
  176. {
  177. if ( ht != cmDocumentation::HTML &&
  178. ht != cmDocumentation::Man )
  179. {
  180. this->PrintVersion(os);
  181. }
  182. switch (ht)
  183. {
  184. case cmDocumentation::Usage: return this->PrintDocumentationUsage(os);
  185. case cmDocumentation::Single:
  186. return this->PrintDocumentationSingle(os);
  187. case cmDocumentation::SingleModule:
  188. return this->PrintDocumentationSingleModule(os);
  189. case cmDocumentation::List: return this->PrintDocumentationList(os);
  190. case cmDocumentation::ModuleList: return this->PrintModuleList(os);
  191. case cmDocumentation::Full: return this->PrintDocumentationFull(os);
  192. case cmDocumentation::HTML: return this->PrintDocumentationHTML(os);
  193. case cmDocumentation::Man: return this->PrintDocumentationMan(os);
  194. case cmDocumentation::Copyright: return this->PrintCopyright(os);
  195. case cmDocumentation::Version: return true;
  196. default: return false;
  197. }
  198. }
  199. //----------------------------------------------------------------------------
  200. bool cmDocumentation::CreateModulesSection()
  201. {
  202. this->ModulesSection.push_back(cmDocumentationModulesHeader[0]);
  203. std::string cmakeModules = this->CMakeRoot;
  204. cmakeModules += "/Modules";
  205. cmsys::Directory dir;
  206. dir.Load(cmakeModules.c_str());
  207. for(unsigned int i = 0; i < dir.GetNumberOfFiles(); ++i)
  208. {
  209. std::string fname = dir.GetFile(i);
  210. if(fname.length() > 6)
  211. {
  212. if(fname.substr(fname.length()-6, 6) == ".cmake")
  213. {
  214. std::string moduleName = fname.substr(0, fname.length()-6);
  215. std::string path = cmakeModules;
  216. path += "/";
  217. path += fname;
  218. this->CreateSingleModule(path.c_str(), moduleName.c_str());
  219. }
  220. }
  221. }
  222. cmDocumentationEntry e = { 0, 0, 0 };
  223. this->ModulesSection.push_back(e);
  224. return true;
  225. }
  226. //----------------------------------------------------------------------------
  227. bool cmDocumentation::CreateSingleModule(const char* fname,
  228. const char* moduleName)
  229. {
  230. std::ifstream fin(fname);
  231. if(!fin)
  232. {
  233. std::cerr << "Internal error: can not open module." << fname << std::endl;
  234. return false;
  235. }
  236. std::string line;
  237. std::string text;
  238. std::string brief;
  239. brief = " ";
  240. bool newParagraph = true;
  241. while ( fin && cmSystemTools::GetLineFromStream(fin, line) )
  242. {
  243. if(line.size() && line[0] == '#')
  244. {
  245. // blank line
  246. if(line.size() <= 2)
  247. {
  248. text += "\n";
  249. newParagraph = true;
  250. }
  251. else if(line[2] == '-')
  252. {
  253. brief = line.c_str()+4;
  254. }
  255. else
  256. {
  257. // two spaces
  258. if(line[1] == ' ' && line[2] == ' ')
  259. {
  260. if(!newParagraph)
  261. {
  262. text += "\n";
  263. newParagraph = true;
  264. }
  265. // Skip #, and leave space for preformatted
  266. text += line.c_str()+1;
  267. text += "\n";
  268. }
  269. else if(line[1] == ' ')
  270. {
  271. if(!newParagraph)
  272. {
  273. text += " ";
  274. }
  275. newParagraph = false;
  276. // skip # and space
  277. text += line.c_str()+2;
  278. }
  279. else
  280. {
  281. if(!newParagraph)
  282. {
  283. text += " ";
  284. }
  285. newParagraph = false;
  286. // skip #
  287. text += line.c_str()+1;
  288. }
  289. }
  290. }
  291. else
  292. {
  293. if(text.length() < 2 && brief.length() == 1)
  294. {
  295. return false;
  296. }
  297. char* pname = strcpy(new char[strlen(moduleName)+1], moduleName);
  298. char* ptext = strcpy(new char[text.length()+1], text.c_str());
  299. this->ModuleStrings.push_back(pname);
  300. this->ModuleStrings.push_back(ptext);
  301. char* pbrief = strcpy(new char[brief.length()+1], brief.c_str());
  302. this->ModuleStrings.push_back(pbrief);
  303. cmDocumentationEntry e = { pname, pbrief, ptext };
  304. this->ModulesSection.push_back(e);
  305. return true;
  306. }
  307. }
  308. return true;
  309. }
  310. //----------------------------------------------------------------------------
  311. bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os)
  312. {
  313. bool result = true;
  314. // Loop over requested documentation types.
  315. for(RequestedMapType::const_iterator i = this->RequestedMap.begin();
  316. i != this->RequestedMap.end(); ++i)
  317. {
  318. // Special case for printing help for a single command.
  319. if(i->first == cmDocumentation::Usage && i->second.length() > 0 &&
  320. !this->CommandsSection.empty())
  321. {
  322. // Check if the argument to the usage request was a command.
  323. for(cmDocumentationEntry* entry = &this->CommandsSection[0];
  324. entry->brief; ++entry)
  325. {
  326. if(entry->name && (strcmp(entry->name, i->second.c_str()) == 0))
  327. {
  328. this->PrintDocumentationCommand(os, entry);
  329. return true;
  330. }
  331. }
  332. // Argument was not a command. Complain.
  333. os << "Help argument \"" << i->second.c_str()
  334. << "\" is not a CMake command. "
  335. << "Use --help-command-list to see all commands.\n";
  336. return false;
  337. }
  338. // If a file name was given, use it. Otherwise, default to the
  339. // given stream.
  340. std::ofstream* fout = 0;
  341. std::ostream* s = &os;
  342. if(i->second.length() > 0)
  343. {
  344. fout = new std::ofstream(i->second.c_str(), std::ios::out);
  345. if(fout)
  346. {
  347. s = fout;
  348. }
  349. else
  350. {
  351. result = false;
  352. }
  353. }
  354. // Print this documentation type to the stream.
  355. if(!this->PrintDocumentation(i->first, *s) || !*s)
  356. {
  357. result = false;
  358. }
  359. // Close the file if we wrote one.
  360. if(fout)
  361. {
  362. delete fout;
  363. }
  364. }
  365. return result;
  366. }
  367. //----------------------------------------------------------------------------
  368. bool cmDocumentation::CheckOptions(int argc, const char* const* argv)
  369. {
  370. // Providing zero arguments gives usage information.
  371. if(argc == 1)
  372. {
  373. this->RequestedMap[cmDocumentation::Usage] = "";
  374. return true;
  375. }
  376. // Search for supported help options.
  377. bool result = false;
  378. for(int i=1; i < argc; ++i)
  379. {
  380. // Check if this is a supported help option.
  381. Type type = cmDocumentation::None;
  382. if((strcmp(argv[i], "-help") == 0) ||
  383. (strcmp(argv[i], "--help") == 0) ||
  384. (strcmp(argv[i], "/?") == 0) ||
  385. (strcmp(argv[i], "-usage") == 0) ||
  386. (strcmp(argv[i], "-h") == 0) ||
  387. (strcmp(argv[i], "-H") == 0))
  388. {
  389. type = cmDocumentation::Usage;
  390. }
  391. else if(strcmp(argv[i], "--help-full") == 0)
  392. {
  393. type = cmDocumentation::Full;
  394. }
  395. else if(strcmp(argv[i], "--help-html") == 0)
  396. {
  397. type = cmDocumentation::HTML;
  398. }
  399. else if(strcmp(argv[i], "--help-man") == 0)
  400. {
  401. type = cmDocumentation::Man;
  402. }
  403. else if(strcmp(argv[i], "--help-command") == 0)
  404. {
  405. type = cmDocumentation::Single;
  406. if((i+1 < argc) && !this->IsOption(argv[i+1]))
  407. {
  408. this->SingleCommand = argv[i+1];
  409. this->SingleCommand = cmSystemTools::UpperCase(this->SingleCommand);
  410. i = i+1;
  411. }
  412. }
  413. else if(strcmp(argv[i], "--help-module") == 0)
  414. {
  415. type = cmDocumentation::SingleModule;
  416. if((i+1 < argc) && !this->IsOption(argv[i+1]))
  417. {
  418. this->SingleModuleName = argv[i+1];
  419. i = i+1;
  420. }
  421. }
  422. else if(strcmp(argv[i], "--help-command-list") == 0)
  423. {
  424. type = cmDocumentation::List;
  425. }
  426. else if(strcmp(argv[i], "--help-module-list") == 0)
  427. {
  428. type = cmDocumentation::ModuleList;
  429. }
  430. else if(strcmp(argv[i], "--copyright") == 0)
  431. {
  432. type = cmDocumentation::Copyright;
  433. }
  434. else if((strcmp(argv[i], "--version") == 0) ||
  435. (strcmp(argv[i], "-version") == 0) ||
  436. (strcmp(argv[i], "/V") == 0))
  437. {
  438. type = cmDocumentation::Version;
  439. }
  440. if(type)
  441. {
  442. // This is a help option. See if there is a file name given.
  443. result = true;
  444. if((i+1 < argc) && !this->IsOption(argv[i+1]))
  445. {
  446. this->RequestedMap[type] = argv[i+1];
  447. i = i+1;
  448. }
  449. else
  450. {
  451. this->RequestedMap[type] = "";
  452. }
  453. }
  454. }
  455. return result;
  456. }
  457. //----------------------------------------------------------------------------
  458. void cmDocumentation::Print(Form f, std::ostream& os)
  459. {
  460. this->CurrentForm = f;
  461. for(unsigned int i=0; i < this->Sections.size(); ++i)
  462. {
  463. this->PrintSection(os, this->Sections[i], this->Names[i]);
  464. }
  465. }
  466. //----------------------------------------------------------------------------
  467. void cmDocumentation::SetName(const char* name)
  468. {
  469. this->NameString = name?name:"";
  470. }
  471. //----------------------------------------------------------------------------
  472. void cmDocumentation::SetNameSection(const cmDocumentationEntry* section)
  473. {
  474. this->SetSection(0, section, 0, this->NameSection);
  475. }
  476. //----------------------------------------------------------------------------
  477. void cmDocumentation::SetUsageSection(const cmDocumentationEntry* section)
  478. {
  479. this->SetSection(0, section, 0, this->UsageSection);
  480. }
  481. //----------------------------------------------------------------------------
  482. void cmDocumentation
  483. ::SetDescriptionSection(const cmDocumentationEntry* section)
  484. {
  485. this->SetSection(0, section, 0, this->DescriptionSection);
  486. }
  487. //----------------------------------------------------------------------------
  488. void cmDocumentation::SetOptionsSection(const cmDocumentationEntry* section)
  489. {
  490. this->SetSection(0, section, cmDocumentationStandardOptions,
  491. this->OptionsSection);
  492. }
  493. //----------------------------------------------------------------------------
  494. void cmDocumentation::SetCommandsSection(const cmDocumentationEntry* section)
  495. {
  496. this->SetSection(cmDocumentationCommandsHeader, section, 0,
  497. this->CommandsSection);
  498. }
  499. //----------------------------------------------------------------------------
  500. void cmDocumentation
  501. ::SetGeneratorsSection(const cmDocumentationEntry* section)
  502. {
  503. this->SetSection(cmDocumentationGeneratorsHeader, section, 0,
  504. this->GeneratorsSection);
  505. }
  506. //----------------------------------------------------------------------------
  507. void cmDocumentation::SetSeeAlsoList(const cmDocumentationEntry* also)
  508. {
  509. this->SeeAlsoString = ".B ";
  510. for(const cmDocumentationEntry* i = also; i->brief; ++i)
  511. {
  512. this->SeeAlsoString += i->brief;
  513. this->SeeAlsoString += (i+1)->brief? "(1), ":"(1)";
  514. }
  515. cmDocumentationEntry e = {0, 0, 0};
  516. e.brief = this->SeeAlsoString.c_str();
  517. this->SeeAlsoSection.push_back(e);
  518. e.brief = 0;
  519. this->SeeAlsoSection.push_back(e);
  520. }
  521. //----------------------------------------------------------------------------
  522. void cmDocumentation::PrintSection(std::ostream& os,
  523. const cmDocumentationEntry* section,
  524. const char* name)
  525. {
  526. switch (this->CurrentForm)
  527. {
  528. case TextForm: this->PrintSectionText(os, section, name); break;
  529. case HTMLForm: this->PrintSectionHTML(os, section, name); break;
  530. case ManForm: this->PrintSectionMan(os, section, name); break;
  531. case UsageForm: this->PrintSectionUsage(os, section, name); break;
  532. }
  533. }
  534. //----------------------------------------------------------------------------
  535. void cmDocumentation::PrintSectionText(std::ostream& os,
  536. const cmDocumentationEntry* section,
  537. const char* name)
  538. {
  539. if(name)
  540. {
  541. os <<
  542. "---------------------------------------"
  543. "---------------------------------------\n";
  544. os << name << "\n\n";
  545. }
  546. if(!section) { return; }
  547. for(const cmDocumentationEntry* op = section; op->brief; ++op)
  548. {
  549. if(op->name)
  550. {
  551. if(op->name[0])
  552. {
  553. os << " " << op->name << "\n";
  554. }
  555. this->TextIndent = " ";
  556. this->PrintFormatted(os, op->brief);
  557. if(op->full)
  558. {
  559. os << "\n";
  560. this->PrintFormatted(os, op->full);
  561. }
  562. }
  563. else
  564. {
  565. this->TextIndent = "";
  566. this->PrintFormatted(os, op->brief);
  567. }
  568. os << "\n";
  569. }
  570. }
  571. //----------------------------------------------------------------------------
  572. void cmDocumentation::PrintSectionHTML(std::ostream& os,
  573. const cmDocumentationEntry* section,
  574. const char* name)
  575. {
  576. if(name)
  577. {
  578. os << "<h2>" << name << "</h2>\n";
  579. }
  580. if(!section) { return; }
  581. for(const cmDocumentationEntry* op = section; op->brief;)
  582. {
  583. if(op->name)
  584. {
  585. os << "<ul>\n";
  586. for(;op->name;++op)
  587. {
  588. os << " <li>\n";
  589. if(op->name[0])
  590. {
  591. os << " <b><code>";
  592. this->PrintHTMLEscapes(os, op->name);
  593. os << "</code></b>: ";
  594. }
  595. this->PrintHTMLEscapes(os, op->brief);
  596. if(op->full)
  597. {
  598. os << "<br>\n ";
  599. this->PrintFormatted(os, op->full);
  600. }
  601. os << "\n";
  602. os << " </li>\n";
  603. }
  604. os << "</ul>\n";
  605. }
  606. else
  607. {
  608. this->PrintFormatted(os, op->brief);
  609. os << "\n";
  610. ++op;
  611. }
  612. }
  613. }
  614. //----------------------------------------------------------------------------
  615. void cmDocumentation::PrintSectionMan(std::ostream& os,
  616. const cmDocumentationEntry* section,
  617. const char* name)
  618. {
  619. if(name)
  620. {
  621. os << ".SH " << name << "\n";
  622. }
  623. if(!section) { return; }
  624. for(const cmDocumentationEntry* op = section; op->brief; ++op)
  625. {
  626. if(op->name)
  627. {
  628. os << ".TP\n"
  629. << ".B " << (op->name[0]?op->name:"*") << "\n";
  630. this->PrintFormatted(os, op->brief);
  631. this->PrintFormatted(os, op->full);
  632. }
  633. else
  634. {
  635. os << ".PP\n";
  636. this->PrintFormatted(os, op->brief);
  637. }
  638. }
  639. }
  640. //----------------------------------------------------------------------------
  641. void cmDocumentation::PrintSectionUsage(std::ostream& os,
  642. const cmDocumentationEntry* section,
  643. const char* name)
  644. {
  645. if(name)
  646. {
  647. os << name << "\n";
  648. }
  649. if(!section) { return; }
  650. for(const cmDocumentationEntry* op = section; op->brief; ++op)
  651. {
  652. if(op->name)
  653. {
  654. os << " " << op->name;
  655. this->TextIndent = " ";
  656. int align = static_cast<int>(strlen(this->TextIndent))-4;
  657. for(int i = static_cast<int>(strlen(op->name)); i < align; ++i)
  658. {
  659. os << " ";
  660. }
  661. if ( strlen(op->name) > strlen(this->TextIndent)-4 )
  662. {
  663. os << "\n";
  664. os.write(this->TextIndent, strlen(this->TextIndent)-2);
  665. }
  666. os << "= ";
  667. this->PrintColumn(os, op->brief);
  668. os << "\n";
  669. }
  670. else
  671. {
  672. os << "\n";
  673. this->TextIndent = "";
  674. this->PrintFormatted(os, op->brief);
  675. }
  676. }
  677. os << "\n";
  678. }
  679. //----------------------------------------------------------------------------
  680. void cmDocumentation::PrintFormatted(std::ostream& os, const char* text)
  681. {
  682. if(!text)
  683. {
  684. return;
  685. }
  686. const char* ptr = text;
  687. while(*ptr)
  688. {
  689. // Any ptrs starting in a space are treated as preformatted text.
  690. std::string preformatted;
  691. while(*ptr == ' ')
  692. {
  693. for(char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr)
  694. {
  695. preformatted.append(1, ch);
  696. }
  697. if(*ptr)
  698. {
  699. ++ptr;
  700. preformatted.append(1, '\n');
  701. }
  702. }
  703. if(preformatted.length())
  704. {
  705. this->PrintPreformatted(os, preformatted.c_str());
  706. }
  707. // Other ptrs are treated as paragraphs.
  708. std::string paragraph;
  709. for(char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr)
  710. {
  711. paragraph.append(1, ch);
  712. }
  713. if(*ptr)
  714. {
  715. ++ptr;
  716. paragraph.append(1, '\n');
  717. }
  718. if(paragraph.length())
  719. {
  720. this->PrintParagraph(os, paragraph.c_str());
  721. }
  722. }
  723. }
  724. //----------------------------------------------------------------------------
  725. void cmDocumentation::PrintPreformatted(std::ostream& os, const char* text)
  726. {
  727. switch (this->CurrentForm)
  728. {
  729. case TextForm: this->PrintPreformattedText(os, text); break;
  730. case HTMLForm: this->PrintPreformattedHTML(os, text); break;
  731. case ManForm: this->PrintPreformattedMan(os, text); break;
  732. case UsageForm: this->PrintPreformattedText(os, text); break;
  733. }
  734. }
  735. //----------------------------------------------------------------------------
  736. void cmDocumentation::PrintParagraph(std::ostream& os, const char* text)
  737. {
  738. switch (this->CurrentForm)
  739. {
  740. case TextForm: this->PrintParagraphText(os, text); break;
  741. case HTMLForm: this->PrintParagraphHTML(os, text); break;
  742. case ManForm: this->PrintParagraphMan(os, text); break;
  743. case UsageForm: this->PrintParagraphText(os, text); break;
  744. }
  745. }
  746. //----------------------------------------------------------------------------
  747. void cmDocumentation
  748. ::PrintPreformattedText(std::ostream& os, const char* text)
  749. {
  750. bool newline = true;
  751. for(const char* ptr = text; *ptr; ++ptr)
  752. {
  753. if(newline)
  754. {
  755. os << this->TextIndent;
  756. newline = false;
  757. }
  758. os << *ptr;
  759. if(*ptr == '\n')
  760. {
  761. newline = true;
  762. }
  763. }
  764. os << "\n";
  765. }
  766. //----------------------------------------------------------------------------
  767. void cmDocumentation::PrintParagraphText(std::ostream& os, const char* text)
  768. {
  769. os << this->TextIndent;
  770. this->PrintColumn(os, text);
  771. os << "\n";
  772. }
  773. //----------------------------------------------------------------------------
  774. void cmDocumentation
  775. ::PrintPreformattedHTML(std::ostream& os, const char* text)
  776. {
  777. os << "<pre>";
  778. this->PrintHTMLEscapes(os, text);
  779. os << "</pre>\n ";
  780. }
  781. //----------------------------------------------------------------------------
  782. void cmDocumentation::PrintParagraphHTML(std::ostream& os, const char* text)
  783. {
  784. os << "<p>";
  785. this->PrintHTMLEscapes(os, text);
  786. }
  787. //----------------------------------------------------------------------------
  788. void cmDocumentation::PrintPreformattedMan(std::ostream& os, const char* text)
  789. {
  790. os << text << "\n";
  791. }
  792. //----------------------------------------------------------------------------
  793. void cmDocumentation::PrintParagraphMan(std::ostream& os, const char* text)
  794. {
  795. os << text << "\n\n";
  796. }
  797. //----------------------------------------------------------------------------
  798. void cmDocumentation::PrintColumn(std::ostream& os, const char* text)
  799. {
  800. // Print text arranged in an indented column of fixed witdh.
  801. const char* l = text;
  802. int column = 0;
  803. bool newSentence = false;
  804. bool firstLine = true;
  805. int width = this->TextWidth - static_cast<int>(strlen(this->TextIndent));
  806. // Loop until the end of the text.
  807. while(*l)
  808. {
  809. // Parse the next word.
  810. const char* r = l;
  811. while(*r && (*r != '\n') && (*r != ' ')) { ++r; }
  812. // Does it fit on this line?
  813. if(r-l < (width-column-(newSentence?1:0)))
  814. {
  815. // Word fits on this line.
  816. if(r > l)
  817. {
  818. if(column)
  819. {
  820. // Not first word on line. Separate from the previous word
  821. // by a space, or two if this is a new sentence.
  822. if(newSentence)
  823. {
  824. os << " ";
  825. column += 2;
  826. }
  827. else
  828. {
  829. os << " ";
  830. column += 1;
  831. }
  832. }
  833. else
  834. {
  835. // First word on line. Print indentation unless this is the
  836. // first line.
  837. os << (firstLine?"":this->TextIndent);
  838. }
  839. // Print the word.
  840. os.write(l, static_cast<long>(r-l));
  841. newSentence = (*(r-1) == '.');
  842. }
  843. if(*r == '\n')
  844. {
  845. // Text provided a newline. Start a new line.
  846. os << "\n";
  847. ++r;
  848. column = 0;
  849. firstLine = false;
  850. }
  851. else
  852. {
  853. // No provided newline. Continue this line.
  854. column += static_cast<long>(r-l);
  855. }
  856. }
  857. else
  858. {
  859. // Word does not fit on this line. Start a new line.
  860. os << "\n";
  861. firstLine = false;
  862. if(r > l)
  863. {
  864. os << this->TextIndent;
  865. os.write(l, static_cast<long>(r-l));
  866. column = static_cast<long>(r-l);
  867. newSentence = (*(r-1) == '.');
  868. }
  869. else
  870. {
  871. column = 0;
  872. }
  873. }
  874. // Move to beginning of next word. Skip over whitespace.
  875. l = r;
  876. while(*l && (*l == ' ')) { ++l; }
  877. }
  878. }
  879. //----------------------------------------------------------------------------
  880. void cmDocumentation::PrintHTMLEscapes(std::ostream& os, const char* text)
  881. {
  882. static cmDocumentationEntry escapes[] =
  883. {
  884. {"<", "&lt;", 0},
  885. {">", "&gt;", 0},
  886. {"&", "&amp;", 0},
  887. {"\n", "<br>", 0},
  888. {0,0,0}
  889. };
  890. for(const char* p = text; *p; ++p)
  891. {
  892. bool found = false;
  893. for(const cmDocumentationEntry* op = escapes; !found && op->name; ++op)
  894. {
  895. if(op->name[0] == *p)
  896. {
  897. os << op->brief;
  898. found = true;
  899. }
  900. }
  901. if(!found)
  902. {
  903. os << *p;
  904. }
  905. }
  906. }
  907. //----------------------------------------------------------------------------
  908. bool cmDocumentation::PrintDocumentationSingle(std::ostream& os)
  909. {
  910. if(this->CommandsSection.empty())
  911. {
  912. os << "Internal error: commands list is empty." << std::endl;
  913. return false;
  914. }
  915. if(this->SingleCommand.length() == 0)
  916. {
  917. os << "Argument --help-command needs a command name.\n";
  918. return false;
  919. }
  920. for(cmDocumentationEntry* entry = &this->CommandsSection[0];
  921. entry->brief; ++entry)
  922. {
  923. if(entry->name && this->SingleCommand == entry->name)
  924. {
  925. this->PrintDocumentationCommand(os, entry);
  926. return true;
  927. }
  928. }
  929. // Argument was not a command. Complain.
  930. os << "Argument \"" << this->SingleCommand.c_str()
  931. << "\" to --help-command is not a CMake command. "
  932. << "Use --help-command-list to see all commands.\n";
  933. return false;
  934. }
  935. //----------------------------------------------------------------------------
  936. bool cmDocumentation::PrintDocumentationSingleModule(std::ostream& os)
  937. {
  938. if(this->SingleModuleName.length() == 0)
  939. {
  940. os << "Argument --help-module needs a module name.\n";
  941. return false;
  942. }
  943. std::string cmakeModules = this->CMakeRoot;
  944. cmakeModules += "/Modules/";
  945. cmakeModules += this->SingleModuleName;
  946. cmakeModules += ".cmake";
  947. if(cmSystemTools::FileExists(cmakeModules.c_str())
  948. && this->CreateSingleModule(cmakeModules.c_str(),
  949. this->SingleModuleName.c_str()))
  950. {
  951. this->PrintDocumentationCommand(os, &this->ModulesSection[0]);
  952. os << "\n Defined in: ";
  953. os << cmakeModules << "\n";
  954. return true;
  955. }
  956. // Argument was not a module. Complain.
  957. os << "Argument \"" << this->SingleModuleName.c_str()
  958. << "\" to --help-module is not a CMake module.";
  959. return false;
  960. }
  961. //----------------------------------------------------------------------------
  962. bool cmDocumentation::PrintDocumentationList(std::ostream& os)
  963. {
  964. if(this->CommandsSection.empty())
  965. {
  966. os << "Internal error: commands list is empty." << std::endl;
  967. return false;
  968. }
  969. for(cmDocumentationEntry* entry = &this->CommandsSection[0];
  970. entry->brief; ++entry)
  971. {
  972. if(entry->name)
  973. {
  974. os << entry->name << std::endl;
  975. }
  976. }
  977. return true;
  978. }
  979. //----------------------------------------------------------------------------
  980. bool cmDocumentation::PrintModuleList(std::ostream& os)
  981. {
  982. this->CreateModulesSection();
  983. if(this->ModulesSection.empty())
  984. {
  985. os << "Internal error: modules list is empty." << std::endl;
  986. return false;
  987. }
  988. for(cmDocumentationEntry* entry = &this->ModulesSection[0];
  989. entry->brief; ++entry)
  990. {
  991. if(entry->name)
  992. {
  993. os << entry->name << std::endl;
  994. }
  995. }
  996. return true;
  997. }
  998. //----------------------------------------------------------------------------
  999. bool cmDocumentation::PrintDocumentationUsage(std::ostream& os)
  1000. {
  1001. this->CreateUsageDocumentation();
  1002. this->Print(UsageForm, os);
  1003. return true;
  1004. }
  1005. //----------------------------------------------------------------------------
  1006. bool cmDocumentation::PrintDocumentationFull(std::ostream& os)
  1007. {
  1008. this->CreateFullDocumentation();
  1009. this->Print(TextForm, os);
  1010. return true;
  1011. }
  1012. //----------------------------------------------------------------------------
  1013. bool cmDocumentation::PrintDocumentationHTML(std::ostream& os)
  1014. {
  1015. this->CreateFullDocumentation();
  1016. os << "<html><body>\n";
  1017. this->Print(HTMLForm, os);
  1018. os << "</body></html>\n";
  1019. return true;
  1020. }
  1021. //----------------------------------------------------------------------------
  1022. bool cmDocumentation::PrintDocumentationMan(std::ostream& os)
  1023. {
  1024. this->CreateManDocumentation();
  1025. os << ".TH " << this->GetNameString() << " 1 \""
  1026. << cmSystemTools::GetCurrentDateTime("%B %d, %Y").c_str()
  1027. << "\" \"" << this->GetNameString()
  1028. << " " << cmVersion::GetCMakeVersion()
  1029. << "\"\n";
  1030. this->Print(ManForm, os);
  1031. return true;
  1032. }
  1033. //----------------------------------------------------------------------------
  1034. void cmDocumentation::PrintDocumentationCommand(std::ostream& os,
  1035. cmDocumentationEntry* entry)
  1036. {
  1037. cmDocumentationEntry singleCommandSection[3] =
  1038. {
  1039. {entry->name, entry->brief, entry->full},
  1040. {0,0,0}
  1041. };
  1042. this->ClearSections();
  1043. this->AddSection(0, &singleCommandSection[0]);
  1044. this->Print(TextForm, os);
  1045. }
  1046. //----------------------------------------------------------------------------
  1047. void cmDocumentation::CreateUsageDocumentation()
  1048. {
  1049. this->ClearSections();
  1050. if(!this->UsageSection.empty())
  1051. {
  1052. this->AddSection("Usage", &this->UsageSection[0]);
  1053. }
  1054. if(!this->OptionsSection.empty())
  1055. {
  1056. this->AddSection("Command-Line Options", &this->OptionsSection[0]);
  1057. }
  1058. if(!this->GeneratorsSection.empty())
  1059. {
  1060. this->AddSection("Generators", &this->GeneratorsSection[0]);
  1061. }
  1062. }
  1063. //----------------------------------------------------------------------------
  1064. void cmDocumentation::CreateFullDocumentation()
  1065. {
  1066. this->ClearSections();
  1067. if(!this->NameSection.empty())
  1068. {
  1069. this->AddSection("Name", &this->NameSection[0]);
  1070. }
  1071. if(!this->UsageSection.empty())
  1072. {
  1073. this->AddSection("Usage", &this->UsageSection[0]);
  1074. }
  1075. if(!this->DescriptionSection.empty())
  1076. {
  1077. this->AddSection(0, &this->DescriptionSection[0]);
  1078. }
  1079. if(!this->OptionsSection.empty())
  1080. {
  1081. this->AddSection("Command-Line Options", &this->OptionsSection[0]);
  1082. }
  1083. if(!this->GeneratorsSection.empty())
  1084. {
  1085. this->AddSection("Generators", &this->GeneratorsSection[0]);
  1086. }
  1087. if(!this->CommandsSection.empty())
  1088. {
  1089. this->AddSection("Listfile Commands", &this->CommandsSection[0]);
  1090. }
  1091. this->CreateModulesSection();
  1092. if(!this->ModulesSection.empty())
  1093. {
  1094. this->AddSection("Standard CMake Modules", &this->ModulesSection[0]);
  1095. }
  1096. this->AddSection("Copyright", cmDocumentationCopyright);
  1097. this->AddSection("Mailing List", cmDocumentationMailingList);
  1098. }
  1099. //----------------------------------------------------------------------------
  1100. void cmDocumentation::CreateManDocumentation()
  1101. {
  1102. this->ClearSections();
  1103. if(!this->NameSection.empty())
  1104. {
  1105. this->AddSection("NAME", &this->NameSection[0]);
  1106. }
  1107. if(!this->UsageSection.empty())
  1108. {
  1109. this->AddSection("SYNOPSIS", &this->UsageSection[0]);
  1110. }
  1111. if(!this->DescriptionSection.empty())
  1112. {
  1113. this->AddSection("DESCRIPTION", &this->DescriptionSection[0]);
  1114. }
  1115. if(!this->OptionsSection.empty())
  1116. {
  1117. this->AddSection("OPTIONS", &this->OptionsSection[0]);
  1118. }
  1119. if(!this->GeneratorsSection.empty())
  1120. {
  1121. this->AddSection("GENERATORS", &this->GeneratorsSection[0]);
  1122. }
  1123. if(!this->CommandsSection.empty())
  1124. {
  1125. this->AddSection("COMMANDS", &this->CommandsSection[0]);
  1126. }
  1127. this->CreateModulesSection();
  1128. if(!this->ModulesSection.empty())
  1129. {
  1130. this->AddSection("MODULES", &this->ModulesSection[0]);
  1131. }
  1132. this->AddSection("COPYRIGHT", cmDocumentationCopyright);
  1133. this->AddSection("MAILING LIST", cmDocumentationMailingList);
  1134. if(!this->SeeAlsoSection.empty())
  1135. {
  1136. this->AddSection("SEE ALSO", &this->SeeAlsoSection[0]);
  1137. }
  1138. this->AddSection("AUTHOR", cmDocumentationAuthor);
  1139. }
  1140. //----------------------------------------------------------------------------
  1141. void cmDocumentation::SetSection(const cmDocumentationEntry* header,
  1142. const cmDocumentationEntry* section,
  1143. const cmDocumentationEntry* footer,
  1144. std::vector<cmDocumentationEntry>& vec)
  1145. {
  1146. vec.erase(vec.begin(), vec.end());
  1147. if(header)
  1148. {
  1149. for(const cmDocumentationEntry* op = header; op->brief; ++op)
  1150. {
  1151. vec.push_back(*op);
  1152. }
  1153. }
  1154. if(section)
  1155. {
  1156. for(const cmDocumentationEntry* op = section; op->brief; ++op)
  1157. {
  1158. vec.push_back(*op);
  1159. }
  1160. }
  1161. if(footer)
  1162. {
  1163. for(const cmDocumentationEntry* op = footer; op->brief; ++op)
  1164. {
  1165. vec.push_back(*op);
  1166. }
  1167. }
  1168. cmDocumentationEntry empty = {0,0,0};
  1169. vec.push_back(empty);
  1170. }
  1171. //----------------------------------------------------------------------------
  1172. const char* cmDocumentation::GetNameString()
  1173. {
  1174. if(this->NameString.length() > 0)
  1175. {
  1176. return this->NameString.c_str();
  1177. }
  1178. else
  1179. {
  1180. return "CMake";
  1181. }
  1182. }
  1183. //----------------------------------------------------------------------------
  1184. bool cmDocumentation::IsOption(const char* arg)
  1185. {
  1186. return ((arg[0] == '-') || (strcmp(arg, "/V") == 0) ||
  1187. (strcmp(arg, "/?") == 0));
  1188. }