OSDN Git Service

カーネルのターゲット非依存部1.7.0およびCFGをマージ
[toppersasp4lpc/asp.git] / asp / cfg / cfg / cfg2.cpp
1 /*
2  *  TOPPERS Software
3  *      Toyohashi Open Platform for Embedded Real-Time Systems
4  *
5  *  Copyright (C) 2007-2011 by TAKAGI Nobuhisa
6  * 
7  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
8  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
10  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
11  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
12  *      スコード中に含まれていること.
13  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
14  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
15  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
16  *      の無保証規定を掲載すること.
17  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
18  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
19  *      と.
20  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
21  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
22  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
23  *        報告すること.
24  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
25  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
26  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
27  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
28  *      免責すること.
29  * 
30  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
31  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
32  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
33  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
34  *  の責任を負わない.
35  * 
36  */
37 #include <fstream>
38 #include <sstream>
39 #include "toppers/diagnostics.hpp"
40 #include "toppers/s_record.hpp"
41 #include "toppers/macro_processor.hpp"
42 #include "toppers/itronx/component.hpp"
43 #include "cfg.hpp"
44 #include <boost/spirit/include/classic.hpp>
45 #include <boost/filesystem/path.hpp>
46 #include <boost/filesystem/operations.hpp>
47
48 /*!
49  *  \brief  オブジェクトID番号の割付け
50  *  \param[in]  api_map   ソースに記述された静的APIを登録したコンテナ
51  */
52 void assign_id( toppers::itronx::cfg1_out::static_api_map& api_map )
53 {
54   using namespace toppers;
55   using namespace toppers::itronx;
56
57   std::string id_input_file( get_global< std::string >( "id-input-file" ) );
58   if ( id_input_file.empty() )  // --id-input-file オプションが指定されていない場合...
59   {
60     for ( cfg1_out::static_api_map::iterator iter( api_map.begin() ), last( api_map.end() );
61           iter != last;
62           ++iter )
63     {
64       static_api::assign_id( iter->second.begin(), iter->second.end() );
65     }
66   }
67   else  // --id-input-file オプションが指定されている場合...
68   {
69     typedef std::map< std::string, std::pair< long, bool > > id_map_t;
70     id_map_t id_map;
71     std::ifstream ifs( id_input_file.c_str() );
72     while ( ifs )
73     {
74       std::string linebuf;
75       std::getline( ifs, linebuf );
76       if ( ifs.bad() )
77       {
78         fatal( _( "I/O error" ) );
79       }
80       if ( linebuf.empty() || linebuf == "\r" )
81       {
82         break;
83       }
84
85       std::istringstream iss( linebuf );
86       std::string name;
87       iss >> name;
88       if ( iss.fail() )
89       {
90         fatal( _( "id file `%1%\' is invalid" ), id_input_file );
91       }
92
93       long value;
94       iss >> value;
95       if ( iss.fail() )
96       {
97         fatal( _( "id file `%1%\' is invalid" ), id_input_file );
98       }
99
100       if ( id_map.find( name ) != id_map.end() )
101       {
102         fatal( _( "E_OBJ: `%1%\' is duplicated" ), name );
103       }
104       else
105       {
106         id_map[ name ] = std::make_pair( value, false );
107       }
108     }
109
110     for ( cfg1_out::static_api_map::iterator iter( api_map.begin() ), last( api_map.end() );
111           iter != last;
112           ++iter )
113     {
114       for ( std::vector< static_api >::iterator iter2( iter->second.begin() ), last2( iter->second.end() );
115             iter2 != last2;
116             ++iter2 )
117       {
118         static_api::info const* info = iter2->get_info();
119         if ( info->id_pos >= 0 )
120         {
121           std::string name( iter2->at( info->id_pos ).text );
122           std::string symbol( iter2->at( info->id_pos ).symbol );
123           if ( !info->slave && symbol[0] == '#' )
124           {
125             id_map_t::iterator hit( id_map.find( name ) );
126             if ( hit != id_map.end() )
127             {
128               long id_value = hit->second.first;
129               if ( id_value > 0 )
130               {
131                 iter2->at( info->id_pos ).value = id_value;
132                 hit->second.second = true;
133               }
134             }
135           }
136         }
137       }
138       static_api::assign_id( iter->second.begin(), iter->second.end() );
139     }
140
141     for ( id_map_t::const_iterator iter( id_map.begin() ), last( id_map.end() ); iter != last; ++iter )  // 残り物があれば...
142     {
143       if ( !iter->second.second )
144       {
145         warning( _( "object identifier `%1%\' is not used" ), iter->first );
146       }
147     }
148   }
149
150   // --id-output-file オプションが指定されている場合
151   std::string id_output_file( get_global< std::string >( "id-output-file" ) );
152   if ( !id_output_file.empty() )
153   {
154     std::ofstream ofs( id_output_file.c_str() );
155     for ( cfg1_out::static_api_map::iterator iter( api_map.begin() ), last( api_map.end() );
156       iter != last;
157       ++iter )
158     {
159       for ( std::vector< static_api >::const_iterator iter2( iter->second.begin() ), last2( iter->second.end() );
160             iter2 != last2;
161             ++iter2 )
162       {
163         static_api::info const* info = iter2->get_info();
164         if ( info->id_pos >= 0 )
165         {
166           std::string name( iter2->at( info->id_pos ).text );
167           std::string symbol( iter2->at( info->id_pos ).symbol );
168           if ( !info->slave && symbol[0] == '#' )
169           {
170             ofs << name << '\t' << iter2->at( info->id_pos ).value.get() << std::endl;
171           }
172         }
173       }
174     }
175   }
176 }
177
178
179 /*!
180  *  \brief  マクロプロセッサに登録するID割付け関数
181  *  \param[in]  line      行番号
182  *  \param[in]  arg_list  マクロ実引数リスト
183  *  \param[in]  p_ctx     マクロコンテキスト
184  *  \retval     マクロ返却値
185  */
186 toppers::macro_processor::var_t bf_assignid( toppers::text_line const& line,
187                                              std::vector< toppers::macro_processor::var_t > const& arg_list,
188                                              toppers::macro_processor::context* p_ctx )
189 {
190   using namespace toppers;
191   using namespace toppers::itronx;
192   using toppers::text_line;
193   typedef toppers::macro_processor::element element;
194   typedef toppers::macro_processor::var_t var_t;
195   typedef toppers::macro_processor::context context;
196
197   return var_t();
198 }
199
200 //! 組み込み関数ASSIGNIDを登録する
201 void register_bf_assignid( toppers::macro_processor* mproc )
202 {
203   // ↓ 追加組み込み関数の登録
204   toppers::macro_processor::func_t func_info = {};
205   func_info.name = "ASSIGNID";
206   func_info.f = &bf_assignid;
207   mproc->add_builtin_function( func_info );
208 }
209
210 /*!
211  *  \brief  パス2処理
212  *  \retval true  成功
213  *  \retval false 失敗
214  */
215 bool cfg2_main()
216 {
217   using namespace toppers;
218   using namespace toppers::itronx;
219
220   std::string kernel( get_global< std::string >( "kernel" ) );
221   itronx::factory factory( kernel );
222   global( "factory" ) = &factory;
223
224   // *.cfgとcfg1_out.srecの読み込み
225   std::string input_file;
226   try
227   {
228     input_file = get_global< std::string >( "input-file" );
229   }
230   catch ( boost::bad_any_cast& )
231   {
232     fatal( _( "no input files" ) );
233   }
234   std::string cfg1_out_name( get_global< std::string >( "cfg1_out" ) );
235   std::auto_ptr< cfg1_out > cfg1_out( factory.create_cfg1_out( cfg1_out_name ) );
236
237   codeset_t codeset = get_global< codeset_t >( "codeset" );
238   cfg1_out->load_cfg( input_file, codeset, *factory.get_static_api_info_map() );
239   cfg1_out->load_srec();
240
241   std::auto_ptr< macro_processor > mproc;
242   std::auto_ptr< component > component_ptr;
243
244   if ( get_global< bool >( "with-software-components" ) )
245   {
246     mproc = factory.create_macro_processor( *cfg1_out, cfg1_out->get_static_api_array() );
247     component_ptr.reset( new component( mproc.get() ) );
248   }
249   else  // 従来仕様(ソフトウェア部品非対応)
250   {
251     cfg1_out::static_api_map api_map( cfg1_out->merge() );
252     assign_id( api_map ); // ID番号の割付け
253     mproc = factory.create_macro_processor( *cfg1_out, api_map );
254   }
255
256   // テンプレート処理
257   boost::any template_file( global( "template-file" ) );
258   namespace fs = boost::filesystem;
259 //  fs::path cfg_dir( get_global< std::string >( "cfg-directory" ), fs::native );
260   fs::path cfg_dir( get_global< std::string >( "cfg-directory" ) );  // filesystem3対応
261   std::vector< std::string > include_paths = get_global< std::vector< std::string > >( "include-path" );
262 //  include_paths.push_back( cfg_dir.empty() ? "." : cfg_dir.native_file_string() );
263   include_paths.push_back( cfg_dir.empty() ? "." : cfg_dir.string() );  // filesystem3対応
264   if ( !template_file.empty() )
265   {
266     toppers::text in_text;
267     toppers::text pp_text;
268     std::string file_name( boost::any_cast< std::string& >( template_file ) );
269
270     in_text.set_line( file_name, 1 );
271     std::ifstream ifs( file_name.c_str() );
272     in_text.append( ifs );
273     macro_processor::preprocess( in_text, pp_text );
274     mproc->evaluate( pp_text );
275   }
276   else  // テンプレートファイルが指定されていないので、共通部分(kernel.tf)のみを処理
277   {
278     fs::path kernel_cfg_template_file( cfg_dir/fs::path( "../../kernel/kernel.tf" ) );
279     if ( !fs::exists( kernel_cfg_template_file ) )
280     {
281 //      error( _( "cannot open file `%1%\'" ), kernel_cfg_template_file.native_file_string() );
282       error( _( "cannot open file `%1%\'" ), kernel_cfg_template_file.string() );  // filesystem3対応
283     }
284     else
285     {
286       toppers::text in_text;
287       toppers::text pp_text;
288
289 //      in_text.set_line( kernel_cfg_template_file.native_file_string(), 1 );
290       in_text.set_line( kernel_cfg_template_file.string(), 1 );  // filesystem3対応
291 //      std::ifstream ifs( kernel_cfg_template_file.native_file_string().c_str() );
292       std::ifstream ifs( kernel_cfg_template_file.string().c_str() );  // filesystem3対応
293       in_text.append( ifs );
294       macro_processor::preprocess( in_text, pp_text );
295       mproc->evaluate( pp_text );
296     }
297   }
298
299   if ( get_error_count() > 0 )
300   {
301     return false;
302   }
303   output_file::save();
304   return true;
305 }