1 /* G-Cows - scripting language for creation of web sites
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Andrea Sozzi
3
4 This file is part of G-Cows.
5
6 G-Cows is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; version 2 of the License.
9
10 G-Cows is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
20
21 #include <fstream>
22 #include <sys/stat.h>
23 #include <cstdio>
24 #include <sys/wait.h>
25 #include <typeinfo>
26 #include "language.H"
27 #include "file_utils.H"
28
29
Exec_tree(string input,string output,string root_dir,string noext_in)30 Exec_tree::Exec_tree (string input, string output,
31 string root_dir, string noext_in)
32 {
33 input_file = input;
34 output_file = output;
35 noext = noext_in;
36 string launching_dir = string (get_w_dir ()) + "/"; // absolute
37 abs_input_file = launching_dir + input;
38 abs_output_file = launching_dir + output;
39 if (root_dir == "./")
40 root_dir_level = get_dir_level ();
41 else
42 {
43 root_dir = add_slash (root_dir);
44 root_dir_level = get_dir_level (root_dir);
45 }
46 if (output != "-")
47 starting_dir_level = get_dir_level (output);
48 vars.set_var ("_argc", 1);
49 Gen_type tmp_argv ('a');
50 tmp_argv.push (Gen_type (input));
51 vars.set_var ("_argv", tmp_argv);
52 }
53
54 Node *
push_node(Node * node)55 Exec_tree::push_node (Node *node)
56 {
57 node->p2tree = this;
58 node->log_infos = Msg::inst()->get_parse_infos ();
59 nodes.push_back (node);
60 //cout << "DEBUG: Nodes in tree: " << nodes.size () << endl;
61 return node;
62 }
63
64 Node *
push_node(Node * node)65 Deps_tree::push_node (Node *node)
66 {
67 node->p2tree = this;
68 node->log_infos = Msg::inst()->get_parse_infos ();
69 node->deps ();
70 nodes.push_back (node);
71 // cout << "Nodes in tree: " << nodes.size () << endl;
72 return node;
73 }
74
75 void
start()76 Exec_tree::start ()
77 {
78 if ( nodes.empty () )
79 return;
80 Node_Iter last_pushed = nodes.end () - 1;
81 Msg::inst()->set_log_mode (Msg::exec_log_mode);
82 (*last_pushed)->exec ();
83 Msg::inst()->set_log_mode (Msg::parsing_log_mode);
84 delete *last_pushed;
85 nodes.erase (nodes.begin (), nodes.end ());
86 }
87
88 void
save_args()89 Exec_tree::save_args ()
90 {
91 restore_flags_stack.push_back (true);
92 Gen_type var_argc = vars.get_var ("_argc");
93 if (! var_argc.is_int ())
94 Msg::inst()->error ("_argc must be an integer");
95 argc_stack.push_back (var_argc.get_int ());
96 Gen_type var_argv = vars.get_var ("_argv");
97 /* if (! var_argv.is_array ())
98 Msg::inst()->error ("_argv must be an array"); */
99 argv_stack.push_back (var_argv);
100 }
101
102 void
restore_args()103 Exec_tree::restore_args ()
104 {
105 Bool_iter iter_restore_flags = restore_flags_stack.end ();
106 bool flag = *(--iter_restore_flags);
107 if (flag)
108 {
109 Int_iter iterc = argc_stack.end ();
110 int argc = *(--iterc);
111 vars.set_var ("_argc", argc);
112 argc_stack.erase (iterc);
113
114 Gen_type_iter iterv = argv_stack.end ();
115 Gen_type args = *(--iterv);
116 vars.set_var ("_argv", args);
117 argv_stack.erase (iterv);
118 }
119 restore_flags_stack.erase (iter_restore_flags);
120 }
121
122 void
start()123 Deps_tree::start ()
124 {
125 if (nodes.empty ())
126 return;
127 Node_Iter last_pushed = nodes.end () - 1;
128 delete *last_pushed;
129 nodes.erase (nodes.begin (), nodes.end ());
130 }
131
132 string
format_date(time_t time,string fmt_string)133 Exec_tree::format_date (time_t time, string fmt_string)
134 {
135 struct tm *loc_time = localtime (&time);
136 int start = -1;
137 std::ostringstream tmp;
138 while ((start = fmt_string.find ("#", start + 1)) != (int)string::npos)
139 {
140 switch (fmt_string.at (start+1))
141 {
142 case 'y':
143 tmp << 1900 + loc_time->tm_year;
144 fmt_string.replace (start, 2, tmp.str());
145 tmp.str("");
146 break;
147 case 'm':
148 tmp << loc_time->tm_mon + 1;
149 fmt_string.replace (start, 2, tmp.str());
150 tmp.str("");
151 break;
152 case 'd':
153 tmp << loc_time->tm_mday;
154 fmt_string.replace (start, 2, tmp.str());
155 tmp.str("");
156 break;
157 case 'h':
158 tmp << loc_time->tm_hour;
159 fmt_string.replace (start, 2, tmp.str());
160 tmp.str("");
161 break;
162 case 'n':
163 tmp << loc_time->tm_min;
164 if (loc_time->tm_min < 10)
165 {
166 fmt_string.replace (start, 2, string("0").append (tmp.str()));
167 }
168 else
169 fmt_string.replace (start, 2, tmp.str());
170 tmp.str("");
171 break;
172 case 's':
173 tmp << loc_time->tm_sec;
174 if (loc_time->tm_sec < 10)
175 {
176 fmt_string.replace (start, 2, string("0").append (tmp.str()));
177 }
178 else
179 fmt_string.replace (start, 2, tmp.str());
180 tmp.str("");
181 break;
182 case 'M':
183 fmt_string.replace
184 (start, 2, (vars.get_array_element (
185 "_months",
186 loc_time->tm_mon)).get_string());
187 break;
188 case 'D':
189 fmt_string.replace
190 (start, 2, (vars.get_array_element (
191 "_days",
192 loc_time->tm_wday)).get_string());
193 break;
194 }
195 }
196 return fmt_string;
197 }
198
199 // Adjust file names adding a variable number of `../'
200
201 string
adjust_level()202 Tree::adjust_level ()
203 {
204 string res = "";
205 int diff_levels = starting_dir_level - root_dir_level;
206 if (diff_levels < 0)
207 Msg::inst()->warning (
208 "Can't adjust level: output file outside root directory",
209 "No adjust");
210 else
211 for (int i = 0; i < diff_levels; i++)
212 res += "../";
213 return res;
214 }
215
216 void
set_up(string file_scanned)217 Deps_tree::set_up (string file_scanned)
218 {
219 current_dir = get_dir_from_file_name (file_scanned);
220 first_file = true;
221 }
222
223 string
get_output_file()224 Deps_tree::get_output_file ()
225 {
226 if (custom_extension != "")
227 return output_file + custom_extension;
228 else
229 return output_file + target_extension;
230 }
231
232 string
get_and_delete_custom_ext()233 Deps_tree::get_and_delete_custom_ext ()
234 {
235 string ext = custom_extension;
236 custom_extension = "";
237 return ext;
238 }
239
240 string
get_custom_ext()241 Deps_tree::get_custom_ext ()
242 {
243 return custom_extension;
244 }
245
246 void
delete_custom_ext()247 Deps_tree::delete_custom_ext ()
248 {
249 custom_extension = "";
250 }
251
252 void
refresh(string file_name)253 Deps_tree::refresh (string file_name)
254 {
255 unsigned int last_slash;
256 current_dir_stack.push_back (current_dir);
257 if ( (last_slash = file_name.rfind("/")) != string::npos )
258 current_dir += ( file_name.substr (0, last_slash) + "/" );
259 }
260
261 void
undo_refresh()262 Deps_tree::undo_refresh ()
263 {
264 if (current_dir_stack.empty ())
265 Msg::inst()->fatal ("Deps_tree::undo_refresh () - internal error");
266 String_iter iter = current_dir_stack.end ();
267 current_dir = *(--iter);
268 current_dir_stack.erase (iter);
269 }
270
271 void
write_file_list(string text)272 Deps_tree::write_file_list (string text)
273 {
274 if ( ! always_update)
275 file_list += text;
276 else
277 always_list += text;
278 }
279
280 string
get_sources_list()281 Deps_tree::get_sources_list ()
282 {
283 string ret;
284 for (String_set_iter i=src_cache.begin (); i!= src_cache.end (); i++)
285 ret += *i;
286 src_cache.erase (src_cache.begin (), src_cache.end ());
287 return ret;
288 }
289
290 void
dump_cache()291 Deps_tree::dump_cache ()
292 {
293 for (String_set_iter i=dep_cache.begin (); i!= dep_cache.end (); i++)
294 output << *i;
295 }
296
297 void
clear_cache()298 Deps_tree::clear_cache ()
299 {
300 dep_cache.erase (dep_cache.begin (), dep_cache.end ());
301 }
302
303 void
deps()304 N_dep::deps ()
305 {
306 if (( strstr (typeid (*file).name (), "const") )
307 || ( strstr (typeid (*file).name (), "input") )
308 || ( strstr (typeid (*file).name (), "output") )
309 )
310 {
311 p2tree->ensure_dep ();
312 set_msg_buffers ();
313 Gen_type gfile = file->exec ();
314 if (!gfile.is_string ())
315 Msg::inst()->fatal ("N_dep::deps () -- Internal Error");
316 string sfile = gfile.get_string ();
317 string dep;
318 if (*(sfile.c_str()) != '/')
319 dep = ((Deps_tree *)p2tree)->get_current_dir () + sfile;
320 else
321 dep = sfile;
322 ((Deps_tree *)p2tree)->write_cache (" \\\n\t" + opt_file_name (dep));
323 }
324 else
325 {
326 if (! ((Deps_tree *)p2tree)->is_always ())
327 Msg::inst()->warning ("unable to get dependency");
328 }
329 }
330
331 // Constants and Variables
332
333 Gen_type
exec()334 N_const::exec ()
335 {
336 set_msg_buffers ();
337 if (cst->is_int ())
338 return *cst;
339 else if (cst->is_string ())
340 {
341 string escaped = cst->get_string ();
342 int start = -1;
343 while ((start=escaped.find ("\\", start + 1)) != (int)string::npos)
344 {
345 if (escaped[start+1] == '\\')
346 escaped.replace (start, 2, "\\");
347 else if (escaped[start+1] == 'n')
348 escaped.replace (start, 2, "\n");
349 else if (escaped[start+1] == 't')
350 escaped.replace (start, 2, "\t");
351 else if (escaped[start+1] == '"')
352 escaped.replace (start, 2, "\"");
353 else if (escaped[start+1] == '\'')
354 escaped.replace (start, 2, "\'");
355 else if (escaped[start+1] == '`')
356 escaped.replace (start, 2, "`");
357 else if (escaped[start+1] == '\n')
358 escaped.erase (start, 2);
359 }
360 return Gen_type (escaped);
361 }
362 else
363 {
364 Msg::inst()->fatal ("N_const::exec () -- Internal Error");
365 }
366 return Gen_type (-1);
367 }
368
369 string
get_var_name()370 N_base_var::get_var_name ()
371 {
372 if ( type == 'I')
373 return ((N_base_var *)var)->get_var_name ();
374 return var_name;
375 }
376
377 Gen_type
get_base_index()378 N_base_var::get_base_index ()
379 {
380 return (((N_base_var *)var)->index)->exec ();
381 }
382
383 Gen_type
exec()384 N_var::exec ()
385 {
386 set_msg_buffers ();
387 if ( ! (item_syntax () || var_item_syntax ()) )
388 return p2tree->vars.get_var (var_name);
389 Gen_type num_index = index->exec ();
390 if (! num_index.is_int ())
391 {
392 Msg::inst()->error ("array index must be an integer");
393 return Gen_type ("");
394 }
395 if (item_syntax ())
396 {
397 Gen_type new_var = p2tree->vars.get_var (var_name);
398 if (! new_var.is_array ())
399 {
400 // FIXME: this check should be done within get_element ()
401 Msg::inst()->error (var_name + " is not an array");
402 return Gen_type ("");
403 }
404 return new_var.get_element (num_index.get_int ());
405 }
406 if (var_item_syntax ())
407 {
408 Gen_type new_var = var->exec ();
409 if (! new_var.is_array ())
410 {
411 // FIXME: this check should be done within get_element ()
412 /*
413 Msg::inst()->error (((N_base_var *)var)->get_var_name ()
414 + " is not an array");
415 */
416 Msg::inst()->error (
417 "trying to extract element from non array variable");
418 return Gen_type ("");
419 }
420 return new_var.get_element (num_index);
421 }
422 Msg::inst()->fatal ("N_var::exec () -- internal error");
423 return Gen_type (-1);
424 }
425
426 Gen_type
exec()427 N_ind_expr::exec ()
428 {
429 set_msg_buffers ();
430 string var_name = get_var_name ();
431 if ( ! (item_syntax () || var_item_syntax ()) )
432 return p2tree->vars.get_var (var_name);
433 Gen_type num_index = index->exec ();
434 if (! num_index.is_int ())
435 {
436 Msg::inst()->error ("array index must be an integer");
437 return Gen_type ("");
438 }
439 if ( item_syntax ())
440 {
441 Gen_type new_var = p2tree->vars.get_var (var_name);
442 if (! new_var.is_array ())
443 {
444 // FIXME: this check should be done within get_element ()
445 Msg::inst()->error (var_name + " is not an array");
446 return Gen_type ("");
447 }
448 return new_var.get_element (num_index.get_int ());
449 }
450 Msg::inst()->fatal ("N_ind_expr::exec () -- Internal Error");
451 return Gen_type (-1);
452 }
453
454 string
get_var_name()455 N_ind_expr::get_var_name ()
456 {
457 Gen_type var = var_exp->exec ();
458 if (!var.is_string ())
459 {
460 Msg::inst()->error ("$ (expr): expr must be a string variable");
461 return "";
462 }
463 return var.get_string ();
464 }
465
466 Gen_type
exec()467 N_undef::exec ()
468 {
469 set_msg_buffers ();
470 N_base_var *bvar = ((N_base_var *)var);
471 string name = bvar->get_var_name ();
472 if (bvar->item_syntax ())
473 Msg::inst()->error ("can't undef an array element");
474 else
475 if ( ! p2tree->vars.undef (name))
476 Msg::inst()->warning ("variable `" + name + "' not defined");
477 return Gen_type (0);
478 }
479
480 Gen_type
exec()481 N_tobool::exec ()
482 {
483 set_msg_buffers ();
484 return Gen_type ((var->exec()).to_bool ());
485 }
486
487 Gen_type
exec()488 N_toint::exec ()
489 {
490 set_msg_buffers ();
491 Gen_type variable = var->exec();
492 if (variable.is_array ())
493 Msg::inst()->error ("can't convert array to integer");
494 return Gen_type (variable.to_int ());
495 }
496
497 Gen_type
exec()498 N_tostring::exec ()
499 {
500 set_msg_buffers ();
501 return Gen_type ((var->exec()).to_string ());
502 }
503
504 Gen_type
exec()505 N_toarray::exec ()
506 {
507 set_msg_buffers ();
508 Gen_type in_var = var->exec ();
509 if (in_var.is_array ())
510 return in_var;
511 else if (in_var.is_int () || in_var.is_string ())
512 {
513 Gen_type ret_value ('a');
514 ret_value.push (in_var);
515 return ret_value;
516 }
517 else if (in_var.is_undefined ())
518 return Gen_type (0);
519 else
520 Msg::inst()->fatal ("N_toarray::exec () -- Internal Error");
521 return Gen_type (-1);
522 }
523
524
525 // Operators
526
527 Gen_type
exec()528 N_assign::exec ()
529 {
530 set_msg_buffers ();
531 N_base_var *bvar = ((N_base_var *)var);
532 string name = bvar->get_var_name ();
533
534 if ( (only_if_undef) && (p2tree->vars.is_def (name)) )
535 {
536 return value->exec ();
537 }
538
539 Gen_type val = value->exec ();
540 if (bvar->array_syntax () && (! val.is_array ()))
541 {
542 Msg::inst()->error ("can't assign scalar value to array variable");
543 return Gen_type ("");
544 }
545 if (bvar->item_syntax ()) // array [4] = ...
546 return p2tree->vars.set_array_element (name,
547 ((N_var *)var)->get_index (),
548 val);
549 else if (bvar->var_item_syntax ())
550 { // array [4][1] = ...
551 Gen_type new_var
552 = (p2tree->vars.get_var (bvar->get_var_name())).get_element (
553 (((N_var *)var)->get_base_index()).get_int ());
554
555 new_var.set_element ((((N_var *)var)->get_index()).get_int (), val);
556 return p2tree->vars.set_array_element (bvar->get_var_name(),
557 (((N_var *)var)->get_base_index()).get_int (),
558 new_var);
559 } else // var = ... | var [] = ...
560 return p2tree->vars.set_var (name, val);
561 }
562
563 Gen_type
exec()564 N_assign_rec::exec ()
565 {
566 set_msg_buffers ();
567 N_base_var *bvar = ((N_base_var *)var);
568 string name = bvar->get_var_name ();
569
570 if ( (only_if_undef) && (p2tree->vars.is_def (name)) )
571 {
572 return value->exec ();
573 }
574
575 Gen_type val = value->exec ();
576 if (bvar->array_syntax () && (! val.is_array ()))
577 {
578 Msg::inst()->error ("can't assign scalar value to array variable");
579 return Gen_type ("");
580 }
581 if (bvar->item_syntax ()) // array [4] = ...
582 return p2tree->vars.set_array_element (name,
583 ((N_var *)var)->get_index (),
584 val);
585 else if (bvar->var_item_syntax ())
586 {
587 // array [4][1] = ...
588 Gen_type new_var
589 = (p2tree->vars.get_var (bvar->get_var_name())).get_element (
590 (((N_var *)var)->get_base_index()).get_int ());
591
592 new_var.set_element ((((N_var *)var)->get_index()).get_int (), val);
593 return p2tree->vars.set_array_element (bvar->get_var_name(),
594 (((N_var *)var)->get_base_index()).get_int (),
595 new_var);
596 }
597 else // var = ... | var [] = ...
598 return p2tree->vars.set_var (name, val);
599 }
600
601 Gen_type
exec()602 N_empty_array::exec ()
603 {
604 set_msg_buffers ();
605 N_base_var *bvar = ((N_base_var *)var);
606 string name = bvar->get_var_name ();
607 return p2tree->vars.set_var (name, Gen_type ('a'));
608 }
609
610 Gen_type
exec()611 N_and::exec ()
612 {
613 set_msg_buffers ();
614 Gen_type st1_result = st1->exec ();
615 if (! (bool) st1_result)
616 return st1_result;
617 else
618 return st2->exec ();
619 }
620
621 Gen_type
exec()622 N_or::exec ()
623 {
624 set_msg_buffers ();
625 Gen_type st1_result = st1->exec ();
626 if ((bool) st1_result)
627 return st1_result;
628 else
629 return st2->exec ();
630 }
631
632 Gen_type
exec()633 N_plus::exec ()
634 {
635 /* Important: we can't simply do: return n1->exec () + n2->exec ();
636 exec () functions often have side effects (++ operator for example)
637 and compiler is not obliged to keep the evaluation order.
638 This could result in something very bad as:
639 i=0; print ("A" + i++ + "B" + i++ + "C" + i++);
640 returning A2B1C0
641 */
642 set_msg_buffers ();
643 Gen_type res1 = n1->exec ();
644 Gen_type res2 = n2->exec ();
645 return res1 + res2;
646 }
647
648 Gen_type
exec()649 N_minus::exec ()
650 {
651 set_msg_buffers ();
652 Gen_type res1 = n1->exec ();
653 Gen_type res2 = n2->exec ();
654 return res1 - res2;
655 }
656
657
658 Gen_type
exec()659 N_times::exec ()
660 {
661 set_msg_buffers ();
662 Gen_type res1 = n1->exec ();
663 Gen_type res2 = n2->exec ();
664 return res1 * res2;
665 }
666
667 Gen_type
exec()668 N_div::exec ()
669 {
670 set_msg_buffers ();
671 Gen_type res1 = n1->exec ();
672 Gen_type res2 = n2->exec ();
673 return res1 / res2;
674 }
675
exec()676 Gen_type N_mod::exec ()
677 {
678 set_msg_buffers ();
679 Gen_type res1 = n1->exec ();
680 Gen_type res2 = n2->exec ();
681 return res1 % res2;
682 }
683
684 Gen_type
exec()685 N_pow ::exec ()
686 {
687 set_msg_buffers ();
688 Gen_type res1 = n1->exec ();
689 Gen_type res2 = n2->exec ();
690 return res1 ^ res2;
691 }
692
693
694 Gen_type
exec()695 N_epp::exec ()
696 {
697 set_msg_buffers ();
698 string op_name = (increment > 0) ? "++" : "--";
699 if (! var->is_var())
700 {
701 Msg::inst()->error (op_name + " can only apply to variables");
702 return Gen_type (-1);
703 }
704 N_base_var *bvar = ((N_base_var *)var);
705 string name = bvar->get_var_name ();
706 if (bvar->item_syntax ())
707 {
708 Gen_type value
709 = p2tree->vars.get_array_element (name,
710 ((N_var *)var)->get_index ());
711 if (! value.is_int ())
712 {
713 Msg::inst()->error (op_name + " can only apply to integers");
714 return Gen_type (-1);
715 }
716 p2tree->vars.set_array_element (name,
717 ((N_var *)var)->get_index (),
718 value.get_int () + increment);
719 return postfix ? value : Gen_type (value.get_int () + increment);
720 }
721 else
722 {
723 Gen_type value = p2tree->vars.get_var (name);
724 if (! value.is_int ())
725 {
726 Msg::inst()->error (op_name + " can only apply to integers");
727 return Gen_type (-1);
728 }
729 p2tree->vars.set_var (name, value.get_int () + increment);
730 return postfix ? value : Gen_type (value.get_int () + increment);
731 }
732 }
733
734 Gen_type
exec()735 N_eq::exec ()
736 {
737 set_msg_buffers ();
738 Gen_type var1 = st1->exec ();
739 Gen_type var2 = st2->exec ();
740 if (var1.get_type () != var2.get_type ())
741 {
742 Msg::inst()->opt ("==: Operands have different type; comparison FALSE",
743 "==: different types; FALSE");
744 return Gen_type (0);
745 }
746 return var1 == var2;
747 }
748
749 Gen_type
exec()750 N_neq::exec ()
751 {
752 set_msg_buffers ();
753 Gen_type var1 = st1->exec ();
754 Gen_type var2 = st2->exec ();
755 if (var1.get_type () != var2.get_type ())
756 {
757 Msg::inst()->opt ("!=: Operands have different type; comparison TRUE",
758 "!=: different types; TRUE");
759 return Gen_type (1);
760 }
761 return var1 != var2;
762 }
763
764 // Display
765
766 Gen_type
exec()767 N_echo::exec ()
768 {
769 set_msg_buffers ();
770 Gen_type res = message->exec ();
771 p2tree->write_output (res.to_string ());
772 return res;
773 }
774
775 Gen_type
exec()776 N_print::exec ()
777 {
778 set_msg_buffers ();
779 Gen_type res = message->exec ();
780 p2tree->write_output (res.to_string () + "\n");
781 return res;
782 }
783
784 // Conditionals
785
786 Gen_type
exec()787 N_if::exec ()
788 {
789 set_msg_buffers ();
790 if (cond->exec().to_bool())
791 {
792 st->exec ();
793 return Gen_type (1);
794 }
795 return Gen_type (0);
796 }
797
798 Gen_type
exec()799 N_ifdef::exec ()
800 {
801 set_msg_buffers ();
802 switch ( ((N_base_var *)var)->get_type () )
803 {
804 case 's':
805 case 'a':
806 if ( p2tree->vars.is_def (((N_var *)var)->get_var_name ()))
807 {
808 st->exec ();
809 return Gen_type (1);
810 }
811 break;
812 case 'i':
813 Msg::inst()->error
814 ("Ifdef (var): <var> can't be an array element");
815 break;
816 default:
817 Msg::inst()->fatal ("N_ifdef::exec ()-- Internal Error");
818 }
819 return Gen_type (0);
820 }
821
822 Gen_type
exec()823 N_ifndef::exec ()
824 {
825 set_msg_buffers ();
826 switch ( ((N_base_var *)var)->get_type () )
827 {
828 case 's':
829 case 'a':
830 if ( ! p2tree->vars.is_def (((N_var *)var)->get_var_name ()))
831 {
832 st->exec ();
833 return Gen_type (1);
834 }
835 break;
836 case 'i':
837 Msg::inst()->error
838 ("Ifndef (var): <var> can't be an array element");
839 break;
840 default:
841 Msg::inst()->fatal ("N_ifndef::exec () -- Internal Error");
842 }
843 return Gen_type (0);
844 }
845
846 Gen_type
exec()847 N_cond_seq::exec ()
848 {
849 set_msg_buffers ();
850 Gen_type seq_res = seq->exec ();
851 if (! seq_res.is_int ())
852 Msg::inst()->fatal ("N_cond_seq::exec () -- Internal Error");
853 if ( ! seq_res.get_int ())
854 return if_st->exec ();
855 return Gen_type (1);
856 }
857
858 Gen_type
exec()859 N_if_else::exec ()
860 {
861 set_msg_buffers ();
862 Gen_type seq_res = seq->exec ();
863 if (! seq_res.is_int ())
864 Msg::inst()->fatal ("N_if_else::exec () -- Internal Error");
865 if ( ! seq_res.get_int ())
866 {
867 st->exec ();
868 return Gen_type (1);
869 }
870 return Gen_type (0);
871 }
872
873 // Functions
874
N_input(Gen_type * prefix_in)875 N_input::N_input (Gen_type *prefix_in)
876 {
877 if (prefix_in->is_string ())
878 prefix = prefix_in->get_string ();
879 else
880 Msg::inst()->error ("input (prefix): prefix must be a string literal");
881 }
882
N_output(Gen_type * prefix_in)883 N_output::N_output (Gen_type *prefix_in)
884 {
885 if (prefix_in->is_string ())
886 prefix = prefix_in->get_string ();
887 else
888 Msg::inst()->error
889 ("output (prefix): prefix must be a string literal");
890 }
891
892 Gen_type
exec()893 N_date::exec ()
894 {
895 set_msg_buffers ();
896 p2tree->ensure_exec ();
897 Gen_type fmt = format->exec ();
898 if (! fmt.is_string ())
899 {
900 Msg::inst()->error ("date (format): format must be a string");
901 return Gen_type ("");
902 }
903 return ((Exec_tree *)p2tree)->format_date (time (NULL), fmt.get_string ());
904 }
905
906 Gen_type
exec()907 N_fdate::exec ()
908 {
909 set_msg_buffers ();
910 p2tree->ensure_exec ();
911 struct stat f_stat;
912 Gen_type fl = file->exec ();
913 if (! fl.is_string ())
914 {
915 Msg::inst()->error ("fdate (file, format): file must be a string");
916 return Gen_type ("");
917 }
918 Gen_type fmt = format->exec ();
919 if (! fmt.is_string ())
920 {
921 Msg::inst()->error ("fdate (file, format): format must be a string");
922 return Gen_type ("");
923 }
924 // The current working dir could have been changed so we use the
925 // one stored while building syntax tree
926 //string file = dir + fl.get_string();
927 string file = fl.get_string();
928 if (file[0] != '/')
929 file = dir + file;
930
931 if (stat (file.c_str(), &f_stat))
932 {
933 Msg::inst()->warning ("unable to get infos about " + file, file);
934 return Gen_type ("");
935 }
936 return ((Exec_tree *)p2tree)->format_date
937 (f_stat.st_mtime, fmt.get_string ());
938 }
939
940 Gen_type
exec()941 N_fsize::exec ()
942 {
943 set_msg_buffers ();
944 p2tree->ensure_exec ();
945 struct stat f_stat;
946 Gen_type fl = file->exec ();
947 if (! fl.is_string ())
948 {
949 Msg::inst()->error ("fsize (file, format): file must be a string");
950 return Gen_type ("");
951 }
952 Gen_type fmt = format->exec ();
953 if (! fmt.is_string ())
954 {
955 Msg::inst()->error ("fsize (file, format): format must be a string");
956 return Gen_type ("");
957 }
958 string fmt_string = fmt.get_string ();
959 // The current working dir could have been changed so we use the
960 // one stored while building syntax tree
961 //string file = dir + fl.get_string();
962 string file = fl.get_string();
963 if (file[0] != '/')
964 file = dir + file;
965 if (stat (file.c_str(), &f_stat))
966 {
967 Msg::inst()->warning ("unable to get infos about " + file, file);
968 return Gen_type ("");
969 }
970 else
971 {
972 int start = -1;
973 std::ostringstream tmp;
974 while ((start = fmt_string.find("#", start + 1)) != (int)string::npos)
975 {
976 switch (fmt_string.at (start+1))
977 {
978 case 'b':
979 tmp << f_stat.st_size;
980 fmt_string.replace (start, 2, tmp.str());
981 tmp.str("");
982 break;
983 case 'k':
984 tmp << (double) f_stat.st_size / 1024;
985 fmt_string.replace (start, 2, tmp.str());
986 tmp.str("");
987 break;
988 case 'm':
989 tmp << (double) f_stat.st_size / 1048576;
990 fmt_string.replace (start, 2, tmp.str());
991 tmp.str("");
992 break;
993 }
994 }
995 }
996 return Gen_type (fmt_string);
997 }
998
999 Gen_type
exec()1000 N_substr::exec ()
1001 {
1002 set_msg_buffers ();
1003 string str = (str_n->exec ()).to_string (true);
1004 Gen_type index_from = from->exec();
1005 if (! index_from.is_int ())
1006 {
1007 Msg::inst()->error ("substring() second parameter must be an integer");
1008 return Gen_type ("");
1009 }
1010 int from_int=index_from.get_int ();
1011 int len_int;
1012 if (from_int < 0)
1013 {
1014 Msg::inst()->error ("substring() second parameter can't be negative");
1015 return Gen_type ("");
1016 }
1017 if (len == NULL)
1018 {
1019 len_int=str.length()-from_int;
1020 }
1021 else
1022 {
1023 Gen_type length = len->exec();
1024 if (! length.is_int ())
1025 {
1026 Msg::inst()->error ("substring() third parameter must be an integer");
1027 return Gen_type ("");
1028 }
1029 len_int=length.get_int ();
1030 }
1031 if (len_int < 0)
1032 {
1033 Msg::inst()->error ("substring() third parameter can't be negative");
1034 return Gen_type ("");
1035 }
1036 return Gen_type (str.substr(from_int, len_int));
1037 }
1038
1039 Gen_type
exec()1040 N_find::exec ()
1041 {
1042 set_msg_buffers ();
1043 string src_str = (src->exec ()).to_string (true);
1044 string chars_str = (chars->exec ()).to_string (true);
1045 int from_int;
1046 if (from == NULL)
1047 {
1048 if (rev)
1049 from_int=src_str.length();
1050 else
1051 from_int=0;
1052 }
1053 else
1054 {
1055 Gen_type search_from=from->exec();
1056 if (! search_from.is_int ())
1057 {
1058 Msg::inst()->error ("find() third parameter must be an integer");
1059 return Gen_type (-1);
1060 }
1061 from_int=search_from.get_int ();
1062 }
1063 int index;
1064 if (rev)
1065 index = src_str.rfind (chars_str, from_int);
1066 else
1067 index = src_str.find (chars_str, from_int);
1068 return (Gen_type (index));
1069 }
1070
1071 Gen_type
exec()1072 N_find_match::exec ()
1073 {
1074 set_msg_buffers ();
1075 string src_str = (src->exec ()).to_string (true);
1076 string chrs_str = (chrs->exec ()).to_string (true);
1077 int index;
1078 if (last_flg && not_flg)
1079 index = src_str.find_last_not_of (chrs_str);
1080 else if (last_flg && (! not_flg))
1081 index = src_str.find_last_of (chrs_str);
1082 else if ((!last_flg) && not_flg)
1083 index = src_str.find_first_not_of (chrs_str);
1084 else if ((!last_flg) && (!not_flg))
1085 index = src_str.find_first_not_of (chrs_str);
1086 else
1087 index = -1;
1088 return (Gen_type (index));
1089 }
1090
1091 Gen_type
exec()1092 N_char::exec ()
1093 {
1094 set_msg_buffers ();
1095 string src_str = (src->exec ()).to_string (true);
1096 Gen_type ind = index->exec();
1097 if (! ind.is_int ())
1098 {
1099 Msg::inst()->error ("char() second parameter must be an integer");
1100 return Gen_type ("");
1101 }
1102 int ind_int=ind.get_int ();
1103 if (ind_int<0)
1104 {
1105 Msg::inst()->error ("char() negative index not allowed");
1106 return Gen_type ("");
1107 }
1108 if ((unsigned int) ind_int>src_str.length()-1)
1109 {
1110 Msg::inst()->error ("char() index beyond string bounds");
1111 return Gen_type ("");
1112 }
1113 return Gen_type (src_str.substr(ind_int,1));
1114 }
1115
1116 Gen_type
exec()1117 N_startswith::exec ()
1118 {
1119 set_msg_buffers ();
1120 string src_str = (src->exec ()).to_string (true);
1121 string start_str = (start->exec ()).to_string (true);
1122 return Gen_type (src_str.substr (0, start_str.length()) == start_str);
1123 }
1124
1125 Gen_type
exec()1126 N_endswith::exec ()
1127 {
1128 set_msg_buffers ();
1129 string src_str = (src->exec ()).to_string (true);
1130 string end_str = (end->exec ()).to_string (true);
1131 return Gen_type (src_str.substr (src_str.length() - end_str.length(),
1132 src_str.length()) == end_str);
1133 }
1134
1135 Gen_type
exec()1136 N_insert::exec ()
1137 {
1138 set_msg_buffers ();
1139 string src_str = (source->exec ()).to_string (true);
1140 string ins_str = (ins->exec ()).to_string (true);
1141 Gen_type index_gen = index->exec();
1142 if (! index_gen.is_int ())
1143 {
1144 Msg::inst()->error ("insert() second parameter must be an integer");
1145 return Gen_type ("");
1146 }
1147 int index_int=index_gen.get_int ();
1148 if (index_int<0)
1149 {
1150 Msg::inst()->error ("char() negative index not allowed");
1151 return Gen_type ("");
1152 }
1153 if ((unsigned int) index_int > src_str.length()-1)
1154 {
1155 Msg::inst()->error ("insert(): index beyond string bounds");
1156 return Gen_type ("");
1157 }
1158 return Gen_type (src_str.insert (index_int, ins_str));
1159 }
1160
1161 Gen_type
exec()1162 N_replace::exec ()
1163 {
1164 set_msg_buffers ();
1165 string source_str = (source->exec ()).to_string (true);
1166 string from_str = (from->exec ()).to_string (true);
1167 if (from_str == "")
1168 return Gen_type (source_str);
1169 string to_str = (to->exec ()).to_string (true);
1170 int start = -1;
1171
1172 if (source_str.find (from_str) == string::npos)
1173 {
1174 string funct_name;
1175 funct_name = (all) ? "replaceall ()" : "replace ()";
1176 Msg::inst()->opt (funct_name + "; couldn't find " + from_str +
1177 " within " + source_str, funct_name
1178 + "; no replacement" );
1179 return Gen_type (source_str);
1180 }
1181
1182 if (all)
1183 {
1184 while ((start=source_str.find (from_str, start + 1))!=(int)string::npos)
1185 {
1186 source_str.replace (start, from_str.length (), to_str);
1187 start += to_str.length () -1;
1188 }
1189 }
1190 else
1191 {
1192 if ((start=source_str.find(from_str, 0)) != (int)string::npos )
1193 {
1194 source_str.replace (start, from_str.length (), to_str);
1195 }
1196 }
1197 return Gen_type (source_str);
1198 }
1199
1200 Gen_type
exec()1201 N_tok::exec ()
1202 {
1203 set_msg_buffers ();
1204 string source_str = (source->exec ()).to_string (true);
1205 Gen_type separators = sep_list->exec ();
1206 Gen_type ret_val ('a');
1207 if (separators.get_type () == 'c')
1208 {
1209 string sep_str = separators.to_string (true);
1210 int beg_tok = 0;
1211 int sep_pos = -1;
1212 while ((sep_pos=source_str.find (sep_str, sep_pos + 1))
1213 !=(int)string::npos)
1214 {
1215 ret_val.push (source_str.substr (beg_tok, sep_pos - beg_tok));
1216 beg_tok = (sep_pos + sep_str.length ());
1217 }
1218 if (beg_tok)
1219 ret_val.push (source_str.substr (beg_tok, sep_pos - beg_tok));
1220 else
1221 ret_val.push (source_str);
1222 }
1223 else
1224 {
1225 Msg::inst()->error ("tokenize; Separator must be a string");
1226 }
1227 return ret_val;
1228 }
1229
1230 Gen_type
exec()1231 N_join::exec ()
1232 {
1233 set_msg_buffers ();
1234 Gen_type src_arr = source->exec ();
1235 if (! src_arr.is_array ())
1236 {
1237 Msg::inst()->error ("join requires an array as first variable");
1238 return Gen_type (-1);
1239 }
1240 string str_sep = (sep->exec ()).to_string (true);
1241 string ret_value = "";
1242 for (Gen_type_c_iter i = (src_arr.get_array ())->begin ();
1243 i != (src_arr.get_array ())->end (); i++)
1244 {
1245 if (i != (src_arr.get_array ())->begin ())
1246 ret_value += str_sep;
1247 ret_value += i->to_string ();
1248 }
1249 return Gen_type (ret_value);
1250 }
1251
1252 Gen_type
exec()1253 N_trim::exec ()
1254 {
1255 set_msg_buffers ();
1256 string source_str = (source->exec ()).to_string (true);
1257 return Gen_type (Utils::trim (source_str));
1258 }
1259
1260 Gen_type
exec()1261 N_ltrim::exec ()
1262 {
1263 set_msg_buffers ();
1264 string source_str = (source->exec ()).to_string (true);
1265 return Gen_type (Utils::ltrim (source_str));
1266 }
1267
1268 Gen_type
exec()1269 N_rtrim::exec ()
1270 {
1271 set_msg_buffers ();
1272 string source_str = (source->exec ()).to_string (true);
1273 return Gen_type (Utils::rtrim (source_str));
1274 }
1275
1276 Gen_type
exec()1277 N_ch_case::exec ()
1278 {
1279 set_msg_buffers ();
1280 string source_str = (source->exec ()).to_string (true);
1281 char* buf = new char[source_str.length()];
1282 source_str.copy(buf, source_str.length());
1283 if (to_lower)
1284 {
1285 for (unsigned int i = 0; i < source_str.length(); i++)
1286 buf[i] = tolower (buf[i]);
1287 }
1288 else
1289 {
1290 for (unsigned int i = 0; i < source_str.length(); i++)
1291 buf[i] = toupper (buf[i]);
1292 }
1293 Gen_type ret = Gen_type (std::string (buf, source_str.length()));
1294 delete buf;
1295 return ret;
1296 }
1297
1298 Gen_type
exec()1299 N_length::exec ()
1300 {
1301 set_msg_buffers ();
1302 Gen_type expr_eval = expr->exec ();
1303 switch (expr_eval.get_type ())
1304 {
1305 case 'a':
1306 return Gen_type ((int) (expr_eval.get_array ())->size ());
1307 break;
1308 case 'c':
1309 return Gen_type ((int) (expr_eval.get_string ()).size ());
1310 break;
1311 case 'i':
1312 return Gen_type ((int) (expr_eval.to_string ()).size ());
1313 break;
1314 case 'u':
1315 return Gen_type (0);
1316 break;
1317 default:
1318 Msg::inst()->fatal ("N_length::exec () -- Internal Error");
1319 }
1320 return Gen_type (0);
1321 }
1322
1323 Gen_type
exec()1324 N_raiseerr::exec ()
1325 {
1326 set_msg_buffers ();
1327 Gen_type expr1_eval = expr1->exec ();
1328 if (! expr1_eval.is_string ())
1329 Msg::inst()->error ("raiseerror called with non string expression");
1330 if (expr2 != NULL)
1331 {
1332 Gen_type expr2_eval = expr2->exec ();
1333 if (! expr2_eval.is_string ())
1334 Msg::inst()->error ("raiseerror called with non string expression");
1335 Msg::inst()->error (expr1_eval.get_string (),
1336 expr2_eval.get_string ());
1337 }
1338 else
1339 {
1340 Msg::inst()->error (expr1_eval.get_string (),
1341 expr1_eval.get_string ());
1342 }
1343 return Gen_type (0);
1344 }
1345
1346 Gen_type
exec()1347 N_raisewarn::exec ()
1348 {
1349 set_msg_buffers ();
1350 Gen_type expr1_eval = expr1->exec ();
1351 if (! expr1_eval.is_string ())
1352 Msg::inst()->error ("raisewarning called with non string expression");
1353 /*
1354 if (! expr2) {
1355 Msg::inst()->warning (expr1_eval.get_string ());
1356 return Gen_type (0);
1357 }
1358 */
1359 if (expr2 != NULL)
1360 {
1361 Gen_type expr2_eval = expr2->exec ();
1362 if (! expr2_eval.is_string ())
1363 Msg::inst()->error ("raisewarning called with non string expression");
1364 Msg::inst()->warning (expr1_eval.get_string (),
1365 expr2_eval.get_string ());
1366 }
1367 else
1368 {
1369 Msg::inst()->warning (expr1_eval.get_string (),
1370 expr1_eval.get_string ());
1371 }
1372 return Gen_type (0);
1373 }
1374
1375 Gen_type
exec()1376 N_term::exec ()
1377 {
1378 set_msg_buffers ();
1379 Gen_type res = msg->exec ();
1380 std::cout << res.to_string () << std::endl;
1381 return res;
1382 }
1383
1384 // Inclusions
1385
1386 Gen_type
exec()1387 N_verbatim::exec ()
1388 {
1389 set_msg_buffers ();
1390 string sfile = file->exec ().get_string ();
1391 if (sfile [0] != '/')
1392 sfile = dir + sfile;
1393 std::ifstream in (sfile.c_str ());
1394 if ( !in )
1395 Msg::inst()->error ("can't open file " + sfile, "open " + sfile);
1396 else
1397 {
1398 std::ostringstream tmp;
1399 tmp << in.rdbuf();
1400 p2tree->write_output (tmp.str());
1401 }
1402 return Gen_type (0);
1403 }
1404
1405 Gen_type
exec()1406 N_include::exec ()
1407 {
1408 set_msg_buffers ();
1409 ((Exec_tree *)p2tree)->set_include_flag ();
1410 return Gen_type (0);
1411 }
1412
1413 Gen_type
exec()1414 N_arg_include::exec ()
1415 {
1416 set_msg_buffers ();
1417 ((Exec_tree *)p2tree)->save_args ();
1418 Gen_type args = n_args->exec ();
1419 if (args.is_list ())
1420 {
1421 p2tree->vars.set_var ("_argc",
1422 Gen_type ((int) (args.get_list())->size()+1));
1423 p2tree->vars.set_var ("_argv", file->exec () + args);
1424 }
1425 else
1426 {
1427 p2tree->vars.set_var ("_argc", 2);
1428 Gen_type tmp_argv ('a');
1429 tmp_argv.push (file->exec ());
1430 tmp_argv.push (args);
1431 p2tree->vars.set_var ("_argv", tmp_argv);
1432 }
1433 return Gen_type (0);
1434 }
1435
1436 // External Commands and Scripts
1437
1438 Gen_type
exec()1439 N_cmd::exec ()
1440 {
1441 set_msg_buffers ();
1442 if ( ((Exec_tree *)p2tree)->get_noext () == "warning")
1443 Msg::inst()->warning ("can't execute command: --noext-warning used");
1444 else if ( ((Exec_tree *)p2tree)->get_noext () == "error")
1445 Msg::inst()->error ("can't execute command: --noext-error used");
1446 string sfile = (cmd->exec ().get_string ());
1447 string eval_output;
1448 FILE *output = popen (sfile.c_str (), "r");
1449 if (!output)
1450 {
1451 Msg::inst()->error ("error while executing " + sfile, "exec " + sfile);
1452 return Gen_type (-1);
1453 }
1454 char *buffer = new char [buff_size+1];
1455 int bytes_read;
1456 while ( (bytes_read = fread (buffer, sizeof (char), buff_size, output))
1457 == buff_size )
1458 {
1459 buffer [bytes_read] = '\0';
1460 if (eval)
1461 eval_output += string (buffer);
1462 else
1463 p2tree->write_output (buffer);
1464 }
1465 buffer [bytes_read] = '\0';
1466 if (eval)
1467 eval_output += string (buffer);
1468 else
1469 p2tree->write_output (buffer);
1470 if (pclose (output) != 0)
1471 {
1472 Msg::inst()->error ("error while executing " + sfile, "exec " + sfile);
1473 return Gen_type (-1);
1474 }
1475 if (eval)
1476 return Gen_type (eval_output);
1477 else
1478 return Gen_type (0);
1479 }
1480
1481 void
deps()1482 N_exec::deps ()
1483 {
1484 N_dep::deps ();
1485 Gen_type gfile = file->exec ();
1486 if (!gfile.is_string ())
1487 Msg::inst()->fatal ("N_exec::deps () -- Internal Error");
1488 string sfile = gfile.get_string ();
1489 ((Deps_tree *)p2tree)->write_sources_list (sfile+"\n" + sfile+"~\n");
1490 }
1491
1492 Gen_type
exec()1493 N_exec::exec ()
1494 {
1495 set_msg_buffers ();
1496 if ( ((Exec_tree *)p2tree)->get_noext () == "warning")
1497 {
1498 Msg::inst()->warning ("can't execute script: --noext-warning used");
1499 return Gen_type ("");
1500 }
1501 else if ( ((Exec_tree *)p2tree)->get_noext () == "error")
1502 {
1503 Msg::inst()->error ("can't execute script: --noext-error used");
1504 return Gen_type (-1);
1505 }
1506 string sfile = (file->exec ().get_string ());
1507 string eval_output;
1508 int fd_pipe[2];
1509 if (pipe (fd_pipe))
1510 {
1511 Msg::inst()->error ("error while executing " + sfile, "exec " + sfile);
1512 return Gen_type (-1);
1513 }
1514
1515 pid_t pid = fork ();
1516
1517 if (pid == (pid_t) 0)
1518 {
1519 int args_no = 2; // at least file name and NULL terminator
1520 char **ch_args;
1521
1522 if (! n_args)
1523 ch_args = new char * [2];
1524 else
1525 {
1526 Gen_type args = n_args->exec ();
1527 if (args.get_type () == 'l')
1528 {
1529 args_no += args.get_list ()->size ();
1530 ch_args = new char * [args_no];
1531 int index = 1;
1532 for (Gen_type_c_iter i = args.get_list ()->begin ();
1533 i != args.get_list ()->end (); i++)
1534 {
1535 char *arg = new char [i->get_string ().length()];
1536 i->get_string ().copy (arg, i->get_string ().length());
1537 ch_args[index++] = arg;
1538 }
1539 }
1540 else if (args.get_type () == 'c')
1541 {
1542 args_no++;
1543 ch_args = new char * [args_no];
1544 char *arg = new char [args.get_string ().length()];
1545 args.get_string ().copy (arg, args.get_string ().length());
1546 ch_args[1] = arg;
1547 }
1548 else
1549 {
1550 Msg::inst()->fatal ("N_exec::exec () -- internal error");
1551 // Should raise an error telling user that a string is needed
1552 }
1553 }
1554 char *ch_file = new char[sfile.length ()];
1555 sfile.copy (ch_file, sfile.length ());
1556 ch_args[0] = ch_file;
1557 ch_args[args_no - 1] = NULL;
1558 string env_str = "LA=" + p2tree->adjust_level ();
1559 char *env_ch = new char [env_str.length()];
1560 env_str.copy (env_ch, env_str.length ());
1561 char * env[] = { env_ch, NULL };
1562 close (fd_pipe[0]);
1563 dup2 (fd_pipe[1], STDOUT_FILENO);
1564 execve (sfile.c_str (), ch_args, env);
1565 }
1566 else if (pid < (pid_t) 0)
1567 {
1568 Msg::inst()->error ("error while executing " + sfile, "exec " + sfile);
1569 return Gen_type (-1);
1570 }
1571 else
1572 {
1573 close (fd_pipe[1]);
1574 char *buffer = new char [buff_size+1];
1575 waitpid (pid, NULL, 0);
1576 // Child process has exited so we can read its output
1577 ssize_t bytes_read;
1578 while ((bytes_read=read (fd_pipe[0], buffer, buff_size*sizeof(char)))
1579 == buff_size)
1580 {
1581 buffer [bytes_read] = '\0';
1582 if (eval)
1583 eval_output += string (buffer);
1584 else
1585 p2tree->write_output (buffer);
1586 }
1587 buffer [bytes_read] = '\0';
1588 if (eval)
1589 eval_output += string (buffer);
1590 else
1591 p2tree->write_output (buffer);
1592 close (fd_pipe[0]);
1593
1594 }
1595 if (eval)
1596 return Gen_type (eval_output);
1597 else
1598 return Gen_type (0);
1599 }
1600
1601 Gen_type
exec()1602 N_for::exec ()
1603 {
1604 set_msg_buffers ();
1605 before->exec ();
1606 while (cond->exec ())
1607 {
1608 stmt->exec ();
1609 action->exec ();
1610 }
1611 return Gen_type (0);
1612 }
1613
1614 Gen_type
exec()1615 N_while::exec ()
1616 {
1617 set_msg_buffers ();
1618 while (cond->exec ())
1619 stmt->exec ();
1620 return Gen_type (0);
1621 }
1622
1623
1624 // Arrays
1625
1626 Gen_type
exec()1627 N_foreach::exec ()
1628 {
1629 set_msg_buffers ();
1630 Gen_type arr = arr_expr->exec ();
1631 if (! arr.is_array ())
1632 {
1633 Msg::inst()->error
1634 ("Foreach loops work on arrays as in: foreach (item in array [])");
1635 return Gen_type (1);
1636 }
1637 N_base_var *bvar = ((N_var *)loop_var);
1638 for (Gen_type_c_iter i = (arr.get_array ())->begin ();
1639 i != (arr.get_array ())->end ();
1640 i++)
1641 {
1642 if (bvar->array_syntax ())
1643 if (i->is_array ())
1644 p2tree->vars.set_var (bvar->get_var_name (), *i);
1645 else
1646 Msg::inst()->error ("Can't assign scalar to array value");
1647 else if (bvar->item_syntax () || bvar->var_item_syntax ())
1648 p2tree->vars.set_array_element (bvar->get_var_name (),
1649 ((N_var *)loop_var)->get_index (),
1650 *i);
1651 else
1652 p2tree->vars.set_var (bvar->get_var_name (), *i);
1653 stmt->exec ();
1654 }
1655 return Gen_type (0);
1656 }
1657
1658 Gen_type
exec()1659 N_list::exec ()
1660 {
1661 set_msg_buffers ();
1662 Gen_type list = expr_list->exec ();
1663 if (! list.is_list ())
1664 {
1665 // We are starting building the list
1666 Gen_type ret_value ('l');
1667 ret_value.push (list);
1668 list = ret_value;
1669 }
1670 Gen_type to_add = new_expr->exec ();
1671 list.push (to_add);
1672 return list;
1673 }
1674
1675 Gen_type
exec()1676 N_fix_list::exec ()
1677 {
1678 set_msg_buffers ();
1679 Gen_type list_obj = list->exec ();
1680 if (list_obj.is_array () )
1681 {
1682 Gen_type ret_value ('a');
1683 ret_value.push (list_obj);
1684 return ret_value;
1685 }
1686 else
1687 {
1688 list_obj.fix_list ();
1689 return list_obj;
1690 }
1691 }
1692
1693 Gen_type
exec()1694 N_del::exec ()
1695 {
1696 set_msg_buffers ();
1697 Gen_type src_arr = source->exec ();
1698 if (! src_arr.is_array ())
1699 {
1700 Msg::inst()->error ("delete requires an array as first variable");
1701 return Gen_type (-1);
1702 }
1703 Gen_type pos_gt = pos->exec ();
1704 if (! pos_gt.is_int ())
1705 {
1706 Msg::inst()->error ("delete requires an int as second variable");
1707 return Gen_type (-1);
1708 }
1709 int pos_int = pos_gt.get_int ();
1710 if (pos_int < 0)
1711 {
1712 Msg::inst()->error ("array indexes must be > 0");
1713 return Gen_type (-1);
1714 }
1715 if (len)
1716 {
1717 Gen_type len_gt = len->exec ();
1718 if (! len_gt.is_int ())
1719 {
1720 Msg::inst()->error ("delete requires an int as third variable");
1721 return Gen_type (-1);
1722 }
1723 int len_int = len_gt.get_int ();
1724 if (len_int < 0)
1725 {
1726 Msg::inst()->error ("number of elements to delete must be > 0");
1727 return Gen_type (-1);
1728 }
1729 src_arr.erase (pos_int, len_int);
1730 }
1731 else
1732 {
1733 src_arr.erase (pos_int);
1734 }
1735 return src_arr;
1736 }
1737
1738 Gen_type
exec()1739 N_push::exec ()
1740 {
1741 set_msg_buffers ();
1742 Gen_type src_arr = source->exec ();
1743 if (! src_arr.is_array ())
1744 {
1745 Msg::inst()->error ("push requires an array as first variable");
1746 return Gen_type (-1);
1747 }
1748 if (pos)
1749 src_arr.set_element (pos->exec (), item->exec ());
1750 else
1751 src_arr.set_element (item->exec ());
1752 return src_arr;
1753 }
1754
1755 Gen_type
exec()1756 N_random::exec ()
1757 {
1758 set_msg_buffers ();
1759 Gen_type minimum = from->exec ();
1760 Gen_type maximum = to->exec ();
1761 if (! minimum.is_int ())
1762 {
1763 Msg::inst()->error ("minimum value must be an integer");
1764 return Gen_type ("");
1765 }
1766 if (! maximum.is_int ())
1767 {
1768 Msg::inst()->error ("maximum value must be an integer");
1769 return Gen_type ("");
1770 }
1771 int maximum_int = maximum.get_int () + 1;
1772 int minimum_int = minimum.get_int ();
1773 if (maximum_int <= minimum_int)
1774 {
1775 Msg::inst()->error ("maximum value must be greater than minimum");
1776 return Gen_type ("");
1777 }
1778 int result = minimum_int + (int)
1779 (rand () * (double) (maximum_int - minimum_int) / (double) (RAND_MAX));
1780
1781 return Gen_type (result);
1782 }
1783
1784 // Link Adjustment
1785
1786 Gen_type
exec()1787 N_adj_link::exec ()
1788 {
1789 set_msg_buffers ();
1790 return Gen_type (p2tree->adjust_level ());
1791 }
1792
1793 Gen_type
exec()1794 N_fileexists::exec ()
1795 {
1796 set_msg_buffers ();
1797 string sfile = file->exec ().get_string ();
1798 if (sfile [0] != '/')
1799 sfile = dir + sfile;
1800 return Gen_type (file_exists (sfile));
1801 }
1802
1803 Gen_type
exec()1804 N_fill::exec ()
1805 {
1806 set_msg_buffers ();
1807 string tmpl_str = (tmpl_string->exec ()).to_string (true);
1808 Gen_type fill_vars = n_vars->exec ();
1809 if (fill_vars.is_list () || fill_vars.is_array ())
1810 {
1811 Gen_type_c_iter from;
1812 Gen_type_c_iter to;
1813 if (fill_vars.is_list ())
1814 {
1815 from = fill_vars.get_list ()->begin ();
1816 to = fill_vars.get_list ()->end ();
1817 }
1818 else
1819 {
1820 from = fill_vars.get_array ()->begin ();
1821 to = fill_vars.get_array ()->end ();
1822 }
1823 for (Gen_type_c_iter i = from; i != to; i++)
1824 {
1825 int start = tmpl_str.find ("%s", 0);
1826 if (start >=0)
1827 tmpl_str.replace (start, 2, (i->to_string (true)));
1828 }
1829 }
1830 else
1831 {
1832 int start = tmpl_str.find ("%s", 0);
1833 tmpl_str.replace (start, 2, fill_vars.to_string (true));
1834 }
1835 return Gen_type (tmpl_str);
1836 }
1837