cmdline.cpp

00001 /*
00002  *  TOPPERS/FDMP Kernel
00003  *      Toyohashi Open Platform for Embedded Real-Time Systems/
00004  *      Function Distributed Multiprocessor Kernel
00005  *
00006  *  Copyright (C) 2004 by Witz Corporation, JAPAN  
00007  *  Copyright (C) 2005 by Takagi Nobuhisa
00008  * 
00009  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
00010  *  によって公表されている GNU General Public License の Version 2 に記
00011  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
00012  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
00013  *  利用と呼ぶ)することを無償で許諾する.
00014  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
00015  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
00016  *      スコード中に含まれていること.
00017  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
00018  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
00019  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
00020  *      の無保証規定を掲載すること.
00021  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
00022  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
00023  *      と.
00024  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
00025  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
00026  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
00027  *        報告すること.
00028  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
00029  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
00030  * 
00031  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
00032  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
00033  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
00034  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
00035  * 
00036  */
00037 
00038 /*
00039  *  toppers/cmdline.cpp
00040  */
00041 #include "toppers/cmdline.hpp"
00042 #include "toppers/reporter.hpp"
00043 #include <algorithm>
00044 #include <functional>
00045 #include <sstream>
00046 #include <list>
00047 #include <utility>
00048 #include <cctype>
00049 #include <boost/utility.hpp>
00050 
00051 namespace toppers
00052 {
00053 
00057   cmdline::option_array::option_array()
00058   {
00059   }
00060 
00066   bool cmdline::option_array::find( const std::string& key ) const
00067   {
00068     map::const_iterator nil( map_.end() );
00069     if ( map_.find( key ) == nil )
00070     {
00071       char ch = *key.rbegin();
00072       if ( ch == ':' || ch == '=' )
00073       {
00074         return false;
00075       }
00076       else
00077       {
00078         if ( map_.find( key + ":" ) == nil )
00079         {
00080           if ( map_.find( key + "=" ) == nil )
00081           {
00082             return false;
00083           }
00084         }
00085       }
00086     }
00087     return true;
00088   }
00089 
00096   bool cmdline::option_array::find( const std::string& key, std::string& arg ) const
00097   {
00098     map::const_iterator nil( map_.end() );
00099     map::const_iterator iter( map_.find( key ) );
00100     if ( iter == nil )
00101     {
00102       char ch = *key.rbegin();
00103       if ( ch == ':' || ch == '=' )
00104       {
00105         return false;
00106       }
00107       else
00108       {
00109         iter = map_.find( key + ":" );
00110         if ( iter == nil )
00111         {
00112           iter = map_.find( key + ":" );
00113           if ( iter == nil )
00114           {
00115             return false;
00116           }
00117         }
00118       }
00119     }
00120     arg = iter->second;
00121     return true;
00122   }
00123 
00133   bool cmdline::option_array::find( const std::string& key, std::vector<std::string>& args ) const
00134   {
00135     std::pair<map::const_iterator, map::const_iterator> range( map_.equal_range( key ) );
00136     std::string opt_key( key );
00137     if ( range.first == range.second )
00138     {
00139       char ch = *key.rbegin();
00140       if ( ch == ':' || ch == '=' )
00141       {
00142         return false;
00143       }
00144       else
00145       {
00146         opt_key = key + ":";
00147         range = map_.equal_range( opt_key );
00148         if ( range.first == range.second )
00149         {
00150           opt_key = key + "=";
00151           range = map_.equal_range( key );
00152           if ( range.first == range.second )
00153           {
00154             return false;
00155           }
00156         }
00157       }
00158     }
00159 
00160     std::vector<std::string> t;
00161     for ( map::const_iterator iter( range.first ), last( range.second ); iter != last; ++iter )
00162     {
00163       if ( iter->first == opt_key )
00164       {
00165         t.push_back( iter->second );
00166       }
00167     }
00168     args.swap( t );
00169     return true;
00170   }
00171 
00177   void cmdline::option_array::insert( const std::string& key, const std::string& value )
00178   {
00179     map_.insert( map::value_type( key, value ) );
00180   }
00181 
00188   bool cmdline::option_array::replace( const std::string& key, const std::string& value )
00189   {
00190     map::iterator iter( map_.find( key ) );
00191     if ( iter == map_.end() )
00192     {
00193       return false;
00194     }
00195     iter->second = value;
00196     return true;
00197   }
00198 
00207   void cmdline::option_array::remap_option( const std::string& old_key, const std::string& new_key )
00208   {
00209     map::iterator iter( map_.find( old_key ) );
00210     if ( iter != map_.end() )
00211     {
00212       map::value_type value( new_key, iter->second );
00213       map_.erase( iter );
00214       map_.insert( value );
00215     }
00216   }
00217 
00222   void cmdline::option_array::swap( option_array& other ) throw()
00223   {
00224     map_.swap( other.map_ );
00225     set_.swap( other.set_ );
00226   }
00227 
00228   cmdline::option_array::option_array( const map& options, const set& optset )
00229     : map_( options ), set_( optset )
00230   {
00231   }
00232 
00233 
00239   cmdline::cmdline( int argc, char* argv[] ) : argc_( argc ), argv_( argv )
00240   {
00241   }
00242 
00261   std::auto_ptr<std::vector<std::string> > cmdline::parse( const std::string& pattern, option_array& options ) const
00262   {
00263     std::stringstream sstr( pattern );
00264     option_array::map optmap;
00265     option_array::set optset;
00266     std::list<const char*> args( argv_+1, argv_+argc_ );
00267 
00268     // `options'文字列内の重複要素をまとめる
00269     std::string name;
00270     while ( sstr >> name )
00271     {
00272       if ( name[0] == '-' ) // '-'で始まるもの以外はオプションとして認めない
00273       {
00274         optset.insert( name );
00275       }
00276     }
00277 
00278     const std::set<std::string>::const_iterator last( optset.end() );
00279     for ( std::set<std::string>::const_iterator iter( optset.begin() ); iter != last; ++iter )
00280     {
00281       std::string name( *iter );
00282       bool has_arg = false;
00283       char back = *name.rbegin();
00284       if ( back == ':' ) // ':'で終わるオプションは'='なしの引数を取る
00285       {
00286         has_arg = true;
00287         name.erase( name.size()-1 ); // ':'を除去
00288       }
00289       else if ( back == '=' ) // '='で終わるオプションは'='付きの引数を取る
00290       {
00291         has_arg = true;
00292       }
00293       std::list<const char*>::iterator iter2( args.begin() );
00294       while ( iter2 != args.end() )
00295       {
00296         const char* argv = *iter2;
00297         if ( ( back == '=' && strncmp( argv, name.c_str(), name.size() ) == 0 )
00298           || ( back != '=' && strcmp( argv, name.c_str() ) == 0 ) )
00299         {
00300           typedef option_array::map::value_type option;
00301           if ( has_arg ) // 引数付きオプション
00302           {
00303             if ( argv[name.size()] != '\0' )
00304             {
00305               argv = argv+name.size();
00306             }
00307             else
00308             {
00309               std::list<const char*>::iterator next( boost::next( iter2 ) );
00310               if ( next != args.end() )
00311               {
00312                 argv = *next;
00313               }
00314               else
00315               {
00316                 // このエラーメッセージは翻訳されそうにないが、とりあえず放置する
00317                 rout.error( _( "argument to `%1%\' is missing" ) % name );
00318               }
00319               args.erase( next );
00320             }
00321             while ( std::isspace( *argv ) ) // 念のため、空白類文字を取り除く
00322                  ;
00323             if ( back == ':' )
00324             {
00325               name += ':';
00326             }
00327             option opt( name, std::string( argv ) );
00328             optmap.insert( opt );
00329           }
00330           else // 引数なしオプション
00331           {
00332             option opt( name, "" );
00333             optmap.insert( opt );
00334           }
00335           std::list<const char*>::iterator next = boost::next( iter2 );
00336           args.erase( iter2 );
00337           iter2 = next;
00338         }
00339         else // nameが示すオプション以外
00340         {
00341           ++iter2;
00342         }
00343       }
00344     }
00345 
00346     // 例外安全のため std::auto_ptr を用いて、ここで返却値を組み立てる
00347     std::auto_ptr<std::vector<std::string> > result( new std::vector<std::string>( args.begin(), args.end() ) );
00348 
00349     option_array t( optmap, optset );
00350     options.swap( t );
00351 
00352     return result;
00353   }
00354 
00362   std::vector<std::string>::const_iterator cmdline::find_illegal_options( std::vector<std::string>::const_iterator first, std::vector<std::string>::const_iterator last )
00363   {
00364     for ( std::vector<std::string>::const_iterator iter( first ); iter != last; ++iter )
00365     {
00366       if ( iter->at( 0 ) == '-' )
00367       {
00368         rout.error( _( "illegal option `%1%\'" ) % *iter );
00369         return iter;
00370       }
00371     }
00372     return last;
00373   }
00374 
00375 }

Copyright © 2006 by TAKAGI Nobuhisa.
このページは Wed Apr 12 16:31:55 2006 に Doxygen によって生成されました。