Index: CMT/HEAD/ChangeLog
===================================================================
--- CMT/HEAD/ChangeLog	(revision 609)
+++ CMT/HEAD/ChangeLog	(revision 610)
@@ -1,2 +1,23 @@
+2012-04-16    <rybkin@lal.in2p3.fr> 485
+
+	* source/cmt_system.cxx: In class CmtSystem, re-write split function in
+	order to improve and optimise algorithm
+	* source/cmt_system.h: In class CmtSystem split function, introduce
+	argument bool& unquote with default value true
+	* source/cmt_use.cxx: In classes VersionReader, PackageReader function
+	filter, do not parse comment lines
+	* source/cmt_project.cxx: In class ProjectReader function filter, do not
+	parse comment lines
+	* source/cmt_string.h: In class cmt_string, introduce constructor from
+	character array with
+	* source/cmt_string.cxx: In class cmt_string, implement constructor from
+	character array with
+	* source/cmt_parser.cxx: In class Cmt function vector_to_string, make sure
+	separator is not prepended at beginning
+	* source/cmt_symbol.cxx: Introduce helper function find_path_entry with
+	cmt_string_vector& (rather than cmt_string) first argument, in class
+	PathBuilder function build, perform all calculations on vector of values,
+	rather than string, in order to optimise and improve algorithm
+	
 2012-04-05    <rybkin@lal.in2p3.fr> 484
 
Index: CMT/HEAD/source/cmt_parser.cxx
===================================================================
--- CMT/HEAD/source/cmt_parser.cxx	(revision 609)
+++ CMT/HEAD/source/cmt_parser.cxx	(revision 610)
@@ -9842,5 +9842,6 @@
       if (s == "") continue;
 
-      if (i > 0) result += separator;
+      if (result.size () != 0) result += separator;
+      //if (i > 0) result += separator;
       result += v[i];
     }
Index: CMT/HEAD/source/cmt_project.cxx
===================================================================
--- CMT/HEAD/source/cmt_project.cxx	(revision 609)
+++ CMT/HEAD/source/cmt_project.cxx	(revision 610)
@@ -36,4 +36,6 @@
   void filter (const cmt_string& line)
   {
+    if (0 == line.size () ||
+	line[0] == '#') return;
     CmtSystem::cmt_string_vector words;
     CmtSystem::split (line, " \t", words);
Index: CMT/HEAD/source/cmt_string.cxx
===================================================================
--- CMT/HEAD/source/cmt_string.cxx	(revision 609)
+++ CMT/HEAD/source/cmt_string.cxx	(revision 610)
@@ -49,4 +49,19 @@
       allocate (_size + 1);
       strcpy (_data, text);
+    }
+}
+
+cmt_string::cmt_string (const char* text, int n)
+{
+  _data = 0;
+  _allocated = 0;
+  _size = 0;
+
+  if (text != 0)
+    {
+      _size = strlen (text) < n ? strlen (text) : n;
+      allocate (_size + 1);
+      strncpy (_data, text, _size);
+      _data[_size] = 0;
     }
 }
Index: CMT/HEAD/source/cmt_string.h
===================================================================
--- CMT/HEAD/source/cmt_string.h	(revision 609)
+++ CMT/HEAD/source/cmt_string.h	(revision 610)
@@ -26,4 +26,5 @@
   cmt_string (char c);
   cmt_string (const char* text);
+  cmt_string (const char* text, int n);
   cmt_string (const cmt_string& other);
   ~cmt_string ();
Index: CMT/HEAD/source/cmt_symbol.cxx
===================================================================
--- CMT/HEAD/source/cmt_symbol.cxx	(revision 609)
+++ CMT/HEAD/source/cmt_symbol.cxx	(revision 610)
@@ -2220,8 +2220,10 @@
 }
 
-static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
+static bool find_path_entry (const CmtSystem::cmt_string_vector& items, const cmt_string& value)
 {
   static const cmt_string path_separator = CmtSystem::path_separator ();
   static cmt_vmap <cmt_string, cmt_string> realpaths;
+
+  if (value.size () == 0) return true;
 
   cmt_string rvalue;
@@ -2240,6 +2242,6 @@
     }
 
-  CmtSystem::cmt_string_vector items;
-  CmtSystem::split (paths, path_separator, items);
+  //  CmtSystem::cmt_string_vector items;
+  //  CmtSystem::split (paths, path_separator, items);
 
   bool found = false;
@@ -2248,4 +2250,5 @@
     {
       const cmt_string& item = items[i];
+      if (item.size () == 0) continue;
       cmt_string ritem;
       const cmt_string * pritem;
@@ -2272,4 +2275,56 @@
 }
 
+static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
+{
+  static const cmt_string path_separator = CmtSystem::path_separator ();
+  static cmt_vmap <cmt_string, cmt_string> realpaths;
+
+  cmt_string rvalue;
+  const cmt_string * prvalue;
+
+  if (!(prvalue = realpaths.find (value)))
+    {
+      if (!CmtSystem::realpath_ (value, rvalue))
+	{
+	  rvalue = value;
+	  CmtSystem::compress_path (rvalue);
+	}
+      prvalue = &rvalue;
+      realpaths.add (value, rvalue);
+      //      cerr << "realpaths.add: " << value << " , " << rvalue << endl;
+    }
+
+  CmtSystem::cmt_string_vector items;
+  CmtSystem::split (paths, path_separator, items);
+
+  bool found = false;
+
+  for (int i = 0; i < items.size (); i++)
+    {
+      const cmt_string& item = items[i];
+      cmt_string ritem;
+      const cmt_string * pritem;
+
+      if (!(pritem = realpaths.find (item)))
+	{
+	  if (!CmtSystem::realpath_ (item, ritem))
+	    {
+	      ritem = item;
+	      CmtSystem::compress_path (ritem);
+	    }
+	  pritem = &ritem;
+	  realpaths.add (item, ritem);
+	  //  cerr << "realpaths.add: " << item << " , " << ritem << endl;
+	}
+      if (*pritem == *prvalue)
+	{
+	  found = true;
+	  break;
+	}
+    }
+
+  return (found);
+}
+
 //-------------------------------------------------------------
 const cmt_string PathBuilder::build (const Symbol& symbol,
@@ -2282,5 +2337,7 @@
 
   cmt_string temp;
-  cmt_string previous_temp;
+  CmtSystem::cmt_string_vector temp_vector;
+  //  cmt_string previous_temp;
+  CmtSystem::cmt_string_vector new_value_vector;
   cmt_string new_value;
   static const cmt_string empty;
@@ -2301,5 +2358,6 @@
   level++;
 
-  temp = CmtSystem::getenv (symbol.name);
+  CmtSystem::split (CmtSystem::getenv (symbol.name), path_separator, temp_vector);
+  //temp = CmtSystem::getenv (symbol.name);
 
   bool first_definition = true;
@@ -2337,6 +2395,8 @@
                 !symbol.value_is_reflexive (value.text))
               {
+                Cmt::vector_to_string (temp_vector, path_separator, temp);
                 resolve_value (new_value, symbol.name, temp);
-                temp = new_value;
+		CmtSystem::split (new_value, path_separator, temp_vector);
+                //temp = new_value;
               }
 
@@ -2346,10 +2406,16 @@
             if (new_value != "")
               {
-                if (!find_path_entry (temp, new_value))
-                  {
-                    if (temp != "") temp += path_separator;
-                      
-                    temp += new_value;
-                  }
+		CmtSystem::split (new_value, path_separator, new_value_vector);
+		for (int i = 0; i < new_value_vector.size (); i++)
+		  if (!find_path_entry (temp_vector, new_value_vector[i]))
+		    //if (!find_path_entry (temp, new_value))
+		    {
+		      temp_vector.push_back (new_value_vector[i]);
+		      /*
+			if (temp != "") temp += path_separator;
+			
+			temp += new_value;
+		      */
+		    }
               }
                   
@@ -2359,13 +2425,25 @@
             if (new_value != "")
               {
-                if (!find_path_entry (temp, new_value))
-                  {
-                    previous_temp = temp;
-                    temp = new_value;
-                    if (previous_temp != "") temp += path_separator;
-                    temp += previous_temp;
-                  }
+		CmtSystem::split (new_value, path_separator, new_value_vector);
+		int n (new_value_vector.size ());
+		temp_vector.resize (temp_vector.size () + n);
+		for (int i = temp_vector.size () - 1; i > n - 1; i--)
+		  temp_vector [i] = temp_vector [i - n];
+		for (int i = 0; i < new_value_vector.size (); i++)
+		  if (!find_path_entry (temp_vector, new_value_vector[i]))
+		    //if (!find_path_entry (temp, new_value))
+		    {
+		      temp_vector [i] = new_value_vector[i];
+		      /*
+			previous_temp = temp;
+			temp = new_value;
+			if (previous_temp != "") temp += path_separator;
+			temp += previous_temp;
+		      */
+		    }
+		  else
+		    temp_vector [i] = "";
               }
-                  
+	    
             break;
           case CommandPathRemove :
@@ -2373,4 +2451,14 @@
             if (new_value != "")
               {
+                for (int j = 0; j < temp_vector.size (); ++j)
+                  {
+                    cmt_string& s = temp_vector[j];
+                    
+                    if (s.find (new_value) != cmt_string::npos)
+                      {
+                        s = "";
+                      }
+                  }
+		/*
                 CmtSystem::cmt_string_vector paths;
                   
@@ -2388,4 +2476,5 @@
 
                 Cmt::vector_to_string (paths, path_separator, temp);
+		*/
               }
               
@@ -2397,4 +2486,41 @@
 		cmt_regexp e (new_value);
 
+                for (int j = 0; j < temp_vector.size (); ++j)
+                  {
+                    cmt_string& s = temp_vector[j];
+
+		    if (Cmt::get_debug () &&
+			CmtSystem::getenv ("TESTPRR") != "")
+		      {
+			cerr << "PRR> s=[" << s << "]";
+		      }
+
+                    if (e.match (s))
+                      {
+                        s = "";
+
+			if (Cmt::get_debug () &&
+			    CmtSystem::getenv ("TESTPRR") != "")
+			  {
+			    cerr << " match ";
+			  }
+                      }
+		    else
+                      {
+			if (Cmt::get_debug () &&
+			    CmtSystem::getenv ("TESTPRR") != "")
+			  {
+			    cerr << " no match ";
+			  }
+                      }
+
+		    if (Cmt::get_debug () &&
+			CmtSystem::getenv ("TESTPRR") != "")
+		      {
+			cerr << endl;
+		      }
+                  }
+
+		/*
                 CmtSystem::cmt_string_vector paths;
                   
@@ -2434,4 +2560,5 @@
 
                 Cmt::vector_to_string (paths, path_separator, temp);
+		*/
               }
               
@@ -2440,4 +2567,6 @@
 
     }
+
+  Cmt::vector_to_string (temp_vector, path_separator, temp);
 
   level--;
Index: CMT/HEAD/source/cmt_system.cxx
===================================================================
--- CMT/HEAD/source/cmt_system.cxx	(revision 609)
+++ CMT/HEAD/source/cmt_system.cxx	(revision 610)
@@ -2231,10 +2231,9 @@
 void CmtSystem::split (const cmt_string& text,
                        const cmt_string& separators,
-                       cmt_string_vector& strings)
+                       cmt_string_vector& strings,
+		       const bool& unquote)
 {
   static char* buffer = 0;
   static int allocated = 0;
-
-  bool finished = false;
 
   strings.clear ();
@@ -2277,163 +2276,166 @@
   */
 
-  char* current_word = buffer;
-
-  while (*current_word != 0)
-    {
-      size_t prefix_length;
-      size_t word_length;
-
-      /*
-        while ((*current_word == ' ') ||
-        (*current_word == '\t'))
-        {
-        current_word++;
-        }
-      */
-
-      // first skip all starting separators.
-
-      prefix_length = strspn (current_word, separators.c_str ());
-      if (prefix_length > 0)
-        {
-          // Move to the first non-separator character
-
-          current_word += prefix_length;
-        }
-
-      /*
-        Parse the next word.
-
-        It may contain enclosures in quote characters or not.
-        Quotes must be identical on both sides of each enclosure.
-      */
-
-      char* running_char = current_word;
-
-      word_length = 0;
-
-      for (;;)
-        {
-          size_t unquoted_length;
-          size_t separator_offset;
-
-	  for (int p = 0;;)
+  char * b = buffer;
+  char * begin = b;
+  char * e;
+  char * pq = 0;
+  char * pqm = 0;
+  char q, ev;
+  char * token = 0;
+  bool before_q = false;
+  bool after_q = false;
+  bool matched = false;
+
+//   cerr << "split: " << buffer << endl;
+//   cerr << "seps: `";
+//   for (int i = 0; i < separators.size (); i++)
+//     cerr << separators[i];
+//   cerr << "'" << endl;
+
+  // sep...ab..."cd"ef...sep...
+  while (pq = strpbrk (begin, "\"\'"))
+    {
+      if (begin < pq && *(pq - 1) == '\\')
+	{// quote considered escaped
+	  begin = pq + 1;
+	  continue;
+	}
+
+      if ((b < pq && NULL == strchr (separators.c_str (), *(pq - 1))) ||
+	  (b == pq && after_q))
+	before_q = true;
+      else
+	before_q = false;
+
+      // save quote found
+      q = *pq;
+      // terminate string for standard string functions
+      *pq = 0;
+
+      // parse string - up to quote - into a sequence of tokens
+      if (token = strtok (b, separators.c_str ()))
+	{
+	  if (after_q)
+	    strings.back () += token;
+	  else
+	    strings.add () = token;
+
+// 	  cerr << (after_q ? "append: " : "add: ")
+// 	       << "[" << token << "]{" << strings.back () << "}";
+
+	  while (token = strtok (NULL, separators.c_str ()))
 	    {
-	      unquoted_length = strcspn (running_char + p, "\"\'") + p;
-	      if ((unquoted_length > 0) && (running_char[unquoted_length-1] == '\\'))
-		{
-		  p = unquoted_length + 1;
-		}
-	      else
-		{
-		  break;
-		}
+	      strings.add () = token;
+	      //strings.push_back (token);
+	      //cerr << "[" << token << "]{" << strings.back () << "}";
+	    } // while ( token = strtok (NULL, separators.c_str ()) )
+	  //cerr << endl;
+	}
+
+      if (unquote)
+	{
+	  b = pq + 1;
+	}
+      else
+	{
+	  // restore quote found
+	  *pq = q;
+	  b = pq;
+	}
+      begin = pq + 1;
+
+      // look for matching quote
+      matched = false;
+      while (pqm = strchr (begin, q))
+	{
+	  // commented out because of
+	  // inconsistency of quoting rules
+	  // and backward compatibility
+// 	  if (begin < pqm && *(pqm - 1) == '\\')
+// 	    {// quote considered escaped
+// 	      begin = pqm + 1;
+// 	      continue;
+// 	    }
+	  matched = true;
+
+	  if (*(pqm + 1) && NULL == strchr (separators.c_str (), *(pqm + 1)))
+	    after_q = true;
+	  else
+	    after_q = false;
+
+	  if (unquote)
+	    {
+	      e = pqm;
 	    }
-
-          separator_offset = strcspn (running_char, separators.c_str ());
-
-          if (separator_offset <= unquoted_length)
-            {
-              // no quote in this word -> we are finished for this one.
-              running_char += separator_offset;
-              break;
-            }
-
-          // We have found a quoted enclosure. Move to it.
-
-          running_char += unquoted_length;
-
-          char quote = running_char[0];
-
-          // Remove it.
-          {
-            char* p = running_char;
-            while (p[1] != 0)
-              {
-                *p = p[1];
-                p++;
-              }
-            *p = 0;
-          }
-
-          // Look for the next occurence of this quote.
-          {
-            char* p = strchr (running_char, quote);
-            if (p == 0)
-              {
-                // Unmatched quote : the rest of the line will be taken as a word...
-                running_char += strlen (running_char);
-                finished = true;
-                break;
-              }
-            else
-              {
-                running_char = p;
-              }
-          }
-
-          // Now we remove the ending quote from the word
-          // (by shifting all remaining characters by one place to the left)
-
-          {
-            char* p = running_char;
-            while (p[1] != 0)
-              {
-                *p = p[1];
-                p++;
-              }
-            *p = 0;
-          }
-        }
-
-      word_length = running_char - current_word;
-
-      if (current_word[word_length] == 0)
-        {
-          finished = true;
-        }
-      else
-        {
-          current_word[word_length] = 0;
-        }
-
-      /*
-        if ((t[0] == '"') ||
-        (t[0] == '\'') ||
-        (t[0] == ':'))
-        {
-        char* quote;
-
-        t++;
-        quote = strchr (t, sep);
-        if (quote != 0) *quote = 0;
-        else finished = true;
-        }
-        else
-        {
-        int offset;
-
-        offset = strcspn (t, " \t:");
-        if ((offset < 0) || (t[offset] == 0)) finished = true;
-        if (!finished)
-        {
-        space = t + offset;
-        *space = 0;
-        }
-        }
-      */
-
-      // Store the current word into the vector of strings
-
-      {
-        cmt_string& s = strings.add ();
-        s = current_word;
-      }
-
-      if (finished) break;
-
-      // Move to the next possible word.
-      current_word += word_length + 1;
-    }
+	  else
+	    {
+	      e = pqm + 1;
+	      ev = *e;
+	    }
+	  // terminate string for standard string functions
+	  *e = 0;
+	  
+	  if (before_q)
+	    strings.back () += b;
+	  else
+	    strings.add () = b;
+
+// 	  cerr << (before_q ? "append: " : "add: ")
+// 	       << "|" << b << "|{" << strings.back () << "}" << endl;
+	  
+	  // restore e value
+	  if (!unquote)
+	    {
+	      *e = ev;
+	    }
+	  b = pqm + 1;
+	  begin = b;
+	  break;
+	} // while (pqm = strchr (begin, q))
+
+      if (!matched)
+	{ // unmatched quote : the rest of the line will be taken as a token
+	  if (before_q)
+	    strings.back () += b;
+	  else
+	    strings.add () = b;
+
+	  // append quote to match
+	  if (!unquote)
+	    strings.back () += q;
+	  
+// 	  cerr << (before_q ? "append: " : "add: ")
+// 	       << "|" << b << "|{" << strings.back () << "}" << endl;
+
+	  b = buffer + strlen(buffer);
+	  begin = b;
+	  break;
+	}
+
+    } // while (pq = strpbrk (begin, "\"\'"))
+
+      // parse string - up to end - into a sequence of tokens
+      if (token = strtok (b, separators.c_str ()))
+	{
+	  if (after_q)
+	    strings.back () += token;
+	  else
+	    strings.add () = token;
+
+// 	  cerr << (after_q ? "append: " : "add: ")
+// 	       << "<" << token << ">{" << strings.back () << "}";
+
+	  while (token = strtok (NULL, separators.c_str ()))
+	    {
+	      strings.add () = token;
+	      //cerr << "<" << token << ">{" << strings.back () << "}";
+	    } // while ( token = strtok (NULL, separators.c_str ()) )
+	  //cerr << endl;
+	}
+//       cerr << "strings:";
+//       for (int i = 0; i < strings.size (); i++)
+// 	cerr << " {" << strings[i] << "}";
+//       //	cerr << " `" << strings[i] << "'";
+//       cerr << endl;
 }
 
Index: CMT/HEAD/source/cmt_system.h
===================================================================
--- CMT/HEAD/source/cmt_system.h	(revision 609)
+++ CMT/HEAD/source/cmt_system.h	(revision 610)
@@ -153,5 +153,6 @@
   static void split (const cmt_string& text,
                      const cmt_string& separators,
-                     cmt_string_vector& strings);
+                     cmt_string_vector& strings,
+		     const bool& unquote = true);
   static cmt_string quote (const cmt_string& text,
 			   const cmt_string& separators);
Index: CMT/HEAD/source/cmt_use.cxx
===================================================================
--- CMT/HEAD/source/cmt_use.cxx	(revision 609)
+++ CMT/HEAD/source/cmt_use.cxx	(revision 610)
@@ -5422,4 +5422,6 @@
   void filter (const cmt_string& line)
   {
+    if (0 == line.size () ||
+	line[0] == '#') return;
     CmtSystem::cmt_string_vector words;
     CmtSystem::split (line, " \t", words);
@@ -5450,4 +5452,6 @@
   void filter (const cmt_string& line)
   {
+    if (0 == line.size () ||
+	line[0] == '#') return;
     CmtSystem::cmt_string_vector words;
     CmtSystem::split (line, " \t", words);
