source: cfg_itronx+oil_gcc/toppers/macro_processor.cpp@ 54

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

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

File size: 67.4 KB
RevLine 
[54]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 <cstdlib>
38#include <cctype>
39#include <cerrno>
40#include <algorithm>
41#include <functional>
42#include <iterator>
43#include <sstream>
44#include <fstream>
45#include <limits>
46#include "toppers/workaround.hpp"
47#include "toppers/io.hpp"
48#include "toppers/cpp.hpp"
49#include "toppers/global.hpp"
50#include "toppers/macro_processor.hpp"
51#include "toppers/diagnostics.hpp"
52#include "toppers/misc.hpp"
53#include <boost/spirit/include/classic.hpp>
54#include <boost/spirit/include/classic_dynamic.hpp>
55#include <boost/spirit/include/classic_parse_tree.hpp>
56#include <boost/lexical_cast.hpp>
57
58// 非標準マクロの定義を除去
59#ifdef max
60#undef max
61#endif
62#ifdef min
63#undef min
64#endif
65
66#define DEBUG_TRACE 0
67
68namespace toppers
69{
70
71 namespace
72 {
73
74 struct expr_error {};
75
76 /*!
77 * \struct parser macro_processor.cpp "toppers/macro_processor.cpp"
78 * \brief マクロ内に記述される式のパーサ
79 */
80 struct parser : boost::spirit::classic::grammar< parser >
81 {
82 enum rule_id_t
83 {
84 id_other = 0,
85
86 id_expression, id_assignment_expr, id_logical_or_expr, id_logical_and_expr,
87 id_or_expr, id_xor_expr, id_and_expr, id_equality_expr, id_relational_expr,
88 id_shift_expr, id_additive_expr, id_multiplicative_expr, id_unary_expr,
89 id_postfix_expr, id_primary_expr, id_lvalue_expr, id_identifier, id_constant,
90 id_string_literal, id_ordered_list, id_ordered_sequence, id_ordered_item,
91
92 id_root, id_top,
93 id_function_, id_if_, id_foreach_, id_joineach_, id_while_, id_joinwhile_,
94 id_error_, id_warning_,
95 id_file_, id_expr_, id_plain,
96
97 id_illegal = -1
98 };
99 enum expected_t
100 {
101 doller_expected, end_expected, close_paren_expected, close_brace_expected,
102 close_bracket_expected
103 };
104
105 /*!
106 * \struct error_handler static_api_parser.hpp "toppers/itronx/static_api_parser.hpp"
107 * \brief 静的APIの構文解析におけるエラー処理ファンクタ
108 */
109 struct error_handler
110 {
111 template < class Scanner, class Error >
112 boost::spirit::classic::error_status<> operator()( Scanner const& scan, Error const& error ) const
113 {
114 typename Error::iterator_t iter( error.where );
115 while ( iter != scan.last && *iter != '\0' && *iter != '\n' )
116 {
117 ++iter;
118 }
119 std::string str;
120 if ( error.where == iter )
121 {
122 str = _( "end of line" );
123 }
124 else
125 {
126 str = '\"' + std::string( error.where, iter ) + '\"';
127 }
128
129 text_line ln;
130 if ( error.where != scan.last )
131 {
132 ln = get_text_line( error.where );
133 }
134 else
135 {
136 // テンプレートファイルの最終行を求める
137 typename Error::iterator_t prev( scan.first );
138 for ( iter = scan.first; iter != scan.last; ++iter )
139 {
140 prev = iter;
141 }
142 ln = get_text_line( prev );
143 }
144 switch ( error.descriptor )
145 {
146 case doller_expected:
147 toppers::fatal( ln, _( "missing `%1%\' before %2%" ), '$', str );
148 break;
149 case end_expected:
150 toppers::fatal( ln, _( "missing `%1%\' before %2%" ), "$END$", str );
151 break;
152 case close_paren_expected:
153 toppers::fatal( ln, _( "missing `%1%\' before %2%" ), ")", str );
154 break;
155 case close_brace_expected:
156 toppers::fatal( ln, _( "missing `%1%\' before %2%" ), "}", str );
157 break;
158 case close_bracket_expected:
159 toppers::fatal( ln, _( "missing `%1%\' before %2%" ), "]", str );
160 break;
161 }
162 return boost::spirit::classic::error_status<>( boost::spirit::classic::error_status<>::fail );
163 }
164 };
165
166
167 template < class Scanner >
168 struct definition
169 {
170 typedef boost::spirit::classic::rule< Scanner, boost::spirit::classic::dynamic_parser_tag > rule_t;
171 typedef boost::spirit::classic::guard< expected_t > guard_t;
172 typedef boost::spirit::classic::assertion< expected_t > assertion_t;
173
174 rule_t expression,
175 assignment_expr,
176 logical_or_expr,
177 logical_and_expr,
178 or_expr,
179 xor_expr,
180 and_expr,
181 equality_expr,
182 relational_expr,
183 shift_expr,
184 additive_expr,
185 multiplicative_expr,
186 unary_expr,
187 postfix_expr,
188 primary_expr,
189 lvalue_expr,
190 identifier,
191 constant,
192 string_literal,
193 ordered_list,
194 ordered_sequence,
195 ordered_item;
196
197 rule_t root,
198 top,
199 function_,
200 if_,
201 foreach_,
202 joineach_,
203 while_,
204 joinwhile_,
205 error_,
206 warning_,
207 file_,
208 expr_,
209 call,
210 plain;
211
212 guard_t guard_function_,
213 guard_if_,
214 guard_foreach_,
215 guard_joineach_,
216 guard_while_,
217 guard_joinwhile_,
218 guard_expr,
219 guard_postfix_expr,
220 guard_lvalue_expr,
221 guard_ordered_list;
222
223 assertion_t expect_doller,
224 expect_end,
225 expect_close_paren,
226 expect_close_brace,
227 expect_close_bracket;
228
229 definition( parser const& self )
230 : expect_doller( doller_expected ),
231 expect_end( end_expected ),
232 expect_close_paren( close_paren_expected ),
233 expect_close_brace( close_brace_expected ),
234 expect_close_bracket( close_bracket_expected )
235 {
236 using namespace boost::spirit::classic;
237
238 set_id();
239
240 expression =
241 logical_or_expr;
242 assignment_expr =
243 lvalue_expr >> '=' >> expression;
244 logical_or_expr =
245 logical_and_expr >> *( "||" >> logical_and_expr );
246 logical_and_expr =
247 or_expr >> *( "&&" >> or_expr );
248 or_expr =
249 xor_expr >> *( '|' >> xor_expr );
250 xor_expr =
251 and_expr >> *( '^' >> and_expr );
252 and_expr =
253 equality_expr >> *( '&' >> equality_expr );
254 equality_expr =
255 relational_expr >> *( ( str_p( "==" ) | "!=" ) >> relational_expr );
256 relational_expr =
257 shift_expr >> *( ( str_p( "<=" ) | ">=" | "<" | ">" ) >> shift_expr );
258 shift_expr =
259 additive_expr >> *( ( str_p( "<<" ) | ">>" ) >> additive_expr );
260 additive_expr =
261 multiplicative_expr >> *( chset<>( "+-" ) >> multiplicative_expr );
262 multiplicative_expr =
263 unary_expr >> *( chset<>( "*/%" ) >> unary_expr );
264 unary_expr =
265 *chset<>( "-+~!@" ) >> postfix_expr;
266 postfix_expr =
267 guard_postfix_expr
268 (
269 ( identifier >> '(' >> *( expression % ',' ) >> expect_close_paren( ch_p( ')' ) ) )
270 | primary_expr
271 )
272 [
273 error_handler()
274 ];
275 primary_expr =
276 lvalue_expr | ordered_list | constant | string_literal
277 | ( '(' >> expression >> ')' );
278 lvalue_expr =
279 guard_lvalue_expr
280 (
281 ( identifier >> '[' >> expression >> expect_close_bracket( ch_p( ']' ) ) )
282 | identifier
283 )
284 [
285 error_handler()
286 ];
287 identifier =
288 leaf_node_d[ lexeme_d[ ( alpha_p | '_' ) >> *( alnum_p | '_' | '.' ) ] ] - "ELIF";
289 constant =
290 leaf_node_d
291 [
292 lexeme_d
293 [
294 if_p( '0' ) // 16進または8進
295 [
296 !(
297 ( ( ch_p( 'x' ) | 'X' ) >> ( hex_p | +xdigit_p ) )
298 | ( oct_p | +chset<>( "0-7" ) )
299 )
300 ]
301 .else_p // 10進
302 [
303 ( int_p | +digit_p )
304 ]
305 ]
306 ];
307 string_literal =
308 leaf_node_d[ lexeme_d[ '\"' >> *( c_escape_ch_p - '\"' ) >> '\"' ] ];
309 ordered_list =
310 guard_ordered_list
311 (
312 '{' >> !( ( ordered_sequence | ordered_item ) >> *( ';' >> ( ordered_sequence | ordered_item ) ) ) >> expect_close_brace( ch_p( '}' ) )
313 )
314 [
315 error_handler()
316 ];
317 ordered_sequence =
318 ( constant >> ',' >> constant >> ',' >> "..." >> ',' >> constant );
319 ordered_item =
320 expression >> *( ',' >> expression );
321
322 root =
323 top >> lexeme_d[ !space_p ];
324 top =
325 *( function_ | if_ | foreach_ | joineach_ | while_ | joinwhile_ | warning_ | error_ | file_ | expr_ | plain );
326 function_ =
327 guard_function_
328 (
329 "$FUNCTION" >> identifier >> expect_doller( ch_p( '$' ) ) >> top >> expect_end( str_p( "$END$" ) )
330 )
331 [
332 error_handler()
333 ];
334 if_ =
335 guard_if_
336 (
337 ( "$IF" >> expression >> expect_doller( ch_p( '$' ) ) >> top
338 >> +( "$ELIF" >> expression >> expect_doller( ch_p( '$' ) ) >> top )
339 >> ( "$ELSE$" >> top ) >> expect_end( str_p( "$END$" ) ) )
340 | ( "$IF" >> expression >> expect_doller( ch_p( '$' ) ) >> top
341 >> +( "$ELIF" >> expression >> expect_doller( ch_p( '$' ) ) >> top ) >> expect_end( str_p( "$END$" ) ) )
342 | ( "$IF" >> expression >> expect_doller( ch_p( '$' ) ) >> top >> "$ELSE$" >> top >> expect_end( str_p( "$END$" ) ) )
343 | ( "$IF" >> expression >> expect_doller( ch_p( '$' ) ) >> top >> expect_end( str_p( "$END$" ) ) )
344 )
345 [
346 error_handler()
347 ];
348 foreach_ =
349 guard_foreach_
350 (
351 "$FOREACH" >> identifier >> expression >> expect_doller( ch_p( '$' ) ) >> top >> expect_end( str_p( "$END$" ) )
352 )
353 [
354 error_handler()
355 ];
356 joineach_ =
357 guard_joineach_
358 (
359 "$JOINEACH" >> identifier >> expression >> expression >> expect_doller( ch_p( '$' ) ) >> top >> expect_end( str_p( "$END$" ) )
360 )
361 [
362 error_handler()
363 ];
364 while_ =
365 guard_while_
366 (
367 "$WHILE" >> expression >> expect_doller( ch_p( '$' ) ) >> top >> expect_end( str_p( "$END$" ) )
368 )
369 [
370 error_handler()
371 ];
372 joinwhile_ =
373 guard_joinwhile_
374 (
375 "$JOINWHILE" >> expression >> expression >> expect_doller( ch_p( '$' ) ) >> top >> expect_end( str_p( "$END$" ) )
376 )
377 [
378 error_handler()
379 ];
380 warning_ =
381 "$WARNING$" >> top >> "$END$" >> !eol_p
382 // Ticket #75対策
383 // ちょっと不細工だが、他の方法ではうまくいかなかった
384 | "$WARNING " >> expression >> '$' >> top >> "$END$"
385 | "$WARNING\t" >> expression >> '$' >> top >> "$END$"
386 | "$WARNING\n" >> expression >> '$' >> top >> "$END$";
387 error_ =
388 "$ERROR$" >> top >> "$END$" >> !eol_p
389 // Ticket #75対策
390 // ちょっと不細工だが、他の方法ではうまくいかなかった
391 | "$ERROR " >> expression >> '$' >> top >> "$END$"
392 | "$ERROR\t" >> expression >> '$' >> top >> "$END$"
393 | "$ERROR\n" >> expression >> '$' >> top >> "$END$";
394 file_ =
395 "$FILE" >> string_literal >> '$';
396 expr_ =
397 guard_expr
398 (
399 ( ( '$' >> ( assignment_expr | expression ) >> expect_doller( ch_p( '$' ) ) ) - "$END$" - "$ELSE$" )
400 )
401 [
402 error_handler()
403 ];
404 plain =
405 leaf_node_d[ lexeme_d[ +( anychar_p - '$' ) | "$$" ] ];
406 }
407 rule_t const& start() const { return root; }
408 void set_id()
409 {
410 expression.set_id( id_expression );
411 assignment_expr.set_id( id_assignment_expr );
412 logical_or_expr.set_id( id_logical_or_expr );
413 logical_and_expr.set_id( id_logical_and_expr );
414 or_expr.set_id( id_or_expr );
415 xor_expr.set_id( id_xor_expr );
416 and_expr.set_id( id_and_expr );
417 equality_expr.set_id( id_equality_expr );
418 relational_expr.set_id( id_relational_expr );
419 shift_expr.set_id( id_shift_expr );
420 additive_expr.set_id( id_additive_expr );
421 multiplicative_expr.set_id( id_multiplicative_expr );
422 unary_expr.set_id( id_unary_expr );
423 postfix_expr.set_id( id_postfix_expr );
424 primary_expr.set_id( id_primary_expr );
425 lvalue_expr.set_id( id_lvalue_expr );
426 identifier.set_id( id_identifier );
427 constant.set_id( id_constant );
428 string_literal.set_id( id_string_literal );
429 ordered_list.set_id( id_ordered_list );
430 ordered_sequence.set_id( id_ordered_sequence );
431 ordered_item.set_id( id_ordered_item );
432
433 root.set_id( id_root );
434 top.set_id( id_top );
435 function_.set_id( id_function_ );
436 if_.set_id( id_if_ );
437 foreach_.set_id( id_foreach_ );
438 joineach_.set_id( id_joineach_ );
439 while_.set_id( id_while_ );
440 joinwhile_.set_id( id_joinwhile_ );
441 error_.set_id( id_error_ );
442 warning_.set_id( id_warning_ );
443 file_.set_id( id_file_ );
444 expr_.set_id( id_expr_ );
445 plain.set_id( id_plain );
446 }
447 };
448
449 parser()
450 {
451 }
452 };
453
454 typedef macro_processor::element element;
455 typedef macro_processor::var_t var_t;
456 typedef macro_processor::context context;
457
458 //! 変数が保持する数値の参照
459 std::tr1::int64_t get_i( var_t const& var, context const* p_ctx )
460 {
461 if ( var.empty() )
462 {
463 fatal( p_ctx->line, _( "non-value is referred" ) );
464 return 0;
465 }
466 element e = var.front();
467 if ( !e.i )
468 {
469 fatal( p_ctx->line, _( "non-value is referred" ) );
470 return 0;
471 }
472 return e.i.get();
473 }
474 //! 変数が保持する文字列の参照
475 std::string get_s( var_t const& var, context const* p_ctx )
476 {
477 if ( var.empty() )
478 {
479 return "";
480 }
481 std::string result;
482 for ( var_t::const_iterator iter( var.begin() ), last( var.end() ); iter != last; ++iter )
483 {
484 if ( !iter->s.empty() )
485 {
486 result += iter->s;
487 }
488 else if ( !iter->v.empty() )
489 {
490 result += iter->v;
491 }
492 else if ( iter->i )
493 {
494 result += boost::lexical_cast< std::string >( iter->i.get() );
495 }
496 if ( boost::next( iter ) != last )
497 {
498 result += ",";
499 }
500 }
501 return result;
502 }
503
504 typedef boost::spirit::classic::tree_node< boost::spirit::classic::node_iter_data< text::const_iterator > > tree_node_t;
505 bool eval_node( tree_node_t const& node, context* p_ctx );
506
507 //! 代入式
508 bool assignment_expr( tree_node_t const& node, context* p_ctx )
509 {
510 // 0 1 2
511 // lhs = rhs
512 if ( eval_node( node.children[ 0 ], p_ctx ) )
513 {
514 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
515 std::string name( get_s( lhs, p_ctx ) );
516 if ( eval_node( node.children[ 2 ], p_ctx ) )
517 {
518 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
519 var_t old_var( p_ctx->var_map[ name ] );
520 p_ctx->var_map[ name ] = rhs;
521 // modified by takuya 110823
522 if ( p_ctx->hook_on_assign != 0 )
523 {
524 ( *p_ctx->hook_on_assign )( node.children[0].value.begin().line(), name, old_var, rhs, p_ctx );
525 }
526 }
527 }
528 return true;
529 }
530
531 //! 論理和式
532 bool logical_or_expr( tree_node_t const& node, context* p_ctx )
533 {
534 // 0 1 2
535 // lhs || rhs ...
536 bool result = true;
537
538 if ( eval_node( node.children[ 0 ], p_ctx ) )
539 {
540 std::size_t const n = node.children.size();
541 if ( n == 1 ) // 左辺のみ
542 {
543 return true;
544 }
545 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
546 for ( std::size_t i = 2; i < n; i += 2 )
547 {
548 std::tr1::int64_t value = 0;
549 try
550 {
551 value = get_i( lhs, p_ctx );
552 }
553 catch ( expr_error& )
554 {
555 error( node.children[ 0 ].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( lhs, p_ctx ) );
556 throw;
557 }
558 if ( value )
559 {
560 break;
561 }
562 result = eval_node( node.children[ i ], p_ctx );
563 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
564 element e;
565 std::tr1::int64_t value2 = 0;
566 try
567 {
568 value2 = get_i( rhs, p_ctx );
569 }
570 catch ( expr_error& )
571 {
572 error( node.children[ i ].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( lhs, p_ctx ) );
573 throw;
574 }
575 e.i = ( value || value2 );
576 lhs[ 0 ] = e;
577 }
578 p_ctx->stack.push( lhs );
579 }
580 return result;
581 }
582
583 //! 論理積式
584 bool logical_and_expr( tree_node_t const& node, context* p_ctx )
585 {
586 // 0 1 2
587 // lhs && rhs ...
588 bool result = true;
589
590 if ( eval_node( node.children[ 0 ], p_ctx ) )
591 {
592 std::size_t const n = node.children.size();
593 if ( n == 1 ) // 左辺のみ
594 {
595 return true;
596 }
597 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
598 for ( std::size_t i = 2; i < n; i += 2 )
599 {
600 std::tr1::int64_t value = 0;
601 try
602 {
603 value = get_i( lhs, p_ctx );
604 }
605 catch ( expr_error& )
606 {
607 error( node.children[ 0 ].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( lhs, p_ctx ) );
608 throw;
609 }
610 if ( !value )
611 {
612 break;
613 }
614 result = eval_node( node.children[ i ], p_ctx );
615 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
616 element e;
617 std::tr1::int64_t value2 = 0;
618 try
619 {
620 value2 = get_i( rhs, p_ctx );
621 }
622 catch ( expr_error& )
623 {
624 error( node.children[ i ].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( lhs, p_ctx ) );
625 throw;
626 }
627 e.i = ( value && value2 );
628 lhs[ 0 ] = e;
629 }
630 p_ctx->stack.push( lhs );
631 }
632 return result;
633 }
634
635 //! ビット和式
636 bool or_expr( tree_node_t const& node, context* p_ctx )
637 {
638 // 0 1 2
639 // lhs | rhs ...
640 if ( eval_node( node.children[ 0 ], p_ctx ) )
641 {
642 std::size_t const n = node.children.size();
643 if ( n == 1 ) // 左辺のみ
644 {
645 return true;
646 }
647 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
648 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[ i+1 ], p_ctx ); i += 2 )
649 {
650 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
651 element e;
652 e.i = ( get_i( lhs, p_ctx ) | get_i( rhs, p_ctx ) );
653 lhs[ 0 ] = e;
654 }
655 p_ctx->stack.push( lhs );
656 }
657 return true;
658 }
659
660 //! 排他的論理和式
661 bool xor_expr( tree_node_t const& node, context* p_ctx )
662 {
663 // 0 1 2
664 // lhs ^ rhs ...
665 if ( eval_node( node.children[ 0 ], p_ctx ) )
666 {
667 std::size_t const n = node.children.size();
668 if ( n == 1 ) // 左辺のみ
669 {
670 return true;
671 }
672 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
673 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[ i+1 ], p_ctx ); i += 2 )
674 {
675 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
676 element e;
677 e.i = ( get_i( lhs, p_ctx ) ^ get_i( rhs, p_ctx ) );
678 lhs[ 0 ] = e;
679 }
680 p_ctx->stack.push( lhs );
681 }
682 return true;
683 }
684
685 //! ビット積式
686 bool and_expr( tree_node_t const& node, context* p_ctx )
687 {
688 // 0 1 2
689 // lhs & rhs ...
690 if ( eval_node( node.children[ 0 ], p_ctx ) )
691 {
692 std::size_t const n = node.children.size();
693 if ( n == 1 ) // 左辺のみ
694 {
695 return true;
696 }
697 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
698 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[ i+1 ], p_ctx ); i += 2 )
699 {
700 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
701 element e;
702 e.i = ( get_i( lhs, p_ctx ) & get_i( rhs, p_ctx ) );
703 lhs[ 0 ] = e;
704 }
705 p_ctx->stack.push( lhs );
706 }
707 return true;
708 }
709
710 //! 等価式(==、!=)
711 bool equality_expr( tree_node_t const& node, context* p_ctx )
712 {
713 // 0 1 2
714 // lhs op rhs ...
715 if ( eval_node( node.children[ 0 ], p_ctx ) )
716 {
717 std::size_t const n = node.children.size();
718 if ( n == 1 ) // 左辺のみ
719 {
720 return true;
721 }
722 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
723 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[ i+1 ], p_ctx ); i += 2 )
724 {
725 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
726 std::string op( node.children[ i ].value.begin(), node.children[ i ].value.end() );
727 std::tr1::int64_t value;
728 if ( op == "==" )
729 {
730 value = ( get_i( lhs, p_ctx ) == get_i( rhs, p_ctx ) );
731 }
732 else
733 {
734 value = ( get_i( lhs, p_ctx ) != get_i( rhs, p_ctx ) );
735 }
736 element e;
737 e.i = value;
738 lhs[ 0 ] = e;
739 }
740 p_ctx->stack.push( lhs );
741 }
742 return true;
743 }
744
745 //! 関係式(不等号)
746 bool relational_expr( tree_node_t const& node, context* p_ctx )
747 {
748 // 0 1 2
749 // lhs op rhs ...
750 if ( eval_node( node.children[0], p_ctx ) )
751 {
752 std::size_t const n = node.children.size();
753 if ( n == 1 ) // 左辺のみ
754 {
755 return true;
756 }
757 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
758 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[ i+1 ], p_ctx ); i += 2 )
759 {
760 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
761 std::string op( node.children[i].value.begin(), node.children[ i ].value.end() );
762 std::tr1::int64_t value;
763 if ( op == "<" )
764 {
765 value = ( get_i( lhs, p_ctx ) < get_i( rhs, p_ctx ) );
766 }
767 else if ( op == "<=" )
768 {
769 value = ( get_i( lhs, p_ctx ) <= get_i( rhs, p_ctx ) );
770 }
771 else if ( op == ">" )
772 {
773 value = ( get_i( lhs, p_ctx ) > get_i( rhs, p_ctx ) );
774 }
775 else
776 {
777 value = ( get_i( lhs, p_ctx ) >= get_i( rhs, p_ctx ) );
778 }
779 element e;
780 e.i = value;
781 lhs[ 0 ] = e;
782 }
783 p_ctx->stack.push( lhs );
784 }
785 return true;
786 }
787
788 //! シフト式
789 bool shift_expr( tree_node_t const& node, context* p_ctx )
790 {
791 // 0 1 2
792 // lhs op rhs ...
793 if ( eval_node( node.children[ 0 ], p_ctx ) )
794 {
795 std::size_t const n = node.children.size();
796 if ( n == 1 ) // 左辺のみ
797 {
798 return true;
799 }
800 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
801 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[ i+1 ], p_ctx ); i += 2 )
802 {
803 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
804 std::string op( node.children[ i ].value.begin(), node.children[ i ].value.end() );
805 std::tr1::int64_t value = get_i( lhs, p_ctx );
806 std::tr1::int64_t shift = get_i( rhs, p_ctx );
807 if ( shift < 0 ) // 負の値でシフトしようとした
808 {
809 error( node.children[ 0 ].value.begin().line(), _( "shift with nagative value `%1%\'" ), shift );
810 }
811 if ( shift > 64 )
812 {
813 error( node.children[ 0 ].value.begin().line(), _( "shift with too large value `%1%\'" ), shift );
814 }
815 if ( op == "<<" )
816 {
817 if ( value < 0 )
818 { // 負の値のシフトはできない
819 error( node.children[0].value.begin().line(), _( "negative value `%1%\' is shift" ), value );
820 }
821 else if ( shift != 0 && static_cast< std::tr1::int64_t >( static_cast< std::tr1::uint64_t >( 1 ) << ( 63 - shift ) ) <= value )
822 { // シフトの結果が負になる
823 error( node.children[0].value.begin().line(), _( "shift with too large value `%1%\'" ), shift );
824 }
825 value = value << shift;
826 }
827 else
828 {
829 if ( value < 0 ) // 強制的に算術シフトさせる
830 {
831 value = static_cast< std::tr1::int64_t >( ( static_cast< std::tr1::uint64_t >( value ) >> shift ) | ( ~static_cast< std::tr1::uint64_t >( 0 ) << shift ) );
832 }
833 else
834 {
835 value = value >> shift;
836 }
837 }
838 element e;
839 e.i = value;
840 lhs[ 0 ] = e;
841 }
842 p_ctx->stack.push( lhs );
843 }
844 return true;
845 }
846
847 //! 加減式
848 bool additive_expr( tree_node_t const& node, context* p_ctx )
849 {
850 // 0 1 2
851 // lhs op rhs ...
852 if ( eval_node( node.children[ 0 ], p_ctx ) )
853 {
854 std::size_t const n = node.children.size();
855 if ( n == 1 ) // 左辺のみ
856 {
857 return true;
858 }
859 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
860 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[ i+1 ], p_ctx ); i += 2 )
861 {
862 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
863 std::string op( node.children[ i ].value.begin(), node.children[ i ].value.end() );
864 std::tr1::int64_t x = get_i( lhs, p_ctx );
865 std::tr1::int64_t y = get_i( rhs, p_ctx );
866 element e;
867 if ( op == "+" )
868 {
869 if ( ( y > 0 && ( std::numeric_limits< std::tr1::int64_t >::max() - y ) < x )
870 || ( y < 0 && ( std::numeric_limits< std::tr1::int64_t >::min() - y ) > x ) )
871 {
872 error( node.children[ 0 ].value.begin().line(), _( "overflow at `%1%\'" ), get_s( lhs, p_ctx ) + "+" + get_s( rhs, p_ctx ) );
873 // e.i に値はセットされない
874 }
875 else
876 {
877 e.i = x + y;
878 }
879 }
880 else // "-"
881 {
882 if ( ( y < 0 && ( std::numeric_limits< std::tr1::int64_t >::max() + y ) < x )
883 || ( y > 0 && ( std::numeric_limits< std::tr1::int64_t >::min() + y ) > x ) )
884 {
885 error( node.children[ 0 ].value.begin().line(), _( "overflow at `%1%\'" ), get_s( lhs, p_ctx ) + "-" + get_s( rhs, p_ctx ) );
886 // e.i に値はセットされない
887 }
888 else
889 {
890 e.i = x - y;
891 }
892 }
893 lhs[ 0 ] = e;
894 }
895 p_ctx->stack.push( lhs );
896 }
897 return true;
898 }
899
900 //! 乗除式
901 bool multiplicative_expr( tree_node_t const& node, context* p_ctx )
902 {
903 // 0 1 2
904 // lhs op rhs ...
905 if ( eval_node( node.children[ 0 ], p_ctx ) )
906 {
907 std::size_t const n = node.children.size();
908 if ( n == 1 ) // 左辺のみ
909 {
910 return true;
911 }
912 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
913 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[ i+1 ], p_ctx ); i += 2 )
914 {
915 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
916 std::string op( node.children[i].value.begin(), node.children[i].value.end() );
917 std::tr1::int64_t x = get_i( lhs, p_ctx );
918 std::tr1::int64_t y = get_i( rhs, p_ctx );
919 element e;
920 if ( op == "*" )
921 {
922 if ( ( x == 0 ) || ( y == 0 ) )
923 {
924 e.i = 0;
925 }
926 else if ( ( ( x < 0 ) == ( y < 0 ) ) && ( std::numeric_limits< std::tr1::int64_t >::max() / y < x )
927 || ( ( x < 0 ) != ( y < 0 ) ) && ( std::numeric_limits< std::tr1::int64_t >::min() / y > x ) )
928 {
929 error( node.children[0].value.begin().line(), _( "overflow at `%1%\'" ), get_s( lhs, p_ctx ) + "*" + get_s( rhs, p_ctx ) );
930 // e.i に値はセットされない
931 }
932 else
933 {
934 e.i = x * y;
935 }
936 }
937 else
938 {
939 if ( y == 0 )
940 {
941 error( node.value.begin().line(), _( "devide by zero" ) );
942 // e.i には値がセットされない
943 }
944 else
945 {
946 std::tr1::int64_t value;
947 // 本当はここで一方のオペランドが負の場合の処理を行う必要がある。
948 // そんな変な処理系は実質的にないので放置
949 if ( op == "/" )
950 {
951 value = ( x / y );
952 }
953 else // "%"
954 {
955 value = ( x % y );
956 }
957 e.i = value;
958 }
959 }
960 lhs[ 0 ] = e;
961 }
962 p_ctx->stack.push( lhs );
963 }
964 return true;
965 }
966
967 //! 単項式(後置式、単項演算子 一次式)
968 bool unary_expr( tree_node_t const& node, context* p_ctx )
969 {
970 // 0 1..n-2 n-1
971 // op ...... primary_expr
972 if ( eval_node( node.children[ node.children.size() - 1 ], p_ctx ) )
973 {
974 std::size_t const n = node.children.size();
975 if ( n == 1 ) // 一次式のみ
976 {
977 return true;
978 }
979 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
980 for ( long i = static_cast< long >( n ) - 2, t = 0; i >= 0 && eval_node( node.children[i+1], p_ctx ); i-- )
981 {
982 std::string op( node.children[ i ].value.begin(), node.children[ i ].value.end() );
983 element e;
984 std::tr1::int64_t value = 0;
985 if ( op != "@" )
986 {
987 try
988 {
989 value = get_i( expr, p_ctx );
990 }
991 catch ( expr_error& )
992 {
993 error( node.children[0].value.begin().line(), _( "`%1%\' is undefined" ), get_s( expr, p_ctx ) );
994 throw;
995 }
996 if ( op == "+" )
997 {
998 e.i = +value;
999 }
1000 else if ( op == "-" )
1001 {
1002 if ( value == std::numeric_limits< std::tr1::int64_t >::min() )
1003 {
1004 error( node.children[0].value.begin().line(), _( "overflow at `%1%\'" ), "-" + get_s( expr, p_ctx ) );
1005 // e.i に値はセットされない
1006 }
1007 else
1008 {
1009 e.i = -value;
1010 }
1011 }
1012 else if ( op == "~" )
1013 {
1014 e.i = ~value;
1015 }
1016 else if ( op == "!" )
1017 {
1018 e.i = !value;
1019 }
1020 value = *e.i;
1021 }
1022 else // op == "@" (値属性 → 文字列属性)
1023 {
1024 if ( expr.front().i )
1025 {
1026 e.s = boost::lexical_cast< std::string >( *expr.front().i );
1027 }
1028 else
1029 {
1030 e.s = expr.front().v;
1031 }
1032 }
1033 expr[ 0 ] = e; // 演算結果を累積する
1034 if ( i == t )
1035 {
1036 break;
1037 }
1038 }
1039 p_ctx->stack.push( expr );
1040 }
1041 return true;
1042 }
1043
1044 //! 後置式(関数呼び出し、一次式)
1045 bool postfix_expr( tree_node_t const& node, context* p_ctx )
1046 {
1047 // 0 1 2 3 4..2+2*n-1 2+2*n 2+2*n+1
1048 // identifier ( arg0 , .......... argn )
1049 // primary_expr
1050 if ( eval_node( node.children[0], p_ctx ) )
1051 {
1052 if ( node.children.size() > 1 ) // 関数の呼び出し
1053 {
1054 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1055 std::string func_name( get_s( ident, p_ctx ) );
1056 std::map< std::string, macro_processor::func_t >::const_iterator iter( p_ctx->func_map.find( func_name ) );
1057 if ( iter == p_ctx->func_map.end() ) // そんな関数はない
1058 {
1059 error( node.children[ 0 ].value.begin().line(), _( "function `%1%\' is undefined" ), func_name );
1060 p_ctx->stack.push( var_t() );
1061 }
1062 else // 関数を呼び出す
1063 {
1064 std::vector< var_t > arg_list;
1065 for ( std::size_t i = 0, n = node.children.size() - 1; 2 + 2*i < n; i++ )
1066 {
1067 if ( eval_node( node.children[ 2 + 2*i ], p_ctx ) )
1068 {
1069 var_t arg( p_ctx->stack.top() ); p_ctx->stack.pop();
1070 arg_list.push_back( arg );
1071 }
1072 }
1073 var_t result;
1074 if ( iter->second.f != 0 ) // 組み込み関数
1075 {
1076 result = ( *iter->second.f )( node.children[0].value.begin().line(), arg_list, p_ctx );
1077 }
1078 else if ( iter->second.node != 0 ) // ユーザー定義関数
1079 {
1080 // ARGC
1081 {
1082 element e;
1083 e.i = static_cast< std::tr1::int64_t >( arg_list.size() + 1 );
1084 p_ctx->var_map[ "ARGC" ] = var_t( 1, e );
1085 }
1086
1087 // ARGV
1088 {
1089 element e;
1090 e.s = func_name;
1091 p_ctx->var_map[ "ARGV[0]" ] = var_t( 1, e );
1092
1093 std::size_t n = arg_list.size() + 1;
1094 for ( std::size_t i = 1; i < n; i++ )
1095 {
1096 std::string argv_i = boost::str( boost::format( "ARGV[%d]" ) % i );
1097 p_ctx->var_map[ argv_i ] = arg_list[ i - 1 ];
1098 }
1099
1100 std::string argv_n = boost::str( boost::format( "ARGV[%d]" ) % n );
1101 p_ctx->var_map[ argv_n ] = var_t();
1102 }
1103
1104 set_error_location( func_name.c_str() );
1105 tree_node_t const* func_body_node = reinterpret_cast< tree_node_t const* >( iter->second.node );
1106 if ( !eval_node( *func_body_node, p_ctx ) )
1107 {
1108 // 呼び出し失敗
1109 p_ctx->stack.push( result );
1110 return false;
1111 }
1112
1113 result = p_ctx->var_map[ "RESULT" ];
1114 p_ctx->var_map[ "RESULT" ] = var_t(); // 変数$RESULT$をクリア
1115 }
1116 p_ctx->stack.push( result );
1117 }
1118 }
1119 }
1120 return true;
1121 }
1122
1123 //! 一次式(左辺値式、(式))
1124 bool primary_expr( tree_node_t const& node, context* p_ctx )
1125 {
1126 bool result = true;
1127
1128 if ( node.children.size() == 1 )
1129 {
1130 result = eval_node( node.children[0], p_ctx );
1131 if ( node.children[ 0 ].value.id() == parser::id_lvalue_expr )
1132 {
1133 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1134 std::string name( get_s( ident, p_ctx ) );
1135 var_t value( p_ctx->var_map[ name ] );
1136 p_ctx->stack.push( value );
1137 }
1138 }
1139 else
1140 {
1141 // 0 1 2
1142 // ( expression )
1143 result = eval_node( node.children[1], p_ctx );
1144 }
1145 return result;
1146 }
1147
1148 //! 左辺値式(変数、配列変数)
1149 bool lvalue_expr( tree_node_t const& node, context* p_ctx )
1150 {
1151 // 0 1 2 3
1152 // identifier
1153 // identifier [ expression ]
1154 if ( eval_node( node.children[ 0 ], p_ctx ) )
1155 {
1156 if ( ( node.children.size() > 1 ) && eval_node( node.children[ 2 ], p_ctx ) )
1157 {
1158 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
1159 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1160 element e;
1161 std::string subscript;
1162 try
1163 {
1164 std::tr1::int64_t i = get_i( expr, p_ctx );
1165 subscript = boost::lexical_cast< std::string >( i );
1166 }
1167 catch ( expr_error& )
1168 {
1169 subscript = get_s( expr, p_ctx );
1170 error( node.children[ 0 ].value.begin().line(), _( "`%1%\' does not have a value" ), subscript );
1171 throw;
1172 }
1173 e.s = ( boost::format( "%s[%s]" ) % get_s( ident, p_ctx ) % subscript ).str();
1174 p_ctx->stack.push( var_t( 1, e ) );
1175 }
1176 }
1177 return true;
1178 }
1179
1180 //! 識別子
1181 bool identifier( tree_node_t const& node, context* p_ctx )
1182 {
1183 element e;
1184 std::string ident( node.children[0].value.begin(), node.children[0].value.end() );
1185 std::string::size_type n = ident.find_first_not_of( " \t\r\n" );
1186 e.s = ident.c_str() + n;
1187 p_ctx->stack.push( var_t( 1, e ) );
1188 return true;
1189 }
1190
1191 //! 整数定数
1192 bool constant( tree_node_t const& node, context* p_ctx )
1193 {
1194 element e;
1195 e.s.assign( node.children[0].value.begin(), node.children[0].value.end() );
1196
1197 // Boost 1.39.0?以上で、0の前の空白を含めてトークンとしてしまう不具合の対策
1198 std::string::size_type pos = e.s.find_first_not_of( " \t\n" );
1199 if (pos != std::string::npos )
1200 {
1201 e.s = e.s.substr( pos );
1202 }
1203
1204 std::istringstream iss( e.s );
1205 iss.unsetf( std::ios_base::basefield );
1206 std::tr1::int64_t value;
1207 iss >> value;
1208 if ( iss.bad() )
1209 {
1210 error( node.children[0].value.begin().line(), _( "overflow at `%1%\'" ), e.s );
1211 }
1212 e.i = value;
1213 p_ctx->stack.push( var_t( 1, e ) );
1214 return true;
1215 }
1216
1217 //! 文字列
1218 bool string_literal( tree_node_t const& node, context* p_ctx )
1219 {
1220 // 0 1..n-2 n-1
1221 // " ...... "
1222 element e;
1223 // ここで構文エラー例外になることはあり得ない。(構文解析後なので)
1224 e.s = expand_quote( std::string( node.children[0].value.begin(), node.children[0].value.end() ) );
1225 p_ctx->stack.push( var_t( 1, e ) );
1226 return true;
1227 }
1228
1229 //! 順序付きリスト
1230 bool ordered_list( tree_node_t const& node, context* p_ctx )
1231 {
1232 // 0 1 2 n-1
1233 // { ordered_sequence ; ... }
1234 // { ordered_item ; ... }
1235 if ( node.children.size() < 3 )
1236 {
1237 p_ctx->stack.push( var_t() );
1238 }
1239 else if ( eval_node( node.children[1], p_ctx ) )
1240 {
1241 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
1242 for ( std::size_t i = 1, n = node.children.size(); ( i+2 < n ) && eval_node( node.children[i+2], p_ctx ); i += 2 )
1243 {
1244 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
1245 std::copy( rhs.begin(), rhs.end(), std::back_inserter( lhs ) );
1246 }
1247 p_ctx->stack.push( lhs );
1248 }
1249 return true;
1250 }
1251
1252 //! 順序付きリスト(等差数列)
1253 bool ordered_sequence( tree_node_t const& node, context* p_ctx )
1254 {
1255 // 0 1 2 3 4 5 6
1256 // int , int , ... , int
1257 if ( eval_node( node.children[0], p_ctx ) )
1258 {
1259 var_t first( p_ctx->stack.top() ); p_ctx->stack.pop();
1260 if ( eval_node( node.children[ 2 ], p_ctx ) )
1261 {
1262 var_t second( p_ctx->stack.top() ); p_ctx->stack.pop();
1263 if ( eval_node( node.children[ 6 ], p_ctx ) )
1264 {
1265 var_t last( p_ctx->stack.top() ); p_ctx->stack.pop();
1266 std::tr1::int64_t a0 = get_i( first, p_ctx );
1267 std::tr1::int64_t a1 = get_i( second, p_ctx );
1268 std::tr1::int64_t an = get_i( last, p_ctx );
1269 std::tr1::int64_t d = a1 - a0;
1270 if ( ( an - a0 ) % d != 0 )
1271 {
1272 error( node.children[ 0 ].value.begin().line(), _( "illegal arithmetic sequence" ) );
1273 }
1274 else
1275 {
1276 for ( std::tr1::int64_t i = a1, t = an + d; i != t; i += d )
1277 {
1278 element e;
1279 e.i = i;
1280 first.push_back( e );
1281 }
1282 first[ 1 ].s = second[0].s;
1283 first.back().s = last[ 0 ].s;
1284 }
1285 p_ctx->stack.push( first );
1286 }
1287 }
1288 }
1289 return true;
1290 }
1291
1292 //! 順序付きリスト(列記)
1293 bool ordered_item( tree_node_t const& node, context* p_ctx )
1294 {
1295 // 0 1 2
1296 // int , int ...
1297 if ( eval_node( node.children[ 0 ], p_ctx ) )
1298 {
1299 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
1300 for ( std::size_t i = 1, n = node.children.size(); ( i < n ) && eval_node( node.children[ i+1 ], p_ctx ); i += 2 )
1301 {
1302 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
1303 lhs.push_back( rhs[ 0 ] );
1304 }
1305 p_ctx->stack.push( lhs );
1306 }
1307 return true;
1308 }
1309
1310 //! トップレベル
1311 bool top( tree_node_t const& node, context* p_ctx )
1312 {
1313 bool result = true;
1314
1315 for ( std::size_t i = 0, n = node.children.size(); i < n; i++ )
1316 {
1317 for ( text::const_iterator iter( node.children[ i ].value.begin() ), last( node.children[ i ].value.end() );
1318 iter != last;
1319 ++iter )
1320 {
1321 char c = *iter;
1322 if ( !std::isspace( static_cast< unsigned char >( c ) ) )
1323 {
1324 break;
1325 }
1326 if ( c != '\n' )
1327 {
1328 p_ctx->target_file << c;
1329 }
1330 }
1331 result &= eval_node( node.children[i], p_ctx );
1332 }
1333 return result;
1334 }
1335
1336 //! $FUNCTION命令
1337 bool function_( tree_node_t const& node, context* p_ctx )
1338 {
1339 bool result = true;
1340
1341 if ( node.children.empty() )
1342 {
1343 fatal( node.value.begin().line(), "no body of %1%", "'FUNCTION'" );
1344 }
1345
1346 if ( p_ctx->in_function )
1347 {
1348 fatal( node.value.begin().line(), "function cannot be nested" );
1349 }
1350 p_ctx->in_function = true;
1351
1352 // 0 1 2 3 4
1353 // $FUNCTION identifier $ top $END$
1354 if ( eval_node( node.children[ 1 ], p_ctx ) ) // identifier
1355 {
1356 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1357 macro_processor::func_t func;
1358 func.name = get_s( ident, p_ctx );
1359 func.node = &node.children[ 3 ];
1360 func.f = 0; // 組み込み関数ではないので
1361 p_ctx->func_map[ func.name ] = func;
1362 }
1363 else
1364 {
1365 result = false;
1366 }
1367 p_ctx->in_function = false;
1368 return result;
1369 }
1370
1371 //! $IF命令
1372 bool if_( tree_node_t const& node, context* p_ctx )
1373 {
1374 bool result = true;
1375
1376 if ( node.children.empty() )
1377 {
1378 fatal( node.value.begin().line(), "no body of %1%", "'IF' or 'ELSE'" );
1379 }
1380
1381 // 0 1 2 3 4 5 6 4+4*i 4+4*i+1 4+4*i+2 4+4*i+3 n-3 n-2 n-1
1382 // $IF expression $ top $END$
1383 // $IF expression $ top $ELSE$ top $END$
1384 // $IF expression $ top ... $ELIF expression $ top ... $ELSE$ top $END$
1385 if ( eval_node( node.children[ 1 ], p_ctx ) ) // expression
1386 {
1387 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
1388 bool cond = false;
1389 try
1390 {
1391 cond = !!get_i( expr, p_ctx );
1392 }
1393 catch ( expr_error& )
1394 {
1395 error( node.children[ 0 ].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( expr, p_ctx ) );
1396 throw;
1397 }
1398
1399 std::size_t n = node.children.size();
1400
1401 if ( cond ) // $IF expr$
1402 {
1403 result &= eval_node( node.children[ 3 ], p_ctx ); // top
1404 }
1405 else if ( n == 7 ) // $ELSE$
1406 {
1407 result &= eval_node( node.children[ 5 ], p_ctx ); // top
1408 }
1409 else if ( n > 5 ) // $ELIF...
1410 {
1411 for ( std::size_t i = 0; 4 + 4 * i < n - 1; i++ )
1412 {
1413 std::string token( node.children[ 4 + 4 * i ].value.begin(), node.children[ 4 + 4 * i ].value.end() );
1414 if ( token == "$ELIF" ) // $ELIF
1415 {
1416 if ( eval_node( node.children[ 4 + 4 * i + 1 ], p_ctx ) ) // expression
1417 {
1418 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
1419 cond = false;
1420 try
1421 {
1422 cond = !!get_i( expr, p_ctx );
1423 }
1424 catch ( expr_error& )
1425 {
1426 error( node.children[ 0 ].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( expr, p_ctx ) );
1427 throw;
1428 }
1429 if ( cond ) // $ELIF expr$
1430 {
1431 result &= eval_node( node.children[ 4 + 4 * i + 3 ], p_ctx ); // top
1432 break;
1433 }
1434 }
1435 }
1436 else // ELSE
1437 {
1438 result &= eval_node( node.children[ 4 + 4 * i + 1 ], p_ctx ); // top
1439 break;
1440 }
1441 }
1442 }
1443 }
1444 return result;
1445 }
1446
1447 //! FOREACH命令
1448 bool foreach_( tree_node_t const& node, context* p_ctx )
1449 {
1450 bool result = true;
1451
1452 if ( node.children.empty() )
1453 {
1454 fatal( node.value.begin().line(), "no body of %1%", "'FOREACH'" );
1455 }
1456
1457 // 0 1 2 3 4 5
1458 // $FOREACH identifier order_list $ top $END$
1459 if ( eval_node( node.children[1], p_ctx ) ) // identifier
1460 {
1461 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1462 if ( eval_node( node.children[ 2 ], p_ctx ) ) // order_list
1463 {
1464 var_t order_list( p_ctx->stack.top() ); p_ctx->stack.pop();
1465 if ( !order_list.empty() )
1466 {
1467 for ( var_t::const_iterator iter( order_list.begin() ), last( order_list.end() ); iter != last; ++iter )
1468 {
1469 p_ctx->var_map[ get_s( ident, p_ctx ) ] = var_t( 1, *iter );
1470 result &= eval_node( node.children[ 4 ], p_ctx ); // top
1471 }
1472 }
1473 }
1474 }
1475 return result;
1476 }
1477
1478 //! $JOINEACH命令
1479 bool joineach_( tree_node_t const& node, context* p_ctx )
1480 {
1481 bool result = true;
1482
1483 if ( node.children.empty() )
1484 {
1485 fatal( node.value.begin().line(), "no body of %1%", "'JOINEACH'" );
1486 }
1487
1488 // 0 1 2 3 4 5 6
1489 // $JOINEACH identifier order_list delimitor $ top $END$
1490 if ( eval_node( node.children[ 1 ], p_ctx ) ) // identifier
1491 {
1492 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1493 if ( eval_node( node.children[ 2 ], p_ctx ) ) // order_list
1494 {
1495 var_t order_list( p_ctx->stack.top() ); p_ctx->stack.pop();
1496 //if ( !order_list.empty() && order_list[0].i ) // TODO: 1.8.0と違う
1497 if ( !order_list.empty() ) // TODO: 1.8.0と違う
1498 {
1499 if ( eval_node( node.children[ 3 ], p_ctx ) ) // delimitor
1500 {
1501 var_t delimitor( p_ctx->stack.top() ); p_ctx->stack.pop();
1502 for ( var_t::const_iterator iter( order_list.begin() ), last( order_list.end() ); iter != last; ++iter )
1503 {
1504 p_ctx->var_map[ get_s( ident, p_ctx ) ] = var_t( 1, *iter );
1505 result &= eval_node( node.children[ 5 ], p_ctx ); // top
1506 if ( boost::next( iter ) != last )
1507 {
1508 p_ctx->target_file << get_s( delimitor, p_ctx );
1509 }
1510 }
1511 }
1512 }
1513 }
1514 }
1515 return result;
1516 }
1517
1518 //! WHILE命令
1519 bool while_( tree_node_t const& node, context* p_ctx )
1520 {
1521 bool result = true;
1522
1523 if ( node.children.empty() )
1524 {
1525 fatal( node.value.begin().line(), "no body of %1%", "'WHILE'" );
1526 }
1527
1528 // 0 1 2 3 4
1529 // $WHILE expression $ top $END$
1530 for (;;)
1531 {
1532 if ( eval_node( node.children[1], p_ctx ) ) // expression
1533 {
1534 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
1535 bool cond = false;
1536 try
1537 {
1538 cond = !!get_i( expr, p_ctx );
1539 }
1540 catch ( expr_error& )
1541 {
1542 error( node.children[ 0 ].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( expr, p_ctx ) );
1543 throw;
1544 }
1545 if ( !cond )
1546 {
1547 break;
1548 }
1549 result &= eval_node( node.children[ 3 ], p_ctx ); // top
1550 }
1551 }
1552 return result;
1553 }
1554
1555 //! $JOINWHILE命令
1556 bool joinwhile_( tree_node_t const& node, context* p_ctx )
1557 {
1558 bool result = true;
1559
1560 if ( node.children.empty() )
1561 {
1562 fatal( node.value.begin().line(), "no body of %1%", "'JOINWHILE'" );
1563 }
1564
1565 // 0 1 2 3 4 5
1566 // $JOINWHILE expression delimitor $ top $END$
1567 for ( bool first = true; ; first = false )
1568 {
1569 if ( eval_node( node.children[1], p_ctx ) ) // expression
1570 {
1571 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
1572 bool cond = false;
1573 try
1574 {
1575 cond = !!get_i( expr, p_ctx );
1576 }
1577 catch ( expr_error& )
1578 {
1579 error( node.children[ 0 ].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( expr, p_ctx ) );
1580 throw;
1581 }
1582 if ( !cond )
1583 {
1584 break;
1585 }
1586 if ( !first && eval_node( node.children[ 2 ], p_ctx ) ) // delimitor
1587 {
1588 var_t delimitor( p_ctx->stack.top() ); p_ctx->stack.pop();
1589 p_ctx->target_file << get_s( delimitor, p_ctx );
1590 }
1591 }
1592 result &= eval_node( node.children[ 4 ], p_ctx ); // top
1593 }
1594 return result;
1595 }
1596
1597 //! $ERROR命令
1598 bool error_( tree_node_t const& node, context* p_ctx )
1599 {
1600 // 0 1 2 3 4
1601 // $ERROR$ top $END$
1602 // $WARNING$ top $END$
1603 // $ERROR expr $ top $END$
1604 // $WARNING expr $ top $END$
1605
1606 if ( node.children.empty() )
1607 {
1608 fatal( node.value.begin().line(), "no body of %1%", "'ERROR' or 'WARNING'" );
1609 }
1610
1611 output_file of = p_ctx->target_file;
1612 p_ctx->target_file = output_file( "stderr", std::ios_base::out ); // 出力先を一時的に標準エラー出力に切り替える。
1613
1614 bool is_error = ( static_cast< parser::rule_id_t >( node.value.id().to_long() ) == parser::id_error_ );
1615
1616 p_ctx->target_file << get_program_name() << ':';
1617
1618 bool has_expr = ( node.children.size() > 3 );
1619
1620 if ( has_expr && eval_node( node.children[1], p_ctx ) ) // expr
1621 {
1622 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
1623 if ( !expr.empty() )
1624 {
1625 if ( !expr.front().s.empty() )
1626 {
1627 p_ctx->target_file << expr.front().s << ':';
1628 }
1629 if ( expr.front().i )
1630 {
1631 p_ctx->target_file << expr.front().i.get() << ':';
1632 }
1633 }
1634 }
1635
1636 p_ctx->target_file << ( is_error ? " error: " : " warning: " );
1637
1638 bool result = eval_node( node.children[has_expr ? 3 : 1], p_ctx ); // top
1639 p_ctx->target_file << '\n';
1640 p_ctx->target_file = of;
1641
1642 if ( is_error )
1643 {
1644 increment_error_count(); // error関数を使わないので、明示的にエラーカウントを操作する。
1645 }
1646 return result;
1647 }
1648
1649 //! $WARNING命令
1650 bool warning_( tree_node_t const& node, context* p_ctx )
1651 {
1652 return error_( node, p_ctx );
1653 }
1654
1655 //! $FILE命令
1656 bool file_( tree_node_t const& node, context* p_ctx )
1657 {
1658 // 0 1 2
1659 // $FILE string-literal $
1660 if ( eval_node( node.children[1], p_ctx ) ) // string-literal
1661 {
1662 var_t filename( p_ctx->stack.top() ); p_ctx->stack.pop();
1663 p_ctx->target_file << '\n';
1664 p_ctx->target_file = output_file( get_s( filename, p_ctx ), std::ios_base::out );
1665 }
1666 return true;
1667 }
1668
1669 //! 式
1670 bool expr_( tree_node_t const& node, context* p_ctx )
1671 {
1672 // 0 1 2
1673 // $ expression $
1674 if ( eval_node( node.children[ 1 ], p_ctx ) ) // expression
1675 {
1676 if ( node.children[1].value.id().to_long() == parser::id_expression )
1677 {
1678 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
1679 p_ctx->target_file << get_s( expr, p_ctx );
1680 }
1681 }
1682 return true;
1683 }
1684
1685 // マクロ命令以外
1686 bool plain( tree_node_t const& node, context* p_ctx )
1687 {
1688 std::string buf;
1689 buf.reserve( node.children[ 0 ].value.end() - node.children[ 0 ].value.begin() );
1690 std::size_t offset = 0;
1691
1692 if ( std::isspace( static_cast< unsigned char >( *node.children[ 0 ].value.begin() ) ) ) // plainの先頭が空白類文字の場合、なぜか二重になる不具合の暫定対策
1693 offset = 1;
1694
1695 for ( text::const_iterator iter( node.children[ 0 ].value.begin() + offset ), last( node.children[0].value.end() ); iter != last; ++iter )
1696 {
1697 if ( *iter == '$' )
1698 {
1699 ++iter;
1700 }
1701 switch ( char c = *iter )
1702 {
1703 case '\r':
1704 case '\n':
1705 break;
1706 default:
1707 buf.push_back( c );
1708 break;
1709 }
1710 }
1711 p_ctx->target_file << buf;
1712 return true;
1713 }
1714
1715 // 構文木の各ノードの評価
1716 bool eval_node( tree_node_t const& node, context* p_ctx )
1717 {
1718 bool result = true;
1719 if ( p_ctx != 0 )
1720 {
1721 p_ctx->line = node.value.begin().line();
1722 }
1723
1724#if defined( _MSC_VER ) && DEBUG_TRACE
1725 ::OutputDebugString( ( boost::format( "%s:%d:%s\n" )
1726 % node.children[ 0 ].value.begin().line().file
1727 % node.children[ 0 ].value.begin().line().line
1728 % std::string( node.children[ 0 ].value.begin(), node.children[ 0 ].value.end() )
1729 ).str().c_str() );
1730#elif 0
1731 std::cerr << boost::format( "%s:%d:%s" )
1732 % node.children[ 0 ].value.begin().line().file
1733 % node.children[ 0 ].value.begin().line().line
1734 % std::string( node.children[ 0 ].value.begin(), node.children[ 0 ].value.end() )
1735 << std::endl;
1736#endif
1737
1738 switch ( parser::rule_id_t id = static_cast< parser::rule_id_t >( node.value.id().to_long() ) )
1739 {
1740 case parser::id_expression:
1741 result = eval_node( node.children[ 0 ], p_ctx );
1742 break;
1743 case parser::id_assignment_expr:
1744 result = assignment_expr( node, p_ctx );
1745 break;
1746 case parser::id_logical_or_expr:
1747 result = logical_or_expr( node, p_ctx );
1748 break;
1749 case parser::id_logical_and_expr:
1750 result = logical_and_expr( node, p_ctx );
1751 break;
1752 case parser::id_or_expr:
1753 result = or_expr( node, p_ctx );
1754 break;
1755 case parser::id_xor_expr:
1756 result = xor_expr( node, p_ctx );
1757 break;
1758 case parser::id_and_expr:
1759 result = and_expr( node, p_ctx );
1760 break;
1761 case parser::id_equality_expr:
1762 result = equality_expr( node, p_ctx );
1763 break;
1764 case parser::id_relational_expr:
1765 result = relational_expr( node, p_ctx );
1766 break;
1767 case parser::id_shift_expr:
1768 result = shift_expr( node, p_ctx );
1769 break;
1770 case parser::id_additive_expr:
1771 result = additive_expr( node, p_ctx );
1772 break;
1773 case parser::id_multiplicative_expr:
1774 result = multiplicative_expr( node, p_ctx );
1775 break;
1776 case parser::id_unary_expr:
1777 result = unary_expr( node, p_ctx );
1778 break;
1779 case parser::id_postfix_expr:
1780 result = postfix_expr( node, p_ctx );
1781 break;
1782 case parser::id_primary_expr:
1783 result = primary_expr( node, p_ctx );
1784 break;
1785 case parser::id_lvalue_expr:
1786 result = lvalue_expr( node, p_ctx );
1787 break;
1788 case parser::id_identifier:
1789 result = identifier( node, p_ctx );
1790 break;
1791 case parser::id_constant:
1792 result = constant( node, p_ctx );
1793 break;
1794 case parser::id_string_literal:
1795 result = string_literal( node, p_ctx );
1796 break;
1797 case parser::id_ordered_list:
1798 result = ordered_list( node, p_ctx );
1799 break;
1800 case parser::id_ordered_sequence:
1801 result = ordered_sequence( node, p_ctx );
1802 break;
1803 case parser::id_ordered_item:
1804 result = ordered_item( node, p_ctx );
1805 break;
1806 case parser::id_root:
1807 result = eval_node( node.children[0], p_ctx );
1808 break;
1809 case parser::id_top:
1810 result = top( node, p_ctx );
1811 break;
1812 case parser::id_function_:
1813 result = function_( node, p_ctx );
1814 break;
1815 case parser::id_if_:
1816 result = if_( node, p_ctx );
1817 break;
1818 case parser::id_foreach_:
1819 result = foreach_( node, p_ctx );
1820 break;
1821 case parser::id_joineach_:
1822 result = joineach_( node, p_ctx );
1823 break;
1824 case parser::id_while_:
1825 result = while_( node, p_ctx );
1826 break;
1827 case parser::id_joinwhile_:
1828 result = joinwhile_( node, p_ctx );
1829 break;
1830 case parser::id_error_:
1831 result = error_( node, p_ctx );
1832 break;
1833 case parser::id_warning_:
1834 result = warning_( node, p_ctx );
1835 break;
1836 case parser::id_file_:
1837 result = file_( node, p_ctx );
1838 break;
1839 case parser::id_expr_:
1840 result = expr_( node, p_ctx );
1841 break;
1842 case parser::id_plain:
1843 result = plain( node, p_ctx );
1844 break;
1845 default:
1846 result = false;
1847 break;
1848 }
1849 return result;
1850 }
1851
1852 bool eval_text( text::const_iterator first, text::const_iterator last, context* p_ctx )
1853 {
1854 using namespace boost::spirit::classic;
1855 typedef text::const_iterator iterator_t;
1856 tree_parse_info< iterator_t, node_iter_data_factory<> > info;
1857 info = pt_parse( first, last, parser(), space_p, node_iter_data_factory<>() );
1858 if ( info.full && !info.trees.empty() )
1859 {
1860 bool result;
1861 if ( info.length <= 0 )
1862 {
1863 result = true;
1864 }
1865 else
1866 {
1867 result = eval_node( info.trees[ 0 ], p_ctx );
1868 }
1869 return result;
1870 }
1871 else
1872 {
1873 fatal( info.stop.line(), _( "syntax error" ) );
1874 }
1875 return false;
1876 }
1877
1878 }
1879
1880 std::tr1::int64_t macro_processor::to_integer( var_t const& var, context const* p_ctx )
1881 {
1882 return get_i( var, p_ctx );
1883 }
1884
1885 std::string macro_processor::to_string( var_t const& var, context const* p_ctx )
1886 {
1887 return get_s( var, p_ctx );
1888 }
1889
1890 macro_processor::macro_processor()
1891 : p_ctx_( new context )
1892 {
1893 }
1894
1895 // modified by takuya 110823
1896 macro_processor::macro_processor( hook_t hook_on_assign )
1897 : p_ctx_( new context( hook_on_assign ) )
1898 {
1899 }
1900
1901 macro_processor::macro_processor( macro_processor const& other )
1902 : p_ctx_( new context( *other.p_ctx_ ) )
1903 {
1904 }
1905
1906 macro_processor::macro_processor( text const& in )
1907 : p_ctx_( new context )
1908 {
1909 evaluate( in );
1910 }
1911
1912 // modified by takuya 110823
1913 macro_processor::macro_processor( text const& in, hook_t hook_on_assign )
1914 : p_ctx_( new context( hook_on_assign ) )
1915 {
1916 evaluate( in );
1917 }
1918
1919 macro_processor::~macro_processor()
1920 {
1921 delete p_ctx_;
1922 p_ctx_ = 0;
1923 }
1924
1925 macro_processor& macro_processor::operator=( macro_processor const& other )
1926 {
1927 macro_processor t( *this );
1928 swap( t );
1929 return *this;
1930 }
1931
1932 void macro_processor::swap( macro_processor& other )
1933 {
1934 std::swap( p_ctx_, other.p_ctx_ );
1935 }
1936
1937 void macro_processor::evaluate( text const& in )
1938 {
1939 try
1940 {
1941 for ( func_t const* p_bf = builtin_function_table; !p_bf->name.empty(); p_bf++ )
1942 {
1943 p_ctx_->func_map[ p_bf->name ] = *p_bf;
1944 }
1945 if ( !eval_text( in.begin(), in.end(), p_ctx_ ) )
1946 {
1947 fatal( _( "macro processing error" ) );
1948 }
1949 }
1950 catch ( die_terminate& )
1951 {
1952 // $DIE()$関数が呼ばれた
1953 }
1954 catch ( expr_error& )
1955 {
1956 fatal( _( "macro processing error" ) );
1957 }
1958 }
1959
1960 void macro_processor::set_var( std::string const& name, var_t const& value )
1961 {
1962#if defined( _MSC_VER ) && /* DEBUG_TRACE */ 1
1963 std::string s( "$" + name + " = " + get_s( value, p_ctx_ ) + "$" );
1964 if ( !value.empty() && value[ 0 ].i )
1965 {
1966 s += "(" + boost::lexical_cast< std::string >( get_i( value, p_ctx_ ) ) + ")";
1967 }
1968 s += "\n";
1969 ::OutputDebugString( s.c_str() );
1970#endif
1971 p_ctx_->var_map[ name ] = value;
1972 }
1973
1974 void macro_processor::set_var( std::string const& name, long name2, var_t const& value )
1975 {
1976 set_var( ( boost::format( "%s[%d]" ) % name % name2 ).str(), value );
1977 }
1978
1979 macro_processor::var_t const& macro_processor::get_var( std::string const& name ) const
1980 {
1981 return p_ctx_->var_map[ name ];
1982 }
1983
1984 macro_processor::var_t const& macro_processor::get_var( std::string const& name, long name2 ) const
1985 {
1986 return get_var( ( boost::format( "%s[%d]" ) % name % name2 ).str() );
1987 }
1988
1989 /*!
1990 * \brief コメントの除去
1991 * \param[in] first 処理対象シーケンスの先頭位置
1992 * \param[in] last 処理対象シーケンスの終端位置の次
1993 * \param[out] result 処理結果の格納先
1994 * \return 処理完了後の result の値
1995 *
1996 * 「$ + 空白類文字」で始まり、改行で終わるコメントを除去します。
1997 */
1998 void macro_processor::remove_comment( text const& in, text& out )
1999 {
2000 text::const_iterator first( in.begin() ), last( in.end() );
2001 std::back_insert_iterator< text > result( std::back_inserter( out ) );
2002 out.set_line( first.line().file, first.line().line );
2003
2004 for ( text::const_iterator iter; ( iter = std::find( first, last, '\n' ) ) != last ; first = iter + 1 )
2005 {
2006 std::string buf( first, iter );
2007 std::string::size_type found_pos;
2008
2009 if ( ( ( buf.size() >= 2 ) && ( buf[0] == '$' ) && std::isspace( static_cast< unsigned char >( buf[1] ) ) )
2010 || ( buf.size() == 1 && buf[0] == '$' ) ) // 行頭に限り、'$'単独でもコメントとみなす
2011 {
2012 *result = '\n';
2013 }
2014 else if ( ( found_pos = buf.find( std::string( "$#" ) ) ) != std::string::npos ) // 行の途中に"$#"があれば、それ以降をコメントとみなす
2015 {
2016 result = std::copy( buf.begin(), buf.begin() + found_pos, result );
2017 }
2018 else
2019 {
2020 // コメント行以外は行頭の空白類を除去する。
2021 first = std::find_if( first, iter, std::not1( std::ptr_fun< char, bool >( &toppers::isspace ) ) );
2022 result = std::copy( first, iter + 1, result );
2023 }
2024 }
2025 }
2026
2027 void macro_processor::expand_include( text const& in, text& out )
2028 {
2029 typedef text::container::const_iterator const_row_iterator;
2030 typedef std::string::size_type size_type;
2031 size_type const npos = std::string::npos;
2032std::string debug_str;
2033
2034 if ( in.empty() ) // 空のファイルが入力された場合の対策
2035 {
2036 return;
2037 }
2038
2039 const_row_iterator first( in.begin().get_row() ), last( in.end().get_row() );
2040
2041 out.set_line( first->line.file, first->line.line );
2042 for ( const_row_iterator iter( first ); iter != last; ++iter )
2043 {
2044 std::string const& buf = iter->buf;
2045
2046 for ( size_type i = 0, n = buf.size(); i != n; ++i )
2047 {
2048 using namespace boost::spirit::classic;
2049 char c = buf[i];
2050 std::string headername;
2051 text::const_iterator iter2( iter, i );
2052 if ( iter2 == in.end() )
2053 {
2054 break;
2055 }
2056 parse_info< text::const_iterator > info
2057 = parse( iter2, in.end(),
2058 ( ch_p( '$' ) >> str_p( "INCLUDE" ) >> *space_p
2059 >> '\"' >> ( +( anychar_p - '\"' ) )[ assign( headername ) ] >> '\"'
2060 >> '$' ) );
2061 if ( info.hit )
2062 {
2063 std::vector< std::string > include_paths = get_global< std::vector< std::string > >( "include-path" );
2064 std::string hname = search_include_file( include_paths.begin(), include_paths.end(), headername );
2065 if ( hname.empty() )
2066 {
2067 fatal( iter->line, _( "cannot open file `%1%\'" ), headername );
2068 }
2069 else
2070 {
2071 text t;
2072 t.set_line( hname, 1 );
2073 std::ifstream ifs( hname.c_str() );
2074 t.append( ifs );
2075
2076 preprocess( t, out );
2077 iter = info.stop.get_row();
2078 i = info.stop.get_col() - 1;
2079 out.set_line( iter->line.file, iter->line.line );
2080 }
2081 }
2082 else
2083 {
2084 out.push_back( c );
2085 debug_str.push_back( c );
2086 if ( c == '\n' )
2087 {
2088// ::OutputDebugString( ( out.get_line().file + ":" + boost::lexical_cast< std::string >( out.get_line().line ) + ":" ).c_str() );
2089// ::OutputDebugString( debug_str.c_str() );
2090 debug_str.clear();
2091 }
2092 }
2093 }
2094 }
2095 }
2096
2097 void macro_processor::preprocess( text const& in, text& out )
2098 {
2099 if ( in.empty() )
2100 {
2101 return;
2102 }
2103 text temp;
2104 macro_processor::remove_comment( in, temp );
2105 expand_include( temp, out );
2106 }
2107
2108 void macro_processor::add_builtin_function( func_t const& f )
2109 {
2110 p_ctx_->func_map[ f.name ] = f;
2111 }
2112
2113 macro_processor::var_t macro_processor::call_user_function( text_line const& line, std::vector< var_t > const& arg_list, context* p_ctx )
2114 {
2115 if ( arg_list.empty() )
2116 {
2117 return var_t();
2118 }
2119
2120 func_t func = p_ctx->func_map[ get_s( arg_list.front(), p_ctx ) ];
2121 if ( func.name.empty() )
2122 {
2123 fatal( line, "function is not defined" );
2124 return var_t();
2125 }
2126
2127 // ARGC
2128 {
2129 element e;
2130 e.i = static_cast< std::tr1::int64_t >( arg_list.size() );
2131 p_ctx->var_map[ "ARGC" ] =var_t( 1, e );
2132 }
2133
2134 // ARGV
2135 {
2136 std::size_t n = arg_list.size();
2137 for ( std::size_t i = 0; i < n; i++ )
2138 {
2139 std::string argv_i = boost::str( boost::format( "ARGV[%d]" ) % i );
2140 p_ctx->var_map[ argv_i ] = arg_list[ i ];
2141 }
2142
2143 std::string argv_n = boost::str( boost::format( "ARGV[%d]" ) % n );
2144 p_ctx->var_map[ argv_n ] = var_t();
2145 }
2146
2147 tree_node_t const* func_body_node = reinterpret_cast< tree_node_t const* >( func.node );
2148 if ( !eval_node( *func_body_node, p_ctx ) )
2149 {
2150 return var_t();
2151 }
2152
2153 var_t result = p_ctx->var_map[ "RESULT" ];
2154 p_ctx->var_map[ "RESULT" ] = var_t(); // 変数$RESULT$をクリア
2155 return result;
2156 }
2157
2158}
Note: See TracBrowser for help on using the repository browser.