cmState.cxx 26 KB
Newer Older
1
2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
Stephen Kelly's avatar
Stephen Kelly committed
3
4
#include "cmState.h"

5
#include "cmsys/RegularExpression.hxx"
6
7
8
9
#include <algorithm>
#include <assert.h>
#include <string.h>
#include <utility>
10

11
#include "cmAlgorithms.h"
12
#include "cmCacheManager.h"
13
#include "cmCommand.h"
14
#include "cmDefinitions.h"
15
#include "cmDisallowedCommand.h"
16
#include "cmListFileCache.h"
17
18
#include "cmStatePrivate.h"
#include "cmStateSnapshot.h"
19
#include "cmSystemTools.h"
20
#include "cmUnexpectedCommand.h"
21
#include "cmake.h"
22

23
cmState::cmState()
24
  : IsInTryCompile(false)
25
  , IsGeneratorMultiConfig(false)
26
27
28
29
30
31
  , WindowsShell(false)
  , WindowsVSIDE(false)
  , WatcomWMake(false)
  , MinGWMake(false)
  , NMake(false)
  , MSYSShell(false)
Stephen Kelly's avatar
Stephen Kelly committed
32
{
33
  this->CacheManager = new cmCacheManager;
Stephen Kelly's avatar
Stephen Kelly committed
34
}
35

36
37
cmState::~cmState()
{
38
  delete this->CacheManager;
39
40
  cmDeleteAll(this->BuiltinCommands);
  cmDeleteAll(this->ScriptedCommands);
41
42
}

43
const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType)
44
{
45
  switch (targetType) {
46
    case cmStateEnums::STATIC_LIBRARY:
47
      return "STATIC_LIBRARY";
48
    case cmStateEnums::MODULE_LIBRARY:
49
      return "MODULE_LIBRARY";
50
    case cmStateEnums::SHARED_LIBRARY:
51
      return "SHARED_LIBRARY";
52
    case cmStateEnums::OBJECT_LIBRARY:
53
      return "OBJECT_LIBRARY";
54
    case cmStateEnums::EXECUTABLE:
55
      return "EXECUTABLE";
56
    case cmStateEnums::UTILITY:
57
      return "UTILITY";
58
    case cmStateEnums::GLOBAL_TARGET:
59
      return "GLOBAL_TARGET";
60
    case cmStateEnums::INTERFACE_LIBRARY:
61
      return "INTERFACE_LIBRARY";
62
    case cmStateEnums::UNKNOWN_LIBRARY:
63
64
      return "UNKNOWN_LIBRARY";
  }
65
  assert(false && "Unexpected target type");
Daniel Pfeifer's avatar
Daniel Pfeifer committed
66
  return nullptr;
67
68
}

69
70
const char* cmCacheEntryTypes[] = { "BOOL",          "PATH",     "FILEPATH",
                                    "STRING",        "INTERNAL", "STATIC",
Daniel Pfeifer's avatar
Daniel Pfeifer committed
71
                                    "UNINITIALIZED", nullptr };
72

73
const char* cmState::CacheEntryTypeToString(cmStateEnums::CacheEntryType type)
Stephen Kelly's avatar
Stephen Kelly committed
74
{
75
  if (type > 6) {
76
    return cmCacheEntryTypes[6];
77
  }
78
  return cmCacheEntryTypes[type];
Stephen Kelly's avatar
Stephen Kelly committed
79
80
}

81
cmStateEnums::CacheEntryType cmState::StringToCacheEntryType(const char* s)
Stephen Kelly's avatar
Stephen Kelly committed
82
{
83
  int i = 0;
84
85
  while (cmCacheEntryTypes[i]) {
    if (strcmp(s, cmCacheEntryTypes[i]) == 0) {
86
      return static_cast<cmStateEnums::CacheEntryType>(i);
87
    }
88
89
    ++i;
  }
90
  return cmStateEnums::STRING;
Stephen Kelly's avatar
Stephen Kelly committed
91
92
93
94
}

bool cmState::IsCacheEntryType(std::string const& key)
{
95
96
  for (int i = 0; cmCacheEntryTypes[i]; ++i) {
    if (strcmp(key.c_str(), cmCacheEntryTypes[i]) == 0) {
97
98
      return true;
    }
99
  }
100
  return false;
Stephen Kelly's avatar
Stephen Kelly committed
101
102
}

103
104
105
106
bool cmState::LoadCache(const std::string& path, bool internal,
                        std::set<std::string>& excludes,
                        std::set<std::string>& includes)
{
107
  return this->CacheManager->LoadCache(path, internal, excludes, includes);
108
109
110
111
}

bool cmState::SaveCache(const std::string& path)
{
112
  return this->CacheManager->SaveCache(path);
113
114
115
116
}

bool cmState::DeleteCache(const std::string& path)
{
117
  return this->CacheManager->DeleteCache(path);
118
119
}

Stephen Kelly's avatar
Stephen Kelly committed
120
121
122
std::vector<std::string> cmState::GetCacheEntryKeys() const
{
  std::vector<std::string> definitions;
123
  definitions.reserve(this->CacheManager->GetSize());
124
125
  cmCacheManager::CacheIterator cit = this->CacheManager->GetCacheIterator();
  for (cit.Begin(); !cit.IsAtEnd(); cit.Next()) {
Stephen Kelly's avatar
Stephen Kelly committed
126
    definitions.push_back(cit.GetName());
127
  }
Stephen Kelly's avatar
Stephen Kelly committed
128
129
130
131
132
  return definitions;
}

const char* cmState::GetCacheEntryValue(std::string const& key) const
{
133
134
  cmCacheManager::CacheEntry* e = this->CacheManager->GetCacheEntry(key);
  if (!e) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
135
    return nullptr;
136
  }
Stephen Kelly's avatar
Stephen Kelly committed
137
138
139
  return e->Value.c_str();
}

140
const char* cmState::GetInitializedCacheValue(std::string const& key) const
Stephen Kelly's avatar
Stephen Kelly committed
141
{
142
  return this->CacheManager->GetInitializedCacheValue(key);
Stephen Kelly's avatar
Stephen Kelly committed
143
144
}

145
cmStateEnums::CacheEntryType cmState::GetCacheEntryType(
146
  std::string const& key) const
Stephen Kelly's avatar
Stephen Kelly committed
147
148
{
  cmCacheManager::CacheIterator it =
149
    this->CacheManager->GetCacheIterator(key.c_str());
Stephen Kelly's avatar
Stephen Kelly committed
150
151
152
153
  return it.GetType();
}

void cmState::SetCacheEntryValue(std::string const& key,
154
                                 std::string const& value)
Stephen Kelly's avatar
Stephen Kelly committed
155
{
156
  this->CacheManager->SetCacheEntryValue(key, value);
Stephen Kelly's avatar
Stephen Kelly committed
157
158
159
}

void cmState::SetCacheEntryProperty(std::string const& key,
160
161
                                    std::string const& propertyName,
                                    std::string const& value)
Stephen Kelly's avatar
Stephen Kelly committed
162
163
{
  cmCacheManager::CacheIterator it =
164
    this->CacheManager->GetCacheIterator(key.c_str());
Stephen Kelly's avatar
Stephen Kelly committed
165
166
167
168
  it.SetProperty(propertyName, value.c_str());
}

void cmState::SetCacheEntryBoolProperty(std::string const& key,
169
170
                                        std::string const& propertyName,
                                        bool value)
Stephen Kelly's avatar
Stephen Kelly committed
171
172
{
  cmCacheManager::CacheIterator it =
173
    this->CacheManager->GetCacheIterator(key.c_str());
Stephen Kelly's avatar
Stephen Kelly committed
174
175
176
  it.SetProperty(propertyName, value);
}

177
178
179
180
181
182
183
184
std::vector<std::string> cmState::GetCacheEntryPropertyList(
  const std::string& key)
{
  cmCacheManager::CacheIterator it =
    this->CacheManager->GetCacheIterator(key.c_str());
  return it.GetPropertyList();
}

Stephen Kelly's avatar
Stephen Kelly committed
185
const char* cmState::GetCacheEntryProperty(std::string const& key,
186
                                           std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
187
{
188
189
190
  cmCacheManager::CacheIterator it =
    this->CacheManager->GetCacheIterator(key.c_str());
  if (!it.PropertyExists(propertyName)) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
191
    return nullptr;
192
  }
Stephen Kelly's avatar
Stephen Kelly committed
193
194
195
196
  return it.GetProperty(propertyName);
}

bool cmState::GetCacheEntryPropertyAsBool(std::string const& key,
197
                                          std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
198
{
199
200
  return this->CacheManager->GetCacheIterator(key.c_str())
    .GetPropertyAsBool(propertyName);
Stephen Kelly's avatar
Stephen Kelly committed
201
202
203
}

void cmState::AddCacheEntry(const std::string& key, const char* value,
204
                            const char* helpString,
205
                            cmStateEnums::CacheEntryType type)
Stephen Kelly's avatar
Stephen Kelly committed
206
{
207
  this->CacheManager->AddCacheEntry(key, value, helpString, type);
Stephen Kelly's avatar
Stephen Kelly committed
208
209
210
211
}

void cmState::RemoveCacheEntry(std::string const& key)
{
212
  this->CacheManager->RemoveCacheEntry(key);
Stephen Kelly's avatar
Stephen Kelly committed
213
214
215
}

void cmState::AppendCacheEntryProperty(const std::string& key,
216
217
                                       const std::string& property,
                                       const std::string& value, bool asString)
Stephen Kelly's avatar
Stephen Kelly committed
218
{
219
220
  this->CacheManager->GetCacheIterator(key.c_str())
    .AppendProperty(property, value.c_str(), asString);
Stephen Kelly's avatar
Stephen Kelly committed
221
222
223
}

void cmState::RemoveCacheEntryProperty(std::string const& key,
224
                                       std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
225
{
226
  this->CacheManager->GetCacheIterator(key.c_str())
Daniel Pfeifer's avatar
Daniel Pfeifer committed
227
    .SetProperty(propertyName, nullptr);
Stephen Kelly's avatar
Stephen Kelly committed
228
}
229

230
cmStateSnapshot cmState::Reset()
231
{
232
  this->GlobalProperties.clear();
233
  this->PropertyDefinitions.clear();
234

235
  cmStateDetail::PositionType pos = this->SnapshotData.Truncate();
236
237
  this->ExecutionListFiles.Truncate();

238
  {
239
    cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator it =
240
      this->BuildsystemDirectory.Truncate();
241
242
243
244
245
246
247
    it->IncludeDirectories.clear();
    it->IncludeDirectoryBacktraces.clear();
    it->CompileDefinitions.clear();
    it->CompileDefinitionsBacktraces.clear();
    it->CompileOptions.clear();
    it->CompileOptionsBacktraces.clear();
    it->DirectoryEnd = pos;
248
    it->NormalTargetNames.clear();
249
250
    it->Properties.clear();
    it->Children.clear();
251
  }
252

253
254
255
256
257
258
  this->PolicyStack.Clear();
  pos->Policies = this->PolicyStack.Root();
  pos->PolicyRoot = this->PolicyStack.Root();
  pos->PolicyScope = this->PolicyStack.Root();
  assert(pos->Policies.IsValid());
  assert(pos->PolicyRoot.IsValid());
259
260

  {
261
    std::string srcDir =
262
      cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root);
263
    std::string binDir =
264
      cmDefinitions::Get("CMAKE_BINARY_DIR", pos->Vars, pos->Root);
265
266
267
268
    this->VarTree.Clear();
    pos->Vars = this->VarTree.Push(this->VarTree.Root());
    pos->Parent = this->VarTree.Root();
    pos->Root = this->VarTree.Root();
269

270
271
    pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir.c_str());
    pos->Vars->Set("CMAKE_BINARY_DIR", binDir.c_str());
272
273
  }

274
275
276
277
278
279
280
281
282
283
284
  this->DefineProperty("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, "", "",
                       true);
  this->DefineProperty("RULE_LAUNCH_LINK", cmProperty::DIRECTORY, "", "",
                       true);
  this->DefineProperty("RULE_LAUNCH_CUSTOM", cmProperty::DIRECTORY, "", "",
                       true);

  this->DefineProperty("RULE_LAUNCH_COMPILE", cmProperty::TARGET, "", "",
                       true);
  this->DefineProperty("RULE_LAUNCH_LINK", cmProperty::TARGET, "", "", true);
  this->DefineProperty("RULE_LAUNCH_CUSTOM", cmProperty::TARGET, "", "", true);
285

286
  return cmStateSnapshot(this, pos);
287
288
289
}

void cmState::DefineProperty(const std::string& name,
290
291
292
                             cmProperty::ScopeType scope,
                             const char* ShortDescription,
                             const char* FullDescription, bool chained)
293
{
294
295
  this->PropertyDefinitions[scope].DefineProperty(
    name, scope, ShortDescription, FullDescription, chained);
296
297
}

298
299
cmPropertyDefinition const* cmState::GetPropertyDefinition(
  const std::string& name, cmProperty::ScopeType scope) const
300
{
301
  if (this->IsPropertyDefined(name, scope)) {
302
    cmPropertyDefinitionMap const& defs =
303
      this->PropertyDefinitions.find(scope)->second;
304
    return &defs.find(name)->second;
305
  }
Daniel Pfeifer's avatar
Daniel Pfeifer committed
306
  return nullptr;
307
308
309
}

bool cmState::IsPropertyDefined(const std::string& name,
310
                                cmProperty::ScopeType scope) const
311
{
312
313
314
  std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it =
    this->PropertyDefinitions.find(scope);
  if (it == this->PropertyDefinitions.end()) {
315
    return false;
316
  }
317
  return it->second.IsPropertyDefined(name);
318
319
320
}

bool cmState::IsPropertyChained(const std::string& name,
321
                                cmProperty::ScopeType scope) const
322
{
323
324
325
  std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it =
    this->PropertyDefinitions.find(scope);
  if (it == this->PropertyDefinitions.end()) {
326
    return false;
327
  }
328
  return it->second.IsPropertyChained(name);
329
}
330
331
332

void cmState::SetLanguageEnabled(std::string const& l)
{
333
334
335
  std::vector<std::string>::iterator it = std::lower_bound(
    this->EnabledLanguages.begin(), this->EnabledLanguages.end(), l);
  if (it == this->EnabledLanguages.end() || *it != l) {
336
    this->EnabledLanguages.insert(it, l);
337
  }
338
339
340
341
342
343
344
345
346
347
348
349
350
}

bool cmState::GetLanguageEnabled(std::string const& l) const
{
  return std::binary_search(this->EnabledLanguages.begin(),
                            this->EnabledLanguages.end(), l);
}

std::vector<std::string> cmState::GetEnabledLanguages() const
{
  return this->EnabledLanguages;
}

351
352
353
354
355
void cmState::SetEnabledLanguages(std::vector<std::string> const& langs)
{
  this->EnabledLanguages = langs;
}

356
357
358
359
void cmState::ClearEnabledLanguages()
{
  this->EnabledLanguages.clear();
}
360
361
362
363
364
365
366
367
368
369

bool cmState::GetIsInTryCompile() const
{
  return this->IsInTryCompile;
}

void cmState::SetIsInTryCompile(bool b)
{
  this->IsInTryCompile = b;
}
370

371
372
373
374
375
376
377
378
379
380
bool cmState::GetIsGeneratorMultiConfig() const
{
  return this->IsGeneratorMultiConfig;
}

void cmState::SetIsGeneratorMultiConfig(bool b)
{
  this->IsGeneratorMultiConfig = b;
}

381
382
383
void cmState::AddBuiltinCommand(std::string const& name, cmCommand* command)
{
  assert(name == cmSystemTools::LowerCase(name));
384
385
  assert(this->BuiltinCommands.find(name) == this->BuiltinCommands.end());
  this->BuiltinCommands.insert(std::make_pair(name, command));
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
}

void cmState::AddDisallowedCommand(std::string const& name, cmCommand* command,
                                   cmPolicies::PolicyID policy,
                                   const char* message)
{
  this->AddBuiltinCommand(name,
                          new cmDisallowedCommand(command, policy, message));
}

void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
{
  this->AddBuiltinCommand(name, new cmUnexpectedCommand(name, error));
}

401
402
void cmState::AddScriptedCommand(std::string const& name, cmCommand* command)
{
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
  std::string sName = cmSystemTools::LowerCase(name);

  // if the command already exists, give a new name to the old command.
  if (cmCommand* oldCmd = this->GetCommand(sName)) {
    std::string const newName = "_" + sName;
    std::map<std::string, cmCommand*>::iterator pos =
      this->ScriptedCommands.find(newName);
    if (pos != this->ScriptedCommands.end()) {
      delete pos->second;
      this->ScriptedCommands.erase(pos);
    }
    this->ScriptedCommands.insert(std::make_pair(newName, oldCmd->Clone()));
  }

  // if the command already exists, free the old one
  std::map<std::string, cmCommand*>::iterator pos =
    this->ScriptedCommands.find(sName);
  if (pos != this->ScriptedCommands.end()) {
    delete pos->second;
    this->ScriptedCommands.erase(pos);
  }
  this->ScriptedCommands.insert(std::make_pair(sName, command));
425
426
}

427
428
429
cmCommand* cmState::GetCommand(std::string const& name) const
{
  std::string sName = cmSystemTools::LowerCase(name);
430
431
432
433
  std::map<std::string, cmCommand*>::const_iterator pos;
  pos = this->ScriptedCommands.find(sName);
  if (pos != this->ScriptedCommands.end()) {
    return pos->second;
434
  }
435
436
437
438
  pos = this->BuiltinCommands.find(sName);
  if (pos != this->BuiltinCommands.end()) {
    return pos->second;
  }
Daniel Pfeifer's avatar
Daniel Pfeifer committed
439
  return nullptr;
440
441
442
443
444
}

std::vector<std::string> cmState::GetCommandNames() const
{
  std::vector<std::string> commandNames;
445
446
  commandNames.reserve(this->BuiltinCommands.size() +
                       this->ScriptedCommands.size());
447
448
  for (auto const& bc : this->BuiltinCommands) {
    commandNames.push_back(bc.first);
449
  }
450
451
  for (auto const& sc : this->ScriptedCommands) {
    commandNames.push_back(sc.first);
452
  }
453
454
455
  std::sort(commandNames.begin(), commandNames.end());
  commandNames.erase(std::unique(commandNames.begin(), commandNames.end()),
                     commandNames.end());
456
457
458
459
460
  return commandNames;
}

void cmState::RemoveUserDefinedCommands()
{
461
462
  cmDeleteAll(this->ScriptedCommands);
  this->ScriptedCommands.clear();
463
}
464
465
466

void cmState::SetGlobalProperty(const std::string& prop, const char* value)
{
467
  this->GlobalProperties.SetProperty(prop, value);
468
469
}

470
471
void cmState::AppendGlobalProperty(const std::string& prop, const char* value,
                                   bool asString)
472
{
473
  this->GlobalProperties.AppendProperty(prop, value, asString);
474
475
}

476
const char* cmState::GetGlobalProperty(const std::string& prop)
477
{
478
  if (prop == "CACHE_VARIABLES") {
479
480
    std::vector<std::string> cacheKeys = this->GetCacheEntryKeys();
    this->SetGlobalProperty("CACHE_VARIABLES", cmJoin(cacheKeys, ";").c_str());
481
  } else if (prop == "COMMANDS") {
482
483
    std::vector<std::string> commands = this->GetCommandNames();
    this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";").c_str());
484
  } else if (prop == "IN_TRY_COMPILE") {
485
    this->SetGlobalProperty("IN_TRY_COMPILE",
486
                            this->IsInTryCompile ? "1" : "0");
487
488
489
  } else if (prop == "GENERATOR_IS_MULTI_CONFIG") {
    this->SetGlobalProperty("GENERATOR_IS_MULTI_CONFIG",
                            this->IsGeneratorMultiConfig ? "1" : "0");
490
  } else if (prop == "ENABLED_LANGUAGES") {
491
492
493
    std::string langs;
    langs = cmJoin(this->EnabledLanguages, ";");
    this->SetGlobalProperty("ENABLED_LANGUAGES", langs.c_str());
494
  }
495
#define STRING_LIST_ELEMENT(F) ";" #F
496
  if (prop == "CMAKE_C_KNOWN_FEATURES") {
497
    return FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT) + 1;
498
499
  }
  if (prop == "CMAKE_CXX_KNOWN_FEATURES") {
500
    return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1;
501
  }
502
#undef STRING_LIST_ELEMENT
503
  return this->GlobalProperties.GetPropertyValue(prop);
504
505
506
507
508
509
}

bool cmState::GetGlobalPropertyAsBool(const std::string& prop)
{
  return cmSystemTools::IsOn(this->GetGlobalProperty(prop));
}
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527

void cmState::SetSourceDirectory(std::string const& sourceDirectory)
{
  this->SourceDirectory = sourceDirectory;
  cmSystemTools::ConvertToUnixSlashes(this->SourceDirectory);
}

const char* cmState::GetSourceDirectory() const
{
  return this->SourceDirectory.c_str();
}

void cmState::SetBinaryDirectory(std::string const& binaryDirectory)
{
  this->BinaryDirectory = binaryDirectory;
  cmSystemTools::ConvertToUnixSlashes(this->BinaryDirectory);
}

528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
void cmState::SetWindowsShell(bool windowsShell)
{
  this->WindowsShell = windowsShell;
}

bool cmState::UseWindowsShell() const
{
  return this->WindowsShell;
}

void cmState::SetWindowsVSIDE(bool windowsVSIDE)
{
  this->WindowsVSIDE = windowsVSIDE;
}

bool cmState::UseWindowsVSIDE() const
{
  return this->WindowsVSIDE;
}

void cmState::SetWatcomWMake(bool watcomWMake)
{
  this->WatcomWMake = watcomWMake;
}

bool cmState::UseWatcomWMake() const
{
  return this->WatcomWMake;
}

void cmState::SetMinGWMake(bool minGWMake)
{
  this->MinGWMake = minGWMake;
}

bool cmState::UseMinGWMake() const
{
  return this->MinGWMake;
}

void cmState::SetNMake(bool nMake)
{
  this->NMake = nMake;
}

bool cmState::UseNMake() const
{
  return this->NMake;
}

void cmState::SetMSYSShell(bool mSYSShell)
{
  this->MSYSShell = mSYSShell;
}

bool cmState::UseMSYSShell() const
{
  return this->MSYSShell;
}

588
589
unsigned int cmState::GetCacheMajorVersion() const
{
590
  return this->CacheManager->GetCacheMajorVersion();
591
592
593
594
}

unsigned int cmState::GetCacheMinorVersion() const
{
595
  return this->CacheManager->GetCacheMinorVersion();
596
597
}

598
599
600
601
const char* cmState::GetBinaryDirectory() const
{
  return this->BinaryDirectory.c_str();
}
Stephen Kelly's avatar
Stephen Kelly committed
602

603
cmStateSnapshot cmState::CreateBaseSnapshot()
604
{
605
606
  cmStateDetail::PositionType pos =
    this->SnapshotData.Push(this->SnapshotData.Root());
607
  pos->DirectoryParent = this->SnapshotData.Root();
608
  pos->ScopeParent = this->SnapshotData.Root();
609
  pos->SnapshotType = cmStateEnums::BaseType;
610
  pos->Keep = true;
611
  pos->BuildSystemDirectory =
612
    this->BuildsystemDirectory.Push(this->BuildsystemDirectory.Root());
613
  pos->ExecutionListFile =
614
    this->ExecutionListFiles.Push(this->ExecutionListFiles.Root());
615
616
617
  pos->IncludeDirectoryPosition = 0;
  pos->CompileDefinitionsPosition = 0;
  pos->CompileOptionsPosition = 0;
618
  pos->BuildSystemDirectory->DirectoryEnd = pos;
619
620
621
622
623
  pos->Policies = this->PolicyStack.Root();
  pos->PolicyRoot = this->PolicyStack.Root();
  pos->PolicyScope = this->PolicyStack.Root();
  assert(pos->Policies.IsValid());
  assert(pos->PolicyRoot.IsValid());
624
  pos->Vars = this->VarTree.Push(this->VarTree.Root());
625
626
627
  assert(pos->Vars.IsValid());
  pos->Parent = this->VarTree.Root();
  pos->Root = this->VarTree.Root();
628
  return cmStateSnapshot(this, pos);
629
630
}

631
cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot(
632
  cmStateSnapshot const& originSnapshot)
Stephen Kelly's avatar
Stephen Kelly committed
633
{
634
  assert(originSnapshot.IsValid());
635
636
  cmStateDetail::PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position);
637
  pos->DirectoryParent = originSnapshot.Position;
638
  pos->ScopeParent = originSnapshot.Position;
639
  pos->SnapshotType = cmStateEnums::BuildsystemDirectoryType;
640
  pos->Keep = true;
641
642
  pos->BuildSystemDirectory = this->BuildsystemDirectory.Push(
    originSnapshot.Position->BuildSystemDirectory);
643
  pos->ExecutionListFile =
644
    this->ExecutionListFiles.Push(originSnapshot.Position->ExecutionListFile);
645
  pos->BuildSystemDirectory->DirectoryEnd = pos;
646
647
648
649
650
  pos->Policies = originSnapshot.Position->Policies;
  pos->PolicyRoot = originSnapshot.Position->Policies;
  pos->PolicyScope = originSnapshot.Position->Policies;
  assert(pos->Policies.IsValid());
  assert(pos->PolicyRoot.IsValid());
651

652
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
653
654
  pos->Parent = origin;
  pos->Root = origin;
655
  pos->Vars = this->VarTree.Push(origin);
656

657
  cmStateSnapshot snapshot = cmStateSnapshot(this, pos);
658
  originSnapshot.Position->BuildSystemDirectory->Children.push_back(snapshot);
659
  snapshot.SetDefaultDefinitions();
660
  snapshot.InitializeFromParent();
661
  snapshot.SetDirectoryDefinitions();
662
  return snapshot;
Stephen Kelly's avatar
Stephen Kelly committed
663
664
}

665
cmStateSnapshot cmState::CreateFunctionCallSnapshot(
666
  cmStateSnapshot const& originSnapshot, std::string const& fileName)
667
{
668
  cmStateDetail::PositionType pos =
669
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
670
  pos->ScopeParent = originSnapshot.Position;
671
  pos->SnapshotType = cmStateEnums::FunctionCallType;
672
  pos->Keep = false;
673
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
674
    originSnapshot.Position->ExecutionListFile, fileName);
675
  pos->BuildSystemDirectory->DirectoryEnd = pos;
676
  pos->PolicyScope = originSnapshot.Position->Policies;
677
  assert(originSnapshot.Position->Vars.IsValid());
678
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
679
  pos->Parent = origin;
680
  pos->Vars = this->VarTree.Push(origin);
681
  return cmStateSnapshot(this, pos);
682
683
}

684
cmStateSnapshot cmState::CreateMacroCallSnapshot(
685
  cmStateSnapshot const& originSnapshot, std::string const& fileName)
686
{
687
  cmStateDetail::PositionType pos =
688
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
689
  pos->SnapshotType = cmStateEnums::MacroCallType;
690
  pos->Keep = false;
691
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
692
    originSnapshot.Position->ExecutionListFile, fileName);
693
  assert(originSnapshot.Position->Vars.IsValid());
694
  pos->BuildSystemDirectory->DirectoryEnd = pos;
695
  pos->PolicyScope = originSnapshot.Position->Policies;
696
  return cmStateSnapshot(this, pos);
697
698
}

699
cmStateSnapshot cmState::CreateIncludeFileSnapshot(
700
  cmStateSnapshot const& originSnapshot, std::string const& fileName)
701
{
702
  cmStateDetail::PositionType pos =
703
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
704
  pos->SnapshotType = cmStateEnums::IncludeFileType;
705
  pos->Keep = true;
706
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
707
    originSnapshot.Position->ExecutionListFile, fileName);
708
  assert(originSnapshot.Position->Vars.IsValid());
709
  pos->BuildSystemDirectory->DirectoryEnd = pos;
710
  pos->PolicyScope = originSnapshot.Position->Policies;
711
  return cmStateSnapshot(this, pos);
712
713
}

714
cmStateSnapshot cmState::CreateVariableScopeSnapshot(
715
  cmStateSnapshot const& originSnapshot)
716
{
717
  cmStateDetail::PositionType pos =
718
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
719
  pos->ScopeParent = originSnapshot.Position;
720
  pos->SnapshotType = cmStateEnums::VariableScopeType;
721
  pos->Keep = false;
722
  pos->PolicyScope = originSnapshot.Position->Policies;
723
  assert(originSnapshot.Position->Vars.IsValid());
724

725
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
726
  pos->Parent = origin;
727
  pos->Vars = this->VarTree.Push(origin);
728
  assert(pos->Vars.IsValid());
729
  return cmStateSnapshot(this, pos);
730
731
}

732
cmStateSnapshot cmState::CreateInlineListFileSnapshot(
733
  cmStateSnapshot const& originSnapshot, std::string const& fileName)
734
{
735
  cmStateDetail::PositionType pos =
736
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
737
  pos->SnapshotType = cmStateEnums::InlineListFileType;
738
  pos->Keep = true;
739
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
740
    originSnapshot.Position->ExecutionListFile, fileName);
741
  pos->BuildSystemDirectory->DirectoryEnd = pos;
742
  pos->PolicyScope = originSnapshot.Position->Policies;
743
  return cmStateSnapshot(this, pos);
744
745
}

746
cmStateSnapshot cmState::CreatePolicyScopeSnapshot(
747
  cmStateSnapshot const& originSnapshot)
748
{
749
  cmStateDetail::PositionType pos =
750
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
751
  pos->SnapshotType = cmStateEnums::PolicyScopeType;
752
  pos->Keep = false;
753
  pos->BuildSystemDirectory->DirectoryEnd = pos;
754
  pos->PolicyScope = originSnapshot.Position->Policies;
755
  return cmStateSnapshot(this, pos);
756
757
}

758
cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot)
759
{
760
761
  cmStateDetail::PositionType pos = originSnapshot.Position;
  cmStateDetail::PositionType prevPos = pos;
762
  ++prevPos;
763
  prevPos->IncludeDirectoryPosition =
764
    prevPos->BuildSystemDirectory->IncludeDirectories.size();
765
  prevPos->CompileDefinitionsPosition =
766
    prevPos->BuildSystemDirectory->CompileDefinitions.size();
767
  prevPos->CompileOptionsPosition =
768
    prevPos->BuildSystemDirectory->CompileOptions.size();
769
  prevPos->BuildSystemDirectory->DirectoryEnd = prevPos;
770

771
772
  if (!pos->Keep && this->SnapshotData.IsLast(pos)) {
    if (pos->Vars != prevPos->Vars) {
773
774
      assert(this->VarTree.IsLast(pos->Vars));
      this->VarTree.Pop(pos->Vars);
775
776
    }
    if (pos->ExecutionListFile != prevPos->ExecutionListFile) {
777
778
779
      assert(this->ExecutionListFiles.IsLast(pos->ExecutionListFile));
      this->ExecutionListFiles.Pop(pos->ExecutionListFile);
    }
780
781
    this->SnapshotData.Pop(pos);
  }
782

783
  return cmStateSnapshot(this, prevPos);
784
785
}

786
static bool ParseEntryWithoutType(const std::string& entry, std::string& var,
787
788
789
790
791
792
793
794
795
                                  std::string& value)
{
  // input line is:         key=value
  static cmsys::RegularExpression reg(
    "^([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  // input line is:         "key"=value
  static cmsys::RegularExpression regQuoted(
    "^\"([^\"]*)\"=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  bool flag = false;
796
  if (regQuoted.find(entry)) {
797
798
799
    var = regQuoted.match(1);
    value = regQuoted.match(2);
    flag = true;
800
  } else if (reg.find(entry)) {
801
802
803
    var = reg.match(1);
    value = reg.match(2);
    flag = true;
804
  }
805
806
807

  // if value is enclosed in single quotes ('foo') then remove them
  // it is used to enclose trailing space or tab
808
809
810
811
  if (flag && value.size() >= 2 && value[0] == '\'' &&
      value[value.size() - 1] == '\'') {
    value = value.substr(1, value.size() - 2);
  }
812
813
814
815

  return flag;
}

816
bool cmState::ParseCacheEntry(const std::string& entry, std::string& var,
817
818
                              std::string& value,
                              cmStateEnums::CacheEntryType& type)
819
820
821
822
823
824
825
826
{
  // input line is:         key:type=value
  static cmsys::RegularExpression reg(
    "^([^=:]*):([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  // input line is:         "key":type=value
  static cmsys::RegularExpression regQuoted(
    "^\"([^\"]*)\":([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  bool flag = false;
827
  if (regQuoted.find(entry)) {
828
829
830
831
    var = regQuoted.match(1);
    type = cmState::StringToCacheEntryType(regQuoted.match(2).c_str());
    value = regQuoted.match(3);
    flag = true;
832
  } else if (reg.find(entry)) {
833
834
835
836
    var = reg.match(1);
    type = cmState::StringToCacheEntryType(reg.match(2).c_str());
    value = reg.match(3);
    flag = true;
837
  }
838
839
840

  // if value is enclosed in single quotes ('foo') then remove them
  // it is used to enclose trailing space or tab
841
842
843
844
  if (flag && value.size() >= 2 && value[0] == '\'' &&
      value[value.size() - 1] == '\'') {
    value = value.substr(1, value.size() - 2);
  }
845

846
  if (!flag) {
847
    return ParseEntryWithoutType(entry, var, value);
848
  }
849
850
851

  return flag;
}