/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "cmDocumentation.h"
#include "cmSystemTools.h"
//----------------------------------------------------------------------------
static const cmDocumentationEntry cmDocumentationStandardOptions[] =
{
{"--copyright", "Print the CMake copyright and exit.", 0},
{"--usage", "Print usage information and exit.",
"Usage describes the basic command line interface and its options."},
{"--help", "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."},
{"--help-html", "Print full help in HTML format.",
"This option is used by CMake authors to help produce web pages."},
{"--man", "Print a UNIX man page and exit.",
"This option is used by CMake authors to generate the UNIX man page."},
{"--version", "Show program name/version banner and exit.", 0},
{0,0,0}
};
//----------------------------------------------------------------------------
const cmDocumentationEntry cmDocumentationCopyright[] =
{
{0,
"Copyright (c) 2002 Kitware, Inc., Insight Consortium.\n"
"All rights reserved.\n", 0},
{0,
"Redistribution and use in source and binary forms, with or without "
"modification, are permitted provided that the following conditions are "
"met:\n", 0},
{" * ",
"Redistributions of source code must retain the above copyright notice, "
"this list of conditions and the following disclaimer.\n", 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.\n",
0},
{" * ",
"The names of Kitware, Inc., the Insight Consortium, or the names of "
"any consortium members, or of any contributors, may not be used to "
"endorse or promote products derived from this software without "
"specific prior written permission.\n", 0},
{" * ",
"Modified source versions must be plainly marked as such, and must "
"not be misrepresented as being the original software.\n", 0},
{0,
"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER 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 AUTHORS 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.\n", 0},
{0, 0, 0}
};
//----------------------------------------------------------------------------
cmDocumentation::cmDocumentation()
{
this->Commands = 0;
this->Description = 0;
this->Name = 0;
this->UsageHelp = 0;
this->SetOptions(0);
}
//----------------------------------------------------------------------------
void cmDocumentation::PrintManSection(std::ostream& os,
const cmDocumentationEntry* section,
const char* name)
{
if(!section) { return; }
os << ".SH " << name << "\n";
for(const cmDocumentationEntry* op = section; op->brief; ++op)
{
if(op->name)
{
os << ".TP\n"
<< ".B " << op->name << "\n"
<< op->brief << "\n\n";
if(op->full)
{
this->PrintFull(os, op->full, 0, 0);
}
}
else
{
os << ".PP\n"
<< op->brief << "\n";
}
}
}
//----------------------------------------------------------------------------
void cmDocumentation::PrintHelpSection(std::ostream& os,
const cmDocumentationEntry* section)
{
if(!section) { return; }
for(const cmDocumentationEntry* op = section; op->brief; ++op)
{
if(op->name)
{
os << " " << op->name << "\n"
<< " ";
this->PrintColumn(os, 70, " ", op->brief);
if(op->full)
{
os << "\n"
<< "\n"
<< " ";
this->PrintColumn(os, 70, " ", op->full);
}
os << "\n";
}
else
{
this->PrintColumn(os, 77, "", op->brief);
os << "\n";
}
os << "\n";
}
}
//----------------------------------------------------------------------------
void cmDocumentation::PrintHTMLEscapes(std::ostream& os, const char* text)
{
static cmDocumentationEntry escapes[] =
{
{"<", "<", 0},
{">", ">", 0},
{"&", "&", 0},
{"\n", "
", 0},
{0,0,0}
};
for(const char* p = text; *p; ++p)
{
bool found = false;
for(const cmDocumentationEntry* op = escapes; !found && op->name; ++op)
{
if(op->name[0] == *p)
{
os << op->brief;
found = true;
}
}
if(!found)
{
os << *p;
}
}
}
//----------------------------------------------------------------------------
void cmDocumentation::PrintHTMLPreformatted(std::ostream& os, const char* text)
{
os << "
"; cmDocumentation::PrintHTMLEscapes(os, text); os << ""; } //---------------------------------------------------------------------------- void cmDocumentation::PrintHelpHTMLSection(std::ostream& os, const cmDocumentationEntry* section, const char* header) { if(!section) { return; } if(header) { os << "
";
this->PrintHTMLEscapes(os, op->name);
os << "
: ";
this->PrintHTMLEscapes(os, op->brief);
if(op->full)
{
os << "\n";
this->PrintHelpHTMLSection(os, this->UsageHelp, 0);
os << "
\n";
}
this->PrintHelpHTMLSection(os, this->Description, 0);
this->PrintHelpHTMLSection(os, &this->Options[0], "Command-line Options");
this->PrintHelpHTMLSection(os, this->Commands, "CMakeLists.txt Commands");
os << "\n"
<< "\n";
}
//----------------------------------------------------------------------------
void cmDocumentation::PrintManPage(std::ostream& os)
{
os << ".TH CMake 1 \""
<< cmSystemTools::GetCurrentDateTime("%B %d, %Y").c_str()
<< "\" \"CMake " CMake_VERSION_STRING "\"\n";
this->PrintManSection(os, this->Name, "NAME");
this->PrintManSection(os, this->UsageHelp, "SYNOPSIS");
this->PrintManSection(os, this->Description, "DESCRIPTION");
this->PrintManSection(os, &this->Options[0], "OPTIONS");
this->PrintManSection(os, this->Commands, "COMMANDS");
this->PrintManSection(os, cmDocumentationCopyright, "COPYRIGHT");
os << ".SH MAILING LIST\n";
os << "For help and discussion about using cmake, a mailing list is\n"
<< "provided at\n"
<< ".B cmake@www.cmake.org.\n"
<< "Please first read the full documentation at\n"
<< ".B http://www.cmake.org\n"
<< "before posting questions to the list.\n";
os << ".SH AUTHOR\n"
<< "This manual page was generated by \"cmake --man\".\n";
}
//----------------------------------------------------------------------------
void cmDocumentation::PrintCopyright(std::ostream& os)
{
os << "CMake version " CMake_VERSION_STRING "\n";
for(const cmDocumentationEntry* op = cmDocumentationCopyright;
op->brief; ++op)
{
if(op->name)
{
os << " * ";
this->PrintColumn(os, 74, " ", op->brief);
}
else
{
this->PrintColumn(os, 77, "", op->brief);
}
os << "\n";
}
}
//----------------------------------------------------------------------------
void cmDocumentation::PrintVersion(std::ostream& os)
{
os << "CMake version " CMake_VERSION_STRING "\n";
}
//----------------------------------------------------------------------------
void cmDocumentation::PrintColumn(std::ostream& os, int width,
const char* indent, const char* text)
{
// Print text arranged in a column of fixed witdh indented by the
// "indent" text.
const char* l = text;
int column = 0;
bool newSentence = false;
bool firstLine = true;
bool lastHadBlanks = false;
// Count leading blanks in the text.
int blanks = 0;
for(const char* b = l; *b == ' '; ++b) { ++blanks; }
// Loop until the end of the text.
while(*l)
{
// Parse the next word.
const char* r = l;
while(*r && (*r != '\n') && (*r != ' ')) { ++r; }
// Does it fit on this line?
if(r-l < (width-column-(newSentence?1:0)))
{
// Word fits on this line.
if(r > l)
{
if(column)
{
// Not first word on line. Separate from the previous word
// by a space, or two if this is a new sentence.
if(newSentence)
{
os << " ";
column += 2;
}
else
{
os << " ";
column += 1;
}
}
else
{
// If we are switching from a line that has leading blanks
// to a line that does not, or vice versa, add an extra
// newline.
if(blanks)
{
if(!lastHadBlanks && !firstLine)
{
os << "\n";
}
lastHadBlanks = true;
}
else
{
if(lastHadBlanks && !firstLine)
{
os << "\n";
}
lastHadBlanks = false;
}
// First word on line. Print indentation unless this is the
// first line.
os << (firstLine?"":indent);
// Further indent by leading blanks from the text on this
// line.
for(int i = 0; i < blanks; ++i)
{
os << " ";
++column;
}
blanks = 0;
}
// Print the word.
os.write(l, static_cast