1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmDocumentation.h"
4
5 #include <algorithm>
6 #include <cctype>
7 #include <cstring>
8 #include <utility>
9
10 #include "cmsys/FStream.hxx"
11 #include "cmsys/Glob.hxx"
12
13 #include "cmDocumentationEntry.h"
14 #include "cmDocumentationSection.h"
15 #include "cmRST.h"
16 #include "cmSystemTools.h"
17 #include "cmVersion.h"
18
19 static const char* cmDocumentationStandardOptions[][2] = {
20 { "--help,-help,-usage,-h,-H,/?", "Print usage information and exit." },
21 { "--version,-version,/V [<f>]", "Print version number and exit." },
22 { "--help-full [<f>]", "Print all help manuals and exit." },
23 { "--help-manual <man> [<f>]", "Print one help manual and exit." },
24 { "--help-manual-list [<f>]", "List help manuals available and exit." },
25 { "--help-command <cmd> [<f>]", "Print help for one command and exit." },
26 { "--help-command-list [<f>]",
27 "List commands with help available and exit." },
28 { "--help-commands [<f>]", "Print cmake-commands manual and exit." },
29 { "--help-module <mod> [<f>]", "Print help for one module and exit." },
30 { "--help-module-list [<f>]", "List modules with help available and exit." },
31 { "--help-modules [<f>]", "Print cmake-modules manual and exit." },
32 { "--help-policy <cmp> [<f>]", "Print help for one policy and exit." },
33 { "--help-policy-list [<f>]",
34 "List policies with help available and exit." },
35 { "--help-policies [<f>]", "Print cmake-policies manual and exit." },
36 { "--help-property <prop> [<f>]", "Print help for one property and exit." },
37 { "--help-property-list [<f>]",
38 "List properties with help available and exit." },
39 { "--help-properties [<f>]", "Print cmake-properties manual and exit." },
40 { "--help-variable var [<f>]", "Print help for one variable and exit." },
41 { "--help-variable-list [<f>]",
42 "List variables with help available and exit." },
43 { "--help-variables [<f>]", "Print cmake-variables manual and exit." },
44 { nullptr, nullptr }
45 };
46
47 static const char* cmDocumentationCPackGeneratorsHeader[][2] = {
48 { nullptr, "The following generators are available on this platform:" },
49 { nullptr, nullptr }
50 };
51
52 static const char* cmDocumentationCMakeGeneratorsHeader[][2] = {
53 { nullptr,
54 "The following generators are available on this platform (* marks "
55 "default):" },
56 { nullptr, nullptr }
57 };
58
cmDocumentation()59 cmDocumentation::cmDocumentation()
60 {
61 this->addCommonStandardDocSections();
62 this->ShowGenerators = true;
63 }
64
PrintVersion(std::ostream & os)65 bool cmDocumentation::PrintVersion(std::ostream& os)
66 {
67 /* clang-format off */
68 os <<
69 this->GetNameString() <<
70 " version " << cmVersion::GetCMakeVersion() << "\n"
71 "\n"
72 "CMake suite maintained and supported by Kitware (kitware.com/cmake).\n"
73 ;
74 /* clang-format on */
75 return true;
76 }
77
PrintDocumentation(Type ht,std::ostream & os)78 bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os)
79 {
80 switch (ht) {
81 case cmDocumentation::Usage:
82 return this->PrintUsage(os);
83 case cmDocumentation::Help:
84 return this->PrintHelp(os);
85 case cmDocumentation::Full:
86 return this->PrintHelpFull(os);
87 case cmDocumentation::OneManual:
88 return this->PrintHelpOneManual(os);
89 case cmDocumentation::OneCommand:
90 return this->PrintHelpOneCommand(os);
91 case cmDocumentation::OneModule:
92 return this->PrintHelpOneModule(os);
93 case cmDocumentation::OnePolicy:
94 return this->PrintHelpOnePolicy(os);
95 case cmDocumentation::OneProperty:
96 return this->PrintHelpOneProperty(os);
97 case cmDocumentation::OneVariable:
98 return this->PrintHelpOneVariable(os);
99 case cmDocumentation::ListManuals:
100 return this->PrintHelpListManuals(os);
101 case cmDocumentation::ListCommands:
102 return this->PrintHelpListCommands(os);
103 case cmDocumentation::ListModules:
104 return this->PrintHelpListModules(os);
105 case cmDocumentation::ListProperties:
106 return this->PrintHelpListProperties(os);
107 case cmDocumentation::ListVariables:
108 return this->PrintHelpListVariables(os);
109 case cmDocumentation::ListPolicies:
110 return this->PrintHelpListPolicies(os);
111 case cmDocumentation::ListGenerators:
112 return this->PrintHelpListGenerators(os);
113 case cmDocumentation::Version:
114 return this->PrintVersion(os);
115 case cmDocumentation::OldCustomModules:
116 return this->PrintOldCustomModules(os);
117 default:
118 return false;
119 }
120 }
121
PrintRequestedDocumentation(std::ostream & os)122 bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os)
123 {
124 int count = 0;
125 bool result = true;
126
127 // Loop over requested documentation types.
128 for (RequestedHelpItem const& rhi : this->RequestedHelpItems) {
129 this->CurrentArgument = rhi.Argument;
130 // If a file name was given, use it. Otherwise, default to the
131 // given stream.
132 cmsys::ofstream fout;
133 std::ostream* s = &os;
134 if (!rhi.Filename.empty()) {
135 fout.open(rhi.Filename.c_str());
136 s = &fout;
137 } else if (++count > 1) {
138 os << "\n\n";
139 }
140
141 // Print this documentation type to the stream.
142 if (!this->PrintDocumentation(rhi.HelpType, *s) || s->fail()) {
143 result = false;
144 }
145 }
146 return result;
147 }
148
149 #define GET_OPT_ARGUMENT(target) \
150 do { \
151 if ((i + 1 < argc) && !this->IsOption(argv[i + 1])) { \
152 (target) = argv[i + 1]; \
153 i = i + 1; \
154 }; \
155 } while (false)
156
WarnFormFromFilename(cmDocumentation::RequestedHelpItem & request,bool & result)157 void cmDocumentation::WarnFormFromFilename(
158 cmDocumentation::RequestedHelpItem& request, bool& result)
159 {
160 std::string ext = cmSystemTools::GetFilenameLastExtension(request.Filename);
161 ext = cmSystemTools::UpperCase(ext);
162 if ((ext == ".HTM") || (ext == ".HTML")) {
163 request.HelpType = cmDocumentation::None;
164 result = true;
165 cmSystemTools::Message("Warning: HTML help format no longer supported");
166 } else if (ext == ".DOCBOOK") {
167 request.HelpType = cmDocumentation::None;
168 result = true;
169 cmSystemTools::Message("Warning: Docbook help format no longer supported");
170 }
171 // ".1" to ".9" should be manpages
172 else if ((ext.length() == 2) && (ext[1] >= '1') && (ext[1] <= '9')) {
173 request.HelpType = cmDocumentation::None;
174 result = true;
175 cmSystemTools::Message("Warning: Man help format no longer supported");
176 }
177 }
178
addCommonStandardDocSections()179 void cmDocumentation::addCommonStandardDocSections()
180 {
181 cmDocumentationSection sec{ "Options" };
182 sec.Append(cmDocumentationStandardOptions);
183 this->AllSections.emplace("Options", std::move(sec));
184 }
185
addCMakeStandardDocSections()186 void cmDocumentation::addCMakeStandardDocSections()
187 {
188 cmDocumentationSection sec{ "Generators" };
189 sec.Append(cmDocumentationCMakeGeneratorsHeader);
190 this->AllSections.emplace("Generators", std::move(sec));
191 }
192
addCTestStandardDocSections()193 void cmDocumentation::addCTestStandardDocSections()
194 {
195 // This is currently done for backward compatibility reason
196 // We may suppress some of these.
197 this->addCMakeStandardDocSections();
198 }
199
addCPackStandardDocSections()200 void cmDocumentation::addCPackStandardDocSections()
201 {
202 cmDocumentationSection sec{ "Generators" };
203 sec.Append(cmDocumentationCPackGeneratorsHeader);
204 this->AllSections.emplace("Generators", std::move(sec));
205 }
206
CheckOptions(int argc,const char * const * argv,const char * exitOpt)207 bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
208 const char* exitOpt)
209 {
210 // Providing zero arguments gives usage information.
211 if (argc == 1) {
212 RequestedHelpItem help;
213 help.HelpType = cmDocumentation::Usage;
214 this->RequestedHelpItems.push_back(std::move(help));
215 return true;
216 }
217
218 // Search for supported help options.
219
220 bool result = false;
221 for (int i = 1; i < argc; ++i) {
222 if (exitOpt && strcmp(argv[i], exitOpt) == 0) {
223 return result;
224 }
225 RequestedHelpItem help;
226 // Check if this is a supported help option.
227 if ((strcmp(argv[i], "-help") == 0) || (strcmp(argv[i], "--help") == 0) ||
228 (strcmp(argv[i], "/?") == 0) || (strcmp(argv[i], "-usage") == 0) ||
229 (strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-H") == 0)) {
230 help.HelpType = cmDocumentation::Help;
231 GET_OPT_ARGUMENT(help.Argument);
232 help.Argument = cmSystemTools::LowerCase(help.Argument);
233 // special case for single command
234 if (!help.Argument.empty()) {
235 help.HelpType = cmDocumentation::OneCommand;
236 }
237 } else if (strcmp(argv[i], "--help-properties") == 0) {
238 help.HelpType = cmDocumentation::OneManual;
239 help.Argument = "cmake-properties.7";
240 GET_OPT_ARGUMENT(help.Filename);
241 this->WarnFormFromFilename(help, result);
242 } else if (strcmp(argv[i], "--help-policies") == 0) {
243 help.HelpType = cmDocumentation::OneManual;
244 help.Argument = "cmake-policies.7";
245 GET_OPT_ARGUMENT(help.Filename);
246 this->WarnFormFromFilename(help, result);
247 } else if (strcmp(argv[i], "--help-variables") == 0) {
248 help.HelpType = cmDocumentation::OneManual;
249 help.Argument = "cmake-variables.7";
250 GET_OPT_ARGUMENT(help.Filename);
251 this->WarnFormFromFilename(help, result);
252 } else if (strcmp(argv[i], "--help-modules") == 0) {
253 help.HelpType = cmDocumentation::OneManual;
254 help.Argument = "cmake-modules.7";
255 GET_OPT_ARGUMENT(help.Filename);
256 this->WarnFormFromFilename(help, result);
257 } else if (strcmp(argv[i], "--help-custom-modules") == 0) {
258 GET_OPT_ARGUMENT(help.Filename);
259 cmSystemTools::Message(
260 "Warning: --help-custom-modules no longer supported");
261 if (help.Filename.empty()) {
262 return true;
263 }
264 // Avoid breaking old project builds completely by at least generating
265 // the output file. Abuse help.Argument to give the file name to
266 // PrintOldCustomModules without disrupting our internal API.
267 help.HelpType = cmDocumentation::OldCustomModules;
268 help.Argument = cmSystemTools::GetFilenameName(help.Filename);
269 } else if (strcmp(argv[i], "--help-commands") == 0) {
270 help.HelpType = cmDocumentation::OneManual;
271 help.Argument = "cmake-commands.7";
272 GET_OPT_ARGUMENT(help.Filename);
273 this->WarnFormFromFilename(help, result);
274 } else if (strcmp(argv[i], "--help-compatcommands") == 0) {
275 GET_OPT_ARGUMENT(help.Filename);
276 cmSystemTools::Message(
277 "Warning: --help-compatcommands no longer supported");
278 return true;
279 } else if (strcmp(argv[i], "--help-full") == 0) {
280 help.HelpType = cmDocumentation::Full;
281 GET_OPT_ARGUMENT(help.Filename);
282 this->WarnFormFromFilename(help, result);
283 } else if (strcmp(argv[i], "--help-html") == 0) {
284 GET_OPT_ARGUMENT(help.Filename);
285 cmSystemTools::Message("Warning: --help-html no longer supported");
286 return true;
287 } else if (strcmp(argv[i], "--help-man") == 0) {
288 GET_OPT_ARGUMENT(help.Filename);
289 cmSystemTools::Message("Warning: --help-man no longer supported");
290 return true;
291 } else if (strcmp(argv[i], "--help-command") == 0) {
292 help.HelpType = cmDocumentation::OneCommand;
293 GET_OPT_ARGUMENT(help.Argument);
294 GET_OPT_ARGUMENT(help.Filename);
295 help.Argument = cmSystemTools::LowerCase(help.Argument);
296 this->WarnFormFromFilename(help, result);
297 } else if (strcmp(argv[i], "--help-module") == 0) {
298 help.HelpType = cmDocumentation::OneModule;
299 GET_OPT_ARGUMENT(help.Argument);
300 GET_OPT_ARGUMENT(help.Filename);
301 this->WarnFormFromFilename(help, result);
302 } else if (strcmp(argv[i], "--help-property") == 0) {
303 help.HelpType = cmDocumentation::OneProperty;
304 GET_OPT_ARGUMENT(help.Argument);
305 GET_OPT_ARGUMENT(help.Filename);
306 this->WarnFormFromFilename(help, result);
307 } else if (strcmp(argv[i], "--help-policy") == 0) {
308 help.HelpType = cmDocumentation::OnePolicy;
309 GET_OPT_ARGUMENT(help.Argument);
310 GET_OPT_ARGUMENT(help.Filename);
311 this->WarnFormFromFilename(help, result);
312 } else if (strcmp(argv[i], "--help-variable") == 0) {
313 help.HelpType = cmDocumentation::OneVariable;
314 GET_OPT_ARGUMENT(help.Argument);
315 GET_OPT_ARGUMENT(help.Filename);
316 this->WarnFormFromFilename(help, result);
317 } else if (strcmp(argv[i], "--help-manual") == 0) {
318 help.HelpType = cmDocumentation::OneManual;
319 GET_OPT_ARGUMENT(help.Argument);
320 GET_OPT_ARGUMENT(help.Filename);
321 this->WarnFormFromFilename(help, result);
322 } else if (strcmp(argv[i], "--help-command-list") == 0) {
323 help.HelpType = cmDocumentation::ListCommands;
324 GET_OPT_ARGUMENT(help.Filename);
325 } else if (strcmp(argv[i], "--help-module-list") == 0) {
326 help.HelpType = cmDocumentation::ListModules;
327 GET_OPT_ARGUMENT(help.Filename);
328 } else if (strcmp(argv[i], "--help-property-list") == 0) {
329 help.HelpType = cmDocumentation::ListProperties;
330 GET_OPT_ARGUMENT(help.Filename);
331 } else if (strcmp(argv[i], "--help-variable-list") == 0) {
332 help.HelpType = cmDocumentation::ListVariables;
333 GET_OPT_ARGUMENT(help.Filename);
334 } else if (strcmp(argv[i], "--help-policy-list") == 0) {
335 help.HelpType = cmDocumentation::ListPolicies;
336 GET_OPT_ARGUMENT(help.Filename);
337 } else if (strcmp(argv[i], "--help-manual-list") == 0) {
338 help.HelpType = cmDocumentation::ListManuals;
339 GET_OPT_ARGUMENT(help.Filename);
340 } else if (strcmp(argv[i], "--copyright") == 0) {
341 GET_OPT_ARGUMENT(help.Filename);
342 cmSystemTools::Message("Warning: --copyright no longer supported");
343 return true;
344 } else if ((strcmp(argv[i], "--version") == 0) ||
345 (strcmp(argv[i], "-version") == 0) ||
346 (strcmp(argv[i], "/V") == 0)) {
347 help.HelpType = cmDocumentation::Version;
348 GET_OPT_ARGUMENT(help.Filename);
349 }
350 if (help.HelpType != None) {
351 // This is a help option. See if there is a file name given.
352 result = true;
353 this->RequestedHelpItems.push_back(std::move(help));
354 }
355 }
356 return result;
357 }
358
SetName(const std::string & name)359 void cmDocumentation::SetName(const std::string& name)
360 {
361 this->NameString = name;
362 }
363
SetSection(const char * name,cmDocumentationSection section)364 void cmDocumentation::SetSection(const char* name,
365 cmDocumentationSection section)
366 {
367 this->SectionAtName(name) = std::move(section);
368 }
369
SetSection(const char * name,std::vector<cmDocumentationEntry> & docs)370 void cmDocumentation::SetSection(const char* name,
371 std::vector<cmDocumentationEntry>& docs)
372 {
373 cmDocumentationSection sec{ name };
374 sec.Append(docs);
375 this->SetSection(name, std::move(sec));
376 }
377
SetSection(const char * name,const char * docs[][2])378 void cmDocumentation::SetSection(const char* name, const char* docs[][2])
379 {
380 cmDocumentationSection sec{ name };
381 sec.Append(docs);
382 this->SetSection(name, std::move(sec));
383 }
384
SetSections(std::map<std::string,cmDocumentationSection> sections)385 void cmDocumentation::SetSections(
386 std::map<std::string, cmDocumentationSection> sections)
387 {
388 for (auto& s : sections) {
389 this->SetSection(s.first.c_str(), std::move(s.second));
390 }
391 }
SectionAtName(const char * name)392 cmDocumentationSection& cmDocumentation::SectionAtName(const char* name)
393 {
394 return this->AllSections.emplace(name, cmDocumentationSection{ name })
395 .first->second;
396 }
397
PrependSection(const char * name,const char * docs[][2])398 void cmDocumentation::PrependSection(const char* name, const char* docs[][2])
399 {
400 this->SectionAtName(name).Prepend(docs);
401 }
402
PrependSection(const char * name,std::vector<cmDocumentationEntry> & docs)403 void cmDocumentation::PrependSection(const char* name,
404 std::vector<cmDocumentationEntry>& docs)
405 {
406 this->SectionAtName(name).Prepend(docs);
407 }
408
AppendSection(const char * name,const char * docs[][2])409 void cmDocumentation::AppendSection(const char* name, const char* docs[][2])
410 {
411 this->SectionAtName(name).Append(docs);
412 }
413
AppendSection(const char * name,std::vector<cmDocumentationEntry> & docs)414 void cmDocumentation::AppendSection(const char* name,
415 std::vector<cmDocumentationEntry>& docs)
416 {
417 this->SectionAtName(name).Append(docs);
418 }
419
AppendSection(const char * name,cmDocumentationEntry & docs)420 void cmDocumentation::AppendSection(const char* name,
421 cmDocumentationEntry& docs)
422 {
423
424 std::vector<cmDocumentationEntry> docsVec;
425 docsVec.push_back(docs);
426 this->AppendSection(name, docsVec);
427 }
428
PrependSection(const char * name,cmDocumentationEntry & docs)429 void cmDocumentation::PrependSection(const char* name,
430 cmDocumentationEntry& docs)
431 {
432
433 std::vector<cmDocumentationEntry> docsVec;
434 docsVec.push_back(docs);
435 this->PrependSection(name, docsVec);
436 }
437
GlobHelp(std::vector<std::string> & files,std::string const & pattern)438 void cmDocumentation::GlobHelp(std::vector<std::string>& files,
439 std::string const& pattern)
440 {
441 cmsys::Glob gl;
442 std::string findExpr =
443 cmSystemTools::GetCMakeRoot() + "/Help/" + pattern + ".rst";
444 if (gl.FindFiles(findExpr)) {
445 files = gl.GetFiles();
446 }
447 }
448
PrintNames(std::ostream & os,std::string const & pattern)449 void cmDocumentation::PrintNames(std::ostream& os, std::string const& pattern)
450 {
451 std::vector<std::string> files;
452 this->GlobHelp(files, pattern);
453 std::vector<std::string> names;
454 for (std::string const& f : files) {
455 std::string line;
456 cmsys::ifstream fin(f.c_str());
457 while (fin && cmSystemTools::GetLineFromStream(fin, line)) {
458 if (!line.empty() && (isalnum(line[0]) || line[0] == '<')) {
459 names.push_back(line);
460 break;
461 }
462 }
463 }
464 std::sort(names.begin(), names.end());
465 for (std::string const& n : names) {
466 os << n << "\n";
467 }
468 }
469
PrintFiles(std::ostream & os,std::string const & pattern)470 bool cmDocumentation::PrintFiles(std::ostream& os, std::string const& pattern)
471 {
472 bool found = false;
473 std::vector<std::string> files;
474 this->GlobHelp(files, pattern);
475 std::sort(files.begin(), files.end());
476 cmRST r(os, cmSystemTools::GetCMakeRoot() + "/Help");
477 for (std::string const& f : files) {
478 found = r.ProcessFile(f) || found;
479 }
480 return found;
481 }
482
PrintHelpFull(std::ostream & os)483 bool cmDocumentation::PrintHelpFull(std::ostream& os)
484 {
485 return this->PrintFiles(os, "index");
486 }
487
PrintHelpOneManual(std::ostream & os)488 bool cmDocumentation::PrintHelpOneManual(std::ostream& os)
489 {
490 std::string mname = this->CurrentArgument;
491 std::string::size_type mlen = mname.length();
492 if (mlen > 3 && mname[mlen - 3] == '(' && mname[mlen - 1] == ')') {
493 mname = mname.substr(0, mlen - 3) + "." + mname[mlen - 2];
494 }
495 if (this->PrintFiles(os, "manual/" + mname) ||
496 this->PrintFiles(os, "manual/" + mname + ".[0-9]")) {
497 return true;
498 }
499 // Argument was not a manual. Complain.
500 os << "Argument \"" << this->CurrentArgument
501 << "\" to --help-manual is not an available manual. "
502 << "Use --help-manual-list to see all available manuals.\n";
503 return false;
504 }
505
PrintHelpListManuals(std::ostream & os)506 bool cmDocumentation::PrintHelpListManuals(std::ostream& os)
507 {
508 this->PrintNames(os, "manual/*");
509 return true;
510 }
511
PrintHelpOneCommand(std::ostream & os)512 bool cmDocumentation::PrintHelpOneCommand(std::ostream& os)
513 {
514 std::string cname = cmSystemTools::LowerCase(this->CurrentArgument);
515 if (this->PrintFiles(os, "command/" + cname)) {
516 return true;
517 }
518 // Argument was not a command. Complain.
519 os << "Argument \"" << this->CurrentArgument
520 << "\" to --help-command is not a CMake command. "
521 << "Use --help-command-list to see all commands.\n";
522 return false;
523 }
524
PrintHelpListCommands(std::ostream & os)525 bool cmDocumentation::PrintHelpListCommands(std::ostream& os)
526 {
527 this->PrintNames(os, "command/*");
528 return true;
529 }
530
PrintHelpOneModule(std::ostream & os)531 bool cmDocumentation::PrintHelpOneModule(std::ostream& os)
532 {
533 std::string mname = this->CurrentArgument;
534 if (this->PrintFiles(os, "module/" + mname)) {
535 return true;
536 }
537 // Argument was not a module. Complain.
538 os << "Argument \"" << this->CurrentArgument
539 << "\" to --help-module is not a CMake module.\n";
540 return false;
541 }
542
PrintHelpListModules(std::ostream & os)543 bool cmDocumentation::PrintHelpListModules(std::ostream& os)
544 {
545 std::vector<std::string> files;
546 this->GlobHelp(files, "module/*");
547 std::vector<std::string> modules;
548 for (std::string const& f : files) {
549 std::string module = cmSystemTools::GetFilenameName(f);
550 modules.push_back(module.substr(0, module.size() - 4));
551 }
552 std::sort(modules.begin(), modules.end());
553 for (std::string const& m : modules) {
554 os << m << "\n";
555 }
556 return true;
557 }
558
PrintHelpOneProperty(std::ostream & os)559 bool cmDocumentation::PrintHelpOneProperty(std::ostream& os)
560 {
561 std::string pname = cmSystemTools::HelpFileName(this->CurrentArgument);
562 if (this->PrintFiles(os, "prop_*/" + pname)) {
563 return true;
564 }
565 // Argument was not a property. Complain.
566 os << "Argument \"" << this->CurrentArgument
567 << "\" to --help-property is not a CMake property. "
568 << "Use --help-property-list to see all properties.\n";
569 return false;
570 }
571
PrintHelpListProperties(std::ostream & os)572 bool cmDocumentation::PrintHelpListProperties(std::ostream& os)
573 {
574 this->PrintNames(os, "prop_*/*");
575 return true;
576 }
577
PrintHelpOnePolicy(std::ostream & os)578 bool cmDocumentation::PrintHelpOnePolicy(std::ostream& os)
579 {
580 std::string pname = this->CurrentArgument;
581 std::vector<std::string> files;
582 if (this->PrintFiles(os, "policy/" + pname)) {
583 return true;
584 }
585
586 // Argument was not a policy. Complain.
587 os << "Argument \"" << this->CurrentArgument
588 << "\" to --help-policy is not a CMake policy.\n";
589 return false;
590 }
591
PrintHelpListPolicies(std::ostream & os)592 bool cmDocumentation::PrintHelpListPolicies(std::ostream& os)
593 {
594 this->PrintNames(os, "policy/*");
595 return true;
596 }
597
PrintHelpListGenerators(std::ostream & os)598 bool cmDocumentation::PrintHelpListGenerators(std::ostream& os)
599 {
600 const auto si = this->AllSections.find("Generators");
601 if (si != this->AllSections.end()) {
602 this->Formatter.SetIndent(" ");
603 this->Formatter.PrintSection(os, si->second);
604 }
605 return true;
606 }
607
PrintHelpOneVariable(std::ostream & os)608 bool cmDocumentation::PrintHelpOneVariable(std::ostream& os)
609 {
610 std::string vname = cmSystemTools::HelpFileName(this->CurrentArgument);
611 if (this->PrintFiles(os, "variable/" + vname)) {
612 return true;
613 }
614 // Argument was not a variable. Complain.
615 os << "Argument \"" << this->CurrentArgument
616 << "\" to --help-variable is not a defined variable. "
617 << "Use --help-variable-list to see all defined variables.\n";
618 return false;
619 }
620
PrintHelpListVariables(std::ostream & os)621 bool cmDocumentation::PrintHelpListVariables(std::ostream& os)
622 {
623 this->PrintNames(os, "variable/*");
624 return true;
625 }
626
PrintUsage(std::ostream & os)627 bool cmDocumentation::PrintUsage(std::ostream& os)
628 {
629 const auto si = this->AllSections.find("Usage");
630 if (si != this->AllSections.end()) {
631 this->Formatter.PrintSection(os, si->second);
632 }
633 return true;
634 }
635
PrintHelp(std::ostream & os)636 bool cmDocumentation::PrintHelp(std::ostream& os)
637 {
638 auto si = this->AllSections.find("Usage");
639 if (si != this->AllSections.end()) {
640 this->Formatter.PrintSection(os, si->second);
641 }
642 si = this->AllSections.find("Options");
643 if (si != this->AllSections.end()) {
644 this->Formatter.PrintSection(os, si->second);
645 }
646 if (this->ShowGenerators) {
647 si = this->AllSections.find("Generators");
648 if (si != this->AllSections.end()) {
649 this->Formatter.PrintSection(os, si->second);
650 }
651 }
652 return true;
653 }
654
GetNameString() const655 const char* cmDocumentation::GetNameString() const
656 {
657 if (!this->NameString.empty()) {
658 return this->NameString.c_str();
659 }
660 return "CMake";
661 }
662
IsOption(const char * arg) const663 bool cmDocumentation::IsOption(const char* arg) const
664 {
665 return ((arg[0] == '-') || (strcmp(arg, "/V") == 0) ||
666 (strcmp(arg, "/?") == 0));
667 }
668
PrintOldCustomModules(std::ostream & os)669 bool cmDocumentation::PrintOldCustomModules(std::ostream& os)
670 {
671 // CheckOptions abuses the Argument field to give us the file name.
672 std::string filename = this->CurrentArgument;
673 std::string ext = cmSystemTools::UpperCase(
674 cmSystemTools::GetFilenameLastExtension(filename));
675 std::string name = cmSystemTools::GetFilenameWithoutLastExtension(filename);
676
677 const char* summary = "cmake --help-custom-modules no longer supported\n";
678 const char* detail =
679 "CMake versions prior to 3.0 exposed their internal module help page\n"
680 "generation functionality through the --help-custom-modules option.\n"
681 "CMake versions 3.0 and above use other means to generate their module\n"
682 "help pages so this functionality is no longer available to be exposed.\n"
683 "\n"
684 "This file was generated as a placeholder to provide this information.\n";
685 if ((ext == ".HTM") || (ext == ".HTML")) {
686 os << "<html><title>" << name << "</title><body>\n"
687 << summary << "<p/>\n"
688 << detail << "</body></html>\n";
689 } else if ((ext.length() == 2) && (ext[1] >= '1') && (ext[1] <= '9')) {
690 /* clang-format off */
691 os <<
692 ".TH " << name << " " << ext[1] << " \"" <<
693 cmSystemTools::GetCurrentDateTime("%B %d, %Y") <<
694 "\" \"cmake " << cmVersion::GetCMakeVersion() << "\"\n"
695 ".SH NAME\n"
696 ".PP\n" <<
697 name << " \\- " << summary <<
698 "\n"
699 ".SH DESCRIPTION\n"
700 ".PP\n" <<
701 detail
702 ;
703 /* clang-format on */
704 } else {
705 os << name << "\n\n" << summary << "\n" << detail;
706 }
707 return true;
708 }
709