source: cfg_oil/trunk/toppers/macro_processor.cpp@ 8

Last change on this file since 8 was 8, checked in by msugi, 13 years ago

ディレクトリ構造の作成,ソース一式とReleaseビルドのコミット.

File size: 61.9 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 *
7 * ã‹L’˜ìŒ ŽÒ‚́CˆÈ‰º‚Ì(1)`(4)‚ÌðŒ‚ð–ž‚½‚·ê‡‚ÉŒÀ‚èC–{ƒ\ƒtƒgƒEƒF
8 * ƒAi–{ƒ\ƒtƒgƒEƒFƒA‚ð‰ü•Ï‚µ‚½‚à‚Ì‚ðŠÜ‚ށDˆÈ‰º“¯‚¶j‚ðŽg—pE•¡»E‰ü
9 * •ÏEÄ”z•ziˆÈ‰ºC—˜—p‚ƌĂԁj‚·‚邱‚Ƃ𖳏ž‚Å‹–‘ø‚·‚éD
10 * (1) –{ƒ\ƒtƒgƒEƒFƒA‚ðƒ\[ƒXƒR[ƒh‚ÌŒ`‚Å—˜—p‚·‚éê‡‚ɂ́Cã‹L‚Ì’˜ì
11 * Œ •\Ž¦C‚±‚Ì—˜—pðŒ‚¨‚æ‚щº‹L‚Ì–³•ÛØ‹K’肪C‚»‚Ì‚Ü‚Ü‚ÌŒ`‚Ń\[
12 * ƒXƒR[ƒh’†‚ÉŠÜ‚Ü‚ê‚Ä‚¢‚邱‚ƁD
13 * (2) –{ƒ\ƒtƒgƒEƒFƒA‚ðCƒ‰ƒCƒuƒ‰ƒŠŒ`Ž®‚ȂǁC‘¼‚̃\ƒtƒgƒEƒFƒAŠJ”­‚ÉŽg
14 * —p‚Å‚«‚éŒ`‚ōĔz•z‚·‚éê‡‚ɂ́CÄ”z•z‚É”º‚¤ƒhƒLƒ…
15ƒƒ“ƒgi—˜—p
16 * ŽÒƒ}ƒjƒ…
17ƒAƒ‹‚Ȃǁj‚ɁCã‹L‚Ì’˜ìŒ •\Ž¦C‚±‚Ì—˜—pðŒ‚¨‚æ‚щº‹L
18 * ‚Ì–³•ÛØ‹K’è‚ðŒfÚ‚·‚邱‚ƁD
19 * (3) –{ƒ\ƒtƒgƒEƒFƒA‚ðC‹@Ší‚É‘g‚ݍž‚ނȂǁC‘¼‚̃\ƒtƒgƒEƒFƒAŠJ”­‚ÉŽg
20 * —p‚Å‚«‚È‚¢Œ`‚ōĔz•z‚·‚éê‡‚ɂ́CŽŸ‚Ì‚¢‚¸‚ê‚©‚ÌðŒ‚ð–ž‚½‚·‚±
21 * ‚ƁD
22 * (a) Ä”z•z‚É”º‚¤ƒhƒLƒ…
23ƒƒ“ƒgi—˜—pŽÒƒ}ƒjƒ…
24ƒAƒ‹‚Ȃǁj‚ɁCã‹L‚Ì’˜
25 * ìŒ •\Ž¦C‚±‚Ì—˜—pðŒ‚¨‚æ‚щº‹L‚Ì–³•ÛØ‹K’è‚ðŒfÚ‚·‚邱‚ƁD
26 * (b) Ä”z•z‚ÌŒ`‘Ô‚ðC•Ê‚É’è‚ß‚é•û–@‚É‚æ‚Á‚āCTOPPERSƒvƒƒWƒFƒNƒg‚É
27 * •ñ‚·‚邱‚ƁD
28 * (4) –{ƒ\ƒtƒgƒEƒFƒA‚Ì—˜—p‚É‚æ‚è’¼Ú“I‚Ü‚½‚͊ԐړI‚ɐ¶‚¶‚é‚¢‚©‚Ȃ鑹
29 * ŠQ‚©‚ç‚àCã‹L’˜ìŒ ŽÒ‚¨‚æ‚ÑTOPPERSƒvƒƒWƒFƒNƒg‚ð–Ɛӂ·‚邱‚ƁD
30 * ‚Ü‚½C–{ƒ\ƒtƒgƒEƒFƒA‚̃†[ƒU‚Ü‚½‚̓Gƒ“ƒhƒ†[ƒU‚©‚ç‚Ì‚¢‚©‚Ȃ闝
31 * —R‚ÉŠî‚­¿‹‚©‚ç‚àCã‹L’˜ìŒ ŽÒ‚¨‚æ‚ÑTOPPERSƒvƒƒWƒFƒNƒg‚ð
32 * –Ɛӂ·‚邱‚ƁD
33 *
34 * –{ƒ\ƒtƒgƒEƒFƒA‚́C–³•ÛØ‚Å’ñ‹Ÿ‚³‚ê‚Ä‚¢‚é‚à‚Ì‚Å‚ ‚éDã‹L’˜ìŒ ŽÒ‚¨
35 * ‚æ‚ÑTOPPERSƒvƒƒWƒFƒNƒg‚́C–{ƒ\ƒtƒgƒEƒFƒA‚ÉŠÖ‚µ‚āC“Á’è‚ÌŽg—p–Ú“I
36 * ‚ɑ΂·‚é“K‡«‚àŠÜ‚߂āC‚¢‚©‚È‚é•ÛØ‚às‚í‚È‚¢D‚Ü‚½C–{ƒ\ƒtƒgƒEƒF
37 * ƒA‚Ì—˜—p‚É‚æ‚è’¼Ú“I‚Ü‚½‚͊ԐړI‚ɐ¶‚¶‚½‚¢‚©‚Ȃ鑹ŠQ‚ÉŠÖ‚µ‚Ä‚àC‚»
38 * ‚̐ӔC‚𕉂í‚È‚¢D
39 *
40 */
41#include <cstdlib>
42#include <cctype>
43#include <cerrno>
44#include <algorithm>
45#include <functional>
46#include <iterator>
47#include <sstream>
48#include <fstream>
49#include <limits>
50#include "toppers/workaround.hpp"
51#include "toppers/io.hpp"
52#include "toppers/cpp.hpp"
53#include "toppers/global.hpp"
54#include "toppers/macro_processor.hpp"
55#include "toppers/diagnostics.hpp"
56#include "toppers/misc.hpp"
57#include <boost/spirit.hpp>
58#include <boost/spirit/dynamic.hpp>
59#include <boost/spirit/tree/parse_tree.hpp>
60#include <boost/lexical_cast.hpp>
61
62// ”ñ•W€ƒ}ƒNƒ‚Ì’è‹`‚ðœ‹Ž
63#ifdef max
64#undef max
65#endif
66#ifdef min
67#undef min
68#endif
69
70#define DEBUG_TRACE 0
71
72namespace toppers
73{
74
75 namespace
76 {
77
78 struct expr_error {};
79
80 /*!
81 * \struct parser macro_processor.cpp "toppers/macro_processor.cpp"
82 * \brief ƒ}ƒNƒ“à‚É‹Lq‚³‚ê‚鎮‚̃p[ƒT
83 */
84 struct parser : boost::spirit::grammar< parser >
85 {
86 enum rule_id_t
87 {
88 id_other = 0,
89
90 id_expression, id_assignment_expr, id_logical_or_expr, id_logical_and_expr,
91 id_or_expr, id_xor_expr, id_and_expr, id_equality_expr, id_relational_expr,
92 id_shift_expr, id_additive_expr, id_multiplicative_expr, id_unary_expr,
93 id_postfix_expr, id_primary_expr, id_lvalue_expr, id_identifier, id_constant,
94 id_string_literal, id_ordered_list, id_ordered_sequence, id_ordered_item,
95
96 id_root, id_top,
97 id_function_, id_if_, id_foreach_, id_joineach_, id_error_, id_warning_,
98 id_file_, id_expr_, id_plain,
99
100 id_illegal = -1
101 };
102 enum expected_t
103 {
104 doller_expected, end_expected, close_paren_expected, close_brace_expected,
105 close_bracket_expected
106 };
107
108 /*!
109 * \struct error_handler static_api_parser.hpp "toppers/oil/static_api_parser.hpp"
110 * \brief Ã“IAPI‚̍\•¶‰ðÍ‚É‚¨‚¯‚éƒGƒ‰[ˆ—ƒtƒ@ƒ“ƒNƒ^
111 */
112 struct error_handler
113 {
114 template < class Scanner, class Error >
115 boost::spirit::error_status<> operator()( Scanner const& scan, Error const& error ) const
116 {
117 typename Error::iterator_t iter( error.where );
118 while ( iter != scan.last && *iter != '\0' && *iter != '\n' )
119 {
120 ++iter;
121 }
122 std::string str;
123 if ( error.where == iter )
124 {
125 str = _( "end of line" );
126 }
127 else
128 {
129 str = '\"' + std::string( error.where, iter ) + '\"';
130 }
131
132 text_line ln;
133 if ( error.where != scan.last )
134 {
135 ln = get_text_line( error.where );
136 }
137 else
138 {
139 // ƒeƒ“ƒvƒŒ[ƒgƒtƒ@ƒCƒ‹‚̍ŏIs‚ð‹‚ß‚é
140 typename Error::iterator_t prev( scan.first );
141 for ( iter = scan.first; iter != scan.last; ++iter )
142 {
143 prev = iter;
144 }
145 ln = get_text_line( prev );
146 }
147 switch ( error.descriptor )
148 {
149 case doller_expected:
150 toppers::fatal( ln, _( "missing `%1%\' before %2%" ), '$', str );
151 break;
152 case end_expected:
153 toppers::fatal( ln, _( "missing `%1%\' before %2%" ), "$END$", str );
154 break;
155 case close_paren_expected:
156 toppers::fatal( ln, _( "missing `%1%\' before %2%" ), ")", str );
157 break;
158 case close_brace_expected:
159 toppers::fatal( ln, _( "missing `%1%\' before %2%" ), "}", str );
160 break;
161 case close_bracket_expected:
162 toppers::fatal( ln, _( "missing `%1%\' before %2%" ), "]", str );
163 break;
164 }
165 return boost::spirit::error_status<>( boost::spirit::error_status<>::fail );
166 }
167 };
168
169
170 template < class Scanner >
171 struct definition
172 {
173 typedef boost::spirit::rule< Scanner, boost::spirit::dynamic_parser_tag > rule_t;
174 typedef boost::spirit::guard< expected_t > guard_t;
175 typedef boost::spirit::assertion< expected_t > assertion_t;
176
177 rule_t expression,
178 assignment_expr,
179 logical_or_expr,
180 logical_and_expr,
181 or_expr,
182 xor_expr,
183 and_expr,
184 equality_expr,
185 relational_expr,
186 shift_expr,
187 additive_expr,
188 multiplicative_expr,
189 unary_expr,
190 postfix_expr,
191 primary_expr,
192 lvalue_expr,
193 identifier,
194 constant,
195 string_literal,
196 ordered_list,
197 ordered_sequence,
198 ordered_item;
199
200 rule_t root,
201 top,
202 function_,
203 if_,
204 foreach_,
205 joineach_,
206 error_,
207 warning_,
208 file_,
209 expr_,
210 call,
211 plain;
212
213 guard_t guard_function_,
214 guard_if_,
215 guard_foreach_,
216 guard_joineach_,
217 guard_expr,
218 guard_postfix_expr,
219 guard_lvalue_expr,
220 guard_ordered_list;
221
222 assertion_t expect_doller,
223 expect_end,
224 expect_close_paren,
225 expect_close_brace,
226 expect_close_bracket;
227
228 definition( parser const& self )
229 : expect_doller( doller_expected ),
230 expect_end( end_expected ),
231 expect_close_paren( close_paren_expected ),
232 expect_close_brace( close_brace_expected ),
233 expect_close_bracket( close_bracket_expected )
234 {
235 using namespace boost::spirit;
236
237 set_id();
238
239 expression =
240 logical_or_expr;
241 assignment_expr =
242 lvalue_expr >> '=' >> expression;
243 logical_or_expr =
244 logical_and_expr >> *( "||" >> logical_and_expr );
245 logical_and_expr =
246 or_expr >> *( "&&" >> or_expr );
247 or_expr =
248 xor_expr >> *( '|' >> xor_expr );
249 xor_expr =
250 and_expr >> *( '^' >> and_expr );
251 and_expr =
252 equality_expr >> *( '&' >> equality_expr );
253 equality_expr =
254 relational_expr >> *( ( str_p( "==" ) | "!=" ) >> relational_expr );
255 relational_expr =
256 shift_expr >> *( ( str_p( "<=" ) | ">=" | "<" | ">" ) >> shift_expr );
257 shift_expr =
258 additive_expr >> *( ( str_p( "<<" ) | ">>" ) >> additive_expr );
259 additive_expr =
260 multiplicative_expr >> *( chset<>( "+-" ) >> multiplicative_expr );
261 multiplicative_expr =
262 unary_expr >> *( chset<>( "*/%" ) >> unary_expr );
263 unary_expr =
264 *chset<>( "-+~!@" ) >> postfix_expr;
265 postfix_expr =
266 guard_postfix_expr
267 (
268 ( identifier >> '(' >> *( expression % ',' ) >> expect_close_paren( ch_p( ')' ) ) )
269 | primary_expr
270 )
271 [
272 error_handler()
273 ];
274 primary_expr =
275 lvalue_expr | ordered_list | constant | string_literal
276 | ( '(' >> expression >> ')' );
277 lvalue_expr =
278 guard_lvalue_expr
279 (
280 ( identifier >> '[' >> expression >> expect_close_bracket( ch_p( ']' ) ) )
281 | identifier
282 )
283 [
284 error_handler()
285 ];
286 identifier =
287 leaf_node_d[ lexeme_d[ ( alpha_p | '_' ) >> *( alnum_p | '_' | '.' ) ] ];
288 constant =
289 leaf_node_d
290 [
291 lexeme_d
292 [
293 if_p( '0' ) // 16i‚Ü‚½‚Í8i
294 [
295 !(
296 ( ( ch_p( 'x' ) | 'X' ) >> ( hex_p | +xdigit_p ) )
297 | ( oct_p | +chset<>( "0-7" ) )
298 )
299 ]
300 .else_p // 10i
301 [
302 ( int_p | +digit_p )
303 ]
304 ]
305 ];
306 string_literal =
307 leaf_node_d[ lexeme_d[ '\"' >> *( c_escape_ch_p - '\"' ) >> '\"' ] ];
308 ordered_list =
309 guard_ordered_list
310 (
311 '{' >> !( ( ordered_sequence | ordered_item ) >> *( ';' >> ( ordered_sequence | ordered_item ) ) ) >> expect_close_brace( ch_p( '}' ) )
312 )
313 [
314 error_handler()
315 ];
316 ordered_sequence =
317 ( constant >> ',' >> constant >> ',' >> "..." >> ',' >> constant );
318 ordered_item =
319 expression >> *( ',' >> expression );
320
321 root =
322 top >> lexeme_d[ !space_p ];
323 top =
324 *( function_ | if_ | foreach_ | joineach_ | warning_ | error_ | file_ | expr_ | plain );
325 function_ =
326 guard_function_
327 (
328 "$FUNCTION" >> identifier >> expect_doller( ch_p( '$' ) ) >> top >> expect_end( str_p( "$END$" ) )
329 )
330 [
331 error_handler()
332 ];
333 if_ =
334 guard_if_
335 (
336 ( "$IF" >> expression >> expect_doller( ch_p( '$' ) ) >> top >> "$ELSE$" >> top >> expect_end( str_p( "$END$" ) ) )
337 | ( "$IF" >> expression >> expect_doller( ch_p( '$' ) ) >> top >> expect_end( str_p( "$END$" ) ) )
338 )
339 [
340 error_handler()
341 ];
342 foreach_ =
343 guard_foreach_
344 (
345 "$FOREACH" >> identifier >> expression >> expect_doller( ch_p( '$' ) ) >> top >> expect_end( str_p( "$END$" ) )
346 )
347 [
348 error_handler()
349 ];
350 joineach_ =
351 guard_joineach_
352 (
353 "$JOINEACH" >> identifier >> expression >> expression >> expect_doller( ch_p( '$' ) ) >> top >> expect_end( str_p( "$END$" ) )
354 )
355 [
356 error_handler()
357 ];
358 warning_ =
359 "$WARNING$" >> top >> "$END$" >> !eol_p
360 | "$WARNING" >> expression >> '$' >> top >> "$END$";
361 error_ =
362 "$ERROR$" >> top >> "$END$" >> !eol_p
363 | "$ERROR" >> expression >> '$' >> top >> "$END$";
364 file_ =
365 "$FILE" >> string_literal >> '$';
366 expr_ =
367 guard_expr
368 (
369 ( ( '$' >> ( assignment_expr | expression ) >> expect_doller( ch_p( '$' ) ) ) - "$END$" - "$ELSE$" )
370 )
371 [
372 error_handler()
373 ];
374 plain =
375 leaf_node_d[ lexeme_d[ +( anychar_p - '$' ) | "$$" ] ];
376 }
377 rule_t const& start() const { return root; }
378 void set_id()
379 {
380 expression.set_id( id_expression );
381 assignment_expr.set_id( id_assignment_expr );
382 logical_or_expr.set_id( id_logical_or_expr );
383 logical_and_expr.set_id( id_logical_and_expr );
384 or_expr.set_id( id_or_expr );
385 xor_expr.set_id( id_xor_expr );
386 and_expr.set_id( id_and_expr );
387 equality_expr.set_id( id_equality_expr );
388 relational_expr.set_id( id_relational_expr );
389 shift_expr.set_id( id_shift_expr );
390 additive_expr.set_id( id_additive_expr );
391 multiplicative_expr.set_id( id_multiplicative_expr );
392 unary_expr.set_id( id_unary_expr );
393 postfix_expr.set_id( id_postfix_expr );
394 primary_expr.set_id( id_primary_expr );
395 lvalue_expr.set_id( id_lvalue_expr );
396 identifier.set_id( id_identifier );
397 constant.set_id( id_constant );
398 string_literal.set_id( id_string_literal );
399 ordered_list.set_id( id_ordered_list );
400 ordered_sequence.set_id( id_ordered_sequence );
401 ordered_item.set_id( id_ordered_item );
402
403 root.set_id( id_root );
404 top.set_id( id_top );
405 function_.set_id( id_function_ );
406 if_.set_id( id_if_ );
407 foreach_.set_id( id_foreach_ );
408 joineach_.set_id( id_joineach_ );
409 error_.set_id( id_error_ );
410 warning_.set_id( id_warning_ );
411 file_.set_id( id_file_ );
412 expr_.set_id( id_expr_ );
413 plain.set_id( id_plain );
414 }
415 };
416
417 parser()
418 {
419 }
420 };
421
422 typedef macro_processor::element element;
423 typedef macro_processor::var_t var_t;
424 typedef macro_processor::context context;
425
426 //! •Ï”‚ª•ÛŽ‚·‚鐔’l‚ÌŽQÆ
427 std::tr1::int64_t get_i( var_t const& var, context const* p_ctx )
428 {
429 if ( var.empty() )
430 {
431 fatal( p_ctx->line, _( "non-value is referred" ) );
432 return 0;
433 }
434 element e = var.front();
435 if ( !e.i )
436 {
437 fatal( p_ctx->line, _( "non-value is referred" ) );
438 return 0;
439 }
440 return e.i.get();
441 }
442 //! •Ï”‚ª•ÛŽ‚·‚镶Žš—ñ‚ÌŽQÆ
443 std::string get_s( var_t const& var, context const* p_ctx )
444 {
445 if ( var.empty() )
446 {
447 return "";
448 }
449 std::string result;
450 for ( var_t::const_iterator iter( var.begin() ), last( var.end() ); iter != last; ++iter )
451 {
452 if ( !iter->s.empty() )
453 {
454 result += iter->s;
455 }
456 else if ( !iter->v.empty() )
457 {
458 result += iter->v;
459 }
460 else if ( iter->i )
461 {
462 result += boost::lexical_cast< std::string >( iter->i.get() );
463 }
464 if ( boost::next( iter ) != last )
465 {
466 result += ",";
467 }
468 }
469 return result;
470 }
471
472 typedef boost::spirit::tree_node< boost::spirit::node_iter_data< text::const_iterator > > tree_node_t;
473 bool eval_node( tree_node_t const& node, context* p_ctx );
474
475 //! ‘ã“üŽ®
476 bool assignment_expr( tree_node_t const& node, context* p_ctx )
477 {
478 // 0 1 2
479 // lhs = rhs
480 if ( eval_node( node.children[0], p_ctx ) )
481 {
482 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
483 std::string name( get_s( lhs, p_ctx ) );
484 if ( eval_node( node.children[2], p_ctx ) )
485 {
486 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
487 var_t old_var( p_ctx->var_map[ name ] );
488 p_ctx->var_map[ name ] = rhs;
489 if ( p_ctx->hook_on_assign != 0 )
490 {
491 ( *p_ctx->hook_on_assign )( node.children[0].value.begin().line(), name, old_var, rhs, p_ctx );
492 }
493 }
494 }
495 return true;
496 }
497
498 //! ˜_—˜aŽ®
499 bool logical_or_expr( tree_node_t const& node, context* p_ctx )
500 {
501 // 0 1 2
502 // lhs || rhs ...
503 bool result = true;
504
505 if ( eval_node( node.children[0], p_ctx ) )
506 {
507 std::size_t const n = node.children.size();
508 if ( n == 1 ) // ¶•Ó‚Ì‚Ý
509 {
510 return true;
511 }
512 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
513 for ( std::size_t i = 2; i < n; i += 2 )
514 {
515 std::tr1::int64_t value = 0;
516 try
517 {
518 value = get_i( lhs, p_ctx );
519 }
520 catch ( expr_error& )
521 {
522 error( node.children[0].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( lhs, p_ctx ) );
523 throw;
524 }
525 if ( value )
526 {
527 break;
528 }
529 result = eval_node( node.children[i], p_ctx );
530 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
531 element e;
532 std::tr1::int64_t value2 = 0;
533 try
534 {
535 value2 = get_i( rhs, p_ctx );
536 }
537 catch ( expr_error& )
538 {
539 error( node.children[i].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( lhs, p_ctx ) );
540 throw;
541 }
542 e.i = ( value || value2 );
543 lhs[0] = e;
544 }
545 p_ctx->stack.push( lhs );
546 }
547 return result;
548 }
549
550 //! ˜_—ÏŽ®
551 bool logical_and_expr( tree_node_t const& node, context* p_ctx )
552 {
553 // 0 1 2
554 // lhs && rhs ...
555 bool result = true;
556
557 if ( eval_node( node.children[0], p_ctx ) )
558 {
559 std::size_t const n = node.children.size();
560 if ( n == 1 ) // ¶•Ó‚Ì‚Ý
561 {
562 return true;
563 }
564 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
565 for ( std::size_t i = 2; i < n; i += 2 )
566 {
567 std::tr1::int64_t value = 0;
568 try
569 {
570 value = get_i( lhs, p_ctx );
571 }
572 catch ( expr_error& )
573 {
574 error( node.children[0].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( lhs, p_ctx ) );
575 throw;
576 }
577 if ( !value )
578 {
579 break;
580 }
581 result = eval_node( node.children[i], p_ctx );
582 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
583 element e;
584 std::tr1::int64_t value2 = 0;
585 try
586 {
587 value2 = get_i( rhs, p_ctx );
588 }
589 catch ( expr_error& )
590 {
591 error( node.children[i].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( lhs, p_ctx ) );
592 throw;
593 }
594 e.i = ( value && value2 );
595 lhs[0] = e;
596 }
597 p_ctx->stack.push( lhs );
598 }
599 return result;
600 }
601
602 //! ƒrƒbƒg˜aŽ®
603 bool or_expr( tree_node_t const& node, context* p_ctx )
604 {
605 // 0 1 2
606 // lhs | rhs ...
607 if ( eval_node( node.children[0], p_ctx ) )
608 {
609 std::size_t const n = node.children.size();
610 if ( n == 1 ) // ¶•Ó‚Ì‚Ý
611 {
612 return true;
613 }
614 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
615 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[i+1], p_ctx ); i += 2 )
616 {
617 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
618 element e;
619 e.i = ( get_i( lhs, p_ctx ) | get_i( rhs, p_ctx ) );
620 lhs[0] = e;
621 }
622 p_ctx->stack.push( lhs );
623 }
624 return true;
625 }
626
627 //! ”r‘¼“I˜_—˜aŽ®
628 bool xor_expr( tree_node_t const& node, context* p_ctx )
629 {
630 // 0 1 2
631 // lhs ^ rhs ...
632 if ( eval_node( node.children[0], p_ctx ) )
633 {
634 std::size_t const n = node.children.size();
635 if ( n == 1 ) // ¶•Ó‚Ì‚Ý
636 {
637 return true;
638 }
639 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
640 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[i+1], p_ctx ); i += 2 )
641 {
642 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
643 element e;
644 e.i = ( get_i( lhs, p_ctx ) ^ get_i( rhs, p_ctx ) );
645 lhs[0] = e;
646 }
647 p_ctx->stack.push( lhs );
648 }
649 return true;
650 }
651
652 //! ƒrƒbƒgÏŽ®
653 bool and_expr( tree_node_t const& node, context* p_ctx )
654 {
655 // 0 1 2
656 // lhs & rhs ...
657 if ( eval_node( node.children[0], p_ctx ) )
658 {
659 std::size_t const n = node.children.size();
660 if ( n == 1 ) // ¶•Ó‚Ì‚Ý
661 {
662 return true;
663 }
664 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
665 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[i+1], p_ctx ); i += 2 )
666 {
667 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
668 element e;
669 e.i = ( get_i( lhs, p_ctx ) & get_i( rhs, p_ctx ) );
670 lhs[0] = e;
671 }
672 p_ctx->stack.push( lhs );
673 }
674 return true;
675 }
676
677 //! “™‰¿Ž®i==A!=j
678 bool equality_expr( tree_node_t const& node, context* p_ctx )
679 {
680 // 0 1 2
681 // lhs op rhs ...
682 if ( eval_node( node.children[0], p_ctx ) )
683 {
684 std::size_t const n = node.children.size();
685 if ( n == 1 ) // ¶•Ó‚Ì‚Ý
686 {
687 return true;
688 }
689 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
690 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[i+1], p_ctx ); i += 2 )
691 {
692 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
693 std::string op( node.children[i].value.begin(), node.children[i].value.end() );
694 std::tr1::int64_t value;
695 if ( op == "==" )
696 {
697 value = ( get_i( lhs, p_ctx ) == get_i( rhs, p_ctx ) );
698 }
699 else
700 {
701 value = ( get_i( lhs, p_ctx ) != get_i( rhs, p_ctx ) );
702 }
703 element e;
704 e.i = value;
705 lhs[0] = e;
706 }
707 p_ctx->stack.push( lhs );
708 }
709 return true;
710 }
711
712 //! ŠÖŒWŽ®i•s“™†j
713 bool relational_expr( tree_node_t const& node, context* p_ctx )
714 {
715 // 0 1 2
716 // lhs op rhs ...
717 if ( eval_node( node.children[0], p_ctx ) )
718 {
719 std::size_t const n = node.children.size();
720 if ( n == 1 ) // ¶•Ó‚Ì‚Ý
721 {
722 return true;
723 }
724 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
725 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[i+1], p_ctx ); i += 2 )
726 {
727 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
728 std::string op( node.children[i].value.begin(), node.children[i].value.end() );
729 std::tr1::int64_t value;
730 if ( op == "<" )
731 {
732 value = ( get_i( lhs, p_ctx ) < get_i( rhs, p_ctx ) );
733 }
734 else if ( op == "<=" )
735 {
736 value = ( get_i( lhs, p_ctx ) <= get_i( rhs, p_ctx ) );
737 }
738 else if ( op == ">" )
739 {
740 value = ( get_i( lhs, p_ctx ) > get_i( rhs, p_ctx ) );
741 }
742 else
743 {
744 value = ( get_i( lhs, p_ctx ) >= get_i( rhs, p_ctx ) );
745 }
746 element e;
747 e.i = value;
748 lhs[0] = e;
749 }
750 p_ctx->stack.push( lhs );
751 }
752 return true;
753 }
754
755 //! ƒVƒtƒgŽ®
756 bool shift_expr( tree_node_t const& node, context* p_ctx )
757 {
758 // 0 1 2
759 // lhs op rhs ...
760 if ( eval_node( node.children[0], p_ctx ) )
761 {
762 std::size_t const n = node.children.size();
763 if ( n == 1 ) // ¶•Ó‚Ì‚Ý
764 {
765 return true;
766 }
767 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
768 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[i+1], p_ctx ); i += 2 )
769 {
770 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
771 std::string op( node.children[i].value.begin(), node.children[i].value.end() );
772 std::tr1::int64_t value = get_i( lhs, p_ctx );
773 std::tr1::int64_t shift = get_i( rhs, p_ctx );
774 if ( shift < 0 ) // •‰‚Ì’l‚ŃVƒtƒg‚µ‚悤‚Æ‚µ‚½
775 {
776 error( node.children[0].value.begin().line(), _( "shift with nagative value `%1%\'" ), shift );
777 }
778 if ( shift > 64 )
779 {
780 error( node.children[0].value.begin().line(), _( "shift with too large value `%1%\'" ), shift );
781 }
782 if ( op == "<<" )
783 {
784 if ( value < 0 )
785 { // •‰‚Ì’l‚̃Vƒtƒg‚Í‚Å‚«‚È‚¢
786 error( node.children[0].value.begin().line(), _( "negative value `%1%\' is shift" ), value );
787 }
788 else if ( shift != 0 && static_cast< std::tr1::int64_t >( static_cast< std::tr1::uint64_t >( 1 ) << ( 63 - shift ) ) <= value )
789 { // ƒVƒtƒg‚ÌŒ‹‰Ê‚ª•‰‚É‚È‚é
790 error( node.children[0].value.begin().line(), _( "shift with too large value `%1%\'" ), shift );
791 }
792 value = value << shift;
793 }
794 else
795 {
796 if ( value < 0 ) // ‹­§“I‚ÉŽZpƒVƒtƒg‚³‚¹‚é
797 {
798 value = static_cast< std::tr1::int64_t >( ( static_cast< std::tr1::uint64_t >( value ) >> shift ) | ( ~static_cast< std::tr1::uint64_t >( 0 ) << shift ) );
799 }
800 else
801 {
802 value = value >> shift;
803 }
804 }
805 element e;
806 e.i = value;
807 lhs[0] = e;
808 }
809 p_ctx->stack.push( lhs );
810 }
811 return true;
812 }
813
814 //! ‰ÁŒ¸Ž®
815 bool additive_expr( tree_node_t const& node, context* p_ctx )
816 {
817 // 0 1 2
818 // lhs op rhs ...
819 if ( eval_node( node.children[0], p_ctx ) )
820 {
821 std::size_t const n = node.children.size();
822 if ( n == 1 ) // ¶•Ó‚Ì‚Ý
823 {
824 return true;
825 }
826 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
827 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[i+1], p_ctx ); i += 2 )
828 {
829 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
830 std::string op( node.children[i].value.begin(), node.children[i].value.end() );
831 std::tr1::int64_t x = get_i( lhs, p_ctx );
832 std::tr1::int64_t y = get_i( rhs, p_ctx );
833 element e;
834 if ( op == "+" )
835 {
836 if ( ( y > 0 && ( std::numeric_limits< std::tr1::int64_t >::max() - y ) < x )
837 || ( y < 0 && ( std::numeric_limits< std::tr1::int64_t >::min() - y ) > x ) )
838 {
839 error( node.children[0].value.begin().line(), _( "overflow at `%1%\'" ), get_s( lhs, p_ctx ) + "+" + get_s( rhs, p_ctx ) );
840 // e.i ‚É’l‚̓Zƒbƒg‚³‚ê‚È‚¢
841 }
842 else
843 {
844 e.i = x + y;
845 }
846 }
847 else // "-"
848 {
849 if ( ( y < 0 && ( std::numeric_limits< std::tr1::int64_t >::max() + y ) < x )
850 || ( y > 0 && ( std::numeric_limits< std::tr1::int64_t >::min() + y ) > x ) )
851 {
852 error( node.children[0].value.begin().line(), _( "overflow at `%1%\'" ), get_s( lhs, p_ctx ) + "-" + get_s( rhs, p_ctx ) );
853 // e.i ‚É’l‚̓Zƒbƒg‚³‚ê‚È‚¢
854 }
855 else
856 {
857 e.i = x - y;
858 }
859 }
860 lhs[0] = e;
861 }
862 p_ctx->stack.push( lhs );
863 }
864 return true;
865 }
866
867 //! æœŽ®
868 bool multiplicative_expr( tree_node_t const& node, context* p_ctx )
869 {
870 // 0 1 2
871 // lhs op rhs ...
872 if ( eval_node( node.children[0], p_ctx ) )
873 {
874 std::size_t const n = node.children.size();
875 if ( n == 1 ) // ¶•Ó‚Ì‚Ý
876 {
877 return true;
878 }
879 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
880 for ( std::size_t i = 1; ( i < n ) && eval_node( node.children[i+1], p_ctx ); i += 2 )
881 {
882 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
883 std::string op( node.children[i].value.begin(), node.children[i].value.end() );
884 std::tr1::int64_t x = get_i( lhs, p_ctx );
885 std::tr1::int64_t y = get_i( rhs, p_ctx );
886 element e;
887 if ( op == "*" )
888 {
889 if ( ( x == 0 ) || ( y == 0 ) )
890 {
891 e.i = 0;
892 }
893 else if ( ( ( x < 0 ) == ( y < 0 ) ) && ( std::numeric_limits< std::tr1::int64_t >::max() / y < x )
894 || ( ( x < 0 ) != ( y < 0 ) ) && ( std::numeric_limits< std::tr1::int64_t >::min() / y > x ) )
895 {
896 error( node.children[0].value.begin().line(), _( "overflow at `%1%\'" ), get_s( lhs, p_ctx ) + "*" + get_s( rhs, p_ctx ) );
897 // e.i ‚É’l‚̓Zƒbƒg‚³‚ê‚È‚¢
898 }
899 else
900 {
901 e.i = x * y;
902 }
903 }
904 else
905 {
906 if ( y == 0 )
907 {
908 error( node.value.begin().line(), _( "devide by zero" ) );
909 // e.i ‚É‚Í’l‚ªƒZƒbƒg‚³‚ê‚È‚¢
910 }
911 else
912 {
913 std::tr1::int64_t value;
914 // –{“–‚Í‚±‚±‚ňê•û‚̃Iƒyƒ‰ƒ“ƒh‚ª•‰‚̏ꍇ‚̏ˆ—‚ðs‚¤•K—v‚ª‚ ‚éB
915 // ‚»‚ñ‚ȕςȏˆ—Œn‚ÍŽÀŽ¿“I‚É‚È‚¢‚Ì‚Å•ú’u
916 if ( op == "/" )
917 {
918 value = ( x / y );
919 }
920 else // "%"
921 {
922 value = ( x % y );
923 }
924 e.i = value;
925 }
926 }
927 lhs[0] = e;
928 }
929 p_ctx->stack.push( lhs );
930 }
931 return true;
932 }
933
934 //! ’P€Ž®iŒã’uŽ®A’P€‰‰ŽZŽq ˆêŽŸŽ®j
935 bool unary_expr( tree_node_t const& node, context* p_ctx )
936 {
937 // 0 1..n-2 n-1
938 // op ...... primary_expr
939 if ( eval_node( node.children[ node.children.size() - 1 ], p_ctx ) )
940 {
941 std::size_t const n = node.children.size();
942 if ( n == 1 ) // ˆêŽŸŽ®‚Ì‚Ý
943 {
944 return true;
945 }
946 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
947 for ( long i = static_cast< long >( n ) - 2, t = 0; i >= 0 && eval_node( node.children[i+1], p_ctx ); i-- )
948 {
949 std::string op( node.children[i].value.begin(), node.children[i].value.end() );
950 element e;
951 std::tr1::int64_t value = 0;
952 if ( op != "@" )
953 {
954 try
955 {
956 value = get_i( expr, p_ctx );
957 }
958 catch ( expr_error& )
959 {
960 error( node.children[0].value.begin().line(), _( "`%1%\' is undefined" ), get_s( expr, p_ctx ) );
961 throw;
962 }
963 if ( op == "+" )
964 {
965 e.i = +value;
966 }
967 else if ( op == "-" )
968 {
969 if ( value == std::numeric_limits< std::tr1::int64_t >::min() )
970 {
971 error( node.children[0].value.begin().line(), _( "overflow at `%1%\'" ), "-" + get_s( expr, p_ctx ) );
972 // e.i ‚É’l‚̓Zƒbƒg‚³‚ê‚È‚¢
973 }
974 else
975 {
976 e.i = -value;
977 }
978 }
979 else if ( op == "~" )
980 {
981 e.i = ~value;
982 }
983 else if ( op == "!" )
984 {
985 e.i = !value;
986 }
987 value = *e.i;
988 }
989 else // op == "@" i’l‘®« ¨ •¶Žš—ñ‘®«j
990 {
991 if ( expr.front().i )
992 {
993 e.s = boost::lexical_cast< std::string >( *expr.front().i );
994 }
995 else
996 {
997 e.s = expr.front().v;
998 }
999 }
1000 expr[ 0 ] = e; // ‰‰ŽZŒ‹‰Ê‚ð—ݐς·‚é
1001 if ( i == t )
1002 {
1003 break;
1004 }
1005 }
1006 p_ctx->stack.push( expr );
1007 }
1008 return true;
1009 }
1010
1011 //! Œã’uŽ®iŠÖ”ŒÄ‚яo‚µAˆêŽŸŽ®j
1012 bool postfix_expr( tree_node_t const& node, context* p_ctx )
1013 {
1014 // 0 1 2 3 4..2+2*n-1 2+2*n 2+2*n+1
1015 // identifier ( arg0 , .......... argn )
1016 // primary_expr
1017 if ( eval_node( node.children[0], p_ctx ) )
1018 {
1019 if ( node.children.size() > 1 ) // ŠÖ”‚̌Ăяo‚µ
1020 {
1021 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1022 std::string func_name( get_s( ident, p_ctx ) );
1023 std::map< std::string, macro_processor::func_t >::const_iterator iter( p_ctx->func_map.find( func_name ) );
1024 if ( iter == p_ctx->func_map.end() ) // ‚»‚ñ‚Ȋ֐”‚Í‚È‚¢
1025 {
1026 error( node.children[0].value.begin().line(), _( "function `%1%\' is undefined" ), func_name );
1027 p_ctx->stack.push( var_t() );
1028 }
1029 else // ŠÖ”‚ðŒÄ‚яo‚·
1030 {
1031 std::vector< var_t > arg_list;
1032 for ( std::size_t i = 0, n = node.children.size() - 1; 2 + 2*i < n; i++ )
1033 {
1034 if ( eval_node( node.children[2 + 2*i], p_ctx ) )
1035 {
1036 var_t arg( p_ctx->stack.top() ); p_ctx->stack.pop();
1037 arg_list.push_back( arg );
1038 }
1039 }
1040 var_t result;
1041 if ( iter->second.f != 0 ) // ‘g‚ݍž‚݊֐”
1042 {
1043 result = ( *iter->second.f )( node.children[0].value.begin().line(), arg_list, p_ctx );
1044 }
1045 else if ( iter->second.node != 0 ) // ƒ†[ƒU[’è‹`ŠÖ”
1046 {
1047 // ARGC
1048 {
1049 element e;
1050 e.i = static_cast< std::tr1::int64_t >( arg_list.size() + 1 );
1051 p_ctx->var_map[ "ARGC" ] = var_t( 1, e );
1052 }
1053
1054 // ARGV
1055 {
1056 element e;
1057 e.s = func_name;
1058 p_ctx->var_map[ "ARGV[0]" ] = var_t( 1, e );
1059
1060 std::size_t n = arg_list.size() + 1;
1061 for ( std::size_t i = 1; i < n; i++ )
1062 {
1063 std::string argv_i = boost::str( boost::format( "ARGV[%d]" ) % i );
1064 p_ctx->var_map[ argv_i ] = arg_list[ i - 1 ];
1065 }
1066
1067 std::string argv_n = boost::str( boost::format( "ARGV[%d]" ) % n );
1068 p_ctx->var_map[ argv_n ] = var_t();
1069 }
1070
1071 tree_node_t const* func_body_node = reinterpret_cast< tree_node_t const* >( iter->second.node );
1072 if ( !eval_node( *func_body_node, p_ctx ) )
1073 {
1074 // ŒÄ‚яo‚µŽ¸”s
1075 p_ctx->stack.push( result );
1076 return false;
1077 }
1078
1079 result = p_ctx->var_map[ "RESULT" ];
1080 }
1081 p_ctx->stack.push( result );
1082 }
1083 }
1084 }
1085 return true;
1086 }
1087
1088 //! ˆêŽŸŽ®i¶•Ó’lŽ®A(Ž®)j
1089 bool primary_expr( tree_node_t const& node, context* p_ctx )
1090 {
1091 bool result = true;
1092
1093 if ( node.children.size() == 1 )
1094 {
1095 result = eval_node( node.children[0], p_ctx );
1096 if ( node.children[0].value.id() == parser::id_lvalue_expr )
1097 {
1098 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1099 std::string name( get_s( ident, p_ctx ) );
1100 var_t value( p_ctx->var_map[ name ] );
1101 p_ctx->stack.push( value );
1102 }
1103 }
1104 else
1105 {
1106 // 0 1 2
1107 // ( expression )
1108 result = eval_node( node.children[1], p_ctx );
1109 }
1110 return result;
1111 }
1112
1113 //! ¶•Ó’lŽ®i•Ï”A”z—ñ•Ï”j
1114 bool lvalue_expr( tree_node_t const& node, context* p_ctx )
1115 {
1116 // 0 1 2 3
1117 // identifier
1118 // identifier [ expression ]
1119 if ( eval_node( node.children[0], p_ctx ) )
1120 {
1121 if ( ( node.children.size() > 1 ) && eval_node( node.children[2], p_ctx ) )
1122 {
1123 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
1124 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1125 element e;
1126 std::string subscript;
1127 try
1128 {
1129 std::tr1::int64_t i = get_i( expr, p_ctx );
1130 subscript = boost::lexical_cast< std::string >( i );
1131 }
1132 catch ( expr_error& )
1133 {
1134 subscript = get_s( expr, p_ctx );
1135 error( node.children[0].value.begin().line(), _( "`%1%\' does not have a value" ), subscript );
1136 throw;
1137 }
1138 e.s = ( boost::format( "%s[%s]" ) % get_s( ident, p_ctx ) % subscript ).str();
1139 p_ctx->stack.push( var_t( 1, e ) );
1140 }
1141 }
1142 return true;
1143 }
1144
1145 //! Ž¯•ÊŽq
1146 bool identifier( tree_node_t const& node, context* p_ctx )
1147 {
1148 element e;
1149 std::string ident( node.children[0].value.begin(), node.children[0].value.end() );
1150 std::string::size_type n = ident.find_first_not_of( " \t\r\n" );
1151 e.s = ident.c_str() + n;
1152 p_ctx->stack.push( var_t( 1, e ) );
1153 return true;
1154 }
1155
1156 //! ®”’萔
1157 bool constant( tree_node_t const& node, context* p_ctx )
1158 {
1159 element e;
1160 e.s.assign( node.children[0].value.begin(), node.children[0].value.end() );
1161 std::istringstream iss( e.s );
1162 iss.unsetf( std::ios_base::basefield );
1163 std::tr1::int64_t value;
1164 iss >> value;
1165 if ( iss.bad() )
1166 {
1167 error( node.children[0].value.begin().line(), _( "overflow at `%1%\'" ), e.s );
1168 }
1169 e.i = value;
1170 p_ctx->stack.push( var_t( 1, e ) );
1171 return true;
1172 }
1173
1174 //! •¶Žš—ñ
1175 bool string_literal( tree_node_t const& node, context* p_ctx )
1176 {
1177 // 0 1..n-2 n-1
1178 // " ...... "
1179 element e;
1180 // ‚±‚±‚ō\•¶ƒGƒ‰[—áŠO‚ɂȂ邱‚Æ‚Í‚ ‚蓾‚È‚¢Bi\•¶‰ðÍŒã‚Ȃ̂Łj
1181 e.s = expand_quote( std::string( node.children[0].value.begin(), node.children[0].value.end() ) );
1182 p_ctx->stack.push( var_t( 1, e ) );
1183 return true;
1184 }
1185
1186 //! ‡˜•t‚«ƒŠƒXƒg
1187 bool ordered_list( tree_node_t const& node, context* p_ctx )
1188 {
1189 // 0 1 2 n-1
1190 // { ordered_sequence ; ... }
1191 // { ordered_item ; ... }
1192 if ( node.children.size() < 3 )
1193 {
1194 p_ctx->stack.push( var_t() );
1195 }
1196 else if ( eval_node( node.children[1], p_ctx ) )
1197 {
1198 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
1199 for ( std::size_t i = 1, n = node.children.size(); ( i+2 < n ) && eval_node( node.children[i+2], p_ctx ); i += 2 )
1200 {
1201 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
1202 std::copy( rhs.begin(), rhs.end(), std::back_inserter( lhs ) );
1203 }
1204 p_ctx->stack.push( lhs );
1205 }
1206 return true;
1207 }
1208
1209 //! ‡˜•t‚«ƒŠƒXƒgi“™·”—ñj
1210 bool ordered_sequence( tree_node_t const& node, context* p_ctx )
1211 {
1212 // 0 1 2 3 4 5 6
1213 // int , int , ... , int
1214 if ( eval_node( node.children[0], p_ctx ) )
1215 {
1216 var_t first( p_ctx->stack.top() ); p_ctx->stack.pop();
1217 if ( eval_node( node.children[2], p_ctx ) )
1218 {
1219 var_t second( p_ctx->stack.top() ); p_ctx->stack.pop();
1220 if ( eval_node( node.children[6], p_ctx ) )
1221 {
1222 var_t last( p_ctx->stack.top() ); p_ctx->stack.pop();
1223 std::tr1::int64_t a0 = get_i( first, p_ctx );
1224 std::tr1::int64_t a1 = get_i( second, p_ctx );
1225 std::tr1::int64_t an = get_i( last, p_ctx );
1226 std::tr1::int64_t d = a1 - a0;
1227 if ( ( an - a0 ) % d != 0 )
1228 {
1229 error( node.children[0].value.begin().line(), _( "illegal arithmetic sequence" ) );
1230 }
1231 else
1232 {
1233 for ( std::tr1::int64_t i = a1, t = an + d; i != t; i += d )
1234 {
1235 element e;
1236 e.i = i;
1237 first.push_back( e );
1238 }
1239 first[1].s = second[0].s;
1240 first.back().s = last[0].s;
1241 }
1242 p_ctx->stack.push( first );
1243 }
1244 }
1245 }
1246 return true;
1247 }
1248
1249 //! ‡˜•t‚«ƒŠƒXƒgi—ñ‹Lj
1250 bool ordered_item( tree_node_t const& node, context* p_ctx )
1251 {
1252 // 0 1 2
1253 // int , int ...
1254 if ( eval_node( node.children[0], p_ctx ) )
1255 {
1256 var_t lhs( p_ctx->stack.top() ); p_ctx->stack.pop();
1257 for ( std::size_t i = 1, n = node.children.size(); ( i < n ) && eval_node( node.children[i+1], p_ctx ); i += 2 )
1258 {
1259 var_t rhs( p_ctx->stack.top() ); p_ctx->stack.pop();
1260 lhs.push_back( rhs[0] );
1261 }
1262 p_ctx->stack.push( lhs );
1263 }
1264 return true;
1265 }
1266
1267 //! ƒgƒbƒvƒŒƒxƒ‹
1268 bool top( tree_node_t const& node, context* p_ctx )
1269 {
1270 bool result = true;
1271
1272 for ( std::size_t i = 0, n = node.children.size(); i < n; i++ )
1273 {
1274 for ( text::const_iterator iter( node.children[i].value.begin() ), last( node.children[i].value.end() );
1275 iter != last;
1276 ++iter )
1277 {
1278 char c = *iter;
1279 if ( !std::isspace( static_cast< unsigned char >( c ) ) )
1280 {
1281 break;
1282 }
1283 if ( c != '\n' )
1284 {
1285 p_ctx->target_file << c;
1286 }
1287 }
1288 result &= eval_node( node.children[i], p_ctx );
1289 }
1290 return result;
1291 }
1292
1293 //! $FUNCTION–½—ß
1294 bool function_( tree_node_t const& node, context* p_ctx )
1295 {
1296 bool result = true;
1297
1298 if ( node.children.empty() )
1299 {
1300 fatal( node.value.begin().line(), "no body of %1%", "'FUNCTION'" );
1301 }
1302
1303 if ( p_ctx->in_function )
1304 {
1305 fatal( node.value.begin().line(), "function cannot be nested" );
1306 }
1307 p_ctx->in_function = true;
1308
1309 // 0 1 2 3 4
1310 // $FUNCTION identifier $ top $END$
1311 if ( eval_node( node.children[1], p_ctx ) ) // identifier
1312 {
1313 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1314 macro_processor::func_t func;
1315 func.name = get_s( ident, p_ctx );
1316 func.node = &node.children[3];
1317 func.f = 0; // ‘g‚ݍž‚݊֐”‚Å‚Í‚È‚¢‚Ì‚Å
1318 p_ctx->func_map[ func.name ] = func;
1319 }
1320 else
1321 {
1322 result = false;
1323 }
1324 p_ctx->in_function = false;
1325 return result;
1326 }
1327
1328 //! $IF–½—ß
1329 bool if_( tree_node_t const& node, context* p_ctx )
1330 {
1331 bool result = true;
1332
1333 if ( node.children.empty() )
1334 {
1335 fatal( node.value.begin().line(), "no body of %1%", "'IF' or 'ELSE'" );
1336 }
1337
1338 // 0 1 2 3 4 5 6
1339 // $IF expression $ top $END$
1340 // $IF expression $ top $ELSE$ top $END$
1341 if ( eval_node( node.children[1], p_ctx ) ) // expression
1342 {
1343 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
1344 bool cond = false;
1345 try
1346 {
1347 cond = !!get_i( expr, p_ctx );
1348 }
1349 catch ( expr_error& )
1350 {
1351 error( node.children[0].value.begin().line(), _( "`%1%\' does not have a value" ), get_s( expr, p_ctx ) );
1352 throw;
1353 }
1354 if ( cond ) // $IF expr$
1355 {
1356 result &= eval_node( node.children[3], p_ctx ); // top
1357 }
1358 else if ( node.children.size() == 7 ) // $ELSE$
1359 {
1360 result &= eval_node( node.children[5], p_ctx ); // top
1361 }
1362 }
1363 return result;
1364 }
1365
1366 //! FOREACH–½—ß
1367 bool foreach_( tree_node_t const& node, context* p_ctx )
1368 {
1369 bool result = true;
1370
1371 if ( node.children.empty() )
1372 {
1373 fatal( node.value.begin().line(), "no body of %1%", "'FOREACH'" );
1374 }
1375
1376 // 0 1 2 3 4 5
1377 // $FOREACH identifier order_list $ top $END$
1378 if ( eval_node( node.children[1], p_ctx ) ) // identifier
1379 {
1380 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1381 if ( eval_node( node.children[2], p_ctx ) ) // order_list
1382 {
1383 var_t order_list( p_ctx->stack.top() ); p_ctx->stack.pop();
1384 if ( !order_list.empty() && order_list[0].i )
1385 {
1386 for ( var_t::const_iterator iter( order_list.begin() ), last( order_list.end() ); iter != last; ++iter )
1387 {
1388 p_ctx->var_map[ get_s( ident, p_ctx ) ] = var_t( 1, *iter );
1389 result &= eval_node( node.children[4], p_ctx ); // top
1390 }
1391 }
1392 }
1393 }
1394 return result;
1395 }
1396
1397 //! $JOINEACH–½—ß
1398 bool joineach_( tree_node_t const& node, context* p_ctx )
1399 {
1400 bool result = true;
1401
1402 if ( node.children.empty() )
1403 {
1404 fatal( node.value.begin().line(), "no body of %1%", "'JOINEACH'" );
1405 }
1406
1407 // 0 1 2 3 4 5 6
1408 // $JOINEACH identifier order_list delimitor $ top $END$
1409 if ( eval_node( node.children[1], p_ctx ) ) // identifier
1410 {
1411 var_t ident( p_ctx->stack.top() ); p_ctx->stack.pop();
1412 if ( eval_node( node.children[2], p_ctx ) ) // order_list
1413 {
1414 var_t order_list( p_ctx->stack.top() ); p_ctx->stack.pop();
1415 if ( !order_list.empty() && order_list[0].i )
1416 {
1417 if ( eval_node( node.children[3], p_ctx ) ) // delimitor
1418 {
1419 var_t delimitor( p_ctx->stack.top() ); p_ctx->stack.pop();
1420 for ( var_t::const_iterator iter( order_list.begin() ), last( order_list.end() ); iter != last; ++iter )
1421 {
1422 p_ctx->var_map[ get_s( ident, p_ctx ) ] = var_t( 1, *iter );
1423 result &= eval_node( node.children[5], p_ctx ); // top
1424 if ( boost::next( iter ) != last )
1425 {
1426 p_ctx->target_file << get_s( delimitor, p_ctx );
1427 }
1428 }
1429 }
1430 }
1431 }
1432 }
1433 return result;
1434 }
1435
1436 //! $ERROR–½—ß
1437 bool error_( tree_node_t const& node, context* p_ctx )
1438 {
1439 // 0 1 2 3 4
1440 // $ERROR$ top $END$
1441 // $WARNING$ top $END$
1442 // $ERROR expr $ top $END$
1443 // $WARNING expr $ top $END$
1444
1445 if ( node.children.empty() )
1446 {
1447 fatal( node.value.begin().line(), "no body of %1%", "'ERROR' or 'WARNING'" );
1448 }
1449
1450 output_file of = p_ctx->target_file;
1451 p_ctx->target_file = output_file( "stderr", std::ios_base::out ); // o—͐æ‚ðˆêŽž“I‚É•W€ƒGƒ‰[o—͂ɐ؂è‘Ö‚¦‚éB
1452
1453 bool is_error = ( static_cast< parser::rule_id_t >( node.value.id().to_long() ) == parser::id_error_ );
1454
1455 p_ctx->target_file << get_program_name() << ':';
1456
1457 bool has_expr = ( node.children.size() > 3 );
1458
1459 if ( has_expr && eval_node( node.children[1], p_ctx ) ) // expr
1460 {
1461 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
1462 if ( !expr.empty() )
1463 {
1464 if ( !expr.front().s.empty() )
1465 {
1466 p_ctx->target_file << expr.front().s << ':';
1467 }
1468 if ( expr.front().i )
1469 {
1470 p_ctx->target_file << expr.front().i.get() << ':';
1471 }
1472 }
1473 }
1474
1475 p_ctx->target_file << ( is_error ? " error: " : " warning: " );
1476
1477 bool result = eval_node( node.children[has_expr ? 3 : 1], p_ctx ); // top
1478 p_ctx->target_file << '\n';
1479 p_ctx->target_file = of;
1480
1481 if ( is_error )
1482 {
1483 increment_error_count(); // errorŠÖ”‚ðŽg‚í‚È‚¢‚̂ŁA–¾Ž¦“I‚ɃGƒ‰[ƒJƒEƒ“ƒg‚𑀍삷‚éB
1484 }
1485 return result;
1486 }
1487
1488 //! $WARNING–½—ß
1489 bool warning_( tree_node_t const& node, context* p_ctx )
1490 {
1491 return error_( node, p_ctx );
1492 }
1493
1494 //! $FILE–½—ß
1495 bool file_( tree_node_t const& node, context* p_ctx )
1496 {
1497 // 0 1 2
1498 // $FILE string-literal $
1499 if ( eval_node( node.children[1], p_ctx ) ) // string-literal
1500 {
1501 var_t filename( p_ctx->stack.top() ); p_ctx->stack.pop();
1502 p_ctx->target_file << '\n';
1503 p_ctx->target_file = output_file( get_s( filename, p_ctx ), std::ios_base::out );
1504 }
1505 return true;
1506 }
1507
1508 //! Ž®
1509 bool expr_( tree_node_t const& node, context* p_ctx )
1510 {
1511 // 0 1 2
1512 // $ expression $
1513 if ( eval_node( node.children[1], p_ctx ) ) // expression
1514 {
1515 if ( node.children[1].value.id().to_long() == parser::id_expression )
1516 {
1517 var_t expr( p_ctx->stack.top() ); p_ctx->stack.pop();
1518 p_ctx->target_file << get_s( expr, p_ctx );
1519 }
1520 }
1521 return true;
1522 }
1523
1524 // ƒ}ƒNƒ–½—߈ȊO
1525 bool plain( tree_node_t const& node, context* p_ctx )
1526 {
1527 std::string buf;
1528 buf.reserve( node.children[0].value.end() - node.children[0].value.begin() );
1529 for ( text::const_iterator iter( node.children[0].value.begin() ), last( node.children[0].value.end() ); iter != last; ++iter )
1530 {
1531 if ( *iter == '$' )
1532 {
1533 ++iter;
1534 }
1535 switch ( char c = *iter )
1536 {
1537 case '\r':
1538 case '\n':
1539 break;
1540 default:
1541 buf.push_back( c );
1542 break;
1543 }
1544 }
1545 p_ctx->target_file << buf;
1546 return true;
1547 }
1548
1549 // \•¶–Ø‚ÌŠeƒm[ƒh‚Ì•]‰¿
1550 bool eval_node( tree_node_t const& node, context* p_ctx )
1551 {
1552 bool result = true;
1553 if ( p_ctx != 0 )
1554 {
1555 p_ctx->line = node.value.begin().line();
1556 }
1557
1558#if defined( _MSC_VER ) && DEBUG_TRACE
1559 ::OutputDebugString( ( boost::format( "%s:%d:%s\n" )
1560 % node.children[0].value.begin().line().file
1561 % node.children[0].value.begin().line().line
1562 % std::string( node.children[0].value.begin(), node.children[0].value.end() )
1563 ).str().c_str() );
1564#endif
1565
1566 switch ( parser::rule_id_t id = static_cast< parser::rule_id_t >( node.value.id().to_long() ) )
1567 {
1568 case parser::id_expression:
1569 result = eval_node( node.children[0], p_ctx );
1570 break;
1571 case parser::id_assignment_expr:
1572 result = assignment_expr( node, p_ctx );
1573 break;
1574 case parser::id_logical_or_expr:
1575 result = logical_or_expr( node, p_ctx );
1576 break;
1577 case parser::id_logical_and_expr:
1578 result = logical_and_expr( node, p_ctx );
1579 break;
1580 case parser::id_or_expr:
1581 result = or_expr( node, p_ctx );
1582 break;
1583 case parser::id_xor_expr:
1584 result = xor_expr( node, p_ctx );
1585 break;
1586 case parser::id_and_expr:
1587 result = and_expr( node, p_ctx );
1588 break;
1589 case parser::id_equality_expr:
1590 result = equality_expr( node, p_ctx );
1591 break;
1592 case parser::id_relational_expr:
1593 result = relational_expr( node, p_ctx );
1594 break;
1595 case parser::id_shift_expr:
1596 result = shift_expr( node, p_ctx );
1597 break;
1598 case parser::id_additive_expr:
1599 result = additive_expr( node, p_ctx );
1600 break;
1601 case parser::id_multiplicative_expr:
1602 result = multiplicative_expr( node, p_ctx );
1603 break;
1604 case parser::id_unary_expr:
1605 result = unary_expr( node, p_ctx );
1606 break;
1607 case parser::id_postfix_expr:
1608 result = postfix_expr( node, p_ctx );
1609 break;
1610 case parser::id_primary_expr:
1611 result = primary_expr( node, p_ctx );
1612 break;
1613 case parser::id_lvalue_expr:
1614 result = lvalue_expr( node, p_ctx );
1615 break;
1616 case parser::id_identifier:
1617 result = identifier( node, p_ctx );
1618 break;
1619 case parser::id_constant:
1620 result = constant( node, p_ctx );
1621 break;
1622 case parser::id_string_literal:
1623 result = string_literal( node, p_ctx );
1624 break;
1625 case parser::id_ordered_list:
1626 result = ordered_list( node, p_ctx );
1627 break;
1628 case parser::id_ordered_sequence:
1629 result = ordered_sequence( node, p_ctx );
1630 break;
1631 case parser::id_ordered_item:
1632 result = ordered_item( node, p_ctx );
1633 break;
1634 case parser::id_root:
1635 result = eval_node( node.children[0], p_ctx );
1636 break;
1637 case parser::id_top:
1638 result = top( node, p_ctx );
1639 break;
1640 case parser::id_function_:
1641 result = function_( node, p_ctx );
1642 break;
1643 case parser::id_if_:
1644 result = if_( node, p_ctx );
1645 break;
1646 case parser::id_foreach_:
1647 result = foreach_( node, p_ctx );
1648 break;
1649 case parser::id_joineach_:
1650 result = joineach_( node, p_ctx );
1651 break;
1652 case parser::id_error_:
1653 result = error_( node, p_ctx );
1654 break;
1655 case parser::id_warning_:
1656 result = warning_( node, p_ctx );
1657 break;
1658 case parser::id_file_:
1659 result = file_( node, p_ctx );
1660 break;
1661 case parser::id_expr_:
1662 result = expr_( node, p_ctx );
1663 break;
1664 case parser::id_plain:
1665 result = plain( node, p_ctx );
1666 break;
1667 default:
1668 result = false;
1669 break;
1670 }
1671 return result;
1672 }
1673
1674 bool eval_text( text::const_iterator first, text::const_iterator last, context* p_ctx )
1675 {
1676 using namespace boost::spirit;
1677 typedef text::const_iterator iterator_t;
1678 tree_parse_info< iterator_t, node_iter_data_factory<> > info;
1679 info = pt_parse( first, last, parser(), space_p, node_iter_data_factory<>() );
1680 if ( info.full && !info.trees.empty() )
1681 {
1682 bool result;
1683 if ( info.length <= 0 )
1684 {
1685 result = true;
1686 }
1687 else
1688 {
1689 result = eval_node( info.trees[0], p_ctx );
1690 }
1691 return result;
1692 }
1693 else
1694 {
1695 fatal( info.stop.line(), _( "syntax error" ) );
1696 }
1697 return false;
1698 }
1699
1700 }
1701
1702 std::tr1::int64_t macro_processor::to_integer( var_t const& var, context const* p_ctx )
1703 {
1704 return get_i( var, p_ctx );
1705 }
1706
1707 std::string macro_processor::to_string( var_t const& var, context const* p_ctx )
1708 {
1709 return get_s( var, p_ctx );
1710 }
1711
1712 macro_processor::macro_processor( hook_t hook_on_assign )
1713 : p_ctx_( new context( hook_on_assign ) )
1714 {
1715 }
1716
1717 macro_processor::macro_processor( macro_processor const& other )
1718 : p_ctx_( new context( *other.p_ctx_ ) )
1719 {
1720 }
1721
1722 macro_processor::macro_processor( text const& in, hook_t hook_on_assign )
1723 : p_ctx_( new context( hook_on_assign ) )
1724 {
1725 evaluate( in );
1726 }
1727
1728 macro_processor::~macro_processor()
1729 {
1730 delete p_ctx_;
1731 p_ctx_ = 0;
1732 }
1733
1734 macro_processor& macro_processor::operator=( macro_processor const& other )
1735 {
1736 macro_processor t( *this );
1737 swap( t );
1738 return *this;
1739 }
1740
1741 void macro_processor::swap( macro_processor& other )
1742 {
1743 std::swap( p_ctx_, other.p_ctx_ );
1744 }
1745
1746 void macro_processor::evaluate( text const& in )
1747 {
1748 try
1749 {
1750 for ( func_t const* p_bf = builtin_function_table; !p_bf->name.empty(); p_bf++ )
1751 {
1752 p_ctx_->func_map[ p_bf->name ] = *p_bf;
1753 }
1754 if ( !eval_text( in.begin(), in.end(), p_ctx_ ) )
1755 {
1756 fatal( _( "macro processing error" ) );
1757 }
1758 }
1759 catch ( expr_error& )
1760 {
1761 fatal( _( "macro processing error" ) );
1762 }
1763 }
1764
1765 void macro_processor::set_var( std::string const& name, var_t const& value )
1766 {
1767#if defined( _MSC_VER ) && /* DEBUG_TRACE */ 1
1768 std::string s( "$" + name + " = " + get_s( value, p_ctx_ ) + "$" );
1769 if ( !value.empty() && value[0].i )
1770 {
1771 s += "(" + boost::lexical_cast< std::string >( get_i( value, p_ctx_ ) ) + ")";
1772 }
1773 s += "\n";
1774 ::OutputDebugString( s.c_str() );
1775#endif
1776 p_ctx_->var_map[ name ] = value;
1777 }
1778
1779 void macro_processor::set_var( std::string const& name, long name2, var_t const& value )
1780 {
1781 set_var( ( boost::format( "%s[%d]" ) % name % name2 ).str(), value );
1782 }
1783
1784 macro_processor::var_t const& macro_processor::get_var( std::string const& name ) const
1785 {
1786 return p_ctx_->var_map[ name ];
1787 }
1788
1789 macro_processor::var_t const& macro_processor::get_var( std::string const& name, long name2 ) const
1790 {
1791 return get_var( ( boost::format( "%s[%d]" ) % name % name2 ).str() );
1792 }
1793
1794 /*!
1795 * \brief ƒRƒƒ“ƒg‚̏œ‹Ž
1796 * \param[in] first ˆ—‘ΏۃV[ƒPƒ“ƒX‚̐擪ˆÊ’u
1797 * \param[in] last ˆ—‘ΏۃV[ƒPƒ“ƒX‚̏I’[ˆÊ’u‚ÌŽŸ
1798 * \param[out] result ˆ—Œ‹‰Ê‚ÌŠi”[æ
1799 * \return ˆ—Š®—¹Œã‚Ì result ‚Ì’l
1800 *
1801 * u$ + ‹ó”’—Þ•¶Žšv‚ÅŽn‚Ü‚èA‰üs‚ŏI‚í‚éƒRƒƒ“ƒg‚ðœ‹Ž‚µ‚Ü‚·B
1802 */
1803 void macro_processor::remove_comment( text const& in, text& out )
1804 {
1805 text::const_iterator first( in.begin() ), last( in.end() );
1806 std::back_insert_iterator< text > result( std::back_inserter( out ) );
1807 out.set_line( first.line().file, first.line().line );
1808
1809 for ( text::const_iterator iter; ( iter = std::find( first, last, '\n' ) ) != last ; first = iter + 1 )
1810 {
1811 std::string buf( first, iter );
1812 if ( ( ( buf[0] == '$' ) && ( buf.size() >= 2 ) && std::isspace( static_cast< unsigned char >( buf[1] ) ) ) )
1813 {
1814 *result = '\n';
1815 }
1816 else
1817 {
1818 // ƒRƒƒ“ƒgsˆÈŠO‚͍s“ª‚Ì‹ó”’—Þ‚ðœ‹Ž‚·‚éB
1819 first = std::find_if( first, iter, std::not1( std::ptr_fun< char, bool >( &toppers::isspace ) ) );
1820 result = std::copy( first, iter + 1, result );
1821 }
1822 }
1823 }
1824
1825 void macro_processor::expand_include( text const& in, text& out )
1826 {
1827 typedef text::container::const_iterator const_row_iterator;
1828 typedef std::string::size_type size_type;
1829 size_type const npos = std::string::npos;
1830std::string debug_str;
1831
1832 if ( in.empty() ) // ‹ó‚̃tƒ@ƒCƒ‹‚ª“ü—Í‚³‚ꂽê‡‚̑΍ô
1833 {
1834 return;
1835 }
1836
1837 const_row_iterator first( in.begin().get_row() ), last( in.end().get_row() );
1838
1839 out.set_line( first->line.file, first->line.line );
1840 for ( const_row_iterator iter( first ); iter != last; ++iter )
1841 {
1842 std::string const& buf = iter->buf;
1843
1844 for ( size_type i = 0, n = buf.size(); i != n; ++i )
1845 {
1846 using namespace boost::spirit;
1847 char c = buf[i];
1848 std::string headername;
1849 text::const_iterator iter2( iter, i );
1850 if ( iter2 == in.end() )
1851 {
1852 break;
1853 }
1854 parse_info< text::const_iterator > info
1855 = parse( iter2, in.end(),
1856 ( ch_p( '$' ) >> str_p( "INCLUDE" ) >> *space_p
1857 >> '\"' >> ( +( anychar_p - '\"' ) )[ assign( headername ) ] >> '\"'
1858 >> '$' ) );
1859 if ( info.hit )
1860 {
1861 std::vector< std::string > include_paths = get_global< std::vector< std::string > >( "include-path" );
1862 std::string hname = search_include_file( include_paths.begin(), include_paths.end(), headername );
1863 if ( hname.empty() )
1864 {
1865 fatal( iter->line, _( "cannot open file `%1%\'" ), headername );
1866 }
1867 else
1868 {
1869 text t;
1870 t.set_line( hname, 1 );
1871 std::ifstream ifs( hname.c_str() );
1872 t.append( ifs );
1873
1874 preprocess( t, out );
1875 iter = info.stop.get_row();
1876 i = info.stop.get_col() - 1;
1877 out.set_line( iter->line.file, iter->line.line );
1878 }
1879 }
1880 else
1881 {
1882 out.push_back( c );
1883 debug_str.push_back( c );
1884 if ( c == '\n' )
1885 {
1886// ::OutputDebugString( ( out.get_line().file + ":" + boost::lexical_cast< std::string >( out.get_line().line ) + ":" ).c_str() );
1887// ::OutputDebugString( debug_str.c_str() );
1888 debug_str.clear();
1889 }
1890 }
1891 }
1892 }
1893 }
1894
1895 void macro_processor::preprocess( text const& in, text& out )
1896 {
1897 if ( in.empty() )
1898 {
1899 return;
1900 }
1901 text temp;
1902 macro_processor::remove_comment( in, temp );
1903 expand_include( temp, out );
1904 }
1905
1906 void macro_processor::add_builtin_function( func_t const& f )
1907 {
1908 p_ctx_->func_map[ f.name ] = f;
1909 }
1910
1911 macro_processor::var_t macro_processor::call_user_function( text_line const& line, std::vector< var_t > const& arg_list, context* p_ctx )
1912 {
1913 if ( arg_list.empty() )
1914 {
1915 return var_t();
1916 }
1917
1918 func_t func = p_ctx->func_map[ get_s( arg_list.front(), p_ctx ) ];
1919 if ( func.name.empty() )
1920 {
1921 fatal( line, "function is not defined" );
1922 return var_t();
1923 }
1924
1925 // ARGC
1926 {
1927 element e;
1928 e.i = static_cast< std::tr1::int64_t >( arg_list.size() );
1929 p_ctx->var_map[ "ARGC" ] =var_t( 1, e );
1930 }
1931
1932 // ARGV
1933 {
1934 std::size_t n = arg_list.size();
1935 for ( std::size_t i = 0; i < n; i++ )
1936 {
1937 std::string argv_i = boost::str( boost::format( "ARGV[%d]" ) % i );
1938 p_ctx->var_map[ argv_i ] = arg_list[ i ];
1939 }
1940
1941 std::string argv_n = boost::str( boost::format( "ARGV[%d]" ) % n );
1942 p_ctx->var_map[ argv_n ] = var_t();
1943 }
1944
1945 tree_node_t const* func_body_node = reinterpret_cast< tree_node_t const* >( func.node );
1946 if ( !eval_node( *func_body_node, p_ctx ) )
1947 {
1948 return var_t();
1949 }
1950
1951 return p_ctx->var_map[ "RESULT" ];
1952 }
1953
1954}
Note: See TracBrowser for help on using the repository browser.