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