source: cfg_itronx+oil_gcc/cfg/cfg.cpp@ 54

Last change on this file since 54 was 54, checked in by ertl-ishikawa, 12 years ago

cfg+oil対応コンフィギュレータを追加

File size: 13.1 KB
Line 
1/*
2 * TOPPERS Software
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 *
5 * Copyright (C) 2007-2009 by TAKAGI Nobuhisa
6 * Copyright (C) 2010 by Meika Sugimoto
7 *
8 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
9 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
10 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
11 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
12 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
13 * スコード中に含まれていること.
14 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
15 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
16 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
17 * の無保証規定を掲載すること.
18 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
19 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
20 * と.
21 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
22 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
23 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
24 * 報告すること.
25 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
26 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
27 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
28 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
29 * 免責すること.
30 *
31 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
33 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
34 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
35 * の責任を負わない.
36 *
37 */
38
39// Boost.Filesystem v3内でstd::locale("")が使用されているが、GCCの不具合で
40// 例外が発生する。
41// これを回避するための暫定対応
42#ifdef __GNUC__
43#include <stdlib.h>
44namespace Ticket_83_fix
45{
46 char s_[] = "LANG=C";
47 int _ = putenv(s_);
48}
49#endif
50
51#include "cfg.hpp"
52#include <boost/program_options.hpp>
53#include <boost/spirit/include/classic.hpp>
54
55namespace
56{
57
58 //! 連続したスラッシュ / を単一のスラッシュに置換する
59 std::string slashes_to_single_slash( std::string const& str )
60 {
61 std::string result( str );
62 std::string::size_type pos = 0;
63 while ( ( pos = result.find( "//", pos ) ) != std::string::npos )
64 {
65 result.erase( pos, 1 );
66 }
67 return result;
68 }
69
70 //! 起動オプションの解析
71 int parse_program_options( int argc, char* argv[] )
72 {
73 namespace po = boost::program_options;
74 int pass = 0;
75
76 // 一般オプション
77 po::options_description generic( _( "Generic options" ) );
78 generic.add_options()
79 ( "help", _( "display this information" ) )
80 ( "version,v", _( "display cfg version number" ) )
81 ;
82
83 // 設定オプション
84 po::options_description config( _( "Configuration" ) );
85 config.add_options()
86 ( "kernel,k", po::value< std::string >()->default_value( std::string( "asp" ) ), _( "kernel type (default: asp)" ) )
87 ( "pass,p", po::value< int >( &pass )->default_value( 0 ), _( "run for pass #`arg\'" ) )
88 ( "include-path,I", po::value< std::vector< std::string > >(), _( "include path" ) )
89 ( "template-file,T", po::value< std::string >(), _( "template file" ) )
90 ( "input-charset", po::value< std::string >()->default_value( std::string( "ascii" ) ), _( "character set of input file (default: ascii)" ) )
91 ( "api-table", po::value< std::vector< std::string > >(), _( "specify static API table" ) )
92 ( "cfg1-def-table", po::value< std::vector< std::string > >(), _( "specify cfg1 definition table" ) )
93 ( "cfg1_out", po::value< std::string >()->default_value( std::string( "cfg1_out" ) ), _( "specify file name instead of `cfg1_out.srec\' (default: cfg1_out)" ) )
94 ( "rom-image,r", po::value< std::string >(), _( "ROM image (S-record)" ) )
95 ( "symbol-table,s", po::value< std::string >(), _( "Symbol table (`nm' style)" ) )
96 ( "cfg-directory,d", po::value< std::string >(), _( "cfg directory" ) )
97 ( "msgcat-directory,m", po::value< std::vector< std::string > >(), _( "msgcat(*.po) directory" ) )
98 ( "destination-directory,n", po::value< std::string >()->default_value( "." ), _( "destination directory" ) )
99 ( "id-output-file", po::value< std::string >()->default_value( std::string() ), _( "output file for id assignment" ) )
100 ( "id-input-file", po::value< std::string >()->default_value( std::string() ), _( "input file for id assignment" ) )
101 ( "alignof-fp", po::value< std::size_t >()->default_value( 1 ), _( "alignment of pointer to function" ) )
102 ( "external-id", _( "output ID numbers as external `const\' object" ) )
103 ( "print-dependencies,M", po::value< std::string >(), _( "output dependencies of source file (for `make\')" ) )
104 ( "with-software-components", _( "with software components" ) )
105 ;
106
107 // 非表示オプション
108 po::options_description hidden( _( "Hidden options" ) );
109 hidden.add_options()
110 ( "input-file,s", po::value< std::string >(), _( "input file" ) )
111 ;
112
113 po::options_description cmdline_options;
114 cmdline_options.add( generic ).add( config ).add( hidden );
115
116 po::options_description visible( _( "Allowed options" ) );
117 visible.add( generic ).add( config );
118
119 po::positional_options_description p;
120 p.add( "input-file", -1 );
121
122 po::variables_map vm;
123 try
124 {
125 store( po::command_line_parser( argc, argv ).
126 options( cmdline_options ).positional( p ).run(), vm );
127 notify( vm );
128 }
129 catch ( boost::program_options::error& )
130 {
131 toppers::fatal( _( "illegal options" ) );
132 }
133
134 // グローバル変数の設定
135 if ( vm.count( "print-dependencies" ) )
136 {
137 toppers::global( "print-dependencies" ) = vm[ "print-dependencies" ].as< std::string >();
138 pass = 1; // 依存関係の出力が必要な場合、強制的にパス1に変更
139 }
140
141 toppers::global( "pass" ) = pass;
142 if ( vm.count( "kernel" ) )
143 {
144 std::string kernel = toppers::tolower( vm[ "kernel" ].as< std::string >() );
145 toppers::global( "kernel" ) = kernel;
146 bool has_class = false;
147 bool has_domain = false;
148
149 if ( kernel == "fmp" || kernel == "fmp+hrp2" || kernel == "hrp2+fmp" )
150 {
151 has_class = true;
152 }
153 if ( kernel == "hrp2" || kernel == "fmp+hrp2" || kernel == "hrp2+fmp" )
154 {
155 has_domain = true;
156 }
157
158 toppers::global( "max-pass" ) = ( has_domain ? 4 : 3 );
159 toppers::global( "has-class" ) = has_class;
160 toppers::global( "has-domain" ) = has_domain;
161 }
162 if ( vm.count( "include-path" ) )
163 {
164 std::vector< std::string > v( vm[ "include-path" ].as< std::vector< std::string > >() );
165 std::transform( v.begin(), v.end(), v.begin(), &slashes_to_single_slash );
166 toppers::global( "include-path" ) = v;
167 }
168 if ( vm.count( "template-file" ) )
169 {
170 toppers::global( "template-file" )
171 = slashes_to_single_slash( vm[ "template-file" ].as< std::string >() );
172 }
173 if ( vm.count( "input-file" ) )
174 {
175 toppers::global( "input-file" )
176 = slashes_to_single_slash( vm[ "input-file" ].as< std::string >() );
177 }
178 if ( vm.count( "input-charset" ) )
179 {
180 std::string input_charset( toppers::tolower( vm[ "input-charset" ].as< std::string >() ) );
181 toppers::global( "input-charset" ) = input_charset;
182
183 toppers::codeset_t codeset = toppers::ascii;
184 if ( ( input_charset == "cp932" )
185 || ( input_charset == "shift_jis" )
186 || ( input_charset == "sjis" ) )
187 {
188 codeset = toppers::shift_jis;
189 }
190 else if ( ( input_charset == "eucjp" )
191 || ( input_charset == "euc-jp" )
192 || ( input_charset == "euc" ) )
193 {
194 codeset = toppers::euc_jp;
195 }
196 else if ( ( input_charset == "utf-8" )
197 || ( input_charset == "utf8" ) )
198 {
199 codeset = toppers::utf8;
200 }
201 toppers::global( "codeset" ) = codeset;
202 }
203 if ( vm.count( "api-table" ) )
204 {
205 std::vector< std::string > v( vm[ "api-table" ].as< std::vector< std::string > >() );
206 std::transform( v.begin(), v.end(), v.begin(), &slashes_to_single_slash );
207 toppers::global( "api-table" ) = v;
208 }
209 if ( vm.count( "cfg1-def-table" ) )
210 {
211 std::vector< std::string > v( vm[ "cfg1-def-table" ].as< std::vector< std::string > >() );
212 std::transform( v.begin(), v.end(), v.begin(), &slashes_to_single_slash );
213 toppers::global( "cfg1-def-table" ) = v;
214 }
215 if ( vm.count( "cfg1_out" ) )
216 {
217 toppers::global( "cfg1_out" ) = vm[ "cfg1_out" ].as< std::string >();
218 }
219 else
220 {
221 toppers::global( "cfg1_out" ) = std::string( "cfg1_out" );
222 }
223 if ( vm.count( "cfg-directory" ) )
224 {
225 std::string cfg_directory( vm[ "cfg-directory" ].as< std::string >() );
226 toppers::global( "cfg-directory" ) = slashes_to_single_slash( cfg_directory );
227 toppers::load_msgcat( cfg_directory );
228 }
229 if ( vm.count( "msgcat-directory" ) )
230 {
231 std::vector< std::string > msgcat_dirs( vm[ "msgcat-directory" ].as< std::vector< std::string > >() );
232 std::transform( msgcat_dirs.begin(), msgcat_dirs.end(), msgcat_dirs.begin(), &slashes_to_single_slash );
233 std::for_each( msgcat_dirs.begin(), msgcat_dirs.end(), &toppers::load_msgcat );
234 }
235 if ( true ) // include-path を空にしてはならない
236 {
237 std::vector< std::string > include_path;
238 boost::any t( toppers::global( "include-path" ) );
239 if ( !t.empty() )
240 {
241 include_path = boost::any_cast< std::vector< std::string > >( t );
242 }
243 include_path.push_back( toppers::get_global< std::string >( "cfg-directory" ) );
244 toppers::global( "include-path" ) = include_path;
245 }
246 if ( vm.count( "output-directory" ) )
247 {
248 toppers::global( "output-directory" ) = slashes_to_single_slash( vm[ "output-directory" ].as< std::string >() );
249 }
250 if ( vm.count( "rom-image" ) )
251 {
252 toppers::global( "rom-image" ) = slashes_to_single_slash( vm[ "rom-image" ].as< std::string >() );
253 }
254 if ( vm.count( "symbol-table" ) )
255 {
256 toppers::global( "symbol-table" ) = slashes_to_single_slash( vm[ "symbol-table" ].as< std::string >() );
257 }
258 else
259 {
260 toppers::global( "symbol-table" ) = toppers::get_global< std::string >( "kernel" ) + ".syms";
261 }
262 if ( vm.count( "id-output-file" ) )
263 {
264 toppers::global( "id-output-file" ) = slashes_to_single_slash( vm[ "id-output-file" ].as< std::string >() );
265 }
266 if ( vm.count( "id-input-file" ) )
267 {
268 toppers::global( "id-input-file" ) = slashes_to_single_slash( vm[ "id-input-file" ].as< std::string >() );
269 }
270 if ( vm.count( "alignof-fp" ) )
271 {
272 toppers::global( "alignof-fp" ) = vm[ "alignof-fp" ].as< std::size_t >();
273 }
274 toppers::global( "external-id" ) = vm.count( "external-id" ) ? true : false;
275 toppers::global( "with-software-components" ) = vm.count( "with-software-components" ) ? true : false;
276
277 toppers::global( "version" ) = std::string( CFG_VERSION );
278
279 if ( vm.count( "version" ) )
280 {
281 std::cout << "TOPPERS Kernel Configurator version " << CFG_VERSION << std::endl;
282 toppers::global( "pass0" ) = true;
283 }
284 if ( vm.count( "help" ) )
285 {
286 toppers::global( "help" ) = boost::lexical_cast< std::string >( visible );
287 std::cout << visible << std::endl;
288 toppers::global( "pass0" ) = true;
289 }
290 return pass;
291 }
292
293}
294
295//! コンフィギュレータのメイン処理
296int cfg_main( int argc, char* argv[] )
297{
298 using namespace toppers;
299
300 std::string const cfg_path( argv[0] );
301 std::string const cfg_name( "cfg" );
302 std::string::const_iterator iter = std::find_end( cfg_path.begin(), cfg_path.end(), cfg_name.begin(), cfg_name.end() );
303 // 環境変数のサーチまでは行わない
304 std::string cfg_dir( cfg_path.begin(), iter );
305 if ( *cfg_dir.rbegin() == '/' || *cfg_dir.rbegin() == '\\' )
306 {
307 cfg_dir.resize( cfg_dir.size() - 1 );
308 }
309 toppers::global( "cfg-directory" ) = cfg_dir;
310 toppers::global( "argv0" ) = std::string( argv[ 0 ] ); // プログラム名
311 toppers::global( "timestamp" ) = cfg_timestamp(); // タイムスタンプ
312
313 int pass = parse_program_options( argc, argv );
314 bool ( * pfn_cfg[] )() = { &cfg0_main, &cfg1_main, &cfg2_main, &cfg3_main, &cfg4_main };
315 int max_pass = toppers::get_global< int >( "max-pass" );
316
317 if ( pass < 0 || max_pass < pass )
318 {
319 fatal( _( "illegal cfg pass #%d" ), pass );
320 }
321
322 if ( !( *pfn_cfg[ pass ] )() )
323 {
324 return EXIT_FAILURE;
325 }
326 return EXIT_SUCCESS;
327}
328
329int main( int arg, char* argv[] )
330{
331 int status;
332 try
333 {
334 toppers::set_program_name( "cfg" );
335 status = cfg_main( arg, argv );
336 if ( status != EXIT_SUCCESS && toppers::get_error_count() == 0 )
337 {
338 std::fprintf( stderr, "cfg: %s\n", _( "unknown error" ) );
339 }
340 if ( toppers::get_error_count() > 0 )
341 {
342 status = EXIT_FAILURE;
343 }
344 }
345 catch ( toppers::normal_exit& )
346 {
347 status = EXIT_SUCCESS;
348 }
349 catch ( std::exception& e )
350 {
351 std::fprintf( stderr, "cfg: %s\n", e.what() );
352 status = EXIT_FAILURE;
353 }
354 catch ( ... )
355 {
356 std::fprintf( stderr, "cfg: %s\n", _( "internal error" ) );
357 status = EXIT_FAILURE;
358 }
359 return status;
360}
Note: See TracBrowser for help on using the repository browser.