ENH: add submit via cp mode
[cmake.git] / Source / cmLoadCacheCommand.cxx
blob47b676f3fc1253e7ef810d1ec0f1502d6b2789e3
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmLoadCacheCommand.cxx,v $
5 Language: C++
6 Date: $Date: 2008-01-23 15:27:59 $
7 Version: $Revision: 1.19 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmLoadCacheCommand.h"
19 #include <cmsys/RegularExpression.hxx>
21 // cmLoadCacheCommand
22 bool cmLoadCacheCommand
23 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
25 if (args.size()< 1)
27 this->SetError("called with wrong number of arguments.");
30 if(args.size() >= 2 && args[1] == "READ_WITH_PREFIX")
32 return this->ReadWithPrefix(args);
35 // Cache entries to be excluded from the import list.
36 // If this set is empty, all cache entries are brought in
37 // and they can not be overridden.
38 bool excludeFiles=false;
39 unsigned int i;
40 std::set<cmStdString> excludes;
42 for(i=0; i<args.size(); i++)
44 if (excludeFiles)
46 excludes.insert(args[i]);
48 if (args[i] == "EXCLUDE")
50 excludeFiles=true;
52 if (excludeFiles && (args[i] == "INCLUDE_INTERNALS"))
54 break;
58 // Internal cache entries to be imported.
59 // If this set is empty, no internal cache entries are
60 // brought in.
61 bool includeFiles=false;
62 std::set<cmStdString> includes;
64 for(i=0; i<args.size(); i++)
66 if (includeFiles)
68 includes.insert(args[i]);
70 if (args[i] == "INCLUDE_INTERNALS")
72 includeFiles=true;
74 if (includeFiles && (args[i] == "EXCLUDE"))
76 break;
80 // Loop over each build directory listed in the arguments. Each
81 // directory has a cache file.
82 for(i=0; i<args.size(); i++)
84 if ((args[i] == "EXCLUDE") || (args[i] == "INCLUDE_INTERNALS"))
86 break;
88 this->Makefile->GetCacheManager()->LoadCache(args[i].c_str(), false,
89 excludes, includes);
93 return true;
96 //----------------------------------------------------------------------------
97 bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args)
99 // Make sure we have a prefix.
100 if(args.size() < 3)
102 this->SetError("READ_WITH_PREFIX form must specify a prefix.");
103 return false;
106 // Make sure the cache file exists.
107 std::string cacheFile = args[0]+"/CMakeCache.txt";
108 if(!cmSystemTools::FileExists(cacheFile.c_str()))
110 std::string e = "Cannot load cache file from " + cacheFile;
111 this->SetError(e.c_str());
112 return false;
115 // Prepare the table of variables to read.
116 this->Prefix = args[2];
117 for(unsigned int i=3; i < args.size(); ++i)
119 this->VariablesToRead.insert(args[i]);
122 // Read the cache file.
123 std::ifstream fin(cacheFile.c_str());
125 // This is a big hack read loop to overcome a buggy ifstream
126 // implementation on HP-UX. This should work on all platforms even
127 // for small buffer sizes.
128 const int bufferSize = 4096;
129 char buffer[bufferSize];
130 std::string line;
131 while(fin)
133 // Read a block of the file.
134 fin.read(buffer, bufferSize);
135 if(fin.gcount())
137 // Parse for newlines directly.
138 const char* i = buffer;
139 const char* end = buffer+fin.gcount();
140 while(i != end)
142 const char* begin = i;
143 while(i != end && *i != '\n') { ++i; }
144 if(i == begin || *(i-1) != '\r')
146 // Include this portion of the line.
147 line += std::string(begin, i-begin);
149 else
151 // Include this portion of the line.
152 // Don't include the \r in a \r\n pair.
153 line += std::string(begin, i-1-begin);
155 if(i != end)
157 // Completed a line.
158 this->CheckLine(line.c_str());
159 line = "";
161 // Skip the newline character.
162 ++i;
167 if(line.length())
169 // Partial last line.
170 this->CheckLine(line.c_str());
173 return true;
176 //----------------------------------------------------------------------------
177 void cmLoadCacheCommand::CheckLine(const char* line)
179 // Check one line of the cache file.
180 std::string var;
181 std::string value;
182 if(this->ParseEntry(line, var, value))
184 // Found a real entry. See if this one was requested.
185 if(this->VariablesToRead.find(var) != this->VariablesToRead.end())
187 // This was requested. Set this variable locally with the given
188 // prefix.
189 var = this->Prefix + var;
190 if(value.length())
192 this->Makefile->AddDefinition(var.c_str(), value.c_str());
194 else
196 this->Makefile->RemoveDefinition(var.c_str());
202 //----------------------------------------------------------------------------
203 bool cmLoadCacheCommand::ParseEntry(const char* entry, std::string& var,
204 std::string& value)
206 // input line is: key:type=value
207 cmsys::RegularExpression reg("^([^:]*):([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
208 // input line is: "key":type=value
209 cmsys::RegularExpression
210 regQuoted("^\"([^\"]*)\":([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
211 bool flag = false;
212 if(regQuoted.find(entry))
214 var = regQuoted.match(1);
215 value = regQuoted.match(3);
216 flag = true;
218 else if (reg.find(entry))
220 var = reg.match(1);
221 value = reg.match(3);
222 flag = true;
225 // if value is enclosed in single quotes ('foo') then remove them
226 // it is used to enclose trailing space or tab
227 if (flag &&
228 value.size() >= 2 &&
229 value[0] == '\'' &&
230 value[value.size() - 1] == '\'')
232 value = value.substr(1, value.size() - 2);
234 return flag;