diff options
author | Brad King <brad.king@kitware.com> | 2002-12-11 23:13:33 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2002-12-11 23:13:33 (GMT) |
commit | 4888c088ae0ca829862e8b2f9568abca12dc34d1 (patch) | |
tree | 2c0fb825f1d1adff97d98373b555f00b84da14f7 /Source/cmListFileCache.cxx | |
parent | 5a321605bcc15c7e559c8da5168eef00796148b1 (diff) | |
download | CMake-4888c088ae0ca829862e8b2f9568abca12dc34d1.zip CMake-4888c088ae0ca829862e8b2f9568abca12dc34d1.tar.gz CMake-4888c088ae0ca829862e8b2f9568abca12dc34d1.tar.bz2 |
ENH: Moved ExpandListVariables out of individual commands. Argument evaluation rules are now very consistent. Double quotes can always be used to create exactly one argument, regardless of contents inside.
Diffstat (limited to 'Source/cmListFileCache.cxx')
-rw-r--r-- | Source/cmListFileCache.cxx | 189 |
1 files changed, 183 insertions, 6 deletions
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 0893cf6..fce13db 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -16,7 +16,7 @@ =========================================================================*/ #include "cmListFileCache.h" #include "cmSystemTools.h" - +#include "cmRegularExpression.h" cmListFileCache* cmListFileCache::Instance = 0; @@ -89,17 +89,17 @@ bool cmListFileCache::CacheFile(const char* path, bool requireProjectCommand) cmSystemTools::Error("cmListFileCache: error can not open file ", path); return false; } + long line=0; cmListFile inFile; inFile.m_ModifiedTime = cmSystemTools::ModifiedTime(path); bool parseError; while ( fin ) { cmListFileFunction inFunction; - if(cmSystemTools::ParseFunction(fin, - inFunction.m_Name, - inFunction.m_Arguments, - path, parseError)) + if(cmListFileCache::ParseFunction(fin, inFunction, path, parseError, + &line)) { + inFunction.m_FilePath = path; inFile.m_Functions.push_back(inFunction); } if (parseError) @@ -126,7 +126,8 @@ bool cmListFileCache::CacheFile(const char* path, bool requireProjectCommand) { cmListFileFunction project; project.m_Name = "PROJECT"; - project.m_Arguments.push_back("Project"); + cmListFileArgument prj("Project", false); + project.m_Arguments.push_back(prj); inFile.m_Functions.insert(inFile.m_Functions.begin(),project); } } @@ -143,3 +144,179 @@ void cmListFileCache::FlushCache(const char* path) return; } } + +inline void RemoveComments(char* ptr) +{ + while(*ptr) + { + if(*ptr == '#') + { + *ptr = 0; + break; + } + ++ptr; + } +} + +bool cmListFileCache::ParseFunction(std::ifstream& fin, + cmListFileFunction& function, + const char* filename, + bool& parseError, + long* line) +{ + parseError = false; + std::string& name = function.m_Name; + std::vector<cmListFileArgument>& arguments = function.m_Arguments; + name = ""; + arguments = std::vector<cmListFileArgument>(); + const int BUFFER_SIZE = 4096; + char inbuffer[BUFFER_SIZE]; + if(!fin) + { + return false; + } + if(fin.getline(inbuffer, BUFFER_SIZE ) ) + { + if(line) { ++*line; } + RemoveComments(inbuffer); + cmRegularExpression blankLine("^[ \t\r]*$"); + cmRegularExpression oneLiner("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)\\)[ \t\r]*$"); + cmRegularExpression multiLine("^[ \t]*([A-Za-z_0-9]*)[ \t]*\\((.*)$"); + cmRegularExpression lastLine("^(.*)\\)[ \t\r]*$"); + + // check for blank line or comment + if(blankLine.find(inbuffer) ) + { + return false; + } + // look for a oneline fun(arg arg2) + else if(oneLiner.find(inbuffer)) + { + // the arguments are the second match + std::string args = oneLiner.match(2); + name = oneLiner.match(1); + // break up the arguments + cmListFileCache::GetArguments(args, arguments); + if(line) + { + function.m_Line = *line; + } + return true; + } + // look for a start of a multiline with no trailing ")" fun(arg arg2 + else if(multiLine.find(inbuffer)) + { + name = multiLine.match(1); + std::string args = multiLine.match(2); + cmListFileCache::GetArguments(args, arguments); + if(line) + { + function.m_Line = *line; + } + // Read lines until the closing paren is hit + bool done = false; + while(!done) + { + // read lines until the end paren is found + if(fin.getline(inbuffer, BUFFER_SIZE ) ) + { + ++line; + RemoveComments(inbuffer); + // Check for comment lines and ignore them. + if(blankLine.find(inbuffer)) + { continue; } + // Is this the last line? + if(lastLine.find(inbuffer)) + { + done = true; + std::string gargs = lastLine.match(1); + cmListFileCache::GetArguments(gargs, arguments); + } + else + { + std::string line = inbuffer; + cmListFileCache::GetArguments(line, arguments); + } + } + else + { + parseError = true; + cmSystemTools::Error("Parse error in read function missing end )\nIn File: ", + filename, "\nCurrent line:", inbuffer); + return false; + } + } + return true; + } + else + { + parseError = true; + cmSystemTools::Error("Parse error in read function\nIn file:", + filename, "\nCurrent line:", inbuffer); + return false; + } + } + return false; + +} + +void cmListFileCache::GetArguments(std::string& line, + std::vector<cmListFileArgument>& arguments) +{ + // Match a normal argument (not quoted, no spaces). + cmRegularExpression normalArgument("[ \t]*(([^ \t\r\\]|[\\].)+)[ \t\r]*"); + // Match a quoted argument (surrounded by double quotes, spaces allowed). + cmRegularExpression quotedArgument("[ \t]*(\"([^\"\\]|[\\].)*\")[ \t\r]*"); + + bool done = false; + while(!done) + { + std::string arg; + std::string::size_type endpos=0; + bool quoted = false; + bool foundQuoted = quotedArgument.find(line.c_str()); + bool foundNormal = normalArgument.find(line.c_str()); + + if(foundQuoted && foundNormal) + { + // Both matches were found. Take the earlier one. + // Favor double-quoted version if there is a tie. + if(normalArgument.start(1) < quotedArgument.start(1)) + { + arg = normalArgument.match(1); + endpos = normalArgument.end(1); + } + else + { + arg = quotedArgument.match(1); + endpos = quotedArgument.end(1); + // Strip off the double quotes on the ends. + arg = arg.substr(1, arg.length()-2); + quoted = true; + } + } + else if(foundQuoted) + { + arg = quotedArgument.match(1); + endpos = quotedArgument.end(1); + // Strip off the double quotes on the ends. + arg = arg.substr(1, arg.length()-2); + quoted = true; + } + else if(foundNormal) + { + arg = normalArgument.match(1); + endpos = normalArgument.end(1); + } + else + { + done = true; + } + if(!done) + { + cmListFileArgument a(cmSystemTools::RemoveEscapes(arg.c_str()), quoted); + arguments.push_back(a); + line = line.substr(endpos, line.length() - endpos); + } + } +} |