Index: trunk/SophyaPI/PIext/basexecut.cc
===================================================================
--- trunk/SophyaPI/PIext/basexecut.cc	(revision 1270)
+++ trunk/SophyaPI/PIext/basexecut.cc	(revision 1276)
@@ -34,4 +34,5 @@
 mImgApp = app;
 dynlink = NULL;
+dynlink2 = NULL;
 RegisterCommands();
 }
@@ -39,4 +40,6 @@
 PIABaseExecutor::~PIABaseExecutor()
 {
+  if (dynlink) delete dynlink;
+  if (dynlink2) delete dynlink2;
 }
 
@@ -124,11 +127,22 @@
   if (rc == 0)  cout << "PIABaseExecutor: Link from " << tokens[0] << " OK " << endl;
 }
+else if (kw == "linkff2" ) {
+  if (tokens.size() < 2) { cout << "Usage: linkff2 fnameso f1 [f2 f3]" << endl;  return(0); }
+  string sph = "";
+  for(int gg=0; gg<5; gg++)   tokens.push_back(sph);
+  int rc = LinkUserFuncs2(tokens[0], tokens[1], tokens[2], tokens[3]);
+  if (rc == 0)  cout << "PIABaseExecutor: Link2 from " << tokens[0] << " OK " << endl;
+}
 else if (kw == "call" ) {
   if (tokens.size() < 1) { cout << "Usage: call userf [arg1 arg2 ...]" << endl;  return(0); }
-  UsFmap::iterator it = usfmap.find(tokens[0]);
-  if (it == usfmap.end()) {
+  UsFmap::iterator it;
+  UsFmap::iterator it1 = usfmap.find(tokens[0]);
+  UsFmap::iterator it2 = usfmap2.find(tokens[0]);
+  if ((it1 == usfmap.end()) && (it2 == usfmap2.end()) ) {
     cerr << "PIABaseExecutor: No User Function " << tokens[0] << endl;
     return(0);
   }
+  if (it1 == usfmap.end())  it = it2;
+  else it = it1;
   cout << "PIABaseExecutor: Call " << tokens[0] << "( ... )" << endl;
 // on est oblige de faire un cast  etant donne qu'on 
@@ -138,4 +152,5 @@
   bool red = mImgApp->HasRedirectedStdOutErr();
   mImgApp->RedirectStdOutErr(false);
+#ifdef SANS_EVOLPLANCK
   TRY {
     tokens.erase(tokens.begin());
@@ -143,9 +158,25 @@
   }  CATCH(merr) {
     fflush(stdout); 
+    string es = PeidaExc(merr);
+    cerr << "\n PIABaseExecutor: Call UserFunc  Exception :" << merr << es;
     cout << endl; 
-    cerr << endl;
-//CMV_A_FAIRE    string es = PeidaExc(merr);
-//CMV_A_FAIRE    cerr << "PIABaseExecutor: Call UserFunc  Exception :" << merr << es;
-    }
+    }
+#else
+  try {
+    tokens.erase(tokens.begin());
+    fuf(tokens);
+  }
+  catch ( PThrowable & exc ) {
+    cerr << "\n PIABaseExecutor: Call / Catched Exception :" 
+	 << (string)typeid(exc).name() << " Msg= " 
+	 << exc.Msg() << endl;
+    cout << endl; 
+  }
+  catch ( ... ) {
+    cerr << "\n PIABaseExecutor: Call / Catched Exception ... " 
+	 << endl;
+    cout << endl; 
+  }
+#endif
   mImgApp->RedirectStdOutErr(red);
 }
@@ -677,5 +708,10 @@
 usage = "Dynamic linking of compiled user functions \n  Usage: link fnameso f1 [f2 f3]";
 usage += "\n  fnameso: Shared-object file name, f1,f2,f3 : User function names ";
-usage += "\n  Related commands: call loadmodule";  
+usage += "\n  Related commands: call loadmodule linkff2";  
+mpiac->RegisterCommand(kw, usage, this, "External Modules");
+kw = "linkff2";
+usage = "Dynamic linking of compiled user functions (Set 2)\n  Usage: linkff2 fnameso f1 [f2 f3]";
+usage += "\n  fnameso: Shared-object file name, f1,f2,f3 : User function names ";
+usage += "\n  Related commands: call link loadmodule";  
 mpiac->RegisterCommand(kw, usage, this, "External Modules");
 kw = "call";
@@ -1098,4 +1134,43 @@
 }
 
+/* --Methode-- */
+int PIABaseExecutor::LinkUserFuncs2(string& fnameso, string& func1, string& func2, string& func3)
+{
+string cmd;
+
+if (dynlink2) delete dynlink2;    dynlink2 = NULL;
+usfmap2.clear();
+
+dynlink2 = new PDynLinkMgr(fnameso, true);
+if (dynlink2 == NULL) { 
+  string sn = fnameso; 
+  cerr << "PIABaseExecutor/LinkUserFuncs2_Erreur: Erreur ouverture SO " << sn << endl; 
+  return(2); 
+  }
+
+int nok=0;
+// on utilise donc des DlFunction  (Reza 20/08/98)  voir commentaire ds .h (pb g++)
+// DlUserProcFunction f = NULL;
+DlFunction f = NULL;
+if ((func1.length() < 1) || (func1 == "-") || (func1 == ".") )  goto fin;
+f = dynlink2->GetFunction(func1);
+if (f) { nok++;  usfmap2[func1] = f; }
+else cerr << "PIABaseExecutor/LinkUserFuncs2_Erreur: Erreur linking " << func1 << endl;
+
+if ((func2.length() < 1) || (func2 == "-") || (func2 == ".") )  goto fin;
+f = dynlink2->GetFunction(func2);
+if (f) { nok++;  usfmap2[func2] = f; }
+else cerr << "PIABaseExecutor/LinkUserFuncs2_Erreur: Erreur linking " << func2 << endl;
+
+if ((func3.length() < 1) || (func3 == "-") || (func3 == ".") )  goto fin;
+f = dynlink2->GetFunction(func3);
+if (f) { nok++;  usfmap2[func3] = f; }
+else cerr << "PIABaseExecutor/LinkUserFuncs2_Erreur: Erreur linking " << func3 << endl;
+
+fin:
+if (nok < 1) { if (dynlink2) delete dynlink2;    dynlink2 = NULL;  return(3); }
+else return(0);
+}
+
 /* Nouvelle-Fonction */
 void RegisterPIGraphicsHelp(PIACmd* piac)
Index: trunk/SophyaPI/PIext/basexecut.h
===================================================================
--- trunk/SophyaPI/PIext/basexecut.h	(revision 1270)
+++ trunk/SophyaPI/PIext/basexecut.h	(revision 1276)
@@ -19,4 +19,5 @@
 //  Link dynamique de fonction user
   int 		LinkUserFuncs(string& fnameso, string& func1, string& func2, string& func3);
+  int 		LinkUserFuncs2(string& fnameso, string& func1, string& func2, string& func3);
 //                            string& func4, string& func5);   compil avec g++ 2.7.2
   PIACmd* mpiac;
@@ -28,4 +29,6 @@
   PDynLinkMgr* dynlink;
   UsFmap usfmap;
+  PDynLinkMgr* dynlink2;
+  UsFmap usfmap2;
 
 };
Index: trunk/SophyaPI/PIext/cxxexecutor.cc
===================================================================
--- trunk/SophyaPI/PIext/cxxexecutor.cc	(revision 1270)
+++ trunk/SophyaPI/PIext/cxxexecutor.cc	(revision 1276)
@@ -509,5 +509,5 @@
 NamedObjMgr omg;
 PIACmd* mpiac = omg.GetImgApp()->CmdInterpreter();
-string key("link");
+string key("linkff2");
 vector<string> arg; arg.push_back(libname); arg.push_back(func);
 string toks = libname + " " + func;
Index: trunk/SophyaPI/PIext/nobjmgr.cc
===================================================================
--- trunk/SophyaPI/PIext/nobjmgr.cc	(revision 1270)
+++ trunk/SophyaPI/PIext/nobjmgr.cc	(revision 1276)
@@ -129,6 +129,5 @@
   char* varenv;
   TmpDir = new string("");
-  if ( (varenv=getenv("PEIDA_TMP")) != NULL )  (*TmpDir) = varenv; 
-  else if ( (varenv=getenv("TMPDIR")) != NULL )  (*TmpDir) = varenv; 
+  if ( (varenv=getenv("TMPDIR")) != NULL )  (*TmpDir) = varenv; 
   int l = (*TmpDir).length();
   if ( (l>0) && ((*TmpDir)[l-1] != '/') )  (*TmpDir) += '/';
@@ -206,4 +205,7 @@
 if(tmpdir.length()<1) return;
 *TmpDir = tmpdir;
+int l = (*TmpDir).length();
+if ( (l>0) && ((*TmpDir)[l-1] != '/') )  (*TmpDir) += '/';
+servnobjm->SetTmpDir(*TmpDir);
 }
 
Index: trunk/SophyaPI/PIext/piacmd.cc
===================================================================
--- trunk/SophyaPI/PIext/piacmd.cc	(revision 1270)
+++ trunk/SophyaPI/PIext/piacmd.cc	(revision 1276)
@@ -169,4 +169,5 @@
   for(int kk=1; kk<args.size(); kk++) strlist.push_back(args[kk]);
   typ = BT_ForeachList;
+  blkok = true;
   }
 else { // This is an integer or float loop
@@ -189,4 +190,5 @@
   if (fl) { 
     typ = BT_ForeachFloat;
+    blkok = true;
     f1 = atof(a1.c_str());
     f2 = atof(a2.c_str());
@@ -196,4 +198,5 @@
   else { 
     typ = BT_ForeachInt;
+    blkok = true;
     i1 = atoi(a1.c_str());
     i2 = atoi(a2.c_str());
@@ -285,4 +288,6 @@
 bloccxx = false;
 bloctest = false;
+mulinecmd = "";
+mulinefg = false;
 
 cmdhgrp["All"] = 0;
@@ -490,9 +495,23 @@
 if (s[0] == '#') return(0); // si c'est un commentaire
 
+// Logique de gestion des lignes suite
+// un \ en derniere position indique la presence d'une ligne suite
+if (s[l-1] == '\\' ) { // Lignes suite ...
+  mulinefg = true;
+  mulinecmd += s.substr(0,l-1);
+  mImgApp->GetConsole()->SetPrompt("...? ");
+  return(0);
+}
+
+if (mulinefg) {  // Il y avait des lignes suite
+  s = mulinecmd + s;
+  mulinecmd = "";
+  mulinefg = false;
+  const char * rprompt = (curblk == NULL) ? "Cmd> " : "foreach? ";
+  mImgApp->GetConsole()->SetPrompt(rprompt);
+}
 
 // Removing leading blanks
-size_t p,q,q2;
-l = s.length();
-if (l < 1)  return(0);
+size_t p,q;
 
 p=s.find_first_not_of(" \t");
@@ -534,7 +553,7 @@
        }
     else  {
-      char prompt[64];
-      sprintf(prompt, "foreach-%d? ", felevel);
-      mImgApp->GetConsole()->SetPrompt(prompt);
+      //      char prompt[64];
+      //      sprintf(prompt, "foreach-%d? ", felevel);
+      mImgApp->GetConsole()->SetPrompt("foreach? ");
       }
     return(0);
@@ -544,5 +563,6 @@
 
 // Nous ne sommes donc pas dans un bloc ....  Substitution de variables
-
+string s2;
+int rcs ;
 // Execution de code C++
 
@@ -553,9 +573,9 @@
     return(99);
   }
-  if (s[1] == '@') { // Sans substitution des variables $
-    return(cxxe->ExecuteCXX(s.substr(2)));
-  } else { // Avec substitution de variables $
-    string s2;
-    SubstituteVars(s, s2);
+  // Sans substitution des variables $
+  if (s[1] == '@') return(cxxe->ExecuteCXX(s.substr(2)));
+  else { // AVEC substitution des variables $
+    rcs = SubstituteVars(s, s2);
+    if (rcs) return(rcs);
     return(cxxe->ExecuteCXX(s2.substr(1)));    
   }
@@ -563,6 +583,6 @@
 
 
-string s2;
-SubstituteVars(s, s2);
+rcs = SubstituteVars(s, s2);
+if (rcs) return(rcs);
 
 // >>>> Separating keyword and tokens 
@@ -579,5 +599,15 @@
   p = toks.find_first_not_of(" \t",q+1); // au debut d'un token
   if (p>=l) break;
-  q = toks.find_first_of(" \t",p); // la fin du token;
+  if ( (toks[p] == '\'') || (toks[p] == '"') ) {
+    q = toks.find(toks[p],p+1);
+    if (q>=l)  { 
+      cerr << "Syntax Error - Unbalenced quotes " << toks[p] << '.' << endl;
+      return(2);
+    }
+    p++;
+  }
+  else {
+    q = toks.find_first_of(" \t",p); // la fin du token;
+  }
   string token = toks.substr(p,q-p);
   tokens.push_back(token);
@@ -629,6 +659,16 @@
 while (p < l) {
   q = s.find('$',p);
+  if (q > l) break;
+  q2 = s.find('\'',p);
+  if ((q2 < l) && (q2 < q)) {  // On saute la chaine delimitee par ' '
+    q2 = s.find('\'',q2+1);
+    if (q2 >= l) {
+      cerr << " Syntax error - Unbalenced  quotes !!! " << endl;
+      return(1);
+      }
+    s2 += s.substr(p, q2-p+1);
+    p = q2+1;  continue;  
+  }
   //  cout << "DBG: " << s2 << " p= " << p << " q= " << q << " L= " << l << endl;
-  if (q > l) break;
   if ((q>0) && (s[q-1] == '\\')) {   // Escape character \$
      s2 += (s.substr(p,q-1-p) + '$') ; p = q+1;
@@ -636,6 +676,6 @@
      }
   if (q >= l-1) {
-      cerr << " Syntax error !!! " << endl;
-      return(0);
+      cerr << " Syntax error - line ending with $ !!! " << endl;
+      return(2);
       }
   vn = "";
@@ -643,6 +683,6 @@
     q2 = s.find('}',q+1);
     if (q2 >= l) {
-      cerr << " Syntax error !!! " << endl;
-      return(0);
+      cerr << " Syntax error -  Unbalenced  brace {} !!! " << endl;
+      return(3);
       }
     vn = s.substr(q+2,q2-q-2);
@@ -652,11 +692,11 @@
     q2 = s.find(']',q+1);
     if (q2 >= l) {
-      cerr << " Syntax error !!! " << endl;
-      return(0);
+      cerr << " Syntax error - Unbalenced  brace [] !!! " << endl;
+      return(4);
       }
     vn = s.substr(q+2,q2-q-2);
     if ( (vn.length() < 1) || (!omg.HasVar(vn)) )  {
       cerr << " Error: Undefined variable " << vn << " ! " << endl;
-      return(0);
+      return(5);
       }
     vn = omg.GetVar(vn);
@@ -664,5 +704,5 @@
     }
   else { 
-    q2 = s.find_first_of(" .:/,]()$",q+1); 
+    q2 = s.find_first_of(" .:/,]()$\"'",q+1); 
     if (q2 > l) q2 = l;
     vn = s.substr(q+1, q2-q-1); 
@@ -670,5 +710,5 @@
   if ( (vn.length() < 1) || (!omg.HasVar(vn)) )  {
     cerr << " Error: Undefined variable " << vn << " ! " << endl;
-    return(0);
+    return(5);
     }
   s2 += (s.substr(p, q-p) + omg.GetVar(vn));
@@ -705,7 +745,7 @@
     return(0);
     }
-  string xx = tokens[1];
-  for (int kk=2; kk<tokens.size(); kk++)  xx += (' ' + tokens[kk] );
-  omg.SetVar(tokens[0], xx);
+  //  string xx = tokens[1];
+  //  for (int kk=2; kk<tokens.size(); kk++)  xx += (' ' + tokens[kk] );
+  omg.SetVar(tokens[0], tokens[1]);
   }
 
@@ -756,8 +796,8 @@
   }
 else if (kw == "echo") {
-  for (int kk=0; kk<tokens.size(); kk++)  cout << tokens[kk] << " " ;
+  for (int ii=0; ii<tokens.size(); ii++)
+    cout << tokens[ii] << " " ;
   cout << endl;
-  }
-
+ }
 else if (kw == "readstdin") {
   if (tokens.size() < 1) { cout << "PIACmd::Interpret() Usage: readstdin varname" << endl;  return(0); }
@@ -816,8 +856,11 @@
 else if (kw == "shell") {
   if (tokens.size() < 1) { cout << "PIACmd::Interpret() Usage: shell cmdline" << endl;  return(0); }
-  system(toks.c_str());
-  }
+  string cmd;
+  for (int ii=0; ii<tokens.size(); ii++)
+    cmd += (tokens[ii] + ' ');
+  system(cmd.c_str());
+  }
+
 //  Execution d'une commande enregistree
-// CMV c'est ici qu'il faut passer la string
 else rc = ExecuteCommand(kw, tokens, toks);
 
@@ -894,5 +937,4 @@
 // Setting $0 ... $99 variables 
 int k;
-CmdVarList::iterator it;
 char buff[32];
 // First, we clear all previous values
Index: trunk/SophyaPI/PIext/piacmd.h
===================================================================
--- trunk/SophyaPI/PIext/piacmd.h	(revision 1270)
+++ trunk/SophyaPI/PIext/piacmd.h	(revision 1276)
@@ -134,5 +134,4 @@
 //  Pour stocker les variables definies par l'interpreteur
   typedef map<string, string, less<string> > CmdVarList;
-  //  CmdVarList mVars;     Liste des variables 
   CmdVarList mAliases;  // Liste des alias 
 
@@ -143,5 +142,7 @@
   bool bloctest;            // On est ds un bloc test
   bool bloccxx;             // On est ds un bloc code C++
-  string codecxx;
+  string codecxx;           // Bloc de code C++
+  bool mulinefg;            // Bloc multi-lignes (ligne suite)
+  string mulinecmd;         // Commande multi-lignes
 
   ofstream hist;       //  History file 
Index: trunk/SophyaPI/PIext/pistdimgapp.cc
===================================================================
--- trunk/SophyaPI/PIext/pistdimgapp.cc	(revision 1270)
+++ trunk/SophyaPI/PIext/pistdimgapp.cc	(revision 1276)
@@ -391,9 +391,16 @@
     mCmd->Interpret(s);
     }  
-  catch ( PThrowable exc ) {
+  catch ( PThrowable & exc ) {
+    cerr << "\n PIStdImgApp::Process()/ Cmd->Interpret() Exception :" 
+	 << (string)typeid(exc).name() << " Msg= " 
+	 << exc.Msg() << endl;
     cout << endl; 
-    cerr << endl;
-    cerr << "PIStdImgApp::Process()/ Cmd->Interpret() Exception :" << exc.Msg() << endl;
-  }
+  }
+  catch ( ... ) {
+    cerr << "\n PIStdImgApp::Process()/ Cmd->Interpret() Catched Exception ..." 
+	 << endl;
+    cout << endl; 
+  }
+
 #endif
   SetReady();
Index: trunk/SophyaPI/PIext/servnobjm.cc
===================================================================
--- trunk/SophyaPI/PIext/servnobjm.cc	(revision 1270)
+++ trunk/SophyaPI/PIext/servnobjm.cc	(revision 1276)
@@ -49,6 +49,5 @@
 Services2NObjMgr::Services2NObjMgr(NamedObjMgr* omg, string& tmpdir)
 {
-TmpDir = tmpdir;
-PDynLinkMgr::SetTmpDir(tmpdir);
+SetTmpDir(tmpdir);
 mImgapp = NULL;
 mOmg = omg;
@@ -87,4 +86,12 @@
   if (typeid(*o) == typeid(*((*it).obj)))  return((*it).obja->Clone(o));
 return(new NObjMgrAdapter(o));
+}
+
+/* --Methode-- */
+void Services2NObjMgr::SetTmpDir(string const & tmpdir)
+{
+TmpDir = tmpdir;
+PDynLinkMgr::SetTmpDir(tmpdir);
+return;
 }
 
Index: trunk/SophyaPI/PIext/servnobjm.h
===================================================================
--- trunk/SophyaPI/PIext/servnobjm.h	(revision 1270)
+++ trunk/SophyaPI/PIext/servnobjm.h	(revision 1276)
@@ -46,4 +46,5 @@
 
   inline void   SetImgApp(PIStdImgApp* app) {mImgapp = app; }
+  void          SetTmpDir(string const & tmpdir);
 
 // Trace de fonctions 1-D , 2-D
