diff --git a/core/base/src/TSystem.cxx b/core/base/src/TSystem.cxx index 1e14cbc1866a4f55063373f8a7d781f6822adf09..39dd664e0062cc3820a3105f1598f6dcac748988 100644 --- a/core/base/src/TSystem.cxx +++ b/core/base/src/TSystem.cxx @@ -4156,18 +4156,41 @@ TString TSystem::SplitAclicMode(const char* filename, TString &aclicMode, TString &arguments, TString &io) const { char *fname = Strip(filename); - - char *arg = strchr(fname, '('); - // special case for $(HOME)/aap.C(10) - while (arg && *arg && (arg > fname && *(arg-1) == '$') && *(arg+1)) - arg = strchr(arg+1, '('); - if (arg && arg > fname) { - *arg = 0; - char *t = arg-1; - while (*t == ' ') { - *t = 0; t--; + TString filenameCopy = fname; + + if (filenameCopy.EndsWith(")")) { + Ssiz_t posArgEnd = filenameCopy.Length() - 1; + // There is an argument; find its start! + int parenNestCount = 1; + bool inString = false; + Ssiz_t posArgBegin = posArgEnd - 1; + for (; parenNestCount && posArgBegin >= 0; --posArgBegin) { + // Escaped if the previous character is a `\` - but not if it + // itself is preceded by a `\`! + if (posArgBegin > 0 && filenameCopy[posArgBegin] == '\\' && + (posArgBegin == 1 || filenameCopy[posArgBegin - 1] != '\\')) { + // skip escape. + --posArgBegin; + continue; + } + switch (filenameCopy[posArgBegin]) { + case ')': + if (!inString) + ++parenNestCount; + break; + case '(': + if (!inString) + --parenNestCount; + break; + case '"': inString = !inString; break; + } + } + if (parenNestCount || inString) { + Error("SplitAclicMode", "Cannot parse argument in %s", filename); + } else { + arguments = filenameCopy(posArgBegin + 1, posArgEnd - 1); + fname[posArgBegin + 1] = 0; } - arg++; } // strip off I/O redirect tokens from filename @@ -4226,9 +4249,6 @@ TString TSystem::SplitAclicMode(const char* filename, TString &aclicMode, } TString resFilename = fname; - arguments = "("; - if (arg) arguments += arg; - else arguments = ""; delete []fname; return resFilename; diff --git a/interpreter/cling/lib/MetaProcessor/MetaParser.cpp b/interpreter/cling/lib/MetaProcessor/MetaParser.cpp index c70dce4f49ecdd6f216268d54f1967dca4e4d88f..6525686f477a8f11b68ae63fd7c7008603b7cd90 100644 --- a/interpreter/cling/lib/MetaProcessor/MetaParser.cpp +++ b/interpreter/cling/lib/MetaProcessor/MetaParser.cpp @@ -276,13 +276,39 @@ namespace cling { const Token& Tok = getCurTok(); if (Tok.is(tok::ident) && (Tok.getIdent().equals("x") || Tok.getIdent().equals("X"))) { - // There might be ArgList - consumeAnyStringToken(tok::l_paren); - llvm::StringRef file(getCurTok().getIdent()); consumeToken(); - // '(' to end of string: + skipWhitespace(); + + // There might be an ArgList: + int forward = 0; + std::string args; + llvm::StringRef file(getCurTok().getBufStart()); + while (!lookAhead(forward).is(tok::eof)) + ++forward; + // Now track back to find the opening '('. + if (lookAhead(forward - 1).is(tok::r_paren)) { + // Trailing ')' - we interpret that as an argument. + --forward; // skip ')' + int nesting = 1; + while (--forward > 0 && nesting) { + if (lookAhead(forward).is(tok::l_paren)) + --nesting; + else if (lookAhead(forward).is(tok::r_paren)) + ++nesting; + } + if (forward == 0) { + cling::errs() << "cling::MetaParser::isXCommand():" + "error parsing argument in " << getCurTok().getBufStart() << '\n'; + // interpret everything as "the file" + } else { + while (forward--) + consumeToken(); + consumeToken(); // the forward-0 token. + args = getCurTok().getBufStart(); + file = file.drop_back(args.length()); + } + } - std::string args = getCurTok().getBufStart(); if (args.empty()) args = "()"; actionResult = m_Actions->actOnxCommand(file, args, resultValue);