Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "cmtkCommandLine.h"
00034
00035 #include <System/cmtkConsole.h>
00036 #include <System/cmtkExitException.h>
00037
00038 #include <string.h>
00039 #include <sstream>
00040
00041 namespace
00042 cmtk
00043 {
00044
00047
00048 CommandLine::CommandLine( const int properties )
00049 : ArgC( 0 ),
00050 ArgV( NULL )
00051 {
00052 this->SetDefaultInfo();
00053 this->m_Properties = properties;
00054
00055 this->BeginGroup( "MAIN", "Main Options" );
00056 }
00057
00058 CommandLine::~CommandLine()
00059 {
00060 if ( this->Index < this->ArgC-1 )
00061 {
00062 StdErr << "WARNING: the following command line arguments were not used: \n";
00063 for ( size_t i = this->Index; i < this->ArgC; ++i )
00064 {
00065 StdErr << this->ArgV[i] << " ";
00066 }
00067 StdErr << "\n";
00068 }
00069 }
00070
00071 void
00072 CommandLine::SetDefaultInfo()
00073 {
00074 this->m_ProgramInfo[PRG_LCNSE] = "http://www.fsf.org/licensing/licenses/gpl.html";
00075 this->m_ProgramInfo[PRG_CNTRB] = "Torsten Rohlfing, Michael P. Hasak, Greg Jefferis, Calvin R. Maurer, Daniel B. Russakoff";
00076 this->m_ProgramInfo[PRG_ACKNL] = "CMTK is supported by the National Institute of Biomedical Imaging and BioEngineering under Grant EB008381";
00077 this->m_ProgramInfo[PRG_CATEG] = "CMTK.Miscellaneous";
00078 this->m_ProgramInfo[PRG_DOCUM] = "https://neuro.sri.com/cmtk/wiki/";
00079 this->m_ProgramInfo[PRG_VERSN] = CMTK_VERSION_STRING;
00080 }
00081
00082 CommandLine::KeyActionGroupType::SmartPtr&
00083 CommandLine
00084 ::BeginGroup( const char* name, const char* description )
00085 {
00086 this->m_KeyActionGroupList.push_back( KeyActionGroupType::SmartPtr( new KeyActionGroupType( name, description ) ) );
00087 this->m_KeyActionList = &(this->m_KeyActionGroupList.back()->m_KeyActionList);
00088 return this->m_KeyActionGroupList.back();
00089 }
00090
00091 void
00092 CommandLine
00093 ::EndGroup()
00094 {
00095 this->m_KeyActionList = &(this->m_KeyActionGroupList.front()->m_KeyActionList);
00096 }
00097
00098 bool
00099 CommandLine::Parse( const int argc, const char* argv[] ) throw( ExitException, Self::Exception )
00100 {
00101 this->ArgC = argc;
00102 this->ArgV = argv;
00103
00104 this->Index = 1;
00105 while ( (this->Index < this->ArgC) && (this->ArgV[this->Index][0] == '-') )
00106 {
00107
00108 if ( this->ArgV[this->Index][0] != '-' ) return true;
00109
00110
00111 if ( !strcmp( this->ArgV[this->Index], "--" ) )
00112 {
00113 ++this->Index;
00114 break;
00115 }
00116
00117 bool found = false;
00118 if ( this->ArgV[this->Index][1] == '-' )
00119 {
00120
00121 for ( KeyActionListType::iterator it = this->m_KeyActionListComplete.begin(); !found && (it != this->m_KeyActionListComplete.end()); ++it )
00122 {
00123 found = (*it)->MatchAndExecute( std::string( this->ArgV[this->Index]+2 ), this->ArgC, this->ArgV, this->Index );
00124 }
00125
00126
00127 if ( !found )
00128 {
00129
00130 if ( !strcmp( this->ArgV[this->Index], "--xml" ) && !(this->m_Properties & PROPS_NOXML) )
00131 {
00132 this->WriteXML();
00133 throw ExitException( 0 );
00134 }
00135
00136
00137 if ( !strcmp( this->ArgV[this->Index], "--help" ) )
00138 {
00139 this->PrintHelp();
00140 throw ExitException( 0 );
00141 }
00142
00143
00144 if ( !strcmp( this->ArgV[this->Index], "--wiki" ) )
00145 {
00146 this->PrintWiki();
00147 throw ExitException( 0 );
00148 }
00149
00150
00151 if ( !strcmp( this->ArgV[this->Index], "--echo" ) )
00152 {
00153 for ( size_t i = 0; i < this->ArgC; ++i )
00154 {
00155 std::cerr << this->ArgV[i] << " ";
00156 }
00157 std::cerr << std::endl;
00158 found = true;
00159 }
00160
00161 if ( ! found )
00162 throw( Exception( std::string("Unknown option: ") + std::string(this->ArgV[this->Index] ) ) );
00163 }
00164 }
00165 else
00166 {
00167 const char* optChar = this->ArgV[this->Index]+1;
00168 while ( *optChar )
00169 {
00170
00171 for ( KeyActionListType::iterator it = this->m_KeyActionListComplete.begin(); !found && (it != this->m_KeyActionListComplete.end()); ++it )
00172 {
00173 found = (*it)->MatchAndExecute( *optChar, this->ArgC, this->ArgV, this->Index );
00174 }
00175
00176 if ( !found )
00177 {
00178 const char opt[2] = { *optChar, 0 };
00179 throw( Exception( std::string("Unknown option: -") + std::string(opt) ) );
00180 }
00181
00182 ++optChar;
00183 }
00184 }
00185
00186 ++this->Index;
00187 }
00188
00189 for ( NonOptionParameterListType::iterator it = this->m_NonOptionParameterList.begin(); it != this->m_NonOptionParameterList.end(); ++it, ++this->Index )
00190 {
00191 if ( this->Index >= this->ArgC )
00192 {
00193 if ( ! ((*it)->m_Properties & PROPS_OPTIONAL) )
00194 throw( Exception( "Insufficient number of command line arguments", this->Index ) );
00195 }
00196 else
00197 {
00198 (*it)->Evaluate( this->ArgC, this->ArgV, this->Index );
00199 }
00200 }
00201
00202 for ( NonOptionParameterVectorListType::iterator it = this->m_NonOptionParameterVectorList.begin(); it != this->m_NonOptionParameterVectorList.end(); ++it, ++this->Index )
00203 {
00204 if ( this->Index >= this->ArgC )
00205 {
00206 if ( ! ((*it)->m_Properties & PROPS_OPTIONAL) )
00207 throw( Exception( "Insufficient number of command line arguments", this->Index ) );
00208 }
00209 else
00210 {
00211 (*it)->Evaluate( this->ArgC, this->ArgV, this->Index );
00212 }
00213 }
00214
00215 return true;
00216 }
00217
00218 void
00219 CommandLine::PrintHelp
00220 () const
00221 {
00222 const size_t lineWidth = StdErr.GetLineWidth();
00223
00224 ProgramPropertiesMapType::const_iterator ppit = this->m_ProgramInfo.find(PRG_TITLE);
00225 if ( ppit != this->m_ProgramInfo.end() )
00226 {
00227 StdErr << "TITLE:\n\n";
00228 StdErr.FormatText( ppit->second, 5 ) << "\n";
00229 }
00230
00231 ppit = this->m_ProgramInfo.find(PRG_DESCR);
00232 if ( ppit != this->m_ProgramInfo.end() )
00233 {
00234 StdErr << "\nDESCRIPTION:\n\n";
00235 StdErr.FormatText( ppit->second, 5 ) << "\n";
00236 }
00237
00238 ppit = this->m_ProgramInfo.find(PRG_SYNTX);
00239 if ( ppit != this->m_ProgramInfo.end() )
00240 {
00241 StdErr << "\nSYNTAX:\n\n";
00242 StdErr.FormatText( ppit->second, 5 ) << "\n";
00243 }
00244 else
00245 {
00246 if ( this->m_NonOptionParameterList.size() || this->m_NonOptionParameterVectorList.size() )
00247 {
00248 StdErr << "\nSYNTAX:\n\n";
00249
00250 std::ostringstream fmt;
00251 fmt << "[options] ";
00252 for ( NonOptionParameterListType::const_iterator it = this->m_NonOptionParameterList.begin(); it != this->m_NonOptionParameterList.end(); ++it )
00253 {
00254 fmt << (*it)->m_Name << " ";
00255 }
00256 for ( NonOptionParameterVectorListType::const_iterator it = this->m_NonOptionParameterVectorList.begin(); it != this->m_NonOptionParameterVectorList.end(); ++it )
00257 {
00258 fmt << (*it)->m_Name << " ";
00259 }
00260 StdErr.FormatText( fmt.str(), 5, lineWidth );
00261
00262 StdErr << "\n where\n";
00263
00264 const int indent = 20;
00265 for ( NonOptionParameterListType::const_iterator it = this->m_NonOptionParameterList.begin(); it != this->m_NonOptionParameterList.end(); ++it )
00266 {
00267 fmt.str("");
00268
00269 StdErr << "\n";
00270 fmt << (*it)->m_Name << " = ";
00271 if ( fmt.str().length() > static_cast<size_t>( indent-2 ) )
00272 fmt << "\n";
00273 else
00274 {
00275 while ( fmt.str().length() < static_cast<size_t>( indent ) )
00276 fmt << " ";
00277 }
00278 fmt << (*it)->m_Comment;
00279 StdErr.FormatText( fmt.str(), 5+indent, lineWidth, -indent ) << "\n";
00280 }
00281
00282 for ( NonOptionParameterVectorListType::const_iterator it = this->m_NonOptionParameterVectorList.begin(); it != this->m_NonOptionParameterVectorList.end(); ++it )
00283 {
00284 fmt.str("");
00285
00286 StdErr << "\n";
00287 fmt << (*it)->m_Name << " = ";
00288 if ( fmt.str().length() > static_cast<size_t>( indent-2 ) )
00289 fmt << "\n";
00290 else
00291 {
00292 while ( fmt.str().length() < static_cast<size_t>( indent ) )
00293 fmt << " ";
00294 }
00295 fmt << (*it)->m_Comment;
00296 StdErr.FormatText( fmt.str(), 5+indent, lineWidth, -indent ) << "\n";
00297 }
00298 }
00299 }
00300
00301 StdErr << "\nLIST OF SUPPORTED OPTIONS:\n\n";
00302
00303 for ( KeyActionGroupListType::const_iterator grp = this->m_KeyActionGroupList.begin(); grp != this->m_KeyActionGroupList.end(); ++grp )
00304 {
00305 const std::string& name = (*grp)->m_Name;
00306
00307 size_t indent = 0;
00308 if ( name != "MAIN" )
00309 {
00310 StdErr << (*grp)->m_Description << "\n\n";
00311 indent = 2;
00312 }
00313
00314 const KeyActionListType& kal = (*grp)->m_KeyActionList;
00315 for ( KeyActionListType::const_iterator it = kal.begin(); it != kal.end(); ++it )
00316 {
00317 (*it)->PrintHelp( indent );
00318 }
00319 }
00320
00321 StdErr << "\n";
00322 }
00323
00324 void
00325 CommandLine::PrintWiki
00326 () const
00327 {
00328 ProgramPropertiesMapType::const_iterator ppit = this->m_ProgramInfo.find(PRG_TITLE);
00329 if ( ppit != this->m_ProgramInfo.end() )
00330 {
00331 StdOut << "== Title ==\n\n";
00332 StdOut << ppit->second << "\n\n";
00333 }
00334
00335 ppit = this->m_ProgramInfo.find(PRG_DESCR);
00336 if ( ppit != this->m_ProgramInfo.end() )
00337 {
00338 StdOut << "== Description ==\n\n";
00339 StdOut << ppit->second << "\n\n";
00340 }
00341
00342 ppit = this->m_ProgramInfo.find(PRG_SYNTX);
00343 if ( ppit != this->m_ProgramInfo.end() )
00344 {
00345 StdOut << "== Syntax ==\n\n";
00346 StdOut << ppit->second << "\n\n";
00347 }
00348 else
00349 {
00350 if ( this->m_NonOptionParameterList.size() || this->m_NonOptionParameterVectorList.size() )
00351 {
00352 StdOut << "== Syntax ==\n\n";
00353
00354 StdOut << ": <tt>[options] ";
00355 for ( NonOptionParameterListType::const_iterator it = this->m_NonOptionParameterList.begin(); it != this->m_NonOptionParameterList.end(); ++it )
00356 {
00357 StdOut << (*it)->m_Name << " ";
00358 }
00359 for ( NonOptionParameterVectorListType::const_iterator it = this->m_NonOptionParameterVectorList.begin(); it != this->m_NonOptionParameterVectorList.end(); ++it )
00360 {
00361 StdOut << (*it)->m_Name << " ";
00362 }
00363 StdOut << "</tt>\n\nwhere\n";
00364
00365 for ( NonOptionParameterListType::const_iterator it = this->m_NonOptionParameterList.begin(); it != this->m_NonOptionParameterList.end(); ++it )
00366 {
00367 StdOut << "\n";
00368 StdOut << "; <tt>" << (*it)->m_Name << "</tt> : ";
00369 StdOut << (*it)->m_Comment << "\n";;
00370 }
00371 for ( NonOptionParameterVectorListType::const_iterator it = this->m_NonOptionParameterVectorList.begin(); it != this->m_NonOptionParameterVectorList.end(); ++it )
00372 {
00373 StdOut << "\n";
00374 StdOut << "; <tt>" << (*it)->m_Name << "</tt> : ";
00375 StdOut << (*it)->m_Comment << "\n";;
00376 }
00377 }
00378 }
00379
00380 StdOut << "\n== List of Supported Options ==\n\n";
00381
00382 for ( KeyActionGroupListType::const_iterator grp = this->m_KeyActionGroupList.begin(); grp != this->m_KeyActionGroupList.end(); ++grp )
00383 {
00384 const std::string& name = (*grp)->m_Name;
00385 if ( name != "MAIN" )
00386 {
00387 StdOut << "=== " << (*grp)->m_Description << " ===\n\n";
00388 }
00389
00390 const KeyActionListType& kal = (*grp)->m_KeyActionList;
00391 for ( KeyActionListType::const_iterator it = kal.begin(); it != kal.end(); ++it )
00392 {
00393 (*it)->PrintWikiWithPrefix();
00394 StdOut << "\n";
00395 }
00396 }
00397
00398 StdOut << "\n";
00399 }
00400
00401 Console& operator<<( Console& console, CommandLine::Exception e )
00402 {
00403 console << e.Message << " [argument #" << e.Index << "]\n";
00404 return console;
00405 }
00406
00407 }