From 1f55680332c133fddce4a0b85cfb7ee1a20cff75 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 14 Feb 2003 10:53:37 -0500 Subject: [PATCH] ENH: Added cmDocumentation class to generate various forms of documentation. Each executable will be able to generate its own documentation. --- Source/CMakeLists.txt | 1 + Source/CursesDialog/ccmake.cxx | 35 +++ Source/Makefile.in | 1 + Source/cmDocumentation.cxx | 478 +++++++++++++++++++++++++++++++++ Source/cmDocumentation.h | 65 +++++ Source/cmStandardIncludes.h | 8 + Source/cmSystemTools.cxx | 9 + Source/cmSystemTools.h | 2 + Source/cmake.cxx | 17 ++ Source/cmake.h | 2 + Source/cmakemain.cxx | 54 +++- 11 files changed, 663 insertions(+), 9 deletions(-) create mode 100644 Source/cmDocumentation.cxx create mode 100644 Source/cmDocumentation.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 0c83d5357..fd9d006d9 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -9,6 +9,7 @@ cmRegularExpression.cxx cmSourceFile.cxx cmSystemTools.cxx cmDirectory.cxx +cmDocumentation.cxx cmDynamicLoader.cxx cmCommands.cxx cmTarget.cxx diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 8cd2ccb9a..47ae7ee55 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -17,6 +17,7 @@ #include "../cmCacheManager.h" #include "../cmSystemTools.h" #include "../cmake.h" +#include "../cmDocumentation.h" #include #include @@ -26,6 +27,30 @@ #include #include +//---------------------------------------------------------------------------- +static const cmDocumentationEntry cmDocumentationName[] = +{ + {"ccmake", + "- Curses Interface for CMake.", 0}, + {0,0,0} +}; + +//---------------------------------------------------------------------------- +static const cmDocumentationEntry cmDocumentationUsage[] = +{ + {0, + "ccmake ", 0}, + {0,0,0} +}; + +//---------------------------------------------------------------------------- +static const cmDocumentationEntry cmDocumentationDescription[] = +{ + {0, + "CMake reads ... ", 0}, + {0,0,0} +}; + cmCursesForm* cmCursesForm::CurrentForm=0; extern "C" @@ -60,6 +85,16 @@ void CMakeErrorHandler(const char* message, const char* title, bool&, void* clie int main(int argc, char** argv) { + cmDocumentation doc; + if(cmDocumentation::Type ht = doc.CheckOptions(argc, argv)) + { + doc.SetName(cmDocumentationName); + doc.SetUsage(cmDocumentationUsage); + doc.SetDescription(cmDocumentationDescription); + doc.Print(ht, std::cout); + return 0; + } + bool debug = false; unsigned int i; int j; diff --git a/Source/Makefile.in b/Source/Makefile.in index 1d8bd9afb..df42fc32b 100644 --- a/Source/Makefile.in +++ b/Source/Makefile.in @@ -19,6 +19,7 @@ cmakewizard.o \ cmakemain.o \ cmMakeDepend.o \ cmMakefile.o \ +cmDocumentation.o \ cmGlobalGenerator.o \ cmLocalGenerator.o \ cmRegularExpression.o \ diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx new file mode 100644 index 000000000..2532c16f9 --- /dev/null +++ b/Source/cmDocumentation.cxx @@ -0,0 +1,478 @@ +/*========================================================================= + + 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"; + if(op->full) { os << op->full << "\n"; } + } + 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" + << " "; + 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}, + {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::PrintHelpHTMLSection(std::ostream& os, + const cmDocumentationEntry* section, + const char* header) +{ + if(!section) { return; } + if(header) + { + os << "

" << header << "

\n"; + } + for(const cmDocumentationEntry* op = section; op->brief;) + { + if(op->name) + { + os << "
    \n"; + for(;op->name;++op) + { + os << "
  • \n"; + os << " "; + this->PrintHTMLEscapes(os, op->name); + os << ": "; + this->PrintHTMLEscapes(os, op->brief); + if(op->full) + { + os << " "; + this->PrintHTMLEscapes(os, op->full); + } + os << "\n"; + os << "
  • \n"; + } + os << "
\n"; + } + else + { + this->PrintHTMLEscapes(os, op->brief); + os << "\n"; + ++op; + } + } +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintUsageSection(std::ostream& os, + const cmDocumentationEntry* section) +{ + if(!section) { return; } + std::ios::fmtflags flags = os.flags(); + os.setf(flags | std::ios::left); + for(const cmDocumentationEntry* op = section; op->brief; ++op) + { + if(op->name) + { + os << " "; + os.width(25); + os << op->name << "= " << op->brief << "\n"; + } + else + { + os << "\n"; + this->PrintColumn(os, 74, "", op->brief); + os << "\n"; + } + } + os.setf(flags); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintUsage(std::ostream& os) +{ + os << "Usage:\n"; + this->PrintUsageSection(os, this->UsageHelp); + this->PrintUsageSection(os, &this->Options[0]); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintHelp(std::ostream& os) +{ + os << "Usage:\n"; + os << "\n"; + this->PrintHelpSection(os, this->UsageHelp); + this->PrintHelpSection(os, this->Description); + os << "--------------------------------------------------------------------------\n"; + this->PrintHelpSection(os, &this->Options[0]); + os << "--------------------------------------------------------------------------\n"; + this->PrintHelpSection(os, this->Commands); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintHelpHTML(std::ostream& os) +{ + os << "\n" + << "\n"; + os << "

Using CMake

\n"; + if(this->UsageHelp) + { + 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 first = true; + 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 + { + // First word on line. Print indentation unless this is the + // first line. + os << (first?"":indent); + } + + // Print the word. + os.write(l, static_cast(r-l)); + newSentence = (*(r-1) == '.'); + } + + if(*r == '\n') + { + // Text provided a newline. Start a new line. + os << "\n"; + ++r; + column = 0; + first = false; + } + else + { + // No provided newline. Continue this line. + column += static_cast(r-l); + } + } + else + { + // Word does not fit on this line. Start a new line. + os << "\n"; + first = false; + if(r > l) + { + os << indent; + os.write(l, static_cast(r-l)); + column = static_cast(r-l); + newSentence = (*(r-1) == '.'); + } + } + + // Move to beginning of next word. Skip over whitespace. + l = r; + while(*l && (*l == ' ')) { ++l; } + } +} + +//---------------------------------------------------------------------------- +void cmDocumentation::Print(Type ht, std::ostream& os) +{ + switch (ht) + { + case cmDocumentation::Usage: this->PrintUsage(os); break; + case cmDocumentation::Help: this->PrintHelp(os); break; + case cmDocumentation::HelpHTML: this->PrintHelpHTML(os); break; + case cmDocumentation::Man: this->PrintManPage(os); break; + case cmDocumentation::Copyright: this->PrintCopyright(os); break; + case cmDocumentation::Version: this->PrintVersion(os); break; + default: break; + } +} + +//---------------------------------------------------------------------------- +cmDocumentation::Type cmDocumentation::CheckOptions(int argc, char** argv) +{ + for(int i=1; i < argc; ++i) + { + if((strcmp(argv[i], "/?") == 0) || + (strcmp(argv[i], "-usage") == 0) || + (strcmp(argv[i], "--usage") == 0)) + { + return cmDocumentation::Usage; + } + if((strcmp(argv[i], "-help") == 0) || + (strcmp(argv[i], "--help") == 0)) + { + return cmDocumentation::Help; + } + if(strcmp(argv[i], "--help-html") == 0) + { + return cmDocumentation::HelpHTML; + } + if(strcmp(argv[i], "--man") == 0) + { + return cmDocumentation::Man; + } + if(strcmp(argv[i], "--copyright") == 0) + { + return cmDocumentation::Copyright; + } + if(strcmp(argv[i], "--version") == 0) + { + return cmDocumentation::Version; + } + } + return cmDocumentation::None; +} + +//---------------------------------------------------------------------------- +void cmDocumentation::SetOptions(const cmDocumentationEntry* d) +{ + this->Options.erase(this->Options.begin(), this->Options.end()); + if(d) + { + for(const cmDocumentationEntry* op = d; op->brief; ++op) + { + this->Options.push_back(*op); + } + } + for(const cmDocumentationEntry* op = cmDocumentationStandardOptions; + op->brief; ++op) + { + this->Options.push_back(*op); + } + cmDocumentationEntry empty = {0,0,0}; + this->Options.push_back(empty); +} diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h new file mode 100644 index 000000000..1081b1289 --- /dev/null +++ b/Source/cmDocumentation.h @@ -0,0 +1,65 @@ +/*========================================================================= + + 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. + +=========================================================================*/ +#ifndef _cmDocumentation_h +#define _cmDocumentation_h + +#include "cmStandardIncludes.h" + +/** Class to generate documentation. */ +class cmDocumentation +{ +public: + cmDocumentation(); + + enum Type { None, Usage, Help, HelpHTML, Man, Copyright, Version }; + + void Print(Type ht, std::ostream& os); + void PrintUsage(std::ostream& os); + void PrintHelp(std::ostream& os); + void PrintHelpHTML(std::ostream& os); + void PrintManPage(std::ostream& os); + void PrintCopyright(std::ostream& os); + void PrintVersion(std::ostream& os); + + void SetCommands(const cmDocumentationEntry* d) {this->Commands = d;} + void SetDescription(const cmDocumentationEntry* d) {this->Description = d;} + void SetName(const cmDocumentationEntry* d) {this->Name = d;} + void SetOptions(const cmDocumentationEntry* d); + void SetUsage(const cmDocumentationEntry* d) {this->UsageHelp = d;} + + Type CheckOptions(int argc, char** argv); +private: + void PrintColumn(std::ostream& os, int width, + const char* indent, const char* text); + void PrintManSection(std::ostream& os, const cmDocumentationEntry* section, + const char* name); + void PrintHelpSection(std::ostream& os, const cmDocumentationEntry* section); + void PrintHTMLEscapes(std::ostream& os, const char* text); + void PrintHelpHTMLSection(std::ostream& os, + const cmDocumentationEntry* section, + const char* header); + void PrintUsageSection(std::ostream& os, + const cmDocumentationEntry* section); + + const cmDocumentationEntry* Commands; + const cmDocumentationEntry* Description; + const cmDocumentationEntry* Name; + std::vector Options; + const cmDocumentationEntry* UsageHelp; +}; + +#endif diff --git a/Source/cmStandardIncludes.h b/Source/cmStandardIncludes.h index 937d9c297..4204b53c9 100644 --- a/Source/cmStandardIncludes.h +++ b/Source/cmStandardIncludes.h @@ -244,4 +244,12 @@ private: }; #endif +/** Standard documentation entry for cmDocumentation's formatting. */ +struct cmDocumentationEntry +{ + const char* name; + const char* brief; + const char* full; +}; + #endif diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 4214132ad..49d6bd855 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2363,6 +2363,15 @@ void cmSystemTools::SplitProgramFromArgs(const char* path, args = ""; } +std::string cmSystemTools::GetCurrentDateTime(const char* format) +{ + char buf[1024]; + time_t t; + time(&t); + strftime(buf, sizeof(buf), format, localtime(&t)); + return buf; +} + std::string cmSystemTools::MakeCindentifier(const char* s) { std::string str(s); diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index db4c3b46e..a66d7929b 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -352,6 +352,8 @@ public: */ static FileFormat GetFileFormat(const char* ext); + static std::string GetCurrentDateTime(const char* format); + /** * On Windows 9x we need a comspec (command.com) substitute to run * programs correctly. This string has to be constant available diff --git a/Source/cmake.cxx b/Source/cmake.cxx index aa5984b41..0dad7cf47 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1120,3 +1120,20 @@ void cmake::UpdateProgress(const char *msg, float prog) return; } } + +void cmake::GetCommandDocumentation(std::vector& v) const +{ + for(RegisteredCommandsMap::const_iterator j = m_Commands.begin(); + j != m_Commands.end(); ++j) + { + cmDocumentationEntry e = + { + (*j).second->GetName(), + (*j).second->GetTerseDocumentation(), + (*j).second->GetFullDocumentation() + }; + v.push_back(e); + } + cmDocumentationEntry empty = {0,0,0}; + v.push_back(empty); +} diff --git a/Source/cmake.h b/Source/cmake.h index 143f1e1dd..941806167 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -232,6 +232,8 @@ class cmake ///! Get the variable watch object cmVariableWatch* GetVariableWatch() { return m_VariableWatch; } + void GetCommandDocumentation(std::vector&) const; + protected: typedef std::map RegisteredCommandsMap; RegisteredCommandsMap m_Commands; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 289f82e7e..f6d8dfa2f 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -19,6 +19,31 @@ #include "cmCacheManager.h" #include "cmDynamicLoader.h" #include "cmListFileCache.h" +#include "cmDocumentation.h" + +//---------------------------------------------------------------------------- +static const cmDocumentationEntry cmDocumentationName[] = +{ + {"cmake", + "- Cross-Platform Makefile Generator.", 0}, + {0,0,0} +}; + +//---------------------------------------------------------------------------- +static const cmDocumentationEntry cmDocumentationUsage[] = +{ + {0, + "cmake ", 0}, + {0,0,0} +}; + +//---------------------------------------------------------------------------- +static const cmDocumentationEntry cmDocumentationDescription[] = +{ + {0, + "CMake reads ... ", 0}, + {0,0,0} +}; int do_cmake(int ac, char** av); void updateProgress(const char *msg, float prog, void *cd); @@ -36,6 +61,20 @@ int main(int ac, char** av) int do_cmake(int ac, char** av) { + cmDocumentation doc; + if(cmDocumentation::Type ht = doc.CheckOptions(ac, av)) + { + cmake hcm; + std::vector commands; + hcm.GetCommandDocumentation(commands); + doc.SetName(cmDocumentationName); + doc.SetUsage(cmDocumentationUsage); + doc.SetDescription(cmDocumentationDescription); + doc.SetCommands(&commands[0]); + doc.Print(ht, std::cout); + return 0; + } + bool wiz = false; bool command = false; std::vector args; @@ -45,16 +84,13 @@ int do_cmake(int ac, char** av) { wiz = true; } - else + else if (strcmp(av[i], "-E") == 0) { - if (strcmp(av[i], "-E") == 0) - { - command = true; - } - else - { - args.push_back(av[i]); - } + command = true; + } + else + { + args.push_back(av[i]); } }