cmState.cxx 25.5 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 "cmListFileCache.h"
16
17
#include "cmStatePrivate.h"
#include "cmStateSnapshot.h"
18
#include "cmSystemTools.h"
19
#include "cmake.h"
20

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

34
35
cmState::~cmState()
{
36
  delete this->CacheManager;
37
38
39
  cmDeleteAll(this->Commands);
}

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

66
67
const char* cmCacheEntryTypes[] = { "BOOL",          "PATH",     "FILEPATH",
                                    "STRING",        "INTERNAL", "STATIC",
Daniel Pfeifer's avatar
Daniel Pfeifer committed
68
                                    "UNINITIALIZED", CM_NULLPTR };
69

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

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

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

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

bool cmState::SaveCache(const std::string& path)
{
109
  return this->CacheManager->SaveCache(path);
110
111
112
113
}

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

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

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

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

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

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

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

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

174
175
176
177
178
179
180
181
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
182
const char* cmState::GetCacheEntryProperty(std::string const& key,
183
                                           std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
184
{
185
186
187
  cmCacheManager::CacheIterator it =
    this->CacheManager->GetCacheIterator(key.c_str());
  if (!it.PropertyExists(propertyName)) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
188
    return CM_NULLPTR;
189
  }
Stephen Kelly's avatar
Stephen Kelly committed
190
191
192
193
  return it.GetProperty(propertyName);
}

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

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

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

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

void cmState::RemoveCacheEntryProperty(std::string const& key,
221
                                       std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
222
{
223
  this->CacheManager->GetCacheIterator(key.c_str())
Daniel Pfeifer's avatar
Daniel Pfeifer committed
224
    .SetProperty(propertyName, (void*)CM_NULLPTR);
Stephen Kelly's avatar
Stephen Kelly committed
225
}
226

227
cmStateSnapshot cmState::Reset()
228
{
229
  this->GlobalProperties.clear();
230
  this->PropertyDefinitions.clear();
231

232
  cmStateDetail::PositionType pos = this->SnapshotData.Truncate();
233
234
  this->ExecutionListFiles.Truncate();

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

250
251
252
253
254
255
  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());
256
257

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

267
268
    pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir.c_str());
    pos->Vars->Set("CMAKE_BINARY_DIR", binDir.c_str());
269
270
  }

271
272
273
274
275
276
277
278
279
280
281
  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);
282

283
  return cmStateSnapshot(this, pos);
284
285
286
}

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

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

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

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

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

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;
}

348
349
350
351
352
void cmState::SetEnabledLanguages(std::vector<std::string> const& langs)
{
  this->EnabledLanguages = langs;
}

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

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

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

368
369
370
371
372
373
374
375
376
377
bool cmState::GetIsGeneratorMultiConfig() const
{
  return this->IsGeneratorMultiConfig;
}

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

378
379
380
381
382
383
384
void cmState::RenameCommand(std::string const& oldName,
                            std::string const& newName)
{
  // if the command already exists, free the old one
  std::string sOldName = cmSystemTools::LowerCase(oldName);
  std::string sNewName = cmSystemTools::LowerCase(newName);
  std::map<std::string, cmCommand*>::iterator pos =
385
386
    this->Commands.find(sOldName);
  if (pos == this->Commands.end()) {
387
    return;
388
  }
389
390
391
  cmCommand* cmd = pos->second;

  pos = this->Commands.find(sNewName);
392
  if (pos != this->Commands.end()) {
393
394
    delete pos->second;
    this->Commands.erase(pos);
395
  }
396
397
398
399
400
401
402
403
404
405
  this->Commands.insert(std::make_pair(sNewName, cmd));
  pos = this->Commands.find(sOldName);
  this->Commands.erase(pos);
}

void cmState::AddCommand(cmCommand* command)
{
  std::string name = cmSystemTools::LowerCase(command->GetName());
  // if the command already exists, free the old one
  std::map<std::string, cmCommand*>::iterator pos = this->Commands.find(name);
406
  if (pos != this->Commands.end()) {
407
408
    delete pos->second;
    this->Commands.erase(pos);
409
  }
410
411
412
413
414
  this->Commands.insert(std::make_pair(name, command));
}

cmCommand* cmState::GetCommand(std::string const& name) const
{
Daniel Pfeifer's avatar
Daniel Pfeifer committed
415
  cmCommand* command = CM_NULLPTR;
416
417
  std::string sName = cmSystemTools::LowerCase(name);
  std::map<std::string, cmCommand*>::const_iterator pos =
418
419
    this->Commands.find(sName);
  if (pos != this->Commands.end()) {
420
    command = (*pos).second;
421
  }
422
423
424
425
426
427
428
  return command;
}

std::vector<std::string> cmState::GetCommandNames() const
{
  std::vector<std::string> commandNames;
  commandNames.reserve(this->Commands.size());
429
430
431
  std::map<std::string, cmCommand*>::const_iterator cmds =
    this->Commands.begin();
  for (; cmds != this->Commands.end(); ++cmds) {
432
    commandNames.push_back(cmds->first);
433
  }
434
435
436
437
438
  return commandNames;
}

void cmState::RemoveUserDefinedCommands()
{
439
  std::vector<cmCommand*> renamedCommands;
440
441
  for (std::map<std::string, cmCommand*>::iterator j = this->Commands.begin();
       j != this->Commands.end();) {
442
    if (j->second->IsUserDefined()) {
443
444
      delete j->second;
      this->Commands.erase(j++);
445
    } else if (j->first != j->second->GetName()) {
446
447
      renamedCommands.push_back(j->second);
      this->Commands.erase(j++);
448
    } else {
449
450
      ++j;
    }
451
  }
452
  for (std::vector<cmCommand*>::const_iterator it = renamedCommands.begin();
453
       it != renamedCommands.end(); ++it) {
454
    this->Commands[cmSystemTools::LowerCase((*it)->GetName())] = *it;
455
  }
456
}
457
458
459

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

463
464
void cmState::AppendGlobalProperty(const std::string& prop, const char* value,
                                   bool asString)
465
{
466
  this->GlobalProperties.AppendProperty(prop, value, asString);
467
468
}

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

bool cmState::GetGlobalPropertyAsBool(const std::string& prop)
{
  return cmSystemTools::IsOn(this->GetGlobalProperty(prop));
}
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520

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);
}

521
522
523
524
525
526
527
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
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;
}

581
582
unsigned int cmState::GetCacheMajorVersion() const
{
583
  return this->CacheManager->GetCacheMajorVersion();
584
585
586
587
}

unsigned int cmState::GetCacheMinorVersion() const
{
588
  return this->CacheManager->GetCacheMinorVersion();
589
590
}

591
592
593
594
const char* cmState::GetBinaryDirectory() const
{
  return this->BinaryDirectory.c_str();
}
Stephen Kelly's avatar
Stephen Kelly committed
595

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

624
625
cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot(
  cmStateSnapshot originSnapshot)
Stephen Kelly's avatar
Stephen Kelly committed
626
{
627
  assert(originSnapshot.IsValid());
628
629
  cmStateDetail::PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position);
630
  pos->DirectoryParent = originSnapshot.Position;
631
  pos->ScopeParent = originSnapshot.Position;
632
  pos->SnapshotType = cmStateEnums::BuildsystemDirectoryType;
633
  pos->Keep = true;
634
635
  pos->BuildSystemDirectory = this->BuildsystemDirectory.Push(
    originSnapshot.Position->BuildSystemDirectory);
636
  pos->ExecutionListFile =
637
    this->ExecutionListFiles.Push(originSnapshot.Position->ExecutionListFile);
638
  pos->BuildSystemDirectory->DirectoryEnd = pos;
639
640
641
642
643
  pos->Policies = originSnapshot.Position->Policies;
  pos->PolicyRoot = originSnapshot.Position->Policies;
  pos->PolicyScope = originSnapshot.Position->Policies;
  assert(pos->Policies.IsValid());
  assert(pos->PolicyRoot.IsValid());
644

645
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
646
647
  pos->Parent = origin;
  pos->Root = origin;
648
  pos->Vars = this->VarTree.Push(origin);
649

650
  cmStateSnapshot snapshot = cmStateSnapshot(this, pos);
651
  originSnapshot.Position->BuildSystemDirectory->Children.push_back(snapshot);
652
  snapshot.SetDefaultDefinitions();
653
  snapshot.InitializeFromParent();
654
  snapshot.SetDirectoryDefinitions();
655
  return snapshot;
Stephen Kelly's avatar
Stephen Kelly committed
656
657
}

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

677
678
cmStateSnapshot cmState::CreateMacroCallSnapshot(
  cmStateSnapshot originSnapshot, std::string const& fileName)
679
{
680
  cmStateDetail::PositionType pos =
681
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
682
  pos->SnapshotType = cmStateEnums::MacroCallType;
683
  pos->Keep = false;
684
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
685
    originSnapshot.Position->ExecutionListFile, fileName);
686
  assert(originSnapshot.Position->Vars.IsValid());
687
  pos->BuildSystemDirectory->DirectoryEnd = pos;
688
  pos->PolicyScope = originSnapshot.Position->Policies;
689
  return cmStateSnapshot(this, pos);
690
691
}

692
693
cmStateSnapshot cmState::CreateIncludeFileSnapshot(
  cmStateSnapshot originSnapshot, const std::string& fileName)
694
{
695
  cmStateDetail::PositionType pos =
696
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
697
  pos->SnapshotType = cmStateEnums::IncludeFileType;
698
  pos->Keep = true;
699
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
700
    originSnapshot.Position->ExecutionListFile, fileName);
701
  assert(originSnapshot.Position->Vars.IsValid());
702
  pos->BuildSystemDirectory->DirectoryEnd = pos;
703
  pos->PolicyScope = originSnapshot.Position->Policies;
704
  return cmStateSnapshot(this, pos);
705
706
}

707
708
cmStateSnapshot cmState::CreateVariableScopeSnapshot(
  cmStateSnapshot originSnapshot)
709
{
710
  cmStateDetail::PositionType pos =
711
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
712
  pos->ScopeParent = originSnapshot.Position;
713
  pos->SnapshotType = cmStateEnums::VariableScopeType;
714
  pos->Keep = false;
715
  pos->PolicyScope = originSnapshot.Position->Policies;
716
  assert(originSnapshot.Position->Vars.IsValid());
717

718
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
719
  pos->Parent = origin;
720
  pos->Vars = this->VarTree.Push(origin);
721
  assert(pos->Vars.IsValid());
722
  return cmStateSnapshot(this, pos);
723
724
}

725
726
cmStateSnapshot cmState::CreateInlineListFileSnapshot(
  cmStateSnapshot originSnapshot, const std::string& fileName)
727
{
728
  cmStateDetail::PositionType pos =
729
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
730
  pos->SnapshotType = cmStateEnums::InlineListFileType;
731
  pos->Keep = true;
732
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
733
    originSnapshot.Position->ExecutionListFile, fileName);
734
  pos->BuildSystemDirectory->DirectoryEnd = pos;
735
  pos->PolicyScope = originSnapshot.Position->Policies;
736
  return cmStateSnapshot(this, pos);
737
738
}

739
740
cmStateSnapshot cmState::CreatePolicyScopeSnapshot(
  cmStateSnapshot originSnapshot)
741
{
742
  cmStateDetail::PositionType pos =
743
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
744
  pos->SnapshotType = cmStateEnums::PolicyScopeType;
745
  pos->Keep = false;
746
  pos->BuildSystemDirectory->DirectoryEnd = pos;
747
  pos->PolicyScope = originSnapshot.Position->Policies;
748
  return cmStateSnapshot(this, pos);
749
750
}

751
cmStateSnapshot cmState::Pop(cmStateSnapshot originSnapshot)
752
{
753
754
  cmStateDetail::PositionType pos = originSnapshot.Position;
  cmStateDetail::PositionType prevPos = pos;
755
  ++prevPos;
756
  prevPos->IncludeDirectoryPosition =
757
    prevPos->BuildSystemDirectory->IncludeDirectories.size();
758
  prevPos->CompileDefinitionsPosition =
759
    prevPos->BuildSystemDirectory->CompileDefinitions.size();
760
  prevPos->CompileOptionsPosition =
761
    prevPos->BuildSystemDirectory->CompileOptions.size();
762
  prevPos->BuildSystemDirectory->DirectoryEnd = prevPos;
763

764
765
  if (!pos->Keep && this->SnapshotData.IsLast(pos)) {
    if (pos->Vars != prevPos->Vars) {
766
767
      assert(this->VarTree.IsLast(pos->Vars));
      this->VarTree.Pop(pos->Vars);
768
769
    }
    if (pos->ExecutionListFile != prevPos->ExecutionListFile) {
770
771
772
      assert(this->ExecutionListFiles.IsLast(pos->ExecutionListFile));
      this->ExecutionListFiles.Pop(pos->ExecutionListFile);
    }
773
774
    this->SnapshotData.Pop(pos);
  }
775

776
  return cmStateSnapshot(this, prevPos);
777
778
}

779
static bool ParseEntryWithoutType(const std::string& entry, std::string& var,
780
781
782
783
784
785
786
787
788
                                  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;
789
  if (regQuoted.find(entry)) {
790
791
792
    var = regQuoted.match(1);
    value = regQuoted.match(2);
    flag = true;
793
  } else if (reg.find(entry)) {
794
795
796
    var = reg.match(1);
    value = reg.match(2);
    flag = true;
797
  }
798
799
800

  // if value is enclosed in single quotes ('foo') then remove them
  // it is used to enclose trailing space or tab
801
802
803
804
  if (flag && value.size() >= 2 && value[0] == '\'' &&
      value[value.size() - 1] == '\'') {
    value = value.substr(1, value.size() - 2);
  }
805
806
807
808

  return flag;
}

809
bool cmState::ParseCacheEntry(const std::string& entry, std::string& var,
810
811
                              std::string& value,
                              cmStateEnums::CacheEntryType& type)
812
813
814
815
816
817
818
819
{
  // 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;
820
  if (regQuoted.find(entry)) {
821
822
823
824
    var = regQuoted.match(1);
    type = cmState::StringToCacheEntryType(regQuoted.match(2).c_str());
    value = regQuoted.match(3);
    flag = true;
825
  } else if (reg.find(entry)) {
826
827
828
829
    var = reg.match(1);
    type = cmState::StringToCacheEntryType(reg.match(2).c_str());
    value = reg.match(3);
    flag = true;
830
  }
831
832
833

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

839
  if (!flag) {
840
    return ParseEntryWithoutType(entry, var, value);
841
  }
842
843
844

  return flag;
}