Index: trunk/SophyaPI/PIext/piacmd.cc
===================================================================
--- trunk/SophyaPI/PIext/piacmd.cc	(revision 2214)
+++ trunk/SophyaPI/PIext/piacmd.cc	(revision 2215)
@@ -10,4 +10,5 @@
 #include "ctimer.h"
 #include "strutil.h"
+#include "strutilxx.h"
 // #include "dlftypes.h"
 
@@ -141,7 +142,9 @@
   inline void	AddLine(string& line)  
     { lines.push_back(line); bloclineid.push_back(lines.size()); }
+  void	        AddLine(string& line, string& kw);  
   inline void	AddBloc(PIACmdBloc* blk)  
     { blocs.push_back(blk); bloclineid.push_back(-blocs.size()); }
   PIACmdBloc*	Execute();
+  inline int&   TestLevel()  { return testlevel; }
 protected:
   PIACmd* piacmd;
@@ -156,4 +159,5 @@
   int i1,i2,di;
   float f1,f2,df;
+  int testlevel;   // niveau d'imbrication des if 
 };
 
@@ -167,4 +171,5 @@
 i1 = 0;  i2 = -1;  di = 1;
 f1 = 0.; f2 = -1.; df = 1.;
+testlevel = 0;
 if ((args.size() < 2) ||  !isalpha((int)args[0][0]) )  return; 
 if ((kw != "foreach") && (kw != "for"))  return;
@@ -172,5 +177,6 @@
 //if (isalpha((int)args[1][0]) ) {  This is a foreach bloc with string list
 if (kw == "foreach" ) { // This is a foreach bloc with string list
-  for(int kk=1; kk<args.size(); kk++) strlist.push_back(args[kk]);
+  if ((args[1] != "(") || (args[args.size()-1] != ")") ) return;
+  for(int kk=2; kk<args.size()-1; kk++) strlist.push_back(args[kk]);
   typ = BT_ForeachList;
   blkok = true;
@@ -219,4 +225,12 @@
 
 /* --Methode-- */
+void PIACmdBloc::AddLine(string& line, string& kw)
+{
+  AddLine(line);
+  if (kw == "if")  testlevel++;
+  else if (kw == "endif")  testlevel--; 
+}
+
+/* --Methode-- */
 PIACmdBloc* PIACmdBloc::Execute()
 {
@@ -228,4 +242,6 @@
 int kk=0;
 char buff[32];
+int rcc = 0;
+
 if (typ == BT_ForeachList)   // foreach string loop
   for(k=0; k<strlist.size(); k++) {
@@ -234,7 +250,11 @@
     for(kj=0; kj<bloclineid.size(); kj++) {
       kk = bloclineid[kj]; 
-      if (kk > 0)  piacmd->Interpret(lines[kk-1]);
+      if (kk > 0)  { 
+	rcc = piacmd->Interpret(lines[kk-1]);
+	if (rcc == 77766)  break;
+      }
       else blocs[-kk-1]->Execute();
-      }
+    }
+    if (rcc == 77766)  break;
   }
 else if (typ == BT_ForeachInt)  // Integer loop
@@ -250,7 +270,11 @@
     for(kj=0; kj<bloclineid.size(); kj++) {
       kk = bloclineid[kj]; 
-      if (kk > 0)  piacmd->Interpret(lines[kk-1]);
+      if (kk > 0)  { 
+	rcc = piacmd->Interpret(lines[kk-1]);
+	if (rcc == 77766)  break;
+      }
       else blocs[-kk-1]->Execute();
-      }
+    }
+    if (rcc == 77766)  break;
   }
 else if (typ == BT_ForeachFloat)  // float loop
@@ -266,7 +290,11 @@
     for(kj=0; kj<bloclineid.size(); kj++) {
       kk = bloclineid[kj]; 
-      if (kk > 0)  piacmd->Interpret(lines[kk-1]);
+      if (kk > 0)  { 
+	rcc = piacmd->Interpret(lines[kk-1]);
+	if (rcc == 77766)  break;
+      }
       else blocs[-kk-1]->Execute();
-      }
+    }
+    if (rcc == 77766)  break;
   }
 
@@ -298,8 +326,13 @@
 trace = false;   timing = false;
 gltimer = NULL;
-curblk = NULL;
 felevel = 0;
+
 mulinecmd = "";
 mulinefg = false;
+
+CmdBlks.push(NULL);
+list<char> xtx;
+TestsStack.push(xtx);
+curtestresult = true;
 
 cmdhgrp["All"] = 0;
@@ -517,4 +550,5 @@
 NamedObjMgr omg;
 
+
 // On saute de commandes vides
 size_t l;
@@ -541,5 +575,5 @@
   mulinecmd = "";
   mulinefg = false;
-  const char * rprompt = (curblk == NULL) ? "Cmd> " : "for...? ";
+  const char * rprompt = (CmdBlks.empty()) ? "Cmd> " : "for...? ";
   mImgApp->GetConsole()->SetPrompt(rprompt);
 }
@@ -583,31 +617,34 @@
 }
 
-if (kw == "break") {
-  PIACmdBloc* curb = curblk;
-  while (curb) {
-    PIACmdBloc* dblk = curb;
-    curb = curb->Parent();
-    delete dblk;
-  }
-  testresult.clear();
-  return(0);
-}
-else if (kw == "return")  return(77777);
-
 // On verifie si nous sommes dans un bloc (for , foreach)
-if (curblk != NULL)  { // On est dans un bloc
+if (CmdBlks.top() != NULL)  { // On est dans un bloc
   if ( (kw == "for") || (kw == "foreach")) felevel++;
   else if (kw == "end") felevel--;
   if (felevel == 0) { // Il faut executer le bloc
-    PIACmdBloc* curb = curblk;
-    curblk = curb->Parent();
+    PIACmdBloc* curb = CmdBlks.top();
+    CmdBlks.top() = curb->Parent();
     mImgApp->GetConsole()->SetPrompt("Cmd> ");
+    if (curb->TestLevel() != 0) {
+      cerr << "PIACmd::Interpret()/syntax error - unbalenced if ... endif"
+	   << " within for/foreach bloc ! " << endl;
+      delete curb;
+      return(2);  
+    }
        //       cout << " *DBG* Executing bloc " << endl;
     bool ohv = histon;
     histon = false;
-    curb->Execute();
+    if (curtestresult) { 
+      // We push also PIACmdBloc and testresult on the stack
+      CmdBlks.push(NULL);
+      list<char> xtx;
+      TestsStack.push(xtx);
+      curb->Execute();
+      // And PIACmdBloc and TestResult from the corresponding stacks
+      PopStack(false);
+    }
+    delete curb;
     histon = ohv;
   }
-  else curblk->AddLine(s); 
+  else CmdBlks.top()->AddLine(s, kw); 
   return(0);
 }
@@ -619,5 +656,5 @@
 
 // Sommes-nous dans un bloc de test if then else 
-if (testresult.size() > 0) {  // Nous sommes ds un bloc if 
+if (TestsStack.top().size() > 0) {  // Nous sommes ds un bloc if 
   if (kw == "else") {
     if ((*tresit) & 2) {
@@ -628,4 +665,5 @@
     else { 
       const char * npr = ((*tresit)&1) ? "else-F> " : "else-T> ";
+      if ((*tresit)&1)  curtestresult = false;
       mImgApp->GetConsole()->SetPrompt(npr);
       (*tresit) |= 2;
@@ -636,7 +674,17 @@
     list<char>::iterator dbit = tresit;
     tresit--;
-    testresult.erase(dbit);
+    TestsStack.top().erase(dbit);
     const char * npr = "Cmd> ";
-    if (testresult.size() > 1) {
+    if (TestsStack.top().size() > 1) {
+      curtestresult = true;
+      list<char>::iterator it;
+      for(it=TestsStack.top().begin(); it!=TestsStack.top().end(); it++) {
+	// Si on n'est pas ds le else et le if est faux
+	if ( !((*it)&2) && !((*it)&1) ) curtestresult = false;
+	// Si on est ds else et le if etait vrai !
+	if ( ((*it)&2) && ((*it)&1) )  curtestresult = false;
+	if (!curtestresult)  break;
+      }
+      
       if (!((*tresit)&2)) 
 	npr = ((*tresit)&1) ? "if-T> " : "if-F> ";
@@ -644,4 +692,5 @@
 	npr = ((*tresit)&1) ? "else-F> " : "else-T> ";
     }
+    else curtestresult = true;
     mImgApp->GetConsole()->SetPrompt(npr);
     return(0);
@@ -655,7 +704,7 @@
 
 bool fgcont = true;
-if (testresult.size() > 0) { // Resultat de if ou else
+if (TestsStack.top().size() > 0) { // Resultat de if ou else
   list<char>::iterator it;
-  for(it=testresult.begin(); it!=testresult.end(); it++) {
+  for(it=TestsStack.top().begin(); it!=TestsStack.top().end(); it++) {
     // Si on n'est pas ds le else et le if est faux
     if ( !((*it)&2) && !((*it)&1) )  fgcont = false;
@@ -668,4 +717,8 @@
 if ((!fgcont) && (kw != "if"))  return(0);
 
+
+// Les mots cles break et return peuvent de sortir de boucles/scripts/execfile
+if (kw == "break") return(77766);
+else if (kw == "return")  return(77777);
 
 // Nous ne sommes donc pas dans un bloc ....  Substitution de variables
@@ -725,5 +778,5 @@
 if ((kw == "foreach") || (kw == "for")) {
   //     cout << " *DBG* We got a foreach... " << endl;
-  PIACmdBloc* bloc = new PIACmdBloc(this, curblk, kw, tokens);
+  PIACmdBloc* bloc = new PIACmdBloc(this, CmdBlks.top(), kw, tokens);
   if (!bloc->CheckOK()) {
     cerr << "PIACmd::Interpret() for/foreach syntax Error ! " << endl;
@@ -732,7 +785,7 @@
     }
   felevel++;
-  if (curblk)  curblk->AddBloc(bloc);
+  if (CmdBlks.top())  CmdBlks.top()->AddBloc(bloc);
   else  mImgApp->GetConsole()->SetPrompt("for...> ");
-  curblk = bloc;
+  CmdBlks.top() = bloc;
   //  cout << " *DBG* New Bloc created ... " << endl;
   return(0);
@@ -746,6 +799,6 @@
   }
   char res_tst = (restst) ? 1 : 0;
-  testresult.push_back(res_tst);
-  if (testresult.size() == 1) tresit = testresult.begin();
+  TestsStack.top().push_back(res_tst);
+  if (TestsStack.top().size() == 1) tresit = TestsStack.top().begin();
   else tresit++;
   const char * npr = (restst) ? "if-T> " : "if-F> ";
@@ -768,5 +821,6 @@
 NamedObjMgr& omg = *mObjMgr;
 
-size_t p,q,q2,l;
+int iarr = -1;  // index d'element de tableau
+size_t p,q,q2,q3,l;
 
 s2="";
@@ -805,5 +859,14 @@
     vn = s.substr(q+2,q2-q-2);
     q2++;
-    }
+  }
+  else if ( s[q+1] == '(' ) {  // Variable in the form $(name)
+    q2 = s.find(')',q+1);
+    if (q2 >= l) {
+      cerr << " Syntax error -  Unbalenced  parenthesis () !!! " << endl;
+      return(3);
+      }
+    vn = s.substr(q+2,q2-q-2);
+    q2++;
+  }
   else if ( s[q+1] == '[' ) {  // Variable in the form $[varname]  -> This is $$varname
     q2 = s.find(']',q+1);
@@ -820,10 +883,35 @@
     q2 = s.find_first_of(" .:+-*/,[](){}&|!$\"'",q+1); 
     if (q2 > l) q2 = l;
+    q3 = q2;
     vn = s.substr(q+1, q2-q-1); 
-    }
+    // Si variable de type $varname[index] : element de tableau
+    if ((q2 < l) && (s[q2] == '[') ) {
+      q3 = s.find_first_of("]",q2+1);
+      string sia = s.substr(q2+1, q3-q2-1);
+      int rcdia = ctoi(sia.c_str(), &iarr);
+      if (rcdia < 0) {
+	cerr << " Syntax error - in $varname[iarr] : $" 
+	     << vn << "[" << sia <<"]" << endl;
+	return(4);
+      }
+    }
+  }
   if (!GetVar(vn, vv)) return(5);
-  s2 += (s.substr(p, q-p) + vv);
-  p = q2;
-  } 
+  if (iarr < 0) {
+    s2 += (s.substr(p, q-p) + vv);
+    p = q2;
+  }
+  else {
+    vector<string> vs;
+    FillVStringFrString(vv, vs);
+    if (iarr >= vs.size()) {
+      cerr << " Substitution error - word index out of range in "
+	   << "$varname[iarr] : $" << vn << "[" << iarr <<"]" << endl;
+      return(4);
+    }
+    else s2 += (s.substr(p, q-p) + vs[iarr]);
+    p = q3+1;
+  }
+} 
 if (p < l) s2 += s.substr(p);
 
@@ -884,17 +972,45 @@
 {
   res = true;
-  if ((args.size() < 4) || (args[3] != "then")) return(1);
-  if (args[1] == "==") res = (args[0] == args[2]);
-  else if (args[1] == "!=") res = (args[0] != args[2]);
-  else if (args[1] == "<") 
-    res = (atof(args[0].c_str()) < atof(args[2].c_str()));
-  else if (args[1] == ">") 
-    res = (atof(args[0].c_str()) > atof(args[2].c_str()));
-  else if (args[1] == "<=") 
-    res = (atof(args[0].c_str()) <= atof(args[2].c_str()));
-  else if (args[1] == ">=") 
-    res = (atof(args[0].c_str()) >= atof(args[2].c_str()));
+  if ((args.size() != 6) || (args[5] != "then") || 
+      (args[0] != "(") || (args[4] != ")") ) return(1);
+  if (args[2] == "==") res = (args[1] == args[3]);
+  else if (args[2] == "!=") res = (args[1] != args[3]);
+  else if (args[2] == "<") 
+    res = (atof(args[1].c_str()) < atof(args[3].c_str()));
+  else if (args[2] == ">") 
+    res = (atof(args[1].c_str()) > atof(args[3].c_str()));
+  else if (args[2] == "<=") 
+    res = (atof(args[1].c_str()) <= atof(args[3].c_str()));
+  else if (args[2] == ">=") 
+    res = (atof(args[1].c_str()) >= atof(args[3].c_str()));
   else return(2);
   return(0);
+}
+
+/* --Methode-- */
+void PIACmd::PushStack(vector<string>& args)
+{
+  // We push the argument list (args) on the stack
+  ArgsStack.push(args);
+  // We push also PIACmdBloc and testresult on the stack
+  CmdBlks.push(NULL);
+  list<char> xtx;
+  TestsStack.push(xtx);
+
+}
+
+/* --Methode-- */
+void PIACmd::PopStack(bool psta)
+{
+  // We remove the argument list (args) from the stack
+  if (psta) ArgsStack.pop();
+  // And PIACmdBloc and TestResult from the corresponding stacks
+  PIACmdBloc* curb = CmdBlks.top();
+  while (curb != NULL) {
+    PIACmdBloc* parb = curb->Parent();
+    delete curb;  curb = parb;
+  }
+  CmdBlks.pop();
+  TestsStack.pop();
 }
 
@@ -1122,7 +1238,5 @@
 // hist << "### Executing commands from " << file << endl;
 
-// We push the argument list (args) on the stack
-ArgsStack.push(args);
-
+PushStack(args);
 if (trace) { 
   mImgApp->GetConsole()->AddStr("### Executing commands from ", PIVA_Magenta);
@@ -1149,6 +1263,5 @@
   }
 
-// We remove the argument list (args) from the stack
-ArgsStack.pop();
+PopStack(true);
 
 return(0);
