|
|
@@ -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,
|