source: cfg_itronx+oil_gcc/toppers/itronx/component.cpp@ 54

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

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

  • Property svn:executable set to *
File size: 14.4 KB
RevLine 
[54]1/*
2 * TOPPERS Software
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 *
5 * Copyright (C) 2010 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 <cstdlib>
38#include <cstring>
39#include <cerrno>
40#include <string>
41#include <vector>
42#include <utility>
43#include <algorithm>
44#include <fstream>
45#include "toppers/macro_processor.hpp"
46#include "toppers/diagnostics.hpp"
47#include "toppers/gettext.hpp"
48#include "toppers/cpp.hpp"
49#include "toppers/global.hpp"
50#include "toppers/misc.hpp"
51#include "toppers/itronx/static_api.hpp"
52#include "toppers/itronx/factory.hpp"
53#include "toppers/itronx/component.hpp"
54#include <boost/format.hpp>
55#include <boost/utility.hpp>
56#include <boost/lexical_cast.hpp>
57
58namespace toppers
59{
60 namespace
61 {
62 typedef macro_processor::element element;
63 typedef macro_processor::var_t var_t;
64 typedef macro_processor::context context;
65
66 inline std::tr1::int64_t get_i( var_t const& var, context const* p_ctx )
67 {
68 return macro_processor::to_integer( var, p_ctx );
69 }
70 inline std::string get_s( var_t const& var, context const* p_ctx )
71 {
72 return macro_processor::to_string( var, p_ctx );
73 }
74
75 inline bool less_element( const element& lhs, const element& rhs )
76 {
77 return *lhs.i < *rhs.i;
78 }
79
80 /*!
81 * \brief ID番号を割付ける
82 * \param[in] line 行番号
83 * \param[in] arg_list マクロ実引数リスト
84 * \param[in] p_ctx マクロコンテキスト
85 * \retval マクロ返却値
86 * 第一引数で指定した種別のオブジェクトに対してID番号を割付け、個々のパラメータを表す変数、
87 * TEXT_LINE、ID_LIST、ORDER_LIST、およびRORDER_LISTを設定する。ただし、ID番号を持たない
88 * オブジェクトの場合、ID_LISTは設定しない。
89 */
90 var_t bf_assignid( text_line const& line, std::vector< var_t > const& arg_list, context* p_ctx )
91 {
92 if ( macro_processor::check_arity( line, arg_list.size(), 1, "ASSIGNID" ) )
93 {
94 itronx::factory* factory = get_global< itronx::factory* >( "factory" );
95 std::map< std::string, itronx::static_api::info > const* info_map = factory->get_static_api_info_map();
96
97 std::string type = get_s( arg_list[ 0 ], p_ctx ); // 出力先リストの識別名
98 std::string TYPE = toppers::toupper( type );
99 typedef std::map< std::string, long > id_map_t;
100 typedef std::map< long, std::string > id_rmap_t;
101 id_map_t id_map;
102 id_rmap_t id_rmap;
103 var_t id_list, order_list, rorder_list;
104 bool has_id = false;
105
106 std::string id_input_file( get_global< std::string >( "id-input-file" ) );
107 if ( !id_input_file.empty() ) // --id-input-file オプションが指定されている場合...
108 {
109 std::ifstream ifs( id_input_file.c_str() );
110 while ( ifs )
111 {
112 std::string linebuf;
113 std::getline( ifs, linebuf );
114 if ( ifs.bad() )
115 {
116 fatal( _( "I/O error" ) );
117 }
118 if ( linebuf.empty() || linebuf == "\r" )
119 {
120 break;
121 }
122
123 std::istringstream iss( linebuf );
124 std::string name;
125 iss >> name;
126 if ( iss.fail() )
127 {
128 fatal( _( "id file `%1%\' is invalid" ), id_input_file );
129 }
130
131 long value;
132 iss >> value;
133 if ( iss.fail() )
134 {
135 fatal( _( "id file `%1%\' is invalid" ), id_input_file );
136 }
137
138 if ( id_map.find( name ) != id_map.end() )
139 {
140 fatal( _( "E_OBJ: `%1%\' is duplicated" ), name );
141 }
142 else
143 {
144 id_map[ name ] = value;
145 id_rmap[ value ] = name;
146 }
147 }
148 }
149 long order = 1;
150 for ( int i = 1; ; i++ )
151 {
152 std::string str_i = boost::lexical_cast< std::string >( i );
153 if ( p_ctx->var_map.find( "API.TYPE[" + str_i + "]" ) == p_ctx->var_map.end() )
154 {
155 break;
156 }
157 std::string api_name = p_ctx->var_map[ "API.NAME[" + str_i + "]" ].at( 0 ).s;
158 std::map< std::string, itronx::static_api::info >::const_iterator it = info_map->find( api_name );
159 if ( it == info_map->end() )
160 {
161 break;
162 }
163 itronx::static_api::info info = it->second;
164 if ( info.type != type )
165 {
166 continue;
167 }
168
169 var_t params = p_ctx->var_map[ "API.PARAMS[" + str_i + "]" ];
170 var_t args = p_ctx->var_map[ "API.ARGS[" + str_i + "]" ];
171 long id = -1;
172
173 if ( info.id_pos >= 0 ) // ID番号のあるもの...
174 {
175 if ( !info.slave )
176 {
177 if ( std::strchr( info.params, '#' ) != 0 ) // オブジェクト識別名を持つ場合...
178 {
179 for ( id = 1; id_rmap.find( id ) != id_rmap.end(); id++ ) // 未使用のID番号を検索
180 ;
181 args.at( info.id_pos ).i = id; // ID番号を設定
182 }
183 else
184 {
185 id = static_cast< long >( *args.at( info.id_pos ).i );
186 }
187 std::string idname = args[ info.id_pos ].s; // IDの字面
188 id_map[ idname ] = id;
189 id_rmap[ id ] = idname;
190 order_list.push_back( args[ info.id_pos ] );
191 }
192 else
193 {
194 id_map_t::iterator it = id_map.find( args.at( info.id_pos ).s );
195 if ( it == id_map.end() )
196 {
197 fatal( line, _( "`%1%\' is undefined" ), args[ info.id_pos ].s );
198 }
199 args.at( info.id_pos ).i = it->second;
200 }
201 has_id = true;
202 }
203 else // ID番号の無いもの...
204 {
205 element e;
206 e.i = order;
207 order_list.push_back( e );
208 }
209 std::string str_id = boost::lexical_cast< std::string >( id > 0 ? id : order );
210
211 // 各パラメータの変数を設定
212 for ( var_t::size_type i = 0, n = params.size(); i < n; i++ )
213 {
214 std::string var_name = params[ i ].s + "[" + str_id + "]";
215 p_ctx->var_map[ var_name ] = var_t( 1, args.at( i ) );
216 }
217 p_ctx->var_map[ TYPE + ".TEXT_LINE[" + str_id + "]" ] = p_ctx->var_map[ "API.TEXT_LINE[" + str_i + "]" ];
218 ++order;
219 }
220
221 id_list = order_list;
222 std::sort( id_list.begin(), id_list.end(), less_element );
223 rorder_list = order_list;
224 std::reverse( rorder_list.begin(), rorder_list.end() );
225 p_ctx->var_map[ TYPE + ".ID_LIST" ] = id_list;
226 p_ctx->var_map[ TYPE + ".ORDER_LIST" ] = order_list;
227 p_ctx->var_map[ TYPE + ".RORDER_LIST" ] = rorder_list;
228 }
229 return var_t();
230 }
231
232 /*!
233 * \brief 指定した連想配列群に静的APIを追加する
234 * \param[in] line 行番号
235 * \param[in] arg_list マクロ実引数リスト
236 * \param[in] p_ctx マクロコンテキスト
237 * \retval マクロ返却値
238 * API.で始まる連想配列群を、必要に応じて適切に変換を行った上で、別のプレフィックスで始まる
239 * 連想配列群に追加する。想定する使用方法としては、特定のソフトウェア部品で理解可能な静的API
240 * に関しては、追加を行わないか、他の静的APIに置き換えて追加を行う。理解できない静的APIに関して
241 * はそのまま追加を行う。
242 * この関数の第一引数にはAPI.で始まる連想配列の連番を、第二引数には追加先に連想配列群の
243 * プレフィックスを、第三引数には対象とする静的API名を、第四引数には追加するパラメータシンボルの
244 * 並びを、第五引数にはパラメータの並びを指定する。
245 */
246 var_t bf_addapi( text_line const& line, std::vector< var_t > const& arg_list, context* p_ctx )
247 {
248 element e;
249 if ( macro_processor::check_arity( line, arg_list.size(), 5, "ADDAPI" ) )
250 {
251 itronx::factory* factory = get_global< itronx::factory* >( "factory" );
252 std::map< std::string, itronx::static_api::info > const* info_map = factory->get_static_api_info_map();
253
254 std::tr1::int64_t order = get_i( arg_list[ 0 ], p_ctx ); // 元の静的APIの連番
255 std::string list_name = get_s( arg_list[ 1 ], p_ctx ); // 出力先リストの識別名
256 std::string api_name = get_s( arg_list[ 2 ], p_ctx ); // 静的API名
257 var_t params = arg_list[ 3 ]; // パラメータシンボルの並び
258 var_t args = arg_list[ 4 ]; // パラメータの並び
259
260 std::map< std::string, itronx::static_api::info >::const_iterator it = info_map->find( api_name );
261 if ( it != info_map->end() )
262 {
263 itronx::static_api::info info = it->second;
264 std::string str_order = boost::lexical_cast< std::string >( order );
265 p_ctx->var_map[ list_name + ".TEXT_LINE[" + str_order + "]" ] = p_ctx->var_map[ "API.TEXT_LINE[" + str_order + "]" ];
266 e.s = api_name;
267 p_ctx->var_map[ list_name + ".NAME[" + str_order + "]" ] = var_t( 1, e );
268 e.s = info.type;
269 p_ctx->var_map[ list_name + ".TYPE[" + str_order + "]" ] = var_t( 1, e );
270 p_ctx->var_map[ list_name + ".PARAMS[" + str_order + "]" ] = params;
271 p_ctx->var_map[ list_name + ".ARGS[" + str_order + "]" ] = args;
272
273 e.s.clear();
274 if ( !p_ctx->var_map[ list_name + ".ORDER_LIST" ].empty() )
275 {
276 e.i = *p_ctx->var_map[ list_name + ".ORDER_LIST" ].back().i + 1;
277 }
278 else
279 {
280 e.i = 1;
281 }
282 p_ctx->var_map[ list_name + ".ORDER_LIST" ].push_back( e );
283
284 e.s.clear();
285 e.i = 1;
286 }
287 }
288 return var_t( 1, e );
289 }
290
291 /*!
292 * \brief 変数群の交換
293 * \param[in] line 行番号
294 * \param[in] arg_list マクロ実引数リスト
295 * \param[in] p_ctx マクロコンテキスト
296 * \retval マクロ返却値
297 * 第一引数および第二引数で指定したプレフィックスを持つ変数群を入れ替える。
298 * ‘ADDAPI’関数で、別のプレフィックスを持つ連想配列を組み立てたあとは、この関数を用いることで、
299 * API.をプレフィックスに持つ連想配列と交換することができる。
300 */
301 var_t bf_swapprefix( text_line const& line, std::vector< var_t > const& arg_list, context* p_ctx )
302 {
303 if ( macro_processor::check_arity( line, arg_list.size(), 2, "SWAPPREFIX" ) )
304 {
305 std::string list1_name = get_s( arg_list[ 0 ], p_ctx ) + "."; // 一方のAPIリストの識別名.
306 std::string list2_name = get_s( arg_list[ 1 ], p_ctx ) + "."; // 他方のAPIリストの識別名.
307 std::string::size_type list1_size = list1_name.size();
308 std::string::size_type list2_size = list2_name.size();
309
310 std::map< std::string, var_t > temp;
311 for ( std::map< std::string, var_t >::const_iterator iter = p_ctx->var_map.begin(), last = p_ctx->var_map.end();
312 iter != last;
313 ++iter )
314 {
315 std::pair< std::string, var_t > element = *iter;
316 if ( std::strncmp( iter->first.c_str(), list1_name.c_str(), list1_size ) == 0 )
317 {
318 element.first = list2_name + ( iter->first.c_str() + list1_size );
319 }
320 else if ( std::strncmp( iter->first.c_str(), list2_name.c_str(), list2_size ) == 0 )
321 {
322 element.first = list1_name + ( iter->first.c_str() + list2_size );
323 }
324 temp.insert( element );
325 }
326 p_ctx->var_map.swap( temp );
327 }
328 return var_t();
329 }
330
331 /*!
332 * \brief 変数群の交換
333 * \param[in] line 行番号
334 * \param[in] arg_list マクロ実引数リスト
335 * \param[in] p_ctx マクロコンテキスト
336 * \retval マクロ返却値
337 * 第一引数で指定したプレフィックスで始まる変数群を削除する。’SWAPPREFIX’関数で交換したあと、
338 * 不要になった変数群はこの関数で削除しておくことが望ましい。
339 */
340 var_t bf_cleanvars( text_line const& line, std::vector< var_t > const& arg_list, context* p_ctx )
341 {
342 if ( macro_processor::check_arity( line, arg_list.size(), 1, "CLEANVARS" ) )
343 {
344 std::string prefix = get_s( arg_list[ 0 ], p_ctx ) + "."; // 変数の接頭辞
345 std::size_t n = prefix.size();
346 std::map< std::string, var_t > temp_map;
347
348 for ( std::map< std::string, var_t >::const_iterator iter = p_ctx->var_map.begin(), last =p_ctx->var_map.end();
349 iter != last;
350 ++iter )
351 {
352 if ( std::strncmp( iter->first.c_str(), prefix.c_str(), n ) != 0 )
353 {
354 temp_map.insert( *iter );
355 }
356 }
357 p_ctx->var_map.swap( temp_map );
358 }
359 return var_t();
360 }
361
362 macro_processor::func_t const function_table[] =
363 {
364 { "ASSIGNID", &bf_assignid },
365 { "ADDAPI", &bf_addapi },
366 { "SWAPPREFIX", &bf_swapprefix },
367 { "CLEANVARS", &bf_cleanvars },
368 };
369
370 }
371
372 namespace itronx
373 {
374
375 component::component( macro_processor* mproc )
376 : mproc_( mproc )
377 {
378 for ( std::size_t i = 0; i < sizeof( function_table ) / sizeof( function_table[ 0 ] ); i++ )
379 {
380 mproc_->add_builtin_function( function_table[ i ] );
381 }
382 }
383
384 }
385}
Note: See TracBrowser for help on using the repository browser.