cmState.cxx 26.2 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
447
448
449
450
451
452
453
454
  commandNames.reserve(this->BuiltinCommands.size() +
                       this->ScriptedCommands.size());
  for (std::map<std::string, cmCommand*>::const_iterator cmds =
         this->BuiltinCommands.begin();
       cmds != this->BuiltinCommands.end(); ++cmds) {
    commandNames.push_back(cmds->first);
  }
  for (std::map<std::string, cmCommand*>::const_iterator cmds =
         this->ScriptedCommands.begin();
       cmds != this->ScriptedCommands.end(); ++cmds) {
455
    commandNames.push_back(cmds->first);
456
  }
457
458
459
  std::sort(commandNames.begin(), commandNames.end());
  commandNames.erase(std::unique(commandNames.begin(), commandNames.end()),
                     commandNames.end());
460
461
462
463
464
  return commandNames;
}

void cmState::RemoveUserDefinedCommands()
{
465
466
  cmDeleteAll(this->ScriptedCommands);
  this->ScriptedCommands.clear();
467
}
468
469
470

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

474
475
void cmState::AppendGlobalProperty(const std::string& prop, const char* value,
                                   bool asString)
476
{
477
  this->GlobalProperties.AppendProperty(prop, value, asString);
478
479
}

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

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

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

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
588
589
590
591
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;
}

592
593
unsigned int cmState::GetCacheMajorVersion() const
{
594
  return this->CacheManager->GetCacheMajorVersion();
595
596
597
598
}

unsigned int cmState::GetCacheMinorVersion() const
{
599
  return this->CacheManager->GetCacheMinorVersion();
600
601
}

602
603
604
605
const char* cmState::GetBinaryDirectory() const
{
  return this->BinaryDirectory.c_str();
}
Stephen Kelly's avatar
Stephen Kelly committed
606

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

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

656
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
657
658
  pos->Parent = origin;
  pos->Root = origin;
659
  pos->Vars = this->VarTree.Push(origin);
660

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

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

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

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

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

729
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
730
  pos->Parent = origin;
731
  pos->Vars = this->VarTree.Push(origin);
732
  assert(pos->Vars.IsValid());
733
  return cmStateSnapshot(this, pos);
734
735
}

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

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

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

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

787
  return cmStateSnapshot(this, prevPos);
788
789
}

790
static bool ParseEntryWithoutType(const std::string& entry, std::string& var,
791
792
793
794
795
796
797
798
799
                                  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;
800
  if (regQuoted.find(entry)) {
801
802
803
    var = regQuoted.match(1);
    value = regQuoted.match(2);
    flag = true;
804
  } else if (reg.find(entry)) {
805
806
807
    var = reg.match(1);
    value = reg.match(2);
    flag = true;
808
  }
809
810
811

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

  return flag;
}

820
bool cmState::ParseCacheEntry(const std::string& entry, std::string& var,
821
822
                              std::string& value,
                              cmStateEnums::CacheEntryType& type)
823
824
825
826
827
828
829
830
{
  // 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;
831
  if (regQuoted.find(entry)) {
832
833
834
835
    var = regQuoted.match(1);
    type = cmState::StringToCacheEntryType(regQuoted.match(2).c_str());
    value = regQuoted.match(3);
    flag = true;
836
  } else if (reg.find(entry)) {
837
838
839
840
    var = reg.match(1);
    type = cmState::StringToCacheEntryType(reg.match(2).c_str());
    value = reg.match(3);
    flag = true;
841
  }
842
843
844

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

850
  if (!flag) {
851
    return ParseEntryWithoutType(entry, var, value);
852
  }
853
854
855

  return flag;
}