/*============================================================================ CMake - Cross Platform Makefile Generator Copyright 2000-2009 Kitware, Inc., Insight Software Consortium Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ #include "cmDocumentation.h" #include "cmSystemTools.h" #include "cmVersion.h" #include #include #include //---------------------------------------------------------------------------- static const char *cmDocumentationStandardOptions[][3] = { {"--copyright [file]", "Print the CMake copyright and exit.", "If a file is specified, the copyright is written into it."}, {"--help,-help,-usage,-h,-H,/?", "Print usage information and exit.", "Usage describes the basic command line interface and its options."}, {"--help-full [file]", "Print full help and exit.", "Full help displays most of the documentation provided by the UNIX " "man page. It is provided for use on non-UNIX platforms, but is " "also convenient if the man page is not installed. If a file is " "specified, the help is written into it."}, {"--help-html [file]", "Print full help in HTML format.", "This option is used by CMake authors to help produce web pages. " "If a file is specified, the help is written into it."}, {"--help-man [file]", "Print full help as a UNIX man page and exit.", "This option is used by the cmake build to generate the UNIX man page. " "If a file is specified, the help is written into it."}, {"--version,-version,/V [file]", "Show program name/version banner and exit.", "If a file is specified, the version is written into it."}, {0,0,0} }; //---------------------------------------------------------------------------- static const char *cmModulesDocumentationDescription[][3] = { {0, " CMake Modules - Modules coming with CMake, the Cross-Platform Makefile " "Generator.", 0}, // CMAKE_DOCUMENTATION_OVERVIEW, {0, "This is the documentation for the modules and scripts coming with CMake. " "Using these modules you can check the computer system for " "installed software packages, features of the compiler and the " "existence of headers to name just a few.", 0}, {0,0,0} }; //---------------------------------------------------------------------------- static const char *cmCustomModulesDocumentationDescription[][3] = { {0, " Custom CMake Modules - Additional Modules for CMake.", 0}, // CMAKE_DOCUMENTATION_OVERVIEW, {0, "This is the documentation for additional modules and scripts for CMake. " "Using these modules you can check the computer system for " "installed software packages, features of the compiler and the " "existence of headers to name just a few.", 0}, {0,0,0} }; //---------------------------------------------------------------------------- static const char *cmPropertiesDocumentationDescription[][3] = { {0, " CMake Properties - Properties supported by CMake, " "the Cross-Platform Makefile Generator.", 0}, // CMAKE_DOCUMENTATION_OVERVIEW, {0, "This is the documentation for the properties supported by CMake. " "Properties can have different scopes. They can either be assigned to a " "source file, a directory, a target or globally to CMake. By modifying the " "values of properties the behaviour of the build system can be customized.", 0}, {0,0,0} }; //---------------------------------------------------------------------------- static const char *cmCompatCommandsDocumentationDescription[][3] = { {0, " CMake Compatibility Listfile Commands - " "Obsolete commands supported by CMake for compatibility.", 0}, // CMAKE_DOCUMENTATION_OVERVIEW, {0, "This is the documentation for now obsolete listfile commands from previous " "CMake versions, which are still supported for compatibility reasons. You " "should instead use the newer, faster and shinier new commands. ;-)", 0}, {0,0,0} }; //---------------------------------------------------------------------------- static const char *cmDocumentationModulesHeader[][3] = { {0, "The following modules are provided with CMake. " "They can be used with INCLUDE(ModuleName).", 0}, {0,0,0} }; //---------------------------------------------------------------------------- static const char *cmDocumentationCustomModulesHeader[][3] = { {0, "The following modules are also available for CMake. " "They can be used with INCLUDE(ModuleName).", 0}, {0,0,0} }; //---------------------------------------------------------------------------- static const char *cmDocumentationGeneratorsHeader[][3] = { {0, "The following generators are available on this platform:", 0}, {0,0,0} }; //---------------------------------------------------------------------------- static const char *cmDocumentationStandardSeeAlso[][3] = { {0, "The following resources are available to get help using CMake:", 0}, {"Home Page", "http://www.cmake.org", "The primary starting point for learning about CMake."}, {"Frequently Asked Questions", "http://www.cmake.org/Wiki/CMake_FAQ", "A Wiki is provided containing answers to frequently asked questions. "}, {"Online Documentation", "http://www.cmake.org/HTML/Documentation.html", "Links to available documentation may be found on this web page."}, {"Mailing List", "http://www.cmake.org/HTML/MailingLists.html", "For help and discussion about using cmake, a mailing list is provided at " "cmake@cmake.org. " "The list is member-post-only but one may sign up on the CMake web page. " "Please first read the full documentation at " "http://www.cmake.org before posting questions to the list."}, {0,0,0} }; //---------------------------------------------------------------------------- static const char *cmDocumentationCopyright[][3] = { {0, "Copyright 2000-2012 Kitware, Inc., Insight Software Consortium. " "All rights reserved.", 0}, {0, "Redistribution and use in source and binary forms, with or without " "modification, are permitted provided that the following conditions are " "met:", 0}, {"", "Redistributions of source code must retain the above copyright notice, " "this list of conditions and the following disclaimer.", 0}, {"", "Redistributions in binary form must reproduce the above copyright " "notice, this list of conditions and the following disclaimer in the " "documentation and/or other materials provided with the distribution.", 0}, {"", "Neither the names of Kitware, Inc., the Insight Software Consortium, " "nor the names of their contributors may be used to endorse or promote " "products derived from this software without specific prior written " "permission.", 0}, {0, "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT " "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR " "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT " "HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, " "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT " "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, " "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY " "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT " "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE " "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", 0}, {0, 0, 0} }; //---------------------------------------------------------------------------- #define DOCUMENT_INTRO(type, default_name, desc) \ static char const *cmDocumentation##type##Intro[2] = { default_name, desc }; #define GET_DOCUMENT_INTRO(type) cmDocumentation##type##Intro DOCUMENT_INTRO(Modules, "cmakemodules", "Reference of available CMake modules."); DOCUMENT_INTRO(CustomModules, "cmakecustommodules", "Reference of available CMake custom modules."); DOCUMENT_INTRO(Policies, "cmakepolicies", "Reference of CMake policies."); DOCUMENT_INTRO(Properties, "cmakeprops", "Reference of CMake properties."); DOCUMENT_INTRO(Variables, "cmakevars", "Reference of CMake variables."); DOCUMENT_INTRO(Commands, "cmakecommands", "Reference of available CMake commands."); DOCUMENT_INTRO(CompatCommands, "cmakecompat", "Reference of CMake compatibility commands."); //---------------------------------------------------------------------------- cmDocumentation::cmDocumentation() :CurrentFormatter(0) { this->SetForm(TextForm, 0); this->addCommonStandardDocSections(); this->ShowGenerators = true; } //---------------------------------------------------------------------------- cmDocumentation::~cmDocumentation() { for(std::vector< char* >::iterator i = this->ModuleStrings.begin(); i != this->ModuleStrings.end(); ++i) { delete [] *i; } for(std::map::iterator i = this->AllSections.begin(); i != this->AllSections.end(); ++i) { delete i->second; } } //---------------------------------------------------------------------------- bool cmDocumentation::PrintCopyright(std::ostream& os) { cmDocumentationSection *sec = this->AllSections["Copyright"]; const std::vector &entries = sec->GetEntries(); for(std::vector::const_iterator op = entries.begin(); op != entries.end(); ++op) { if(op->Name.size()) { os << " * "; this->TextFormatter.SetIndent(" "); this->TextFormatter.PrintColumn(os, op->Brief.c_str()); } else { this->TextFormatter.SetIndent(""); this->TextFormatter.PrintColumn(os, op->Brief.c_str()); } os << "\n"; } return true; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintVersion(std::ostream& os) { os << this->GetNameString() << " version " << cmVersion::GetCMakeVersion() << "\n"; return true; } //---------------------------------------------------------------------------- void cmDocumentation::AddSectionToPrint(const char *section) { if (this->AllSections.find(section) != this->AllSections.end()) { this->PrintSections.push_back(this->AllSections[section]); } } //---------------------------------------------------------------------------- void cmDocumentation::ClearSections() { this->PrintSections.erase(this->PrintSections.begin(), this->PrintSections.end()); this->ModulesFound.clear(); } //---------------------------------------------------------------------------- void cmDocumentation::AddDocumentIntroToPrint(const char* intro[2]) { const char* docname = this->GetDocName(false); if(intro && docname) { cmDocumentationSection* section; std::string desc(""); desc += docname; desc += " - "; desc += intro[1]; section = new cmDocumentationSection("Introduction", "NAME"); section->Append(0, desc.c_str(), 0); this->PrintSections.push_back(section); } } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os, const char* docname) { // Handle Document Name. docname==0 disables intro. this->SetDocName(""); if (docname) { if (*docname) this->SetDocName(docname); else // empty string was given. select default if possible this->SetDocName(this->GetDefaultDocName(ht)); } switch (ht) { case cmDocumentation::Usage: return this->PrintDocumentationUsage(os); case cmDocumentation::Single: return this->PrintDocumentationSingle(os); case cmDocumentation::SingleModule: return this->PrintDocumentationSingleModule(os); case cmDocumentation::SinglePolicy: return this->PrintDocumentationSinglePolicy(os); case cmDocumentation::SingleProperty: return this->PrintDocumentationSingleProperty(os); case cmDocumentation::SingleVariable: return this->PrintDocumentationSingleVariable(os); case cmDocumentation::List: this->PrintDocumentationList(os,"Commands"); this->PrintDocumentationList(os,"Compatibility Commands"); return true; case cmDocumentation::ModuleList: // find the modules first, print the custom module docs only if // any custom modules have been found actually, Alex this->CreateCustomModulesSection(); this->CreateModulesSection(); if (this->AllSections.find("Custom CMake Modules") != this->AllSections.end()) { this->PrintDocumentationList(os,"Custom CMake Modules"); } this->PrintDocumentationList(os,"Modules"); return true; case cmDocumentation::PropertyList: this->PrintDocumentationList(os,"Properties Description"); for (std::vector::iterator i = this->PropertySections.begin(); i != this->PropertySections.end(); ++i) { this->PrintDocumentationList(os,i->c_str()); } return true; case cmDocumentation::VariableList: for (std::vector::iterator i = this->VariableSections.begin(); i != this->VariableSections.end(); ++i) { this->PrintDocumentationList(os,i->c_str()); } return true; case cmDocumentation::PolicyList: this->PrintDocumentationList(os,"Policies"); return true; case cmDocumentation::Full: return this->PrintDocumentationFull(os); case cmDocumentation::Modules: return this->PrintDocumentationModules(os); case cmDocumentation::CustomModules: return this->PrintDocumentationCustomModules(os); case cmDocumentation::Policies: return this->PrintDocumentationPolicies(os); case cmDocumentation::Properties: return this->PrintDocumentationProperties(os); case cmDocumentation::Variables: return this->PrintDocumentationVariables(os); case cmDocumentation::Commands: return this->PrintDocumentationCurrentCommands(os); case cmDocumentation::CompatCommands: return this->PrintDocumentationCompatCommands(os); case cmDocumentation::Copyright: return this->PrintCopyright(os); case cmDocumentation::Version: return this->PrintVersion(os); default: return false; } } //---------------------------------------------------------------------------- bool cmDocumentation::CreateModulesSection() { cmDocumentationSection *sec = new cmDocumentationSection("Standard CMake Modules", "MODULES"); this->AllSections["Modules"] = sec; std::string cmakeModules = this->CMakeRoot; cmakeModules += "/Modules"; cmsys::Directory dir; dir.Load(cmakeModules.c_str()); if (dir.GetNumberOfFiles() > 0) { sec->Append(cmDocumentationModulesHeader[0]); sec->Append(cmModulesDocumentationDescription); this->CreateModuleDocsForDir(dir, *this->AllSections["Modules"]); } return true; } //---------------------------------------------------------------------------- bool cmDocumentation::CreateCustomModulesSection() { bool sectionHasHeader = false; std::vector dirs; cmSystemTools::ExpandListArgument(this->CMakeModulePath, dirs); for(std::vector::const_iterator dirIt = dirs.begin(); dirIt != dirs.end(); ++dirIt) { cmsys::Directory dir; dir.Load(dirIt->c_str()); if (dir.GetNumberOfFiles() > 0) { if (!sectionHasHeader) { cmDocumentationSection *sec = new cmDocumentationSection("Custom CMake Modules","CUSTOM MODULES"); this->AllSections["Custom CMake Modules"] = sec; sec->Append(cmDocumentationCustomModulesHeader[0]); sec->Append(cmCustomModulesDocumentationDescription); sectionHasHeader = true; } this->CreateModuleDocsForDir (dir, *this->AllSections["Custom CMake Modules"]); } } return true; } //---------------------------------------------------------------------------- void cmDocumentation ::CreateModuleDocsForDir(cmsys::Directory& dir, cmDocumentationSection &moduleSection) { // sort the files alphabetically, so the docs for one module are easier // to find than if they are in random order std::vector sortedFiles; for(unsigned int i = 0; i < dir.GetNumberOfFiles(); ++i) { sortedFiles.push_back(dir.GetFile(i)); } std::sort(sortedFiles.begin(), sortedFiles.end()); for(std::vector::const_iterator fname = sortedFiles.begin(); fname!=sortedFiles.end(); ++fname) { if(fname->length() > 6) { if(fname->substr(fname->length()-6, 6) == ".cmake") { std::string moduleName = fname->substr(0, fname->length()-6); // this check is to avoid creating documentation for the modules with // the same name in multiple directories of CMAKE_MODULE_PATH if (this->ModulesFound.find(moduleName) == this->ModulesFound.end()) { this->ModulesFound.insert(moduleName); std::string path = dir.GetPath(); path += "/"; path += (*fname); this->CreateSingleModule(path.c_str(), moduleName.c_str(), moduleSection); } } } } } //---------------------------------------------------------------------------- bool cmDocumentation::CreateSingleModule(const char* fname, const char* moduleName, cmDocumentationSection &moduleSection) { std::ifstream fin(fname); if(!fin) { std::cerr << "Internal error: can not open module." << fname << std::endl; return false; } std::string line; std::string text; std::string brief; brief = " "; bool newParagraph = true; while ( fin && cmSystemTools::GetLineFromStream(fin, line) ) { if(line.size() && line[0] == '#') { // blank line if(line.size() <= 2) { text += "\n"; newParagraph = true; } else if(line[2] == '-') { brief = line.c_str()+4; } else { // two spaces if(line[1] == ' ' && line[2] == ' ') { if(!newParagraph) { text += "\n"; newParagraph = true; } // Skip #, and leave space for preformatted text += line.c_str()+1; text += "\n"; } else if(line[1] == ' ') { if(!newParagraph) { text += " "; } newParagraph = false; // skip # and space text += line.c_str()+2; } else { if(!newParagraph) { text += " "; } newParagraph = false; // skip # text += line.c_str()+1; } } } else { break; } } if(text.length() < 2 && brief.length() == 1) { return false; } char* pname = strcpy(new char[strlen(moduleName)+1], moduleName); char* ptext = strcpy(new char[text.length()+1], text.c_str()); this->ModuleStrings.push_back(pname); this->ModuleStrings.push_back(ptext); char* pbrief = strcpy(new char[brief.length()+1], brief.c_str()); this->ModuleStrings.push_back(pbrief); moduleSection.Append(pname, pbrief, ptext); return true; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os) { bool result = true; // Loop over requested documentation types. for(std::vector::const_iterator i = this->RequestedHelpItems.begin(); i != this->RequestedHelpItems.end(); ++i) { this->SetForm(i->HelpForm, i->ManSection); this->CurrentArgument = i->Argument; // If a file name was given, use it. Otherwise, default to the // given stream. std::ofstream* fout = 0; std::ostream* s = &os; std::string docname(""); if(i->Filename.length() > 0) { fout = new std::ofstream(i->Filename.c_str(), std::ios::out); if(fout) { s = fout; } else { result = false; } if(i->Filename != "-") { docname = cmSystemTools::GetFilenameWithoutLastExtension(i->Filename); } } // Print this documentation type to the stream. if(!this->PrintDocumentation(i->HelpType, *s, docname.c_str()) || !*s) { result = false; } // Close the file if we wrote one. if(fout) { delete fout; } } return result; } #define GET_OPT_ARGUMENT(target) \ if((i+1 < argc) && !this->IsOption(argv[i+1])) \ { \ target = argv[i+1]; \ i = i+1; \ }; cmDocumentation::Form cmDocumentation::GetFormFromFilename( const std::string& filename, int* manSection) { std::string ext = cmSystemTools::GetFilenameLastExtension(filename); ext = cmSystemTools::UpperCase(ext); if ((ext == ".HTM") || (ext == ".HTML")) { return cmDocumentation::HTMLForm; } if (ext == ".DOCBOOK") { return cmDocumentation::DocbookForm; } // ".1" to ".9" should be manpages if ((ext.length()==2) && (ext[1] >='1') && (ext[1]<='9')) { if (manSection) { *manSection = ext[1] - '0'; } return cmDocumentation::ManForm; } return cmDocumentation::TextForm; } //---------------------------------------------------------------------------- void cmDocumentation::addCommonStandardDocSections() { cmDocumentationSection *sec; sec = new cmDocumentationSection("Author","AUTHOR"); sec->Append(cmDocumentationEntry (0, "This manual page was generated by the \"--help-man\" option.", 0)); this->AllSections["Author"] = sec; sec = new cmDocumentationSection("Copyright","COPYRIGHT"); sec->Append(cmDocumentationCopyright); this->AllSections["Copyright"] = sec; sec = new cmDocumentationSection("See Also","SEE ALSO"); sec->Append(cmDocumentationStandardSeeAlso); this->AllSections["Standard See Also"] = sec; sec = new cmDocumentationSection("Options","OPTIONS"); sec->Append(cmDocumentationStandardOptions); this->AllSections["Options"] = sec; sec = new cmDocumentationSection("Compatibility Commands", "COMPATIBILITY COMMANDS"); sec->Append(cmCompatCommandsDocumentationDescription); this->AllSections["Compatibility Commands"] = sec; } //---------------------------------------------------------------------------- void cmDocumentation::addCMakeStandardDocSections() { cmDocumentationSection *sec; sec = new cmDocumentationSection("Properties","PROPERTIES"); sec->Append(cmPropertiesDocumentationDescription); this->AllSections["Properties Description"] = sec; sec = new cmDocumentationSection("Generators","GENERATORS"); sec->Append(cmDocumentationGeneratorsHeader); this->AllSections["Generators"] = sec; this->PropertySections.push_back("Properties of Global Scope"); this->PropertySections.push_back("Properties on Directories"); this->PropertySections.push_back("Properties on Targets"); this->PropertySections.push_back("Properties on Tests"); this->PropertySections.push_back("Properties on Source Files"); this->PropertySections.push_back("Properties on Cache Entries"); this->VariableSections.push_back("Variables that Provide Information"); this->VariableSections.push_back("Variables That Change Behavior"); this->VariableSections.push_back("Variables That Describe the System"); this->VariableSections.push_back("Variables that Control the Build"); this->VariableSections.push_back("Variables for Languages"); } //---------------------------------------------------------------------------- void cmDocumentation::addCTestStandardDocSections() { // This is currently done for backward compatibility reason // We may suppress some of these. addCMakeStandardDocSections(); } //---------------------------------------------------------------------------- void cmDocumentation::addCPackStandardDocSections() { cmDocumentationSection *sec; sec = new cmDocumentationSection("Generators","GENERATORS"); sec->Append(cmDocumentationGeneratorsHeader); this->AllSections["Generators"] = sec; this->VariableSections.push_back( "Variables common to all CPack generators"); } void cmDocumentation::addAutomaticVariableSections(const std::string& section) { std::vector::iterator it; it = std::find(this->VariableSections.begin(), this->VariableSections.end(), section); /* if the section does not exist then add it */ if (it==this->VariableSections.end()) { this->VariableSections.push_back(section); } } //---------------------------------------------------------------------------- bool cmDocumentation::CheckOptions(int argc, const char* const* argv, const char* exitOpt) { // Providing zero arguments gives usage information. if(argc == 1) { RequestedHelpItem help; help.HelpType = cmDocumentation::Usage; help.HelpForm = cmDocumentation::UsageForm; this->RequestedHelpItems.push_back(help); return true; } // Search for supported help options. bool result = false; for(int i=1; i < argc; ++i) { if(exitOpt && strcmp(argv[i], exitOpt) == 0) { return result; } RequestedHelpItem help; // Check if this is a supported help option. if((strcmp(argv[i], "-help") == 0) || (strcmp(argv[i], "--help") == 0) || (strcmp(argv[i], "/?") == 0) || (strcmp(argv[i], "-usage") == 0) || (strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-H") == 0)) { help.HelpType = cmDocumentation::Usage; help.HelpForm = cmDocumentation::UsageForm; GET_OPT_ARGUMENT(help.Argument); help.Argument = cmSystemTools::LowerCase(help.Argument); // special case for single command if (!help.Argument.empty()) { help.HelpType = cmDocumentation::Single; } } else if(strcmp(argv[i], "--help-properties") == 0) { help.HelpType = cmDocumentation::Properties; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-policies") == 0) { help.HelpType = cmDocumentation::Policies; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-variables") == 0) { help.HelpType = cmDocumentation::Variables; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-modules") == 0) { help.HelpType = cmDocumentation::Modules; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-custom-modules") == 0) { help.HelpType = cmDocumentation::CustomModules; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-commands") == 0) { help.HelpType = cmDocumentation::Commands; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-compatcommands") == 0) { help.HelpType = cmDocumentation::CompatCommands; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-full") == 0) { help.HelpType = cmDocumentation::Full; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-html") == 0) { help.HelpType = cmDocumentation::Full; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = cmDocumentation::HTMLForm; } else if(strcmp(argv[i], "--help-man") == 0) { help.HelpType = cmDocumentation::Full; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = cmDocumentation::ManForm; help.ManSection = 1; } else if(strcmp(argv[i], "--help-command") == 0) { help.HelpType = cmDocumentation::Single; GET_OPT_ARGUMENT(help.Argument); GET_OPT_ARGUMENT(help.Filename); help.Argument = cmSystemTools::LowerCase(help.Argument); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-module") == 0) { help.HelpType = cmDocumentation::SingleModule; GET_OPT_ARGUMENT(help.Argument); GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-property") == 0) { help.HelpType = cmDocumentation::SingleProperty; GET_OPT_ARGUMENT(help.Argument); GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-policy") == 0) { help.HelpType = cmDocumentation::SinglePolicy; GET_OPT_ARGUMENT(help.Argument); GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-variable") == 0) { help.HelpType = cmDocumentation::SingleVariable; GET_OPT_ARGUMENT(help.Argument); GET_OPT_ARGUMENT(help.Filename); help.HelpForm = this->GetFormFromFilename(help.Filename, &help.ManSection); } else if(strcmp(argv[i], "--help-command-list") == 0) { help.HelpType = cmDocumentation::List; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = cmDocumentation::TextForm; } else if(strcmp(argv[i], "--help-module-list") == 0) { help.HelpType = cmDocumentation::ModuleList; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = cmDocumentation::TextForm; } else if(strcmp(argv[i], "--help-property-list") == 0) { help.HelpType = cmDocumentation::PropertyList; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = cmDocumentation::TextForm; } else if(strcmp(argv[i], "--help-variable-list") == 0) { help.HelpType = cmDocumentation::VariableList; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = cmDocumentation::TextForm; } else if(strcmp(argv[i], "--help-policy-list") == 0) { help.HelpType = cmDocumentation::PolicyList; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = cmDocumentation::TextForm; } else if(strcmp(argv[i], "--copyright") == 0) { help.HelpType = cmDocumentation::Copyright; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = cmDocumentation::UsageForm; } else if((strcmp(argv[i], "--version") == 0) || (strcmp(argv[i], "-version") == 0) || (strcmp(argv[i], "/V") == 0)) { help.HelpType = cmDocumentation::Version; GET_OPT_ARGUMENT(help.Filename); help.HelpForm = cmDocumentation::UsageForm; } if(help.HelpType != None) { // This is a help option. See if there is a file name given. result = true; this->RequestedHelpItems.push_back(help); } } return result; } //---------------------------------------------------------------------------- void cmDocumentation::Print(Form f, int manSection, std::ostream& os) { this->SetForm(f, manSection); this->Print(os); } //---------------------------------------------------------------------------- void cmDocumentation::Print(std::ostream& os) { // if the formatter supports it, print a master index for // all sections this->CurrentFormatter->PrintIndex(os, this->PrintSections); for(unsigned int i=0; i < this->PrintSections.size(); ++i) { std::string name = this->PrintSections[i]-> GetName((this->CurrentFormatter->GetForm())); this->CurrentFormatter->PrintSection(os,*this->PrintSections[i], name.c_str()); } } //---------------------------------------------------------------------------- void cmDocumentation::SetName(const char* name) { this->NameString = name?name:""; } //---------------------------------------------------------------------------- void cmDocumentation::SetDocName(const char *docname) { this->DocName = docname?docname:""; } //---------------------------------------------------------------------------- void cmDocumentation::SetSection(const char *name, cmDocumentationSection *section) { if (this->AllSections.find(name) != this->AllSections.end()) { delete this->AllSections[name]; } this->AllSections[name] = section; } //---------------------------------------------------------------------------- void cmDocumentation::SetSection(const char *name, std::vector &docs) { cmDocumentationSection *sec = new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); sec->Append(docs); this->SetSection(name,sec); } //---------------------------------------------------------------------------- void cmDocumentation::SetSection(const char *name, const char *docs[][3]) { cmDocumentationSection *sec = new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str()); sec->Append(docs); this->SetSection(name,sec); } //---------------------------------------------------------------------------- void cmDocumentation ::SetSections(std::map §ions) { for (std::map::const_iterator it = sections.begin(); it != sections.end(); ++it) { this->SetSection(it->first.c_str(),it->second); } } //---------------------------------------------------------------------------- void cmDocumentation::PrependSection(const char *name, const char *docs[][3]) { cmDocumentationSection *sec = 0; if (this->AllSections.find(name) == this->AllSections.end()) { sec = new cmDocumentationSection (name, cmSystemTools::UpperCase(name).c_str()); this->SetSection(name,sec); } else { sec = this->AllSections[name]; } sec->Prepend(docs); } //---------------------------------------------------------------------------- void cmDocumentation::PrependSection(const char *name, std::vector &docs) { cmDocumentationSection *sec = 0; if (this->AllSections.find(name) == this->AllSections.end()) { sec = new cmDocumentationSection (name, cmSystemTools::UpperCase(name).c_str()); this->SetSection(name,sec); } else { sec = this->AllSections[name]; } sec->Prepend(docs); } //---------------------------------------------------------------------------- void cmDocumentation::AppendSection(const char *name, const char *docs[][3]) { cmDocumentationSection *sec = 0; if (this->AllSections.find(name) == this->AllSections.end()) { sec = new cmDocumentationSection (name, cmSystemTools::UpperCase(name).c_str()); this->SetSection(name,sec); } else { sec = this->AllSections[name]; } sec->Append(docs); } //---------------------------------------------------------------------------- void cmDocumentation::AppendSection(const char *name, std::vector &docs) { cmDocumentationSection *sec = 0; if (this->AllSections.find(name) == this->AllSections.end()) { sec = new cmDocumentationSection (name, cmSystemTools::UpperCase(name).c_str()); this->SetSection(name,sec); } else { sec = this->AllSections[name]; } sec->Append(docs); } //---------------------------------------------------------------------------- void cmDocumentation::AppendSection(const char *name, cmDocumentationEntry &docs) { std::vector docsVec; docsVec.push_back(docs); this->AppendSection(name,docsVec); } //---------------------------------------------------------------------------- void cmDocumentation::PrependSection(const char *name, cmDocumentationEntry &docs) { std::vector docsVec; docsVec.push_back(docs); this->PrependSection(name,docsVec); } //---------------------------------------------------------------------------- void cmDocumentation::SetSeeAlsoList(const char *data[][3]) { cmDocumentationSection *sec = new cmDocumentationSection("See Also", "SEE ALSO"); this->AllSections["See Also"] = sec; this->SeeAlsoString = ".B "; int i = 0; while(data[i][1]) { this->SeeAlsoString += data[i][1]; this->SeeAlsoString += data[i+1][1]? "(1), ":"(1)"; ++i; } sec->Append(0,this->SeeAlsoString.c_str(),0); sec->Append(cmDocumentationStandardSeeAlso); } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationGeneric(std::ostream& os, const char *section) { if(this->AllSections.find(section) == this->AllSections.end()) { os << "Internal error: " << section << " list is empty." << std::endl; return false; } if(this->CurrentArgument.length() == 0) { os << "Required argument missing.\n"; return false; } const std::vector &entries = this->AllSections[section]->GetEntries(); for(std::vector::const_iterator ei = entries.begin(); ei != entries.end(); ++ei) { if(this->CurrentArgument == ei->Name) { this->PrintDocumentationCommand(os, *ei); return true; } } return false; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationSingle(std::ostream& os) { if (this->PrintDocumentationGeneric(os,"Commands")) { return true; } if (this->PrintDocumentationGeneric(os,"Compatibility Commands")) { return true; } // Argument was not a command. Complain. os << "Argument \"" << this->CurrentArgument.c_str() << "\" to --help-command is not a CMake command. " << "Use --help-command-list to see all commands.\n"; return false; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationSingleModule(std::ostream& os) { if(this->CurrentArgument.length() == 0) { os << "Argument --help-module needs a module name.\n"; return false; } std::string moduleName; // find the module std::vector dirs; cmSystemTools::ExpandListArgument(this->CMakeModulePath, dirs); for(std::vector::const_iterator dirIt = dirs.begin(); dirIt != dirs.end(); ++dirIt) { moduleName = *dirIt; moduleName += "/"; moduleName += this->CurrentArgument; moduleName += ".cmake"; if(cmSystemTools::FileExists(moduleName.c_str())) { break; } moduleName = ""; } if (moduleName.empty()) { moduleName = this->CMakeRoot; moduleName += "/Modules/"; moduleName += this->CurrentArgument; moduleName += ".cmake"; if(!cmSystemTools::FileExists(moduleName.c_str())) { moduleName = ""; } } if(!moduleName.empty()) { cmDocumentationSection *sec = new cmDocumentationSection("Standard CMake Modules", "MODULES"); this->AllSections["Modules"] = sec; if (this->CreateSingleModule(moduleName.c_str(), this->CurrentArgument.c_str(), *this->AllSections["Modules"])) { if(this->AllSections["Modules"]->GetEntries().size()) { this->PrintDocumentationCommand (os, this->AllSections["Modules"]->GetEntries()[0]); os << "\n Defined in: "; os << moduleName << "\n"; return true; } else { return false; } } } // Argument was not a module. Complain. os << "Argument \"" << this->CurrentArgument.c_str() << "\" to --help-module is not a CMake module.\n"; return false; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationSingleProperty(std::ostream& os) { bool done = false; for (std::vector::iterator i = this->PropertySections.begin(); !done && i != this->PropertySections.end(); ++i) { done = this->PrintDocumentationGeneric(os,i->c_str()); } if (done) { return true; } // Argument was not a command. Complain. os << "Argument \"" << this->CurrentArgument.c_str() << "\" to --help-property is not a CMake property. " << "Use --help-property-list to see all properties.\n"; return false; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationSinglePolicy(std::ostream& os) { if (this->PrintDocumentationGeneric(os,"Policies")) { return true; } // Argument was not a policy. Complain. os << "Argument \"" << this->CurrentArgument.c_str() << "\" to --help-policy is not a CMake policy.\n"; return false; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationSingleVariable(std::ostream& os) { bool done = false; for (std::vector::iterator i = this->VariableSections.begin(); !done && i != this->VariableSections.end(); ++i) { done = this->PrintDocumentationGeneric(os,i->c_str()); } if (done) { return true; } // Argument was not a variable. Complain. os << "Argument \"" << this->CurrentArgument.c_str() << "\" to --help-variable is not a defined variable. " << "Use --help-variable-list to see all defined variables.\n"; return false; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationList(std::ostream& os, const char *section) { if(this->AllSections.find(section) == this->AllSections.end()) { os << "Internal error: " << section << " list is empty." << std::endl; return false; } const std::vector &entries = this->AllSections[section]->GetEntries(); for(std::vector::const_iterator ei = entries.begin(); ei != entries.end(); ++ei) { if(ei->Name.size()) { os << ei->Name << std::endl; } } return true; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationUsage(std::ostream& os) { this->ClearSections(); this->AddSectionToPrint("Usage"); this->AddSectionToPrint("Options"); if(this->ShowGenerators) { this->AddSectionToPrint("Generators"); } this->Print(os); return true; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationFull(std::ostream& os) { this->CreateFullDocumentation(); this->CurrentFormatter->PrintHeader(GetNameString(), GetNameString(), os); this->Print(os); this->CurrentFormatter->PrintFooter(os); return true; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationModules(std::ostream& os) { this->ClearSections(); this->CreateModulesSection(); this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Modules)); this->AddSectionToPrint("Description"); this->AddSectionToPrint("Modules"); this->AddSectionToPrint("Copyright"); this->AddSectionToPrint("See Also"); this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os); this->Print(os); this->CurrentFormatter->PrintFooter(os); return true; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationCustomModules(std::ostream& os) { this->ClearSections(); this->CreateCustomModulesSection(); this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(CustomModules)); this->AddSectionToPrint("Description"); this->AddSectionToPrint("Custom CMake Modules"); // the custom modules are most probably not under Kitware's copyright, Alex // this->AddSectionToPrint("Copyright"); this->AddSectionToPrint("See Also"); this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os); this->Print(os); this->CurrentFormatter->PrintFooter(os); return true; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationPolicies(std::ostream& os) { this->ClearSections(); this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Policies)); this->AddSectionToPrint("Description"); this->AddSectionToPrint("Policies"); this->AddSectionToPrint("Copyright"); this->AddSectionToPrint("See Also"); this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os); this->Print(os); this->CurrentFormatter->PrintFooter(os); return true; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationProperties(std::ostream& os) { this->ClearSections(); this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Properties)); this->AddSectionToPrint("Properties Description"); for (std::vector::iterator i = this->PropertySections.begin(); i != this->PropertySections.end(); ++i) { this->AddSectionToPrint(i->c_str()); } this->AddSectionToPrint("Copyright"); this->AddSectionToPrint("Standard See Also"); this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os); this->Print(os); this->CurrentFormatter->PrintFooter(os); return true; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationVariables(std::ostream& os) { this->ClearSections(); this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Variables)); for (std::vector::iterator i = this->VariableSections.begin(); i != this->VariableSections.end(); ++i) { this->AddSectionToPrint(i->c_str()); } this->AddSectionToPrint("Copyright"); this->AddSectionToPrint("Standard See Also"); this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os); this->Print(os); this->CurrentFormatter->PrintFooter(os); return true; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationCurrentCommands(std::ostream& os) { this->ClearSections(); this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Commands)); this->AddSectionToPrint("Commands"); this->AddSectionToPrint("Copyright"); this->AddSectionToPrint("Standard See Also"); this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os); this->Print(os); this->CurrentFormatter->PrintFooter(os); return true; } //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationCompatCommands(std::ostream& os) { this->ClearSections(); this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(CompatCommands)); this->AddSectionToPrint("Compatibility Commands Description"); this->AddSectionToPrint("Compatibility Commands"); this->AddSectionToPrint("Copyright"); this->AddSectionToPrint("Standard See Also"); this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os); this->Print(os); this->CurrentFormatter->PrintFooter(os); return true; } //---------------------------------------------------------------------------- void cmDocumentation ::PrintDocumentationCommand(std::ostream& os, const cmDocumentationEntry &entry) { // the string "SingleItem" will be used in a few places to detect the case // that only the documentation for a single item is printed cmDocumentationSection *sec = new cmDocumentationSection("SingleItem",""); sec->Append(entry); this->AllSections["temp"] = sec; this->ClearSections(); this->AddSectionToPrint("temp"); this->Print(os); this->AllSections.erase("temp"); delete sec; } //---------------------------------------------------------------------------- void cmDocumentation::CreateFullDocumentation() { this->ClearSections(); this->CreateCustomModulesSection(); this->CreateModulesSection(); std::set emitted; this->AddSectionToPrint("Name"); emitted.insert("Name"); this->AddSectionToPrint("Usage"); emitted.insert("Usage"); this->AddSectionToPrint("Description"); emitted.insert("Description"); this->AddSectionToPrint("Options"); emitted.insert("Options"); this->AddSectionToPrint("Generators"); emitted.insert("Generators"); this->AddSectionToPrint("Commands"); emitted.insert("Commands"); this->AddSectionToPrint("Properties Description"); emitted.insert("Properties Description"); for (std::vector::iterator i = this->PropertySections.begin(); i != this->PropertySections.end(); ++i) { this->AddSectionToPrint(i->c_str()); emitted.insert(i->c_str()); } emitted.insert("Copyright"); emitted.insert("See Also"); emitted.insert("Standard See Also"); emitted.insert("Author"); // add any sections not yet written out, or to be written out for (std::map::iterator i = this->AllSections.begin(); i != this->AllSections.end(); ++i) { if (emitted.find(i->first) == emitted.end()) { this->AddSectionToPrint(i->first.c_str()); } } this->AddSectionToPrint("Copyright"); if(this->CurrentFormatter->GetForm() == ManForm) { this->AddSectionToPrint("See Also"); this->AddSectionToPrint("Author"); } else { this->AddSectionToPrint("Standard See Also"); } } //---------------------------------------------------------------------------- void cmDocumentation::SetForm(Form f, int manSection) { switch(f) { case HTMLForm: this->CurrentFormatter = &this->HTMLFormatter; break; case DocbookForm: this->CurrentFormatter = &this->DocbookFormatter; break; case ManForm: this->ManFormatter.SetManSection(manSection); this->CurrentFormatter = &this->ManFormatter; break; case TextForm: this->CurrentFormatter = &this->TextFormatter; break; case UsageForm: this->CurrentFormatter = & this->UsageFormatter; break; } } //---------------------------------------------------------------------------- const char* cmDocumentation::GetNameString() const { if(this->NameString.length() > 0) { return this->NameString.c_str(); } else { return "CMake"; } } //---------------------------------------------------------------------------- const char* cmDocumentation::GetDocName(bool fallbackToNameString) const { if (this->DocName.length() > 0) { return this->DocName.c_str(); } else if (fallbackToNameString) { return this->GetNameString(); } else return 0; } //---------------------------------------------------------------------------- #define CASE_DEFAULT_DOCNAME(doctype) \ case cmDocumentation::doctype : \ return GET_DOCUMENT_INTRO(doctype)[0]; const char* cmDocumentation::GetDefaultDocName(Type ht) const { switch (ht) { CASE_DEFAULT_DOCNAME(Modules) CASE_DEFAULT_DOCNAME(CustomModules) CASE_DEFAULT_DOCNAME(Policies) CASE_DEFAULT_DOCNAME(Properties) CASE_DEFAULT_DOCNAME(Variables) CASE_DEFAULT_DOCNAME(Commands) CASE_DEFAULT_DOCNAME(CompatCommands) default: break; } return 0; } //---------------------------------------------------------------------------- bool cmDocumentation::IsOption(const char* arg) const { return ((arg[0] == '-') || (strcmp(arg, "/V") == 0) || (strcmp(arg, "/?") == 0)); }