3 * Toyohashi Open Platform for Embedded Real-Time Systems
5 * Copyright (C) 2007-2009 by TAKAGI Nobuhisa
7 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
10 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
11 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
13 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
14 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
15 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
17 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
18 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
20 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
21 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
22 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
24 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
25 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
26 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
27 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
30 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
31 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
32 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
33 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
38 #include <boost/program_options.hpp>
39 #include <boost/spirit/include/classic.hpp>
44 //! 連続したスラッシュ / を単一のスラッシュに置換する
45 std::string slashes_to_single_slash( std::string const& str )
47 std::string result( str );
48 std::string::size_type pos = 0;
49 while ( ( pos = result.find( "//", pos ) ) != std::string::npos )
51 result.erase( pos, 1 );
57 int parse_program_options( int argc, char* argv[] )
59 namespace po = boost::program_options;
63 po::options_description generic( _( "Generic options" ) );
65 ( "help", _( "display this information" ) )
66 ( "version,v", _( "display cfg version number" ) )
70 po::options_description config( _( "Configuration" ) );
72 ( "kernel,k", po::value< std::string >()->default_value( std::string( "asp" ) ), _( "kernel type (default: asp)" ) )
73 ( "pass,p", po::value< int >( &pass )->default_value( 0 ), _( "run for pass #`arg\'" ) )
74 ( "include-path,I", po::value< std::vector< std::string > >(), _( "include path" ) )
75 ( "template-file,T", po::value< std::string >(), _( "template file" ) )
76 ( "input-charset", po::value< std::string >()->default_value( std::string( "ascii" ) ), _( "character set of input file (default: ascii)" ) )
77 ( "api-table", po::value< std::vector< std::string > >(), _( "specify static API table" ) )
78 ( "cfg1-def-table", po::value< std::vector< std::string > >(), _( "specify cfg1 definition table" ) )
79 ( "cfg1_out", po::value< std::string >()->default_value( std::string( "cfg1_out" ) ), _( "specify file name instead of `cfg1_out.srec\' (default: cfg1_out)" ) )
80 ( "rom-image,r", po::value< std::string >(), _( "ROM image (S-record)" ) )
81 ( "symbol-table,s", po::value< std::string >(), _( "Symbol table (`nm' style)" ) )
82 ( "cfg-directory,d", po::value< std::string >(), _( "cfg directory" ) )
83 ( "msgcat-directory,m", po::value< std::vector< std::string > >(), _( "msgcat(*.po) directory" ) )
84 ( "destination-directory,n", po::value< std::string >()->default_value( "." ), _( "destination directory" ) )
85 ( "id-output-file", po::value< std::string >()->default_value( std::string() ), _( "output file for id assignment" ) )
86 ( "id-input-file", po::value< std::string >()->default_value( std::string() ), _( "input file for id assignment" ) )
87 ( "alignof-fp", po::value< std::size_t >()->default_value( 1 ), _( "alignment of pointer to function" ) )
88 ( "external-id", _( "output ID numbers as external `const\' object" ) )
89 ( "print-dependencies,M", po::value< std::string >(), _( "output dependencies of source file (for `make\')" ) )
90 ( "with-software-components", _( "with software components" ) )
94 po::options_description hidden( _( "Hidden options" ) );
96 ( "input-file,s", po::value< std::string >(), _( "input file" ) )
99 po::options_description cmdline_options;
100 cmdline_options.add( generic ).add( config ).add( hidden );
102 po::options_description visible( _( "Allowed options" ) );
103 visible.add( generic ).add( config );
105 po::positional_options_description p;
106 p.add( "input-file", -1 );
108 po::variables_map vm;
111 store( po::command_line_parser( argc, argv ).
112 options( cmdline_options ).positional( p ).run(), vm );
115 catch ( boost::program_options::error& )
117 toppers::fatal( _( "illegal options" ) );
121 if ( vm.count( "print-dependencies" ) )
123 toppers::global( "print-dependencies" ) = vm[ "print-dependencies" ].as< std::string >();
124 pass = 1; // 依存関係の出力が必要な場合、強制的にパス1に変更
127 toppers::global( "pass" ) = pass;
128 if ( vm.count( "kernel" ) )
130 std::string kernel = toppers::tolower( vm[ "kernel" ].as< std::string >() );
131 toppers::global( "kernel" ) = kernel;
132 bool has_class = false;
133 bool has_domain = false;
135 if ( kernel == "fmp" || kernel == "fmp+hrp2" || kernel == "hrp2+fmp" )
139 if ( kernel == "hrp2" || kernel == "fmp+hrp2" || kernel == "hrp2+fmp" )
144 toppers::global( "max-pass" ) = ( has_domain ? 4 : 3 );
145 toppers::global( "has-class" ) = has_class;
146 toppers::global( "has-domain" ) = has_domain;
148 if ( vm.count( "include-path" ) )
150 std::vector< std::string > v( vm[ "include-path" ].as< std::vector< std::string > >() );
151 std::transform( v.begin(), v.end(), v.begin(), &slashes_to_single_slash );
152 toppers::global( "include-path" ) = v;
154 if ( vm.count( "template-file" ) )
156 toppers::global( "template-file" )
157 = slashes_to_single_slash( vm[ "template-file" ].as< std::string >() );
159 if ( vm.count( "input-file" ) )
161 toppers::global( "input-file" )
162 = slashes_to_single_slash( vm[ "input-file" ].as< std::string >() );
164 if ( vm.count( "input-charset" ) )
166 std::string input_charset( toppers::tolower( vm[ "input-charset" ].as< std::string >() ) );
167 toppers::global( "input-charset" ) = input_charset;
169 toppers::codeset_t codeset = toppers::ascii;
170 if ( ( input_charset == "cp932" )
171 || ( input_charset == "shift_jis" )
172 || ( input_charset == "sjis" ) )
174 codeset = toppers::shift_jis;
176 else if ( ( input_charset == "eucjp" )
177 || ( input_charset == "euc-jp" )
178 || ( input_charset == "euc" ) )
180 codeset = toppers::euc_jp;
182 else if ( ( input_charset == "utf-8" )
183 || ( input_charset == "utf8" ) )
185 codeset = toppers::utf8;
187 toppers::global( "codeset" ) = codeset;
189 if ( vm.count( "api-table" ) )
191 std::vector< std::string > v( vm[ "api-table" ].as< std::vector< std::string > >() );
192 std::transform( v.begin(), v.end(), v.begin(), &slashes_to_single_slash );
193 toppers::global( "api-table" ) = v;
195 if ( vm.count( "cfg1-def-table" ) )
197 std::vector< std::string > v( vm[ "cfg1-def-table" ].as< std::vector< std::string > >() );
198 std::transform( v.begin(), v.end(), v.begin(), &slashes_to_single_slash );
199 toppers::global( "cfg1-def-table" ) = v;
201 if ( vm.count( "cfg1_out" ) )
203 toppers::global( "cfg1_out" ) = vm[ "cfg1_out" ].as< std::string >();
207 toppers::global( "cfg1_out" ) = std::string( "cfg1_out" );
209 if ( vm.count( "cfg-directory" ) )
211 std::string cfg_directory( vm[ "cfg-directory" ].as< std::string >() );
212 toppers::global( "cfg-directory" ) = slashes_to_single_slash( cfg_directory );
213 toppers::load_msgcat( cfg_directory );
215 if ( vm.count( "msgcat-directory" ) )
217 std::vector< std::string > msgcat_dirs( vm[ "msgcat-directory" ].as< std::vector< std::string > >() );
218 std::transform( msgcat_dirs.begin(), msgcat_dirs.end(), msgcat_dirs.begin(), &slashes_to_single_slash );
219 std::for_each( msgcat_dirs.begin(), msgcat_dirs.end(), &toppers::load_msgcat );
221 if ( true ) // include-path を空にしてはならない
223 std::vector< std::string > include_path;
224 boost::any t( toppers::global( "include-path" ) );
227 include_path = boost::any_cast< std::vector< std::string > >( t );
229 include_path.push_back( toppers::get_global< std::string >( "cfg-directory" ) );
230 toppers::global( "include-path" ) = include_path;
232 if ( vm.count( "output-directory" ) )
234 toppers::global( "output-directory" ) = slashes_to_single_slash( vm[ "output-directory" ].as< std::string >() );
236 if ( vm.count( "rom-image" ) )
238 toppers::global( "rom-image" ) = slashes_to_single_slash( vm[ "rom-image" ].as< std::string >() );
240 if ( vm.count( "symbol-table" ) )
242 toppers::global( "symbol-table" ) = slashes_to_single_slash( vm[ "symbol-table" ].as< std::string >() );
246 toppers::global( "symbol-table" ) = toppers::get_global< std::string >( "kernel" ) + ".syms";
248 if ( vm.count( "id-output-file" ) )
250 toppers::global( "id-output-file" ) = slashes_to_single_slash( vm[ "id-output-file" ].as< std::string >() );
252 if ( vm.count( "id-input-file" ) )
254 toppers::global( "id-input-file" ) = slashes_to_single_slash( vm[ "id-input-file" ].as< std::string >() );
256 if ( vm.count( "alignof-fp" ) )
258 toppers::global( "alignof-fp" ) = vm[ "alignof-fp" ].as< std::size_t >();
260 toppers::global( "external-id" ) = vm.count( "external-id" ) ? true : false;
261 toppers::global( "with-software-components" ) = vm.count( "with-software-components" ) ? true : false;
263 toppers::global( "version" ) = std::string( CFG_VERSION );
265 if ( vm.count( "version" ) )
267 std::cout << "TOPPERS Kernel Configurator version " << CFG_VERSION << std::endl;
268 toppers::global( "pass0" ) = true;
270 if ( vm.count( "help" ) )
272 toppers::global( "help" ) = boost::lexical_cast< std::string >( visible );
273 std::cout << visible << std::endl;
274 toppers::global( "pass0" ) = true;
282 int cfg_main( int argc, char* argv[] )
284 using namespace toppers;
286 std::string const cfg_path( argv[0] );
287 std::string const cfg_name( "cfg" );
288 std::string::const_iterator iter = std::find_end( cfg_path.begin(), cfg_path.end(), cfg_name.begin(), cfg_name.end() );
290 std::string cfg_dir( cfg_path.begin(), iter );
291 if ( *cfg_dir.rbegin() == '/' || *cfg_dir.rbegin() == '\\' )
293 cfg_dir.resize( cfg_dir.size() - 1 );
295 toppers::global( "cfg-directory" ) = cfg_dir;
296 toppers::global( "argv0" ) = std::string( argv[ 0 ] ); // プログラム名
297 toppers::global( "timestamp" ) = cfg_timestamp(); // タイムスタンプ
299 int pass = parse_program_options( argc, argv );
300 bool ( * pfn_cfg[] )() = { &cfg0_main, &cfg1_main, &cfg2_main, &cfg3_main, &cfg4_main };
301 int max_pass = toppers::get_global< int >( "max-pass" );
303 if ( pass < 0 || max_pass < pass )
305 fatal( _( "illegal cfg pass #%d" ), pass );
308 if ( !( *pfn_cfg[ pass ] )() )
315 int main( int arg, char* argv[] )
320 toppers::set_program_name( "cfg" );
321 status = cfg_main( arg, argv );
322 if ( status != EXIT_SUCCESS && toppers::get_error_count() == 0 )
324 std::fprintf( stderr, "cfg: %s\n", _( "unknown error" ) );
326 if ( toppers::get_error_count() > 0 )
328 status = EXIT_FAILURE;
331 catch ( toppers::normal_exit& )
333 status = EXIT_SUCCESS;
335 catch ( std::exception& e )
337 std::fprintf( stderr, "cfg: %s\n", e.what() );
338 status = EXIT_FAILURE;
342 std::fprintf( stderr, "cfg: %s\n", _( "internal error" ) );
343 status = EXIT_FAILURE;