Ver Fonte

BUG: Reimplemented ExpandListArguments to properly handle escaped backslashes that occur right before semicolons. This is important for lists of paths ending in backslashes on windows.

Brad King há 22 anos atrás
pai
commit
ec78910bac
1 ficheiros alterados com 49 adições e 59 exclusões
  1. 49 59
      Source/cmSystemTools.cxx

+ 49 - 59
Source/cmSystemTools.cxx

@@ -841,82 +841,72 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
   if(arg.find(';') == std::string::npos)
     {
     newargs.push_back(arg);
+    return;
     }
-  else
+  // Break the string at non-escaped semicolons not nested in [].
+  int squareNesting = 0;
+  for(const char* c = arg.c_str(); *c; ++c)
     {
-    std::string::size_type start = 0;
-    std::string::size_type endpos = 0;
-    const std::string::size_type size = arg.size();
-    // break up ; separated sections of the string into separate strings
-    while(endpos != size)
+    switch(*c)
       {
-      endpos = arg.find(';', start); 
-      if(endpos == std::string::npos)
-        {
-        endpos = arg.size();
-        }
-      else
-        {
-        // skip right over escaped ; ( \; )
-        while((endpos != std::string::npos)
-              && (endpos > 0) 
-              && ((arg)[endpos-1] == '\\') )
-          {
-          endpos = arg.find(';', endpos+1);
-          }
-        if(endpos == std::string::npos)
-          {
-          endpos = arg.size();
-          }
-        }
-      std::string::size_type len = endpos - start;
-      if (len > 0)
+      case '\\':
         {
-        // check for a closing ] after the start position
-        if(arg.find('[', start) == std::string::npos)
+        // We only want to allow escaping of semicolons.  Other
+        // escapes should not be processed here.
+        ++c;
+        if(*c == ';')
           {
-          // if there is no [ in the string then keep it
-          newarg = arg.substr(start, len);
+          newarg += ';';
           }
         else
           {
-          int opencount = 0;
-          int closecount = 0;
-          for(std::string::size_type j = start; j < endpos; ++j)
+          newarg += '\\';
+          if(*c)
             {
-            if(arg.at(j) == '[')
-              {
-              ++opencount;
-              }
-            else if (arg.at(j) == ']')
-              {
-              ++closecount;
-              }
+            newarg += *c;
             }
-          if(opencount != closecount)
+          }
+        } break;
+      case '[':
+        {
+        ++squareNesting;
+        newarg += '[';
+        } break;
+      case ']':
+        {
+        --squareNesting;
+        newarg += ']';
+        } break;
+      case ';':
+        {
+        // Break the string here if we are not nested inside square
+        // brackets.
+        if(squareNesting == 0)
+          {
+          if(newarg.length())
             {
-            // skip this one
-            endpos = arg.find(';', endpos+1);  
-            if(endpos == std::string::npos)
-              {
-              endpos = arg.size();
-              }
-            len = endpos - start;
+            // Add an argument if the string is not empty.
+            newargs.push_back(newarg);
+            newarg = "";
             }
-          newarg = arg.substr(start, len);
           }
-        // unescape semicolons 
-        std::string::size_type pos = newarg.find("\\;");
-        while (pos != std::string::npos)
+        else
           {
-          newarg.erase(pos, 1);
-          pos = newarg.find("\\;");
+          newarg += ';';
           }
-        newargs.push_back(newarg);
-        }
-      start = endpos+1;
+        } break;
+      default:
+        {
+        // Just append this character.
+        newarg += *c;
+        } break;
       }
     }
+  if(newarg.length())
+    {
+    // Add the last argument if the string is not empty.
+    newargs.push_back(newarg);
+    }
 }
 
 bool cmSystemTools::SimpleGlob(const std::string& glob,