|
|
@@ -14,7 +14,9 @@
|
|
|
#include "cmSystemTools.h"
|
|
|
#include "cmVersion.h"
|
|
|
#include <cmsys/Directory.hxx>
|
|
|
+#include <cmsys/Glob.hxx>
|
|
|
|
|
|
+#include <algorithm>
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
static const char *cmDocumentationStandardOptions[][3] =
|
|
|
@@ -220,55 +222,7 @@ cmDocumentation::cmDocumentation()
|
|
|
:CurrentFormatter(0)
|
|
|
{
|
|
|
this->SetForm(TextForm);
|
|
|
-
|
|
|
- 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("Properties","PROPERTIES");
|
|
|
- sec->Append(cmPropertiesDocumentationDescription);
|
|
|
- this->AllSections["Properties Description"] = sec;
|
|
|
-
|
|
|
- sec = new cmDocumentationSection("Generators","GENERATORS");
|
|
|
- sec->Append(cmDocumentationGeneratorsHeader);
|
|
|
- this->AllSections["Generators"] = sec;
|
|
|
-
|
|
|
- sec = new cmDocumentationSection("Compatibility Commands",
|
|
|
- "COMPATIBILITY COMMANDS");
|
|
|
- sec->Append(cmCompatCommandsDocumentationDescription);
|
|
|
- this->AllSections["Compatibility Commands"] = 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");
|
|
|
-
|
|
|
+ this->addCommonStandardDocSections();
|
|
|
this->ShowGenerators = true;
|
|
|
}
|
|
|
|
|
|
@@ -559,6 +513,8 @@ bool cmDocumentation::CreateSingleModule(const char* fname,
|
|
|
{
|
|
|
if(line.size() && line[0] == '#')
|
|
|
{
|
|
|
+ /* line beginnings with ## are mark-up ignore them */
|
|
|
+ if (line.size()>=2 && line[1] == '#') continue;
|
|
|
// blank line
|
|
|
if(line.size() <= 2)
|
|
|
{
|
|
|
@@ -709,6 +665,423 @@ cmDocumentation::Form cmDocumentation::GetFormFromFilename(
|
|
|
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<std::string>::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);
|
|
|
+ }
|
|
|
+}
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+int cmDocumentation::getDocumentedModulesListInDir(
|
|
|
+ std::string path,
|
|
|
+ std::string globExpr,
|
|
|
+ documentedModulesList_t& docedModuleList)
|
|
|
+{
|
|
|
+ cmsys::Glob gl;
|
|
|
+ std::string findExpr;
|
|
|
+ std::vector<std::string> files;
|
|
|
+ std::string line;
|
|
|
+ documentedModuleSectionPair_t docPair;
|
|
|
+ int nbDocumentedModules = 0;
|
|
|
+
|
|
|
+ findExpr = path + "/" + globExpr;
|
|
|
+ if (gl.FindFiles(findExpr))
|
|
|
+ {
|
|
|
+ files = gl.GetFiles();
|
|
|
+ for (std::vector<std::string>::iterator itf=files.begin();
|
|
|
+ itf!=files.end();++itf)
|
|
|
+ {
|
|
|
+ std::ifstream fin((*itf).c_str());
|
|
|
+ // file access trouble ignore it (ignore this kind of error)
|
|
|
+ if (!fin) continue;
|
|
|
+ /* read first line in order to get doc section */
|
|
|
+ if (cmSystemTools::GetLineFromStream(fin, line))
|
|
|
+ {
|
|
|
+ /* Doc section indicates that
|
|
|
+ * this file has structured doc in it.
|
|
|
+ */
|
|
|
+ if (line.find("##section")!=std::string::npos)
|
|
|
+ {
|
|
|
+ // ok found one more documented module
|
|
|
+ ++nbDocumentedModules;
|
|
|
+ docPair.first = *itf;
|
|
|
+ // 10 is the size of '##section' + 1
|
|
|
+ docPair.second = line.substr(10,std::string::npos);
|
|
|
+ docedModuleList.push_back(docPair);
|
|
|
+ }
|
|
|
+ // No else if no section is found (undocumented module)
|
|
|
+ }
|
|
|
+ // No else cannot read first line (ignore this kind of error)
|
|
|
+ line = "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (nbDocumentedModules>0)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+static void trim(std::string& s)
|
|
|
+{
|
|
|
+ std::string::size_type pos = s.find_last_not_of(' ');
|
|
|
+ if(pos != std::string::npos)
|
|
|
+ {
|
|
|
+ s.erase(pos + 1);
|
|
|
+ pos = s.find_first_not_of(' ');
|
|
|
+ if(pos != std::string::npos) s.erase(0, pos);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ s.erase(s.begin(), s.end());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int cmDocumentation::GetStructuredDocFromFile(
|
|
|
+ const char* fname,
|
|
|
+ std::vector<cmDocumentationEntry>& commands,
|
|
|
+ cmake* cm)
|
|
|
+{
|
|
|
+ typedef enum sdoce {
|
|
|
+ SDOC_NONE, SDOC_MODULE, SDOC_MACRO, SDOC_FUNCTION, SDOC_VARIABLE,
|
|
|
+ SDOC_SECTION,
|
|
|
+ SDOC_UNKNOWN} sdoc_t;
|
|
|
+ int nbDocItemFound = 0;
|
|
|
+ int docCtxIdx = 0;
|
|
|
+ std::vector<int> docContextStack(60);
|
|
|
+ docContextStack[docCtxIdx]=SDOC_NONE;
|
|
|
+ cmDocumentationEntry e;
|
|
|
+ std::ifstream fin(fname);
|
|
|
+ if(!fin)
|
|
|
+ {
|
|
|
+ return nbDocItemFound;
|
|
|
+ }
|
|
|
+ std::string section;
|
|
|
+ std::string name;
|
|
|
+ std::string full;
|
|
|
+ std::string brief;
|
|
|
+ std::string line;
|
|
|
+ bool newCtx = false; /* we've just entered ##<beginkey> context */
|
|
|
+ bool inBrief = false; /* we are currently parsing brief desc. */
|
|
|
+ bool inFullFirstParagraph = false; /* we are currently parsing full
|
|
|
+ desc. first paragraph */
|
|
|
+ brief = "";
|
|
|
+ full = "";
|
|
|
+ bool newParagraph = true;
|
|
|
+ while ( fin && cmSystemTools::GetLineFromStream(fin, line) )
|
|
|
+ {
|
|
|
+ if(line.size() && line[0] == '#')
|
|
|
+ {
|
|
|
+ /* handle structured doc context */
|
|
|
+ if ((line.size()>=2) && line[1]=='#')
|
|
|
+ {
|
|
|
+ /* markup word is following '##' stopping at first space
|
|
|
+ * Some markup word like 'section' may have more characters
|
|
|
+ * following but we don't handle those here.
|
|
|
+ */
|
|
|
+ std::string mkword = line.substr(2,line.find(' ',2)-2);
|
|
|
+ if (mkword=="macro")
|
|
|
+ {
|
|
|
+ docCtxIdx++;
|
|
|
+ docContextStack[docCtxIdx]=SDOC_MACRO;
|
|
|
+ newCtx = true;
|
|
|
+ }
|
|
|
+ else if (mkword=="variable")
|
|
|
+ {
|
|
|
+ docCtxIdx++;
|
|
|
+ docContextStack[docCtxIdx]=SDOC_VARIABLE;
|
|
|
+ newCtx = true;
|
|
|
+ }
|
|
|
+ else if (mkword=="function")
|
|
|
+ {
|
|
|
+ docCtxIdx++;
|
|
|
+ docContextStack[docCtxIdx]=SDOC_FUNCTION;
|
|
|
+ newCtx = true;
|
|
|
+ }
|
|
|
+ else if (mkword=="module")
|
|
|
+ {
|
|
|
+ docCtxIdx++;
|
|
|
+ docContextStack[docCtxIdx]=SDOC_MODULE;
|
|
|
+ newCtx = true;
|
|
|
+ }
|
|
|
+ else if (mkword=="section")
|
|
|
+ {
|
|
|
+ docCtxIdx++;
|
|
|
+ docContextStack[docCtxIdx]=SDOC_SECTION;
|
|
|
+ // 10 is the size of '##section' + 1
|
|
|
+ section = line.substr(10,std::string::npos);
|
|
|
+ /* drop the rest of the line */
|
|
|
+ line = "";
|
|
|
+ newCtx = true;
|
|
|
+ }
|
|
|
+ else if (mkword.substr(0,3)=="end")
|
|
|
+ {
|
|
|
+ switch (docContextStack[docCtxIdx]) {
|
|
|
+ case SDOC_MACRO:
|
|
|
+ /* for now MACRO and FUNCTION are handled in the same way */
|
|
|
+ case SDOC_FUNCTION:
|
|
|
+ commands.push_back(cmDocumentationEntry(name.c_str(),
|
|
|
+ brief.c_str(),full.c_str()));
|
|
|
+ break;
|
|
|
+ case SDOC_VARIABLE:
|
|
|
+ this->addAutomaticVariableSections(section);
|
|
|
+ cm->DefineProperty
|
|
|
+ (name.c_str(), cmProperty::VARIABLE,
|
|
|
+ brief.c_str(),
|
|
|
+ full.c_str(),false,
|
|
|
+ section.c_str());
|
|
|
+ break;
|
|
|
+ case SDOC_MODULE:
|
|
|
+ /* not implemented */
|
|
|
+ break;
|
|
|
+ case SDOC_SECTION:
|
|
|
+ /* not implemented */
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ /* ignore other cases */
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ docCtxIdx--;
|
|
|
+ newCtx = false;
|
|
|
+ ++nbDocItemFound;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // error out unhandled context
|
|
|
+ return nbDocItemFound;
|
|
|
+ }
|
|
|
+ /* context is set go to next doc line */
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Now parse the text attached to the context
|
|
|
+
|
|
|
+ // The first line after the context mark-up contains::
|
|
|
+ // name - brief until. (brief is dot terminated or
|
|
|
+ // followed by a blank line)
|
|
|
+ if (newCtx)
|
|
|
+ {
|
|
|
+ // no brief (for easy variable definition)
|
|
|
+ if (line.find("-")==std::string::npos)
|
|
|
+ {
|
|
|
+ name = line.substr(1,std::string::npos);
|
|
|
+ trim(name);
|
|
|
+ brief = "";
|
|
|
+ inBrief = false;
|
|
|
+ full = "";
|
|
|
+ }
|
|
|
+ // here we have a name and brief beginning
|
|
|
+ else
|
|
|
+ {
|
|
|
+ name = line.substr(1,line.find("-")-1);
|
|
|
+ trim(name);
|
|
|
+ // we are parsing the brief context
|
|
|
+ brief = line.substr(line.find("-")+1,std::string::npos);
|
|
|
+ trim(brief);
|
|
|
+ // Brief may already be terminated on the first line
|
|
|
+ if (brief.find('.')!=std::string::npos)
|
|
|
+ {
|
|
|
+ inBrief = false;
|
|
|
+ full = brief.substr(brief.find('.')+1,std::string::npos);
|
|
|
+ trim(full);
|
|
|
+ inFullFirstParagraph = true;
|
|
|
+ brief = brief.substr(0,brief.find('.'));
|
|
|
+ }
|
|
|
+ // brief is continued on following lines
|
|
|
+ else
|
|
|
+ {
|
|
|
+ inBrief = true;
|
|
|
+ full = "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ newCtx = false;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // blank line
|
|
|
+ if(line.size() <= 2)
|
|
|
+ {
|
|
|
+ if (inBrief) {
|
|
|
+ inBrief = false;
|
|
|
+ full = "";
|
|
|
+ } else {
|
|
|
+ if (full.length()>0)
|
|
|
+ {
|
|
|
+ full += "\n";
|
|
|
+ }
|
|
|
+ // the first paragraph of full has ended
|
|
|
+ inFullFirstParagraph = false;
|
|
|
+ }
|
|
|
+ newParagraph = true;
|
|
|
+ }
|
|
|
+ // brief is terminated by '.'
|
|
|
+ else if (inBrief && (line.find('.')!=std::string::npos))
|
|
|
+ {
|
|
|
+ /* the brief just ended */
|
|
|
+ inBrief = false;
|
|
|
+ std::string endBrief = line.substr(1,line.find('.'));
|
|
|
+ trim(endBrief);
|
|
|
+ trim(brief);
|
|
|
+ brief += " " + endBrief;
|
|
|
+ full += line.substr(line.find('.')+1,std::string::npos);
|
|
|
+ trim(full);
|
|
|
+ inFullFirstParagraph = true;
|
|
|
+ }
|
|
|
+ // we handle full text or multi-line brief.
|
|
|
+ else
|
|
|
+ {
|
|
|
+ std::string* text;
|
|
|
+ if (inBrief)
|
|
|
+ {
|
|
|
+ text = &brief;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ text = &full;
|
|
|
+ }
|
|
|
+ // two spaces
|
|
|
+ if(line[1] == ' ' && line[2] == ' ')
|
|
|
+ {
|
|
|
+ // there is no "full first paragraph at all."
|
|
|
+ if (line[3] == ' ')
|
|
|
+ {
|
|
|
+ inFullFirstParagraph = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!newParagraph && !inFullFirstParagraph)
|
|
|
+ {
|
|
|
+ *text += "\n";
|
|
|
+ newParagraph = true;
|
|
|
+ }
|
|
|
+ // Skip #, and leave space for pre-formatted
|
|
|
+ if (inFullFirstParagraph)
|
|
|
+ {
|
|
|
+ std::string temp = line.c_str()+1;
|
|
|
+ trim(temp);
|
|
|
+ *text += " " + temp;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ *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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* next line is not the first context line */
|
|
|
+ newCtx = false;
|
|
|
+ }
|
|
|
+ return nbDocItemFound;
|
|
|
+}
|
|
|
+
|
|
|
//----------------------------------------------------------------------------
|
|
|
bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
|
|
|
const char* exitOpt)
|