packaging: Initial packaging
[platform/upstream/cmake.git] / Source / cmDocumentation.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "cmDocumentation.h"
13
14 #include "cmSystemTools.h"
15 #include "cmVersion.h"
16 #include <cmsys/Directory.hxx>
17 #include <cmsys/Glob.hxx>
18
19 #include <algorithm>
20
21 //----------------------------------------------------------------------------
22 static const char *cmDocumentationStandardOptions[][3] =
23 {
24   {"--copyright [file]", "Print the CMake copyright and exit.",
25    "If a file is specified, the copyright is written into it."},
26   {"--help,-help,-usage,-h,-H,/?", "Print usage information and exit.",
27    "Usage describes the basic command line interface and its options."},
28   {"--help-full [file]", "Print full help and exit.",
29    "Full help displays most of the documentation provided by the UNIX "
30    "man page.  It is provided for use on non-UNIX platforms, but is "
31    "also convenient if the man page is not installed.  If a file is "
32    "specified, the help is written into it."},
33   {"--help-html [file]", "Print full help in HTML format.",
34    "This option is used by CMake authors to help produce web pages.  "
35    "If a file is specified, the help is written into it."},
36   {"--help-man [file]", "Print full help as a UNIX man page and exit.",
37    "This option is used by the cmake build to generate the UNIX man page.  "
38    "If a file is specified, the help is written into it."},
39   {"--version,-version,/V [file]",
40    "Show program name/version banner and exit.",
41    "If a file is specified, the version is written into it."},
42   {0,0,0}
43 };
44
45 //----------------------------------------------------------------------------
46 static const char *cmModulesDocumentationDescription[][3] =
47 {
48   {0,
49   "  CMake Modules - Modules coming with CMake, the Cross-Platform Makefile "
50   "Generator.", 0},
51 //  CMAKE_DOCUMENTATION_OVERVIEW,
52   {0,
53   "This is the documentation for the modules and scripts coming with CMake. "
54   "Using these modules you can check the computer system for "
55   "installed software packages, features of the compiler and the "
56   "existence of headers to name just a few.", 0},
57   {0,0,0}
58 };
59
60 //----------------------------------------------------------------------------
61 static const char *cmCustomModulesDocumentationDescription[][3] =
62 {
63   {0,
64   "  Custom CMake Modules - Additional Modules for CMake.", 0},
65 //  CMAKE_DOCUMENTATION_OVERVIEW,
66   {0,
67   "This is the documentation for additional modules and scripts for CMake. "
68   "Using these modules you can check the computer system for "
69   "installed software packages, features of the compiler and the "
70   "existence of headers to name just a few.", 0},
71   {0,0,0}
72 };
73
74 //----------------------------------------------------------------------------
75 static const char *cmPropertiesDocumentationDescription[][3] =
76 {
77   {0,
78    "  CMake Properties - Properties supported by CMake, "
79    "the Cross-Platform Makefile Generator.", 0},
80 //  CMAKE_DOCUMENTATION_OVERVIEW,
81   {0,
82    "This is the documentation for the properties supported by CMake. "
83    "Properties can have different scopes. They can either be assigned to a "
84    "source file, a directory, a target or globally to CMake. By modifying the "
85    "values of properties the behaviour of the build system can be customized.",
86    0},
87   {0,0,0}
88 };
89
90 //----------------------------------------------------------------------------
91 static const char *cmCompatCommandsDocumentationDescription[][3] =
92 {
93   {0,
94    "  CMake Compatibility Listfile Commands - "
95    "Obsolete commands supported by CMake for compatibility.", 0},
96 //  CMAKE_DOCUMENTATION_OVERVIEW,
97   {0,
98   "This is the documentation for now obsolete listfile commands from previous "
99   "CMake versions, which are still supported for compatibility reasons. You "
100   "should instead use the newer, faster and shinier new commands. ;-)", 0},
101   {0,0,0}
102 };
103
104 //----------------------------------------------------------------------------
105 static const char *cmDocumentationModulesHeader[][3] =
106 {
107   {0,
108    "The following modules are provided with CMake. "
109    "They can be used with INCLUDE(ModuleName).", 0},
110   {0,0,0}
111 };
112
113 //----------------------------------------------------------------------------
114 static const char *cmDocumentationCustomModulesHeader[][3] =
115 {
116   {0,
117    "The following modules are also available for CMake. "
118    "They can be used with INCLUDE(ModuleName).", 0},
119   {0,0,0}
120 };
121
122 //----------------------------------------------------------------------------
123 static const char *cmDocumentationGeneratorsHeader[][3] =
124 {
125   {0,
126    "The following generators are available on this platform:", 0},
127   {0,0,0}
128 };
129
130 //----------------------------------------------------------------------------
131 static const char *cmDocumentationStandardSeeAlso[][3] =
132 {
133   {0,
134    "The following resources are available to get help using CMake:", 0},
135   {"Home Page",
136    "http://www.cmake.org",
137    "The primary starting point for learning about CMake."},
138   {"Frequently Asked Questions",
139    "http://www.cmake.org/Wiki/CMake_FAQ",
140    "A Wiki is provided containing answers to frequently asked questions. "},
141   {"Online Documentation",
142    "http://www.cmake.org/HTML/Documentation.html",
143    "Links to available documentation may be found on this web page."},
144   {"Mailing List",
145    "http://www.cmake.org/HTML/MailingLists.html",
146    "For help and discussion about using cmake, a mailing list is provided at "
147    "cmake@cmake.org. "
148    "The list is member-post-only but one may sign up on the CMake web page. "
149    "Please first read the full documentation at "
150    "http://www.cmake.org before posting questions to the list."},
151   {0,0,0}
152 };
153
154 //----------------------------------------------------------------------------
155 static const char *cmDocumentationCopyright[][3] =
156 {
157   {0,
158    "Copyright 2000-2012 Kitware, Inc., Insight Software Consortium.  "
159    "All rights reserved.", 0},
160   {0,
161    "Redistribution and use in source and binary forms, with or without "
162    "modification, are permitted provided that the following conditions are "
163    "met:", 0},
164   {"",
165    "Redistributions of source code must retain the above copyright notice, "
166    "this list of conditions and the following disclaimer.", 0},
167   {"",
168    "Redistributions in binary form must reproduce the above copyright "
169    "notice, this list of conditions and the following disclaimer in the "
170    "documentation and/or other materials provided with the distribution.",
171    0},
172   {"",
173    "Neither the names of Kitware, Inc., the Insight Software Consortium, "
174    "nor the names of their contributors may be used to endorse or promote "
175    "products derived from this software without specific prior written "
176    "permission.", 0},
177   {0,
178    "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "
179    "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT "
180    "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR "
181    "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT "
182    "HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, "
183    "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT "
184    "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, "
185    "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY "
186    "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT "
187    "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE "
188    "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
189    0},
190   {0, 0, 0}
191 };
192
193 //----------------------------------------------------------------------------
194 #define DOCUMENT_INTRO(type, default_name, desc) \
195   static char const *cmDocumentation##type##Intro[2] = { default_name, desc };
196 #define GET_DOCUMENT_INTRO(type) cmDocumentation##type##Intro
197
198 DOCUMENT_INTRO(Modules, "cmakemodules",
199   "Reference of available CMake modules.");
200 DOCUMENT_INTRO(CustomModules, "cmakecustommodules",
201   "Reference of available CMake custom modules.");
202 DOCUMENT_INTRO(Policies, "cmakepolicies",
203   "Reference of CMake policies.");
204 DOCUMENT_INTRO(Properties, "cmakeprops",
205   "Reference of CMake properties.");
206 DOCUMENT_INTRO(Variables, "cmakevars",
207   "Reference of CMake variables.");
208 DOCUMENT_INTRO(Commands, "cmakecommands",
209   "Reference of available CMake commands.");
210 DOCUMENT_INTRO(CompatCommands, "cmakecompat",
211   "Reference of CMake compatibility commands.");
212
213 //----------------------------------------------------------------------------
214 cmDocumentation::cmDocumentation()
215 :CurrentFormatter(0)
216 {
217   this->SetForm(TextForm, 0);
218   this->addCommonStandardDocSections();
219   this->ShowGenerators = true;
220 }
221
222 //----------------------------------------------------------------------------
223 cmDocumentation::~cmDocumentation()
224 {
225   for(std::vector< char* >::iterator i = this->ModuleStrings.begin();
226       i != this->ModuleStrings.end(); ++i)
227     {
228     delete [] *i;
229     }
230   for(std::map<std::string,cmDocumentationSection *>::iterator i =
231         this->AllSections.begin();
232       i != this->AllSections.end(); ++i)
233     {
234     delete i->second;
235     }
236 }
237
238 //----------------------------------------------------------------------------
239 bool cmDocumentation::PrintCopyright(std::ostream& os)
240 {
241   cmDocumentationSection *sec = this->AllSections["Copyright"];
242   const std::vector<cmDocumentationEntry> &entries = sec->GetEntries();
243   for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
244       op != entries.end(); ++op)
245     {
246     if(op->Name.size())
247       {
248       os << " * ";
249       this->TextFormatter.SetIndent("    ");
250       this->TextFormatter.PrintColumn(os, op->Brief.c_str());
251       }
252     else
253       {
254       this->TextFormatter.SetIndent("");
255       this->TextFormatter.PrintColumn(os, op->Brief.c_str());
256       }
257     os << "\n";
258     }
259   return true;
260 }
261
262 //----------------------------------------------------------------------------
263 bool cmDocumentation::PrintVersion(std::ostream& os)
264 {
265   os << this->GetNameString() << " version "
266      << cmVersion::GetCMakeVersion() << "\n";
267   return true;
268 }
269
270 //----------------------------------------------------------------------------
271 void cmDocumentation::AddSectionToPrint(const char *section)
272 {
273   if (this->AllSections.find(section) != this->AllSections.end())
274     {
275     this->PrintSections.push_back(this->AllSections[section]);
276     }
277 }
278
279 //----------------------------------------------------------------------------
280 void cmDocumentation::ClearSections()
281 {
282   this->PrintSections.erase(this->PrintSections.begin(),
283                             this->PrintSections.end());
284   this->ModulesFound.clear();
285 }
286
287 //----------------------------------------------------------------------------
288 void cmDocumentation::AddDocumentIntroToPrint(const char* intro[2])
289 {
290   const char* docname = this->GetDocName(false);
291   if(intro && docname)
292     {
293     cmDocumentationSection* section;
294     std::string desc("");
295
296     desc += docname;
297     desc += " - ";
298     desc += intro[1];
299
300     section = new cmDocumentationSection("Introduction", "NAME");
301     section->Append(0, desc.c_str(), 0);
302     this->PrintSections.push_back(section);
303     }
304 }
305
306 //----------------------------------------------------------------------------
307 bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os,
308                                          const char* docname)
309 {
310   if ((this->CurrentFormatter->GetForm() != HTMLForm)
311        && (this->CurrentFormatter->GetForm() != DocbookForm)
312        && (this->CurrentFormatter->GetForm() != ManForm))
313     {
314     this->PrintVersion(os);
315     }
316
317   // Handle Document Name. docname==0 disables intro.
318   this->SetDocName("");
319   if (docname)
320     {
321     if (*docname)
322       this->SetDocName(docname);
323     else // empty string was given. select default if possible
324       this->SetDocName(this->GetDefaultDocName(ht));
325     }
326
327   switch (ht)
328     {
329     case cmDocumentation::Usage:
330       return this->PrintDocumentationUsage(os);
331     case cmDocumentation::Single:
332       return this->PrintDocumentationSingle(os);
333     case cmDocumentation::SingleModule:
334       return this->PrintDocumentationSingleModule(os);
335     case cmDocumentation::SinglePolicy:
336       return this->PrintDocumentationSinglePolicy(os);
337     case cmDocumentation::SingleProperty:
338       return this->PrintDocumentationSingleProperty(os);
339     case cmDocumentation::SingleVariable:
340       return this->PrintDocumentationSingleVariable(os);
341     case cmDocumentation::List:
342       this->PrintDocumentationList(os,"Commands");
343       this->PrintDocumentationList(os,"Compatibility Commands");
344       return true;
345     case cmDocumentation::ModuleList:
346       // find the modules first, print the custom module docs only if
347       // any custom modules have been found actually, Alex
348       this->CreateCustomModulesSection();
349       this->CreateModulesSection();
350       if (this->AllSections.find("Custom CMake Modules")
351          != this->AllSections.end())
352         {
353         this->PrintDocumentationList(os,"Custom CMake Modules");
354         }
355       this->PrintDocumentationList(os,"Modules");
356       return true;
357     case cmDocumentation::PropertyList:
358       this->PrintDocumentationList(os,"Properties Description");
359       for (std::vector<std::string>::iterator i =
360              this->PropertySections.begin();
361            i != this->PropertySections.end(); ++i)
362         {
363         this->PrintDocumentationList(os,i->c_str());
364         }
365       return true;
366     case cmDocumentation::VariableList:
367       for (std::vector<std::string>::iterator i =
368              this->VariableSections.begin();
369            i != this->VariableSections.end(); ++i)
370         {
371         this->PrintDocumentationList(os,i->c_str());
372         }
373       return true;
374     case cmDocumentation::Full:
375       return this->PrintDocumentationFull(os);
376     case cmDocumentation::Modules:
377       return this->PrintDocumentationModules(os);
378     case cmDocumentation::CustomModules:
379       return this->PrintDocumentationCustomModules(os);
380     case cmDocumentation::Policies:
381       return this->PrintDocumentationPolicies(os);
382     case cmDocumentation::Properties:
383       return this->PrintDocumentationProperties(os);
384     case cmDocumentation::Variables:
385       return this->PrintDocumentationVariables(os);
386     case cmDocumentation::Commands:
387       return this->PrintDocumentationCurrentCommands(os);
388     case cmDocumentation::CompatCommands:
389       return this->PrintDocumentationCompatCommands(os);
390
391     case cmDocumentation::Copyright:
392       return this->PrintCopyright(os);
393     case cmDocumentation::Version:
394       return true;
395     default: return false;
396     }
397 }
398
399 //----------------------------------------------------------------------------
400 bool cmDocumentation::CreateModulesSection()
401 {
402   cmDocumentationSection *sec =
403     new cmDocumentationSection("Standard CMake Modules", "MODULES");
404   this->AllSections["Modules"] = sec;
405   std::string cmakeModules = this->CMakeRoot;
406   cmakeModules += "/Modules";
407   cmsys::Directory dir;
408   dir.Load(cmakeModules.c_str());
409   if (dir.GetNumberOfFiles() > 0)
410     {
411     sec->Append(cmDocumentationModulesHeader[0]);
412     sec->Append(cmModulesDocumentationDescription);
413     this->CreateModuleDocsForDir(dir, *this->AllSections["Modules"]);
414     }
415   return true;
416 }
417
418 //----------------------------------------------------------------------------
419 bool cmDocumentation::CreateCustomModulesSection()
420 {
421   bool sectionHasHeader = false;
422
423   std::vector<std::string> dirs;
424   cmSystemTools::ExpandListArgument(this->CMakeModulePath, dirs);
425
426   for(std::vector<std::string>::const_iterator dirIt = dirs.begin();
427       dirIt != dirs.end();
428       ++dirIt)
429     {
430     cmsys::Directory dir;
431     dir.Load(dirIt->c_str());
432     if (dir.GetNumberOfFiles() > 0)
433       {
434       if (!sectionHasHeader)
435         {
436         cmDocumentationSection *sec =
437           new cmDocumentationSection("Custom CMake Modules","CUSTOM MODULES");
438         this->AllSections["Custom CMake Modules"] = sec;
439         sec->Append(cmDocumentationCustomModulesHeader[0]);
440         sec->Append(cmCustomModulesDocumentationDescription);
441         sectionHasHeader = true;
442         }
443       this->CreateModuleDocsForDir
444         (dir, *this->AllSections["Custom CMake Modules"]);
445       }
446     }
447
448   return true;
449 }
450
451 //----------------------------------------------------------------------------
452 void cmDocumentation
453 ::CreateModuleDocsForDir(cmsys::Directory& dir,
454                          cmDocumentationSection &moduleSection)
455 {
456   // sort the files alphabetically, so the docs for one module are easier
457   // to find than if they are in random order
458   std::vector<std::string> sortedFiles;
459   for(unsigned int i = 0; i < dir.GetNumberOfFiles(); ++i)
460   {
461     sortedFiles.push_back(dir.GetFile(i));
462   }
463   std::sort(sortedFiles.begin(), sortedFiles.end());
464
465   for(std::vector<std::string>::const_iterator fname = sortedFiles.begin();
466       fname!=sortedFiles.end(); ++fname)
467     {
468     if(fname->length() > 6)
469       {
470       if(fname->substr(fname->length()-6, 6) == ".cmake")
471         {
472         std::string moduleName = fname->substr(0, fname->length()-6);
473         // this check is to avoid creating documentation for the modules with
474         // the same name in multiple directories of CMAKE_MODULE_PATH
475         if (this->ModulesFound.find(moduleName) == this->ModulesFound.end())
476           {
477           this->ModulesFound.insert(moduleName);
478           std::string path = dir.GetPath();
479           path += "/";
480           path += (*fname);
481           this->CreateSingleModule(path.c_str(), moduleName.c_str(),
482                                    moduleSection);
483           }
484         }
485       }
486     }
487 }
488
489 //----------------------------------------------------------------------------
490 bool cmDocumentation::CreateSingleModule(const char* fname,
491                                          const char* moduleName,
492                                          cmDocumentationSection &moduleSection)
493 {
494   std::ifstream fin(fname);
495   if(!fin)
496     {
497     std::cerr << "Internal error: can not open module." << fname << std::endl;
498     return false;
499     }
500   std::string line;
501   std::string text;
502   std::string brief;
503   brief = " ";
504   bool newParagraph = true;
505   while ( fin && cmSystemTools::GetLineFromStream(fin, line) )
506     {
507     if(line.size() && line[0] == '#')
508       {
509       /* line beginnings with ## are mark-up ignore them */
510       if (line.size()>=2 && line[1] == '#') continue;
511       // blank line
512       if(line.size() <= 2)
513         {
514         text += "\n";
515         newParagraph = true;
516         }
517       else if(line[2] == '-')
518         {
519         brief = line.c_str()+4;
520         }
521       else
522         {
523         // two spaces
524         if(line[1] == ' ' && line[2] == ' ')
525           {
526           if(!newParagraph)
527             {
528             text += "\n";
529             newParagraph = true;
530             }
531           // Skip #, and leave space for preformatted
532           text += line.c_str()+1;
533           text += "\n";
534           }
535         else if(line[1] == ' ')
536           {
537           if(!newParagraph)
538             {
539             text += " ";
540             }
541           newParagraph = false;
542           // skip # and space
543           text += line.c_str()+2;
544           }
545         else
546           {
547           if(!newParagraph)
548             {
549             text += " ";
550             }
551           newParagraph = false;
552           // skip #
553           text += line.c_str()+1;
554           }
555         }
556       }
557     else
558       {
559       break;
560       }
561     }
562
563   if(text.length() < 2 && brief.length() == 1)
564     {
565     return false;
566     }
567
568   char* pname = strcpy(new char[strlen(moduleName)+1], moduleName);
569   char* ptext = strcpy(new char[text.length()+1], text.c_str());
570   this->ModuleStrings.push_back(pname);
571   this->ModuleStrings.push_back(ptext);
572   char* pbrief = strcpy(new char[brief.length()+1], brief.c_str());
573   this->ModuleStrings.push_back(pbrief);
574   moduleSection.Append(pname, pbrief, ptext);
575   return true;
576 }
577
578
579 //----------------------------------------------------------------------------
580 bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os)
581 {
582   bool result = true;
583
584   // Loop over requested documentation types.
585   for(std::vector<RequestedHelpItem>::const_iterator
586       i = this->RequestedHelpItems.begin();
587       i != this->RequestedHelpItems.end();
588       ++i)
589     {
590     this->SetForm(i->HelpForm, i->ManSection);
591     this->CurrentArgument = i->Argument;
592     // If a file name was given, use it.  Otherwise, default to the
593     // given stream.
594     std::ofstream* fout = 0;
595     std::ostream* s = &os;
596     std::string docname("");
597     if(i->Filename.length() > 0)
598       {
599       fout = new std::ofstream(i->Filename.c_str(), std::ios::out);
600       if(fout)
601         {
602         s = fout;
603         }
604       else
605         {
606         result = false;
607         }
608       if(i->Filename != "-")
609         {
610         docname = cmSystemTools::GetFilenameWithoutLastExtension(i->Filename);
611         }
612       }
613
614     // Print this documentation type to the stream.
615     if(!this->PrintDocumentation(i->HelpType, *s, docname.c_str()) || !*s)
616       {
617       result = false;
618       }
619
620     // Close the file if we wrote one.
621     if(fout)
622       {
623       delete fout;
624       }
625     }
626   return result;
627 }
628
629 #define GET_OPT_ARGUMENT(target)                      \
630      if((i+1 < argc) && !this->IsOption(argv[i+1]))   \
631         {                                             \
632         target = argv[i+1];                           \
633         i = i+1;                                      \
634         };
635
636
637 cmDocumentation::Form cmDocumentation::GetFormFromFilename(
638                                                    const std::string& filename,
639                                                    int* manSection)
640 {
641   std::string ext = cmSystemTools::GetFilenameLastExtension(filename);
642   ext = cmSystemTools::UpperCase(ext);
643   if ((ext == ".HTM") || (ext == ".HTML"))
644     {
645     return cmDocumentation::HTMLForm;
646     }
647
648   if (ext == ".DOCBOOK")
649     {
650     return cmDocumentation::DocbookForm;
651     }
652
653   // ".1" to ".9" should be manpages
654   if ((ext.length()==2) && (ext[1] >='1') && (ext[1]<='9'))
655     {
656     if (manSection)
657       {
658       *manSection = ext[1] - '0';
659       }
660     return cmDocumentation::ManForm;
661     }
662
663   return cmDocumentation::TextForm;
664 }
665
666 //----------------------------------------------------------------------------
667 void cmDocumentation::addCommonStandardDocSections()
668 {
669     cmDocumentationSection *sec;
670
671     sec = new cmDocumentationSection("Author","AUTHOR");
672     sec->Append(cmDocumentationEntry
673                (0,
674                 "This manual page was generated by the \"--help-man\" option.",
675                 0));
676     this->AllSections["Author"] = sec;
677
678     sec = new cmDocumentationSection("Copyright","COPYRIGHT");
679     sec->Append(cmDocumentationCopyright);
680     this->AllSections["Copyright"] = sec;
681
682     sec = new cmDocumentationSection("See Also","SEE ALSO");
683     sec->Append(cmDocumentationStandardSeeAlso);
684     this->AllSections["Standard See Also"] = sec;
685
686     sec = new cmDocumentationSection("Options","OPTIONS");
687     sec->Append(cmDocumentationStandardOptions);
688     this->AllSections["Options"] = sec;
689
690     sec = new cmDocumentationSection("Compatibility Commands",
691                                      "COMPATIBILITY COMMANDS");
692     sec->Append(cmCompatCommandsDocumentationDescription);
693     this->AllSections["Compatibility Commands"] = sec;
694 }
695
696 //----------------------------------------------------------------------------
697 void cmDocumentation::addCMakeStandardDocSections()
698 {
699     cmDocumentationSection *sec;
700
701     sec = new cmDocumentationSection("Properties","PROPERTIES");
702     sec->Append(cmPropertiesDocumentationDescription);
703     this->AllSections["Properties Description"] = sec;
704
705     sec = new cmDocumentationSection("Generators","GENERATORS");
706     sec->Append(cmDocumentationGeneratorsHeader);
707     this->AllSections["Generators"] = sec;
708
709     this->PropertySections.push_back("Properties of Global Scope");
710     this->PropertySections.push_back("Properties on Directories");
711     this->PropertySections.push_back("Properties on Targets");
712     this->PropertySections.push_back("Properties on Tests");
713     this->PropertySections.push_back("Properties on Source Files");
714     this->PropertySections.push_back("Properties on Cache Entries");
715
716     this->VariableSections.push_back("Variables that Provide Information");
717     this->VariableSections.push_back("Variables That Change Behavior");
718     this->VariableSections.push_back("Variables That Describe the System");
719     this->VariableSections.push_back("Variables that Control the Build");
720     this->VariableSections.push_back("Variables for Languages");
721
722 }
723
724 //----------------------------------------------------------------------------
725 void cmDocumentation::addCTestStandardDocSections()
726 {
727     // This is currently done for backward compatibility reason
728     // We may suppress some of these.
729     addCMakeStandardDocSections();
730 }
731
732 //----------------------------------------------------------------------------
733 void cmDocumentation::addCPackStandardDocSections()
734 {
735     cmDocumentationSection *sec;
736
737     sec = new cmDocumentationSection("Generators","GENERATORS");
738     sec->Append(cmDocumentationGeneratorsHeader);
739     this->AllSections["Generators"] = sec;
740
741     this->VariableSections.push_back(
742             "Variables common to all CPack generators");
743 }
744
745 void cmDocumentation::addAutomaticVariableSections(const std::string& section)
746 {
747   std::vector<std::string>::iterator it;
748   it = std::find(this->VariableSections.begin(),
749                  this->VariableSections.end(),
750                  section);
751   /* if the section does not exist then add it */
752   if (it==this->VariableSections.end())
753     {
754     this->VariableSections.push_back(section);
755     }
756 }
757 //----------------------------------------------------------------------------
758 int cmDocumentation::getDocumentedModulesListInDir(
759           std::string path,
760           std::string globExpr,
761           documentedModulesList_t& docedModuleList)
762 {
763   cmsys::Glob gl;
764   std::string findExpr;
765   std::vector<std::string> files;
766   std::string line;
767   documentedModuleSectionPair_t docPair;
768   int nbDocumentedModules = 0;
769
770   findExpr = path + "/" + globExpr;
771   if (gl.FindFiles(findExpr))
772     {
773     files = gl.GetFiles();
774     for (std::vector<std::string>::iterator itf=files.begin();
775         itf!=files.end();++itf)
776       {
777       std::ifstream fin((*itf).c_str());
778       // file access trouble ignore it (ignore this kind of error)
779       if (!fin) continue;
780       /* read first line in order to get doc section */
781       if (cmSystemTools::GetLineFromStream(fin, line))
782         {
783         /* Doc section indicates that
784          * this file has structured doc in it.
785          */
786         if (line.find("##section")!=std::string::npos)
787           {
788           // ok found one more documented module
789           ++nbDocumentedModules;
790           docPair.first = *itf;
791           // 10 is the size of '##section' + 1
792           docPair.second = line.substr(10,std::string::npos);
793           docedModuleList.push_back(docPair);
794           }
795         // No else if no section is found (undocumented module)
796         }
797       // No else cannot read first line (ignore this kind of error)
798       line = "";
799       }
800     }
801   if (nbDocumentedModules>0)
802     {
803     return 0;
804     }
805   else
806     {
807     return 1;
808     }
809 }
810
811 //----------------------------------------------------------------------------
812 static void trim(std::string& s)
813 {
814   std::string::size_type pos = s.find_last_not_of(' ');
815   if(pos != std::string::npos)
816     {
817     s.erase(pos + 1);
818     pos = s.find_first_not_of(' ');
819     if(pos != std::string::npos) s.erase(0, pos);
820     }
821   else
822     {
823     s.erase(s.begin(), s.end());
824     }
825 }
826
827 int cmDocumentation::GetStructuredDocFromFile(
828         const char* fname,
829         std::vector<cmDocumentationEntry>& commands,
830         cmake* cm)
831 {
832     typedef enum sdoce {
833         SDOC_NONE, SDOC_MODULE, SDOC_MACRO, SDOC_FUNCTION, SDOC_VARIABLE,
834         SDOC_SECTION,
835         SDOC_UNKNOWN} sdoc_t;
836     int nbDocItemFound = 0;
837     int docCtxIdx      = 0;
838     std::vector<int> docContextStack(60);
839     docContextStack[docCtxIdx]=SDOC_NONE;
840     cmDocumentationEntry e;
841     std::ifstream fin(fname);
842     if(!fin)
843       {
844       return nbDocItemFound;
845       }
846     std::string section;
847     std::string name;
848     std::string full;
849     std::string brief;
850     std::string line;
851     bool newCtx  = false; /* we've just entered ##<beginkey> context */
852     bool inBrief = false; /* we are currently parsing brief desc. */
853     bool inFullFirstParagraph = false; /* we are currently parsing full
854                                           desc. first paragraph */
855     brief = "";
856     full  = "";
857     bool newParagraph = true;
858     while ( fin && cmSystemTools::GetLineFromStream(fin, line) )
859       {
860       if(line.size() && line[0] == '#')
861         {
862         /* handle structured doc context */
863         if ((line.size()>=2) && line[1]=='#')
864         {
865             /* markup word is following '##' stopping at first space
866              * Some markup word like 'section' may have more characters
867              * following but we don't handle those here.
868              */
869             std::string mkword = line.substr(2,line.find(' ',2)-2);
870             if (mkword=="macro")
871             {
872                docCtxIdx++;
873                docContextStack[docCtxIdx]=SDOC_MACRO;
874                newCtx = true;
875             }
876             else if (mkword=="variable")
877             {
878                docCtxIdx++;
879                docContextStack[docCtxIdx]=SDOC_VARIABLE;
880                newCtx = true;
881             }
882             else if (mkword=="function")
883             {
884                docCtxIdx++;
885                docContextStack[docCtxIdx]=SDOC_FUNCTION;
886                newCtx = true;
887             }
888             else if (mkword=="module")
889             {
890                docCtxIdx++;
891                docContextStack[docCtxIdx]=SDOC_MODULE;
892                newCtx = true;
893             }
894             else if (mkword=="section")
895             {
896                docCtxIdx++;
897                docContextStack[docCtxIdx]=SDOC_SECTION;
898                // 10 is the size of '##section' + 1
899                section = line.substr(10,std::string::npos);
900                /* drop the rest of the line */
901                line = "";
902                newCtx = true;
903             }
904             else if (mkword.substr(0,3)=="end")
905             {
906                switch (docContextStack[docCtxIdx]) {
907                case SDOC_MACRO:
908                    /* for now MACRO and FUNCTION are handled in the same way */
909                case SDOC_FUNCTION:
910                    commands.push_back(cmDocumentationEntry(name.c_str(),
911                            brief.c_str(),full.c_str()));
912                    break;
913                case SDOC_VARIABLE:
914                    this->addAutomaticVariableSections(section);
915                    cm->DefineProperty
916                        (name.c_str(), cmProperty::VARIABLE,
917                         brief.c_str(),
918                         full.c_str(),false,
919                         section.c_str());
920                    break;
921                case SDOC_MODULE:
922                    /*  not implemented */
923                    break;
924                case SDOC_SECTION:
925                    /*  not implemented */
926                    break;
927                default:
928                    /* ignore other cases */
929                    break;
930                }
931                docCtxIdx--;
932                newCtx = false;
933                ++nbDocItemFound;
934             }
935             else
936             {
937                 // error out unhandled context
938                 return nbDocItemFound;
939             }
940             /* context is set go to next doc line */
941             continue;
942         }
943
944         // Now parse the text attached to the context
945
946         // The first line after the context mark-up contains::
947         //  name - brief until. (brief is dot terminated or
948         //                       followed by a blank line)
949         if (newCtx)
950         {
951             // no brief (for easy variable definition)
952             if (line.find("-")==std::string::npos)
953             {
954                 name = line.substr(1,std::string::npos);
955                 trim(name);
956                 brief   = "";
957                 inBrief = false;
958                 full = "";
959             }
960             // here we have a name and brief beginning
961             else
962             {
963                 name = line.substr(1,line.find("-")-1);
964                 trim(name);
965                 // we are parsing the brief context
966                 brief = line.substr(line.find("-")+1,std::string::npos);
967                 trim(brief);
968                 // Brief may already be terminated on the first line
969                 if (brief.find('.')!=std::string::npos)
970                 {
971                    inBrief = false;
972                    full    = brief.substr(brief.find('.')+1,std::string::npos);
973                    trim(full);
974                    inFullFirstParagraph = true;
975                    brief   = brief.substr(0,brief.find('.'));
976                 }
977                 // brief is continued on following lines
978                 else
979                 {
980                     inBrief = true;
981                     full = "";
982                 }
983             }
984             newCtx = false;
985             continue;
986         }
987         // blank line
988         if(line.size() <= 2)
989         {
990             if (inBrief) {
991               inBrief = false;
992               full    = "";
993             } else {
994               if (full.length()>0)
995                 {
996                 full += "\n";
997                 }
998               // the first paragraph of full has ended
999               inFullFirstParagraph = false;
1000             }
1001             newParagraph = true;
1002         }
1003         // brief is terminated by '.'
1004         else if (inBrief && (line.find('.')!=std::string::npos))
1005         {
1006             /* the brief just ended */
1007             inBrief = false;
1008             std::string endBrief  = line.substr(1,line.find('.'));
1009             trim(endBrief);
1010             trim(brief);
1011             brief  += " " + endBrief;
1012             full   += line.substr(line.find('.')+1,std::string::npos);
1013             trim(full);
1014             inFullFirstParagraph = true;
1015         }
1016         // we handle full text or multi-line brief.
1017         else
1018           {
1019           std::string* text;
1020           if (inBrief)
1021             {
1022             text = &brief;
1023             }
1024           else
1025             {
1026             text = &full;
1027             }
1028           // two spaces
1029           if(line[1] == ' ' && line[2] == ' ')
1030             {
1031             // there is no "full first paragraph at all."
1032             if (line[3] == ' ')
1033               {
1034               inFullFirstParagraph = false;
1035               }
1036
1037             if(!newParagraph && !inFullFirstParagraph)
1038               {
1039               *text += "\n";
1040               newParagraph = true;
1041               }
1042             // Skip #, and leave space for pre-formatted
1043             if (inFullFirstParagraph)
1044               {
1045               std::string temp = line.c_str()+1;
1046               trim(temp);
1047               *text += " " + temp;
1048               }
1049             else
1050               {
1051               *text += line.c_str()+1;
1052               *text += "\n";
1053               }
1054             }
1055           else if(line[1] == ' ')
1056             {
1057             if(!newParagraph)
1058               {
1059               *text += " ";
1060               }
1061             newParagraph = false;
1062             // skip # and space
1063             *text += line.c_str()+2;
1064             }
1065           else
1066             {
1067             if(!newParagraph)
1068               {
1069               *text += " ";
1070               }
1071             newParagraph = false;
1072             // skip #
1073             *text += line.c_str()+1;
1074             }
1075           }
1076         }
1077       /* next line is not the first context line */
1078       newCtx = false;
1079       }
1080     return nbDocItemFound;
1081 }
1082
1083 //----------------------------------------------------------------------------
1084 bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
1085                                    const char* exitOpt)
1086 {
1087   // Providing zero arguments gives usage information.
1088   if(argc == 1)
1089     {
1090     RequestedHelpItem help;
1091     help.HelpType = cmDocumentation::Usage;
1092     help.HelpForm = cmDocumentation::UsageForm;
1093     this->RequestedHelpItems.push_back(help);
1094     return true;
1095     }
1096
1097   // Search for supported help options.
1098
1099   bool result = false;
1100   for(int i=1; i < argc; ++i)
1101     {
1102     if(exitOpt && strcmp(argv[i], exitOpt) == 0)
1103       {
1104       return result;
1105       }
1106     RequestedHelpItem help;
1107     // Check if this is a supported help option.
1108     if((strcmp(argv[i], "-help") == 0) ||
1109        (strcmp(argv[i], "--help") == 0) ||
1110        (strcmp(argv[i], "/?") == 0) ||
1111        (strcmp(argv[i], "-usage") == 0) ||
1112        (strcmp(argv[i], "-h") == 0) ||
1113        (strcmp(argv[i], "-H") == 0))
1114       {
1115       help.HelpType = cmDocumentation::Usage;
1116       help.HelpForm = cmDocumentation::UsageForm;
1117       GET_OPT_ARGUMENT(help.Argument);
1118       help.Argument = cmSystemTools::LowerCase(help.Argument);
1119       // special case for single command
1120       if (!help.Argument.empty())
1121         {
1122         help.HelpType = cmDocumentation::Single;
1123         }
1124       }
1125     else if(strcmp(argv[i], "--help-properties") == 0)
1126       {
1127       help.HelpType = cmDocumentation::Properties;
1128       GET_OPT_ARGUMENT(help.Filename);
1129       help.HelpForm = this->GetFormFromFilename(help.Filename,
1130                                                 &help.ManSection);
1131       }
1132     else if(strcmp(argv[i], "--help-policies") == 0)
1133       {
1134       help.HelpType = cmDocumentation::Policies;
1135       GET_OPT_ARGUMENT(help.Filename);
1136       help.HelpForm = this->GetFormFromFilename(help.Filename,
1137                                                 &help.ManSection);
1138       }
1139     else if(strcmp(argv[i], "--help-variables") == 0)
1140       {
1141       help.HelpType = cmDocumentation::Variables;
1142       GET_OPT_ARGUMENT(help.Filename);
1143       help.HelpForm = this->GetFormFromFilename(help.Filename,
1144                                                 &help.ManSection);
1145       }
1146     else if(strcmp(argv[i], "--help-modules") == 0)
1147       {
1148       help.HelpType = cmDocumentation::Modules;
1149       GET_OPT_ARGUMENT(help.Filename);
1150       help.HelpForm = this->GetFormFromFilename(help.Filename,
1151                                                 &help.ManSection);
1152       }
1153     else if(strcmp(argv[i], "--help-custom-modules") == 0)
1154       {
1155       help.HelpType = cmDocumentation::CustomModules;
1156       GET_OPT_ARGUMENT(help.Filename);
1157       help.HelpForm = this->GetFormFromFilename(help.Filename,
1158                                                 &help.ManSection);
1159       }
1160     else if(strcmp(argv[i], "--help-commands") == 0)
1161       {
1162       help.HelpType = cmDocumentation::Commands;
1163       GET_OPT_ARGUMENT(help.Filename);
1164       help.HelpForm = this->GetFormFromFilename(help.Filename,
1165                                                 &help.ManSection);
1166       }
1167     else if(strcmp(argv[i], "--help-compatcommands") == 0)
1168       {
1169       help.HelpType = cmDocumentation::CompatCommands;
1170       GET_OPT_ARGUMENT(help.Filename);
1171       help.HelpForm = this->GetFormFromFilename(help.Filename,
1172                                                 &help.ManSection);
1173       }
1174     else if(strcmp(argv[i], "--help-full") == 0)
1175       {
1176       help.HelpType = cmDocumentation::Full;
1177       GET_OPT_ARGUMENT(help.Filename);
1178       help.HelpForm = this->GetFormFromFilename(help.Filename,
1179                                                 &help.ManSection);
1180       }
1181     else if(strcmp(argv[i], "--help-html") == 0)
1182       {
1183       help.HelpType = cmDocumentation::Full;
1184       GET_OPT_ARGUMENT(help.Filename);
1185       help.HelpForm = cmDocumentation::HTMLForm;
1186       }
1187     else if(strcmp(argv[i], "--help-man") == 0)
1188       {
1189       help.HelpType = cmDocumentation::Full;
1190       GET_OPT_ARGUMENT(help.Filename);
1191       help.HelpForm = cmDocumentation::ManForm;
1192       help.ManSection = 1;
1193       }
1194     else if(strcmp(argv[i], "--help-command") == 0)
1195       {
1196       help.HelpType = cmDocumentation::Single;
1197       GET_OPT_ARGUMENT(help.Argument);
1198       GET_OPT_ARGUMENT(help.Filename);
1199       help.Argument = cmSystemTools::LowerCase(help.Argument);
1200       help.HelpForm = this->GetFormFromFilename(help.Filename,
1201                                                 &help.ManSection);
1202       }
1203     else if(strcmp(argv[i], "--help-module") == 0)
1204       {
1205       help.HelpType = cmDocumentation::SingleModule;
1206       GET_OPT_ARGUMENT(help.Argument);
1207       GET_OPT_ARGUMENT(help.Filename);
1208       help.HelpForm = this->GetFormFromFilename(help.Filename,
1209                                                 &help.ManSection);
1210       }
1211     else if(strcmp(argv[i], "--help-property") == 0)
1212       {
1213       help.HelpType = cmDocumentation::SingleProperty;
1214       GET_OPT_ARGUMENT(help.Argument);
1215       GET_OPT_ARGUMENT(help.Filename);
1216       help.HelpForm = this->GetFormFromFilename(help.Filename,
1217                                                 &help.ManSection);
1218       }
1219     else if(strcmp(argv[i], "--help-policy") == 0)
1220       {
1221       help.HelpType = cmDocumentation::SinglePolicy;
1222       GET_OPT_ARGUMENT(help.Argument);
1223       GET_OPT_ARGUMENT(help.Filename);
1224       help.HelpForm = this->GetFormFromFilename(help.Filename,
1225                                                 &help.ManSection);
1226       }
1227     else if(strcmp(argv[i], "--help-variable") == 0)
1228       {
1229       help.HelpType = cmDocumentation::SingleVariable;
1230       GET_OPT_ARGUMENT(help.Argument);
1231       GET_OPT_ARGUMENT(help.Filename);
1232       help.HelpForm = this->GetFormFromFilename(help.Filename,
1233                                                 &help.ManSection);
1234       }
1235     else if(strcmp(argv[i], "--help-command-list") == 0)
1236       {
1237       help.HelpType = cmDocumentation::List;
1238       GET_OPT_ARGUMENT(help.Filename);
1239       help.HelpForm = cmDocumentation::TextForm;
1240       }
1241     else if(strcmp(argv[i], "--help-module-list") == 0)
1242       {
1243       help.HelpType = cmDocumentation::ModuleList;
1244       GET_OPT_ARGUMENT(help.Filename);
1245       help.HelpForm = cmDocumentation::TextForm;
1246       }
1247     else if(strcmp(argv[i], "--help-property-list") == 0)
1248       {
1249       help.HelpType = cmDocumentation::PropertyList;
1250       GET_OPT_ARGUMENT(help.Filename);
1251       help.HelpForm = cmDocumentation::TextForm;
1252       }
1253     else if(strcmp(argv[i], "--help-variable-list") == 0)
1254       {
1255       help.HelpType = cmDocumentation::VariableList;
1256       GET_OPT_ARGUMENT(help.Filename);
1257       help.HelpForm = cmDocumentation::TextForm;
1258       }
1259     else if(strcmp(argv[i], "--copyright") == 0)
1260       {
1261       help.HelpType = cmDocumentation::Copyright;
1262       GET_OPT_ARGUMENT(help.Filename);
1263       help.HelpForm = cmDocumentation::UsageForm;
1264       }
1265     else if((strcmp(argv[i], "--version") == 0) ||
1266             (strcmp(argv[i], "-version") == 0) ||
1267             (strcmp(argv[i], "/V") == 0))
1268       {
1269       help.HelpType = cmDocumentation::Version;
1270       GET_OPT_ARGUMENT(help.Filename);
1271       help.HelpForm = cmDocumentation::UsageForm;
1272       }
1273     if(help.HelpType != None)
1274       {
1275       // This is a help option.  See if there is a file name given.
1276       result = true;
1277       this->RequestedHelpItems.push_back(help);
1278       }
1279     }
1280   return result;
1281 }
1282
1283 //----------------------------------------------------------------------------
1284 void cmDocumentation::Print(Form f, int manSection, std::ostream& os)
1285 {
1286   this->SetForm(f, manSection);
1287   this->Print(os);
1288 }
1289
1290 //----------------------------------------------------------------------------
1291 void cmDocumentation::Print(std::ostream& os)
1292 {
1293   // if the formatter supports it, print a master index for
1294   // all sections
1295   this->CurrentFormatter->PrintIndex(os, this->PrintSections);
1296   for(unsigned int i=0; i < this->PrintSections.size(); ++i)
1297     {
1298     std::string name = this->PrintSections[i]->
1299       GetName((this->CurrentFormatter->GetForm()));
1300     this->CurrentFormatter->PrintSection(os,*this->PrintSections[i],
1301                                          name.c_str());
1302     }
1303 }
1304
1305 //----------------------------------------------------------------------------
1306 void cmDocumentation::SetName(const char* name)
1307 {
1308   this->NameString = name?name:"";
1309 }
1310
1311 //----------------------------------------------------------------------------
1312 void cmDocumentation::SetDocName(const char *docname)
1313 {
1314   this->DocName = docname?docname:"";
1315 }
1316
1317 //----------------------------------------------------------------------------
1318 void cmDocumentation::SetSection(const char *name,
1319                                  cmDocumentationSection *section)
1320 {
1321   if (this->AllSections.find(name) != this->AllSections.end())
1322     {
1323     delete this->AllSections[name];
1324     }
1325   this->AllSections[name] = section;
1326 }
1327
1328 //----------------------------------------------------------------------------
1329 void cmDocumentation::SetSection(const char *name,
1330                                  std::vector<cmDocumentationEntry> &docs)
1331 {
1332   cmDocumentationSection *sec =
1333     new cmDocumentationSection(name,
1334                                cmSystemTools::UpperCase(name).c_str());
1335   sec->Append(docs);
1336   this->SetSection(name,sec);
1337 }
1338
1339 //----------------------------------------------------------------------------
1340 void cmDocumentation::SetSection(const char *name,
1341                                  const char *docs[][3])
1342 {
1343   cmDocumentationSection *sec =
1344     new cmDocumentationSection(name,
1345                                cmSystemTools::UpperCase(name).c_str());
1346   sec->Append(docs);
1347   this->SetSection(name,sec);
1348 }
1349
1350 //----------------------------------------------------------------------------
1351 void cmDocumentation
1352 ::SetSections(std::map<std::string,cmDocumentationSection *> &sections)
1353 {
1354   for (std::map<std::string,cmDocumentationSection *>::const_iterator
1355          it = sections.begin(); it != sections.end(); ++it)
1356     {
1357     this->SetSection(it->first.c_str(),it->second);
1358     }
1359 }
1360
1361 //----------------------------------------------------------------------------
1362 void cmDocumentation::PrependSection(const char *name,
1363                                      const char *docs[][3])
1364 {
1365   cmDocumentationSection *sec = 0;
1366   if (this->AllSections.find(name) == this->AllSections.end())
1367     {
1368     sec = new cmDocumentationSection
1369       (name, cmSystemTools::UpperCase(name).c_str());
1370     this->SetSection(name,sec);
1371     }
1372   else
1373     {
1374     sec = this->AllSections[name];
1375     }
1376   sec->Prepend(docs);
1377 }
1378
1379 //----------------------------------------------------------------------------
1380 void cmDocumentation::PrependSection(const char *name,
1381                                      std::vector<cmDocumentationEntry> &docs)
1382 {
1383   cmDocumentationSection *sec = 0;
1384   if (this->AllSections.find(name) == this->AllSections.end())
1385     {
1386     sec = new cmDocumentationSection
1387       (name, cmSystemTools::UpperCase(name).c_str());
1388     this->SetSection(name,sec);
1389     }
1390   else
1391     {
1392     sec = this->AllSections[name];
1393     }
1394   sec->Prepend(docs);
1395 }
1396
1397 //----------------------------------------------------------------------------
1398 void cmDocumentation::AppendSection(const char *name,
1399                                     const char *docs[][3])
1400 {
1401   cmDocumentationSection *sec = 0;
1402   if (this->AllSections.find(name) == this->AllSections.end())
1403     {
1404     sec = new cmDocumentationSection
1405       (name, cmSystemTools::UpperCase(name).c_str());
1406     this->SetSection(name,sec);
1407     }
1408   else
1409     {
1410     sec = this->AllSections[name];
1411     }
1412   sec->Append(docs);
1413 }
1414
1415 //----------------------------------------------------------------------------
1416 void cmDocumentation::AppendSection(const char *name,
1417                                     std::vector<cmDocumentationEntry> &docs)
1418 {
1419   cmDocumentationSection *sec = 0;
1420   if (this->AllSections.find(name) == this->AllSections.end())
1421     {
1422     sec = new cmDocumentationSection
1423       (name, cmSystemTools::UpperCase(name).c_str());
1424     this->SetSection(name,sec);
1425     }
1426   else
1427     {
1428     sec = this->AllSections[name];
1429     }
1430   sec->Append(docs);
1431 }
1432
1433 //----------------------------------------------------------------------------
1434 void cmDocumentation::AppendSection(const char *name,
1435                                     cmDocumentationEntry &docs)
1436 {
1437
1438   std::vector<cmDocumentationEntry> docsVec;
1439   docsVec.push_back(docs);
1440   this->AppendSection(name,docsVec);
1441 }
1442
1443 //----------------------------------------------------------------------------
1444 void cmDocumentation::PrependSection(const char *name,
1445                                      cmDocumentationEntry &docs)
1446 {
1447
1448   std::vector<cmDocumentationEntry> docsVec;
1449   docsVec.push_back(docs);
1450   this->PrependSection(name,docsVec);
1451 }
1452
1453 //----------------------------------------------------------------------------
1454 void cmDocumentation::SetSeeAlsoList(const char *data[][3])
1455 {
1456   cmDocumentationSection *sec =
1457     new cmDocumentationSection("See Also", "SEE ALSO");
1458   this->AllSections["See Also"] = sec;
1459   this->SeeAlsoString = ".B ";
1460   int i = 0;
1461   while(data[i][1])
1462     {
1463     this->SeeAlsoString += data[i][1];
1464     this->SeeAlsoString += data[i+1][1]? "(1), ":"(1)";
1465     ++i;
1466     }
1467   sec->Append(0,this->SeeAlsoString.c_str(),0);
1468   sec->Append(cmDocumentationStandardSeeAlso);
1469 }
1470
1471 //----------------------------------------------------------------------------
1472 bool cmDocumentation::PrintDocumentationGeneric(std::ostream& os,
1473                                                 const char *section)
1474 {
1475   if(this->AllSections.find(section) == this->AllSections.end())
1476     {
1477     os << "Internal error: " << section << " list is empty." << std::endl;
1478     return false;
1479     }
1480   if(this->CurrentArgument.length() == 0)
1481     {
1482     os << "Required argument missing.\n";
1483     return false;
1484     }
1485   const std::vector<cmDocumentationEntry> &entries =
1486     this->AllSections[section]->GetEntries();
1487   for(std::vector<cmDocumentationEntry>::const_iterator ei =
1488         entries.begin();
1489       ei != entries.end(); ++ei)
1490     {
1491     if(this->CurrentArgument == ei->Name)
1492       {
1493       this->PrintDocumentationCommand(os, *ei);
1494       return true;
1495       }
1496     }
1497   return false;
1498 }
1499
1500 //----------------------------------------------------------------------------
1501 bool cmDocumentation::PrintDocumentationSingle(std::ostream& os)
1502 {
1503   if (this->PrintDocumentationGeneric(os,"Commands"))
1504     {
1505     return true;
1506     }
1507   if (this->PrintDocumentationGeneric(os,"Compatibility Commands"))
1508     {
1509     return true;
1510     }
1511
1512   // Argument was not a command.  Complain.
1513   os << "Argument \"" << this->CurrentArgument.c_str()
1514      << "\" to --help-command is not a CMake command.  "
1515      << "Use --help-command-list to see all commands.\n";
1516   return false;
1517 }
1518
1519 //----------------------------------------------------------------------------
1520 bool cmDocumentation::PrintDocumentationSingleModule(std::ostream& os)
1521 {
1522   if(this->CurrentArgument.length() == 0)
1523     {
1524     os << "Argument --help-module needs a module name.\n";
1525     return false;
1526     }
1527
1528   std::string moduleName;
1529   // find the module
1530   std::vector<std::string> dirs;
1531   cmSystemTools::ExpandListArgument(this->CMakeModulePath, dirs);
1532   for(std::vector<std::string>::const_iterator dirIt = dirs.begin();
1533       dirIt != dirs.end();
1534       ++dirIt)
1535     {
1536     moduleName = *dirIt;
1537     moduleName += "/";
1538     moduleName += this->CurrentArgument;
1539     moduleName += ".cmake";
1540     if(cmSystemTools::FileExists(moduleName.c_str()))
1541       {
1542       break;
1543       }
1544     moduleName = "";
1545     }
1546
1547   if (moduleName.empty())
1548     {
1549     moduleName = this->CMakeRoot;
1550     moduleName += "/Modules/";
1551     moduleName += this->CurrentArgument;
1552     moduleName += ".cmake";
1553     if(!cmSystemTools::FileExists(moduleName.c_str()))
1554       {
1555       moduleName = "";
1556       }
1557     }
1558
1559   if(!moduleName.empty())
1560     {
1561     cmDocumentationSection *sec =
1562       new cmDocumentationSection("Standard CMake Modules", "MODULES");
1563     this->AllSections["Modules"] = sec;
1564     if (this->CreateSingleModule(moduleName.c_str(),
1565                                  this->CurrentArgument.c_str(),
1566                                  *this->AllSections["Modules"]))
1567       {
1568       if(this->AllSections["Modules"]->GetEntries().size())
1569         {
1570         this->PrintDocumentationCommand
1571           (os,  this->AllSections["Modules"]->GetEntries()[0]);
1572         os <<  "\n       Defined in: ";
1573         os << moduleName << "\n";
1574         return true;
1575         }
1576       else
1577         {
1578         return false;
1579         }
1580       }
1581     }
1582
1583   // Argument was not a module.  Complain.
1584   os << "Argument \"" << this->CurrentArgument.c_str()
1585      << "\" to --help-module is not a CMake module.\n";
1586   return false;
1587 }
1588
1589 //----------------------------------------------------------------------------
1590 bool cmDocumentation::PrintDocumentationSingleProperty(std::ostream& os)
1591 {
1592   bool done = false;
1593   for (std::vector<std::string>::iterator i =
1594          this->PropertySections.begin();
1595        !done && i != this->PropertySections.end(); ++i)
1596     {
1597     done = this->PrintDocumentationGeneric(os,i->c_str());
1598     }
1599
1600   if (done)
1601     {
1602     return true;
1603     }
1604
1605   // Argument was not a command.  Complain.
1606   os << "Argument \"" << this->CurrentArgument.c_str()
1607      << "\" to --help-property is not a CMake property.  "
1608      << "Use --help-property-list to see all properties.\n";
1609   return false;
1610 }
1611
1612 //----------------------------------------------------------------------------
1613 bool cmDocumentation::PrintDocumentationSinglePolicy(std::ostream& os)
1614 {
1615   if (this->PrintDocumentationGeneric(os,"Policies"))
1616     {
1617     return true;
1618     }
1619
1620   // Argument was not a command.  Complain.
1621   os << "Argument \"" << this->CurrentArgument.c_str()
1622      << "\" to --help-policy is not a CMake policy.\n";
1623   return false;
1624 }
1625
1626 //----------------------------------------------------------------------------
1627 bool cmDocumentation::PrintDocumentationSingleVariable(std::ostream& os)
1628 {
1629   bool done = false;
1630   for (std::vector<std::string>::iterator i =
1631          this->VariableSections.begin();
1632        !done && i != this->VariableSections.end(); ++i)
1633     {
1634     done = this->PrintDocumentationGeneric(os,i->c_str());
1635     }
1636
1637   if (done)
1638     {
1639     return true;
1640     }
1641
1642   // Argument was not a command.  Complain.
1643   os << "Argument \"" << this->CurrentArgument.c_str()
1644      << "\" to --help-variable is not a defined variable.  "
1645      << "Use --help-variable-list to see all defined variables.\n";
1646   return false;
1647 }
1648
1649 //----------------------------------------------------------------------------
1650 bool cmDocumentation::PrintDocumentationList(std::ostream& os,
1651                                              const char *section)
1652 {
1653   if(this->AllSections.find(section) == this->AllSections.end())
1654     {
1655     os << "Internal error: " << section << " list is empty." << std::endl;
1656     return false;
1657     }
1658
1659   const std::vector<cmDocumentationEntry> &entries =
1660     this->AllSections[section]->GetEntries();
1661   for(std::vector<cmDocumentationEntry>::const_iterator ei =
1662         entries.begin();
1663       ei != entries.end(); ++ei)
1664     {
1665     if(ei->Name.size())
1666       {
1667       os << ei->Name << std::endl;
1668       }
1669     }
1670   return true;
1671 }
1672
1673 //----------------------------------------------------------------------------
1674 bool cmDocumentation::PrintDocumentationUsage(std::ostream& os)
1675 {
1676   this->ClearSections();
1677   this->AddSectionToPrint("Usage");
1678   this->AddSectionToPrint("Options");
1679   if(this->ShowGenerators)
1680     {
1681     this->AddSectionToPrint("Generators");
1682     }
1683   this->Print(os);
1684   return true;
1685 }
1686
1687 //----------------------------------------------------------------------------
1688 bool cmDocumentation::PrintDocumentationFull(std::ostream& os)
1689 {
1690   this->CreateFullDocumentation();
1691   this->CurrentFormatter->PrintHeader(GetNameString(), GetNameString(), os);
1692   this->Print(os);
1693   this->CurrentFormatter->PrintFooter(os);
1694   return true;
1695 }
1696
1697 //----------------------------------------------------------------------------
1698 bool cmDocumentation::PrintDocumentationModules(std::ostream& os)
1699 {
1700   this->ClearSections();
1701   this->CreateModulesSection();
1702   this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Modules));
1703   this->AddSectionToPrint("Description");
1704   this->AddSectionToPrint("Modules");
1705   this->AddSectionToPrint("Copyright");
1706   this->AddSectionToPrint("See Also");
1707   this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
1708   this->Print(os);
1709   this->CurrentFormatter->PrintFooter(os);
1710   return true;
1711 }
1712
1713 //----------------------------------------------------------------------------
1714 bool cmDocumentation::PrintDocumentationCustomModules(std::ostream& os)
1715 {
1716   this->ClearSections();
1717   this->CreateCustomModulesSection();
1718   this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(CustomModules));
1719   this->AddSectionToPrint("Description");
1720   this->AddSectionToPrint("Custom CMake Modules");
1721 // the custom modules are most probably not under Kitware's copyright, Alex
1722 //  this->AddSectionToPrint("Copyright");
1723   this->AddSectionToPrint("See Also");
1724
1725   this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
1726   this->Print(os);
1727   this->CurrentFormatter->PrintFooter(os);
1728   return true;
1729 }
1730
1731 //----------------------------------------------------------------------------
1732 bool cmDocumentation::PrintDocumentationPolicies(std::ostream& os)
1733 {
1734   this->ClearSections();
1735   this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Policies));
1736   this->AddSectionToPrint("Description");
1737   this->AddSectionToPrint("Policies");
1738   this->AddSectionToPrint("Copyright");
1739   this->AddSectionToPrint("See Also");
1740
1741   this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
1742   this->Print(os);
1743   this->CurrentFormatter->PrintFooter(os);
1744   return true;
1745 }
1746
1747 //----------------------------------------------------------------------------
1748 bool cmDocumentation::PrintDocumentationProperties(std::ostream& os)
1749 {
1750   this->ClearSections();
1751   this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Properties));
1752   this->AddSectionToPrint("Properties Description");
1753   for (std::vector<std::string>::iterator i =
1754          this->PropertySections.begin();
1755        i != this->PropertySections.end(); ++i)
1756     {
1757     this->AddSectionToPrint(i->c_str());
1758     }
1759   this->AddSectionToPrint("Copyright");
1760   this->AddSectionToPrint("Standard See Also");
1761   this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
1762   this->Print(os);
1763   this->CurrentFormatter->PrintFooter(os);
1764   return true;
1765 }
1766
1767 //----------------------------------------------------------------------------
1768 bool cmDocumentation::PrintDocumentationVariables(std::ostream& os)
1769 {
1770   this->ClearSections();
1771   this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Variables));
1772   for (std::vector<std::string>::iterator i =
1773          this->VariableSections.begin();
1774        i != this->VariableSections.end(); ++i)
1775     {
1776     this->AddSectionToPrint(i->c_str());
1777     }
1778   this->AddSectionToPrint("Copyright");
1779   this->AddSectionToPrint("Standard See Also");
1780   this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
1781   this->Print(os);
1782   this->CurrentFormatter->PrintFooter(os);
1783   return true;
1784 }
1785
1786 //----------------------------------------------------------------------------
1787 bool cmDocumentation::PrintDocumentationCurrentCommands(std::ostream& os)
1788 {
1789   this->ClearSections();
1790   this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(Commands));
1791   this->AddSectionToPrint("Commands");
1792   this->AddSectionToPrint("Copyright");
1793   this->AddSectionToPrint("Standard See Also");
1794   this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
1795   this->Print(os);
1796   this->CurrentFormatter->PrintFooter(os);
1797   return true;
1798 }
1799
1800 //----------------------------------------------------------------------------
1801 bool cmDocumentation::PrintDocumentationCompatCommands(std::ostream& os)
1802 {
1803   this->ClearSections();
1804   this->AddDocumentIntroToPrint(GET_DOCUMENT_INTRO(CompatCommands));
1805   this->AddSectionToPrint("Compatibility Commands Description");
1806   this->AddSectionToPrint("Compatibility Commands");
1807   this->AddSectionToPrint("Copyright");
1808   this->AddSectionToPrint("Standard See Also");
1809   this->CurrentFormatter->PrintHeader(GetDocName(), GetNameString(), os);
1810   this->Print(os);
1811   this->CurrentFormatter->PrintFooter(os);
1812   return true;
1813 }
1814
1815 //----------------------------------------------------------------------------
1816 void cmDocumentation
1817 ::PrintDocumentationCommand(std::ostream& os,
1818                             const cmDocumentationEntry &entry)
1819 {
1820   // the string "SingleItem" will be used in a few places to detect the case
1821   // that only the documentation for a single item is printed
1822   cmDocumentationSection *sec = new cmDocumentationSection("SingleItem","");
1823   sec->Append(entry);
1824   this->AllSections["temp"] = sec;
1825   this->ClearSections();
1826   this->AddSectionToPrint("temp");
1827   this->Print(os);
1828   this->AllSections.erase("temp");
1829   delete sec;
1830 }
1831
1832 //----------------------------------------------------------------------------
1833 void cmDocumentation::CreateFullDocumentation()
1834 {
1835   this->ClearSections();
1836   this->CreateCustomModulesSection();
1837   this->CreateModulesSection();
1838
1839   std::set<std::string> emitted;
1840   this->AddSectionToPrint("Name");
1841   emitted.insert("Name");
1842   this->AddSectionToPrint("Usage");
1843   emitted.insert("Usage");
1844   this->AddSectionToPrint("Description");
1845   emitted.insert("Description");
1846   this->AddSectionToPrint("Options");
1847   emitted.insert("Options");
1848   this->AddSectionToPrint("Generators");
1849   emitted.insert("Generators");
1850   this->AddSectionToPrint("Commands");
1851   emitted.insert("Commands");
1852
1853
1854   this->AddSectionToPrint("Properties Description");
1855   emitted.insert("Properties Description");
1856   for (std::vector<std::string>::iterator i =
1857          this->PropertySections.begin();
1858        i != this->PropertySections.end(); ++i)
1859     {
1860     this->AddSectionToPrint(i->c_str());
1861     emitted.insert(i->c_str());
1862     }
1863
1864   emitted.insert("Copyright");
1865   emitted.insert("See Also");
1866   emitted.insert("Standard See Also");
1867   emitted.insert("Author");
1868
1869   // add any sections not yet written out, or to be written out
1870   for (std::map<std::string, cmDocumentationSection*>::iterator i =
1871          this->AllSections.begin();
1872        i != this->AllSections.end(); ++i)
1873     {
1874     if (emitted.find(i->first) == emitted.end())
1875       {
1876       this->AddSectionToPrint(i->first.c_str());
1877       }
1878     }
1879
1880   this->AddSectionToPrint("Copyright");
1881
1882   if(this->CurrentFormatter->GetForm() == ManForm)
1883     {
1884     this->AddSectionToPrint("See Also");
1885     this->AddSectionToPrint("Author");
1886     }
1887   else
1888     {
1889     this->AddSectionToPrint("Standard See Also");
1890     }
1891 }
1892
1893 //----------------------------------------------------------------------------
1894 void cmDocumentation::SetForm(Form f, int manSection)
1895 {
1896   switch(f)
1897   {
1898     case HTMLForm:
1899       this->CurrentFormatter = &this->HTMLFormatter;
1900       break;
1901     case DocbookForm:
1902       this->CurrentFormatter = &this->DocbookFormatter;
1903       break;
1904     case ManForm:
1905       this->ManFormatter.SetManSection(manSection);
1906       this->CurrentFormatter = &this->ManFormatter;
1907       break;
1908     case TextForm:
1909       this->CurrentFormatter = &this->TextFormatter;
1910       break;
1911     case UsageForm:
1912       this->CurrentFormatter = & this->UsageFormatter;
1913       break;
1914   }
1915 }
1916
1917
1918 //----------------------------------------------------------------------------
1919 const char* cmDocumentation::GetNameString() const
1920 {
1921   if(this->NameString.length() > 0)
1922     {
1923     return this->NameString.c_str();
1924     }
1925   else
1926     {
1927     return "CMake";
1928     }
1929 }
1930
1931 //----------------------------------------------------------------------------
1932 const char* cmDocumentation::GetDocName(bool fallbackToNameString) const
1933 {
1934   if (this->DocName.length() > 0)
1935     {
1936     return this->DocName.c_str();
1937     }
1938   else if (fallbackToNameString)
1939     {
1940     return this->GetNameString();
1941     }
1942   else
1943     return 0;
1944 }
1945
1946 //----------------------------------------------------------------------------
1947 #define CASE_DEFAULT_DOCNAME(doctype) \
1948   case cmDocumentation::doctype : \
1949     return GET_DOCUMENT_INTRO(doctype)[0];
1950 const char* cmDocumentation::GetDefaultDocName(Type ht) const
1951 {
1952   switch (ht)
1953     {
1954     CASE_DEFAULT_DOCNAME(Modules)
1955     CASE_DEFAULT_DOCNAME(CustomModules)
1956     CASE_DEFAULT_DOCNAME(Policies)
1957     CASE_DEFAULT_DOCNAME(Properties)
1958     CASE_DEFAULT_DOCNAME(Variables)
1959     CASE_DEFAULT_DOCNAME(Commands)
1960     CASE_DEFAULT_DOCNAME(CompatCommands)
1961     default: break;
1962     }
1963   return 0;
1964 }
1965
1966 //----------------------------------------------------------------------------
1967 bool cmDocumentation::IsOption(const char* arg) const
1968 {
1969   return ((arg[0] == '-') || (strcmp(arg, "/V") == 0) ||
1970           (strcmp(arg, "/?") == 0));
1971 }