~ubuntu-branches/ubuntu/utopic/cmake/utopic

« back to all changes in this revision

Viewing changes to Source/cmGeneratorExpressionEvaluator.cxx

  • Committer: Package Import Robot
  • Author(s): Harald Sitter
  • Date: 2013-10-10 12:54:39 UTC
  • mfrom: (1.14.7)
  • Revision ID: package-import@ubuntu.com-20131010125439-h0ahaj004on6oj92
Tags: 2.8.12-0ubuntu1
New upstream release LP: #1246701

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
//----------------------------------------------------------------------------
46
46
struct cmGeneratorExpressionNode
47
47
{
 
48
  enum {
 
49
    DynamicParameters = 0,
 
50
    OneOrMoreParameters = -1,
 
51
    ZeroOrMoreParameters = -2
 
52
  };
48
53
  virtual ~cmGeneratorExpressionNode() {}
49
54
 
50
55
  virtual bool GeneratesContent() const { return true; }
51
56
 
52
57
  virtual bool RequiresLiteralInput() const { return false; }
53
58
 
54
 
  virtual bool AcceptsSingleArbitraryContentParameter() const
 
59
  virtual bool AcceptsArbitraryContentParameter() const
55
60
    { return false; }
56
61
 
57
62
  virtual int NumExpectedParameters() const { return 1; }
70
75
 
71
76
  virtual bool GeneratesContent() const { return false; }
72
77
 
73
 
  virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
 
78
  virtual bool AcceptsArbitraryContentParameter() const { return true; }
74
79
 
75
80
  std::string Evaluate(const std::vector<std::string> &,
76
81
                       cmGeneratorExpressionContext *,
87
92
{
88
93
  OneNode() {}
89
94
 
90
 
  virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
 
95
  virtual bool AcceptsArbitraryContentParameter() const { return true; }
91
96
 
92
97
  std::string Evaluate(const std::vector<std::string> &,
93
98
                       cmGeneratorExpressionContext *,
110
115
static const struct OP ## Node : public cmGeneratorExpressionNode \
111
116
{ \
112
117
  OP ## Node () {} \
113
 
/* We let -1 carry the meaning 'at least one' */ \
114
 
  virtual int NumExpectedParameters() const { return -1; } \
 
118
  virtual int NumExpectedParameters() const { return OneOrMoreParameters; } \
115
119
 \
116
120
  std::string Evaluate(const std::vector<std::string> &parameters, \
117
121
                       cmGeneratorExpressionContext *context, \
243
247
} semicolonNode;
244
248
 
245
249
//----------------------------------------------------------------------------
 
250
struct CompilerIdNode : public cmGeneratorExpressionNode
 
251
{
 
252
  CompilerIdNode() {}
 
253
 
 
254
  virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
 
255
 
 
256
  std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
 
257
                       cmGeneratorExpressionContext *context,
 
258
                       const GeneratorExpressionContent *content,
 
259
                       cmGeneratorExpressionDAGChecker *,
 
260
                       const std::string &lang) const
 
261
  {
 
262
    const char *compilerId = context->Makefile ?
 
263
                              context->Makefile->GetSafeDefinition((
 
264
                              "CMAKE_" + lang + "_COMPILER_ID").c_str()) : "";
 
265
    if (parameters.size() == 0)
 
266
      {
 
267
      return compilerId ? compilerId : "";
 
268
      }
 
269
    cmsys::RegularExpression compilerIdValidator;
 
270
    compilerIdValidator.compile("^[A-Za-z0-9_]*$");
 
271
    if (!compilerIdValidator.find(parameters.begin()->c_str()))
 
272
      {
 
273
      reportError(context, content->GetOriginalExpression(),
 
274
                  "Expression syntax not recognized.");
 
275
      return std::string();
 
276
      }
 
277
    if (!compilerId)
 
278
      {
 
279
      return parameters.front().empty() ? "1" : "0";
 
280
      }
 
281
 
 
282
    if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0)
 
283
      {
 
284
      return "1";
 
285
      }
 
286
    return "0";
 
287
  }
 
288
};
 
289
 
 
290
//----------------------------------------------------------------------------
 
291
static const struct CCompilerIdNode : public CompilerIdNode
 
292
{
 
293
  CCompilerIdNode() {}
 
294
 
 
295
  std::string Evaluate(const std::vector<std::string> &parameters,
 
296
                       cmGeneratorExpressionContext *context,
 
297
                       const GeneratorExpressionContent *content,
 
298
                       cmGeneratorExpressionDAGChecker *dagChecker) const
 
299
  {
 
300
    if (parameters.size() != 0 && parameters.size() != 1)
 
301
      {
 
302
      reportError(context, content->GetOriginalExpression(),
 
303
          "$<C_COMPILER_ID> expression requires one or two parameters");
 
304
      return std::string();
 
305
      }
 
306
    if (!context->HeadTarget)
 
307
      {
 
308
      reportError(context, content->GetOriginalExpression(),
 
309
          "$<C_COMPILER_ID> may only be used with targets.  It may not "
 
310
          "be used with add_custom_command.");
 
311
      }
 
312
    return this->EvaluateWithLanguage(parameters, context, content,
 
313
                                      dagChecker, "C");
 
314
  }
 
315
} cCompilerIdNode;
 
316
 
 
317
//----------------------------------------------------------------------------
 
318
static const struct CXXCompilerIdNode : public CompilerIdNode
 
319
{
 
320
  CXXCompilerIdNode() {}
 
321
 
 
322
  std::string Evaluate(const std::vector<std::string> &parameters,
 
323
                       cmGeneratorExpressionContext *context,
 
324
                       const GeneratorExpressionContent *content,
 
325
                       cmGeneratorExpressionDAGChecker *dagChecker) const
 
326
  {
 
327
    if (parameters.size() != 0 && parameters.size() != 1)
 
328
      {
 
329
      reportError(context, content->GetOriginalExpression(),
 
330
          "$<CXX_COMPILER_ID> expression requires one or two parameters");
 
331
      return std::string();
 
332
      }
 
333
    if (!context->HeadTarget)
 
334
      {
 
335
      reportError(context, content->GetOriginalExpression(),
 
336
          "$<CXX_COMPILER_ID> may only be used with targets.  It may not "
 
337
          "be used with add_custom_command.");
 
338
      }
 
339
    return this->EvaluateWithLanguage(parameters, context, content,
 
340
                                      dagChecker, "CXX");
 
341
  }
 
342
} cxxCompilerIdNode;
 
343
 
 
344
//----------------------------------------------------------------------------
 
345
struct CompilerVersionNode : public cmGeneratorExpressionNode
 
346
{
 
347
  CompilerVersionNode() {}
 
348
 
 
349
  virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
 
350
 
 
351
  std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
 
352
                       cmGeneratorExpressionContext *context,
 
353
                       const GeneratorExpressionContent *content,
 
354
                       cmGeneratorExpressionDAGChecker *,
 
355
                       const std::string &lang) const
 
356
  {
 
357
    const char *compilerVersion = context->Makefile ?
 
358
                              context->Makefile->GetSafeDefinition((
 
359
                        "CMAKE_" + lang + "_COMPILER_VERSION").c_str()) : "";
 
360
    if (parameters.size() == 0)
 
361
      {
 
362
      return compilerVersion ? compilerVersion : "";
 
363
      }
 
364
 
 
365
    cmsys::RegularExpression compilerIdValidator;
 
366
    compilerIdValidator.compile("^[0-9\\.]*$");
 
367
    if (!compilerIdValidator.find(parameters.begin()->c_str()))
 
368
      {
 
369
      reportError(context, content->GetOriginalExpression(),
 
370
                  "Expression syntax not recognized.");
 
371
      return std::string();
 
372
      }
 
373
    if (!compilerVersion)
 
374
      {
 
375
      return parameters.front().empty() ? "1" : "0";
 
376
      }
 
377
 
 
378
    return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
 
379
                                      parameters.begin()->c_str(),
 
380
                                      compilerVersion) ? "1" : "0";
 
381
  }
 
382
};
 
383
 
 
384
//----------------------------------------------------------------------------
 
385
static const struct CCompilerVersionNode : public CompilerVersionNode
 
386
{
 
387
  CCompilerVersionNode() {}
 
388
 
 
389
  std::string Evaluate(const std::vector<std::string> &parameters,
 
390
                       cmGeneratorExpressionContext *context,
 
391
                       const GeneratorExpressionContent *content,
 
392
                       cmGeneratorExpressionDAGChecker *dagChecker) const
 
393
  {
 
394
    if (parameters.size() != 0 && parameters.size() != 1)
 
395
      {
 
396
      reportError(context, content->GetOriginalExpression(),
 
397
          "$<C_COMPILER_VERSION> expression requires one or two parameters");
 
398
      return std::string();
 
399
      }
 
400
    if (!context->HeadTarget)
 
401
      {
 
402
      reportError(context, content->GetOriginalExpression(),
 
403
          "$<C_COMPILER_VERSION> may only be used with targets.  It may not "
 
404
          "be used with add_custom_command.");
 
405
      }
 
406
    return this->EvaluateWithLanguage(parameters, context, content,
 
407
                                      dagChecker, "C");
 
408
  }
 
409
} cCompilerVersionNode;
 
410
 
 
411
//----------------------------------------------------------------------------
 
412
static const struct CxxCompilerVersionNode : public CompilerVersionNode
 
413
{
 
414
  CxxCompilerVersionNode() {}
 
415
 
 
416
  std::string Evaluate(const std::vector<std::string> &parameters,
 
417
                       cmGeneratorExpressionContext *context,
 
418
                       const GeneratorExpressionContent *content,
 
419
                       cmGeneratorExpressionDAGChecker *dagChecker) const
 
420
  {
 
421
    if (parameters.size() != 0 && parameters.size() != 1)
 
422
      {
 
423
      reportError(context, content->GetOriginalExpression(),
 
424
          "$<CXX_COMPILER_VERSION> expression requires one or two "
 
425
          "parameters");
 
426
      return std::string();
 
427
      }
 
428
    if (!context->HeadTarget)
 
429
      {
 
430
      reportError(context, content->GetOriginalExpression(),
 
431
          "$<CXX_COMPILER_VERSION> may only be used with targets.  It may "
 
432
          "not be used with add_custom_command.");
 
433
      }
 
434
    return this->EvaluateWithLanguage(parameters, context, content,
 
435
                                      dagChecker, "CXX");
 
436
  }
 
437
} cxxCompilerVersionNode;
 
438
 
 
439
 
 
440
//----------------------------------------------------------------------------
 
441
static const struct VersionGreaterNode : public cmGeneratorExpressionNode
 
442
{
 
443
  VersionGreaterNode() {}
 
444
 
 
445
  virtual int NumExpectedParameters() const { return 2; }
 
446
 
 
447
  std::string Evaluate(const std::vector<std::string> &parameters,
 
448
                       cmGeneratorExpressionContext *,
 
449
                       const GeneratorExpressionContent *,
 
450
                       cmGeneratorExpressionDAGChecker *) const
 
451
  {
 
452
    return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
 
453
                                         parameters.front().c_str(),
 
454
                                         parameters[1].c_str()) ? "1" : "0";
 
455
  }
 
456
} versionGreaterNode;
 
457
 
 
458
//----------------------------------------------------------------------------
 
459
static const struct VersionLessNode : public cmGeneratorExpressionNode
 
460
{
 
461
  VersionLessNode() {}
 
462
 
 
463
  virtual int NumExpectedParameters() const { return 2; }
 
464
 
 
465
  std::string Evaluate(const std::vector<std::string> &parameters,
 
466
                       cmGeneratorExpressionContext *,
 
467
                       const GeneratorExpressionContent *,
 
468
                       cmGeneratorExpressionDAGChecker *) const
 
469
  {
 
470
    return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
 
471
                                         parameters.front().c_str(),
 
472
                                         parameters[1].c_str()) ? "1" : "0";
 
473
  }
 
474
} versionLessNode;
 
475
 
 
476
//----------------------------------------------------------------------------
 
477
static const struct VersionEqualNode : public cmGeneratorExpressionNode
 
478
{
 
479
  VersionEqualNode() {}
 
480
 
 
481
  virtual int NumExpectedParameters() const { return 2; }
 
482
 
 
483
  std::string Evaluate(const std::vector<std::string> &parameters,
 
484
                       cmGeneratorExpressionContext *,
 
485
                       const GeneratorExpressionContent *,
 
486
                       cmGeneratorExpressionDAGChecker *) const
 
487
  {
 
488
    return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
 
489
                                         parameters.front().c_str(),
 
490
                                         parameters[1].c_str()) ? "1" : "0";
 
491
  }
 
492
} versionEqualNode;
 
493
 
 
494
//----------------------------------------------------------------------------
 
495
static const struct LinkOnlyNode : public cmGeneratorExpressionNode
 
496
{
 
497
  LinkOnlyNode() {}
 
498
 
 
499
  std::string Evaluate(const std::vector<std::string> &parameters,
 
500
                       cmGeneratorExpressionContext *,
 
501
                       const GeneratorExpressionContent *,
 
502
                       cmGeneratorExpressionDAGChecker *dagChecker) const
 
503
  {
 
504
    if(!dagChecker->GetTransitivePropertiesOnly())
 
505
      {
 
506
      return parameters.front();
 
507
      }
 
508
    return "";
 
509
  }
 
510
} linkOnlyNode;
 
511
 
 
512
//----------------------------------------------------------------------------
246
513
static const struct ConfigurationNode : public cmGeneratorExpressionNode
247
514
{
248
515
  ConfigurationNode() {}
297
564
      const char* loc = 0;
298
565
      const char* imp = 0;
299
566
      std::string suffix;
300
 
      return context->CurrentTarget->GetMappedConfig(context->Config,
 
567
      if (context->CurrentTarget->GetMappedConfig(context->Config,
301
568
                                                  &loc,
302
569
                                                  &imp,
303
 
                                                  suffix) ? "1" : "0";
 
570
                                                  suffix))
 
571
        {
 
572
        // This imported target has an appropriate location
 
573
        // for this (possibly mapped) config.
 
574
        // Check if there is a proper config mapping for the tested config.
 
575
        std::vector<std::string> mappedConfigs;
 
576
        std::string mapProp = "MAP_IMPORTED_CONFIG_";
 
577
        mapProp += cmSystemTools::UpperCase(context->Config);
 
578
        if(const char* mapValue =
 
579
                        context->CurrentTarget->GetProperty(mapProp.c_str()))
 
580
          {
 
581
          cmSystemTools::ExpandListArgument(cmSystemTools::UpperCase(mapValue),
 
582
                                            mappedConfigs);
 
583
          return std::find(mappedConfigs.begin(), mappedConfigs.end(),
 
584
                           cmSystemTools::UpperCase(parameters.front()))
 
585
              != mappedConfigs.end() ? "1" : "0";
 
586
          }
 
587
        }
304
588
      }
305
589
    return "0";
306
590
  }
307
591
} configurationTestNode;
308
592
 
 
593
static const struct JoinNode : public cmGeneratorExpressionNode
 
594
{
 
595
  JoinNode() {}
 
596
 
 
597
  virtual int NumExpectedParameters() const { return 2; }
 
598
 
 
599
  virtual bool AcceptsArbitraryContentParameter() const { return true; }
 
600
 
 
601
  std::string Evaluate(const std::vector<std::string> &parameters,
 
602
                       cmGeneratorExpressionContext *,
 
603
                       const GeneratorExpressionContent *,
 
604
                       cmGeneratorExpressionDAGChecker *) const
 
605
  {
 
606
    std::string result;
 
607
 
 
608
    std::vector<std::string> list;
 
609
    cmSystemTools::ExpandListArgument(parameters.front(), list);
 
610
    std::string sep;
 
611
    for(std::vector<std::string>::const_iterator li = list.begin();
 
612
      li != list.end(); ++li)
 
613
      {
 
614
      result += sep + *li;
 
615
      sep = parameters[1];
 
616
      }
 
617
    return result;
 
618
  }
 
619
} joinNode;
 
620
 
 
621
#define TRANSITIVE_PROPERTY_NAME(PROPERTY) \
 
622
  , #PROPERTY
309
623
 
310
624
//----------------------------------------------------------------------------
311
625
static const char* targetPropertyTransitiveWhitelist[] = {
312
 
    "INTERFACE_INCLUDE_DIRECTORIES"
313
 
  , "INTERFACE_COMPILE_DEFINITIONS"
 
626
  0
 
627
  CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
314
628
};
315
629
 
316
630
std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
373
687
  TargetPropertyNode() {}
374
688
 
375
689
  // This node handles errors on parameter count itself.
376
 
  virtual int NumExpectedParameters() const { return -1; }
 
690
  virtual int NumExpectedParameters() const { return OneOrMoreParameters; }
377
691
 
378
692
  std::string Evaluate(const std::vector<std::string> &parameters,
379
693
                       cmGeneratorExpressionContext *context,
434
748
                      "Target name not supported.");
435
749
        return std::string();
436
750
        }
 
751
      if(propertyName == "ALIASED_TARGET")
 
752
        {
 
753
        if(context->Makefile->IsAlias(targetName.c_str()))
 
754
          {
 
755
          if(cmTarget* tgt =
 
756
                      context->Makefile->FindTargetToUse(targetName.c_str()))
 
757
            {
 
758
            return tgt->GetName();
 
759
            }
 
760
          }
 
761
        return "";
 
762
        }
437
763
      target = context->Makefile->FindTargetToUse(
438
764
                                                targetName.c_str());
439
765
 
475
801
 
476
802
    assert(target);
477
803
 
 
804
    if (propertyName == "LINKER_LANGUAGE")
 
805
      {
 
806
      if (target->LinkLanguagePropagatesToDependents() &&
 
807
          dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
 
808
        {
 
809
        reportError(context, content->GetOriginalExpression(),
 
810
            "LINKER_LANGUAGE target property can not be used while evaluating "
 
811
            "link libraries for a static library");
 
812
        return std::string();
 
813
        }
 
814
      const char *lang = target->GetLinkerLanguage(context->Config);
 
815
      return lang ? lang : "";
 
816
      }
 
817
 
478
818
    cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
479
819
                                               target->GetName(),
480
820
                                               propertyName,
490
830
      // No error. We just skip cyclic references.
491
831
      return std::string();
492
832
    case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
493
 
      for (size_t i = 0;
 
833
      for (size_t i = 1;
494
834
          i < (sizeof(targetPropertyTransitiveWhitelist) /
495
835
                sizeof(*targetPropertyTransitiveWhitelist));
496
836
          ++i)
518
858
        }
519
859
      else
520
860
        {
521
 
        assert(dagCheckerParent->EvaluatingIncludeDirectories()
522
 
            || dagCheckerParent->EvaluatingCompileDefinitions());
 
861
#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) \
 
862
  dagCheckerParent->METHOD () ||
 
863
 
 
864
        assert(
 
865
          CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
 
866
                                            ASSERT_TRANSITIVE_PROPERTY_METHOD)
 
867
          false);
523
868
        }
524
869
      }
525
870
 
532
877
      {
533
878
      interfacePropertyName = "INTERFACE_INCLUDE_DIRECTORIES";
534
879
      }
 
880
    else if (propertyName == "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")
 
881
      {
 
882
      interfacePropertyName = "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES";
 
883
      }
535
884
    else if (propertyName == "INTERFACE_COMPILE_DEFINITIONS"
536
885
        || propertyName == "COMPILE_DEFINITIONS"
537
886
        || strncmp(propertyName.c_str(), "COMPILE_DEFINITIONS_", 20) == 0)
538
887
      {
539
888
      interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
540
889
      }
 
890
    else if (propertyName == "INTERFACE_COMPILE_OPTIONS"
 
891
        || propertyName == "COMPILE_OPTIONS")
 
892
      {
 
893
      interfacePropertyName = "INTERFACE_COMPILE_OPTIONS";
 
894
      }
541
895
 
542
896
    cmTarget *headTarget = context->HeadTarget ? context->HeadTarget : target;
543
897
 
544
 
    const char **transBegin = targetPropertyTransitiveWhitelist;
 
898
    const char **transBegin = targetPropertyTransitiveWhitelist + 1;
545
899
    const char **transEnd = targetPropertyTransitiveWhitelist
546
900
              + (sizeof(targetPropertyTransitiveWhitelist) /
547
901
              sizeof(*targetPropertyTransitiveWhitelist));
548
902
    if (std::find_if(transBegin, transEnd,
549
903
              TransitiveWhitelistCompare(propertyName)) != transEnd)
550
904
      {
551
 
      const cmTarget::LinkInterface *iface = target->GetLinkInterface(
552
 
                                                    context->Config,
553
 
                                                    headTarget);
554
 
      if(iface)
 
905
 
 
906
      std::vector<std::string> libs;
 
907
      target->GetTransitivePropertyLinkLibraries(context->Config,
 
908
                                                 headTarget, libs);
 
909
      if (!libs.empty())
555
910
        {
556
911
        linkedTargetsContent =
557
 
                  getLinkedTargetsContent(iface->Libraries, target,
 
912
                  getLinkedTargetsContent(libs, target,
558
913
                                          headTarget,
559
914
                                          context, &dagChecker,
560
915
                                          interfacePropertyName);
607
962
      return linkedTargetsContent;
608
963
      }
609
964
 
610
 
    for (size_t i = 0;
 
965
    for (size_t i = 1;
611
966
         i < (sizeof(targetPropertyTransitiveWhitelist) /
612
967
              sizeof(*targetPropertyTransitiveWhitelist));
613
968
         ++i)
645
1000
 
646
1001
  virtual bool GeneratesContent() const { return true; }
647
1002
 
648
 
  virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
 
1003
  virtual bool AcceptsArbitraryContentParameter() const { return true; }
649
1004
  virtual bool RequiresLiteralInput() const { return true; }
650
1005
 
651
1006
  std::string Evaluate(const std::vector<std::string> &parameters,
662
1017
 
663
1018
//----------------------------------------------------------------------------
664
1019
static const char* targetPolicyWhitelist[] = {
665
 
    "CMP0003"
666
 
  , "CMP0004"
667
 
  , "CMP0008"
668
 
  , "CMP0020"
 
1020
  0
 
1021
#define TARGET_POLICY_STRING(POLICY) \
 
1022
  , #POLICY
 
1023
 
 
1024
  CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)
 
1025
 
 
1026
#undef TARGET_POLICY_STRING
669
1027
};
670
1028
 
671
1029
cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy)
676
1034
    return tgt->GetPolicyStatus ## POLICY (); \
677
1035
  } \
678
1036
 
679
 
  RETURN_POLICY(CMP0003)
680
 
  RETURN_POLICY(CMP0004)
681
 
  RETURN_POLICY(CMP0008)
682
 
  RETURN_POLICY(CMP0020)
 
1037
  CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY)
683
1038
 
684
1039
#undef RETURN_POLICY
685
1040
 
695
1050
    return cmPolicies:: POLICY_ID; \
696
1051
  } \
697
1052
 
698
 
  RETURN_POLICY_ID(CMP0003)
699
 
  RETURN_POLICY_ID(CMP0004)
700
 
  RETURN_POLICY_ID(CMP0008)
701
 
  RETURN_POLICY_ID(CMP0020)
 
1053
  CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY_ID)
702
1054
 
703
1055
#undef RETURN_POLICY_ID
704
1056
 
728
1080
 
729
1081
    context->HadContextSensitiveCondition = true;
730
1082
 
731
 
    for (size_t i = 0;
 
1083
    for (size_t i = 1;
732
1084
         i < (sizeof(targetPolicyWhitelist) /
733
1085
              sizeof(*targetPolicyWhitelist));
734
1086
         ++i)
754
1106
      }
755
1107
    reportError(context, content->GetOriginalExpression(),
756
1108
      "$<TARGET_POLICY:prop> may only be used with a limited number of "
757
 
      "policies.  Currently it may be used with policies CMP0003, CMP0004, "
758
 
      "CMP0008 and CMP0020."
 
1109
      "policies.  Currently it may be used with the following policies:\n"
 
1110
 
 
1111
#define STRINGIFY_HELPER(X) #X
 
1112
#define STRINGIFY(X) STRINGIFY_HELPER(X)
 
1113
 
 
1114
#define TARGET_POLICY_LIST_ITEM(POLICY) \
 
1115
      " * " STRINGIFY(POLICY) "\n"
 
1116
 
 
1117
      CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)
 
1118
 
 
1119
#undef TARGET_POLICY_LIST_ITEM
759
1120
      );
760
1121
    return std::string();
761
1122
  }
898
1259
  std::string Evaluate(const std::vector<std::string> &parameters,
899
1260
                       cmGeneratorExpressionContext *context,
900
1261
                       const GeneratorExpressionContent *content,
901
 
                       cmGeneratorExpressionDAGChecker *) const
 
1262
                       cmGeneratorExpressionDAGChecker *dagChecker) const
902
1263
  {
903
1264
    // Lookup the referenced target.
904
1265
    std::string name = *parameters.begin();
923
1284
                  "Target \"" + name + "\" is not an executable or library.");
924
1285
      return std::string();
925
1286
      }
 
1287
    if (dagChecker && dagChecker->EvaluatingLinkLibraries(name.c_str()))
 
1288
      {
 
1289
      ::reportError(context, content->GetOriginalExpression(),
 
1290
                    "Expressions which require the linker language may not "
 
1291
                    "be used while evaluating link libraries");
 
1292
      return std::string();
 
1293
      }
926
1294
    context->DependTargets.insert(target);
927
1295
    context->AllTargets.insert(target);
928
1296
 
974
1342
    return &orNode;
975
1343
  else if (identifier == "NOT")
976
1344
    return &notNode;
 
1345
  else if (identifier == "C_COMPILER_ID")
 
1346
    return &cCompilerIdNode;
 
1347
  else if (identifier == "CXX_COMPILER_ID")
 
1348
    return &cxxCompilerIdNode;
 
1349
  else if (identifier == "VERSION_GREATER")
 
1350
    return &versionGreaterNode;
 
1351
  else if (identifier == "VERSION_LESS")
 
1352
    return &versionLessNode;
 
1353
  else if (identifier == "VERSION_EQUAL")
 
1354
    return &versionEqualNode;
 
1355
  else if (identifier == "C_COMPILER_VERSION")
 
1356
    return &cCompilerVersionNode;
 
1357
  else if (identifier == "CXX_COMPILER_VERSION")
 
1358
    return &cxxCompilerVersionNode;
977
1359
  else if (identifier == "CONFIGURATION")
978
1360
    return &configurationNode;
979
1361
  else if (identifier == "CONFIG")
1018
1400
    return &installInterfaceNode;
1019
1401
  else if (identifier == "INSTALL_PREFIX")
1020
1402
    return &installPrefixNode;
 
1403
  else if (identifier == "JOIN")
 
1404
    return &joinNode;
 
1405
  else if (identifier == "LINK_ONLY")
 
1406
    return &linkOnlyNode;
1021
1407
  return 0;
1022
1408
 
1023
1409
}
1038
1424
}
1039
1425
 
1040
1426
//----------------------------------------------------------------------------
 
1427
std::string GeneratorExpressionContent::ProcessArbitraryContent(
 
1428
    const cmGeneratorExpressionNode *node,
 
1429
    const std::string &identifier,
 
1430
    cmGeneratorExpressionContext *context,
 
1431
    cmGeneratorExpressionDAGChecker *dagChecker,
 
1432
    std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
 
1433
    pit) const
 
1434
{
 
1435
  std::string result;
 
1436
 
 
1437
  const
 
1438
  std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
 
1439
                                      pend = this->ParamChildren.end();
 
1440
  for ( ; pit != pend; ++pit)
 
1441
    {
 
1442
    std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
 
1443
                                                            = pit->begin();
 
1444
    const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
 
1445
                                                              = pit->end();
 
1446
    for ( ; it != end; ++it)
 
1447
      {
 
1448
      if (node->RequiresLiteralInput())
 
1449
        {
 
1450
        if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text)
 
1451
          {
 
1452
          reportError(context, this->GetOriginalExpression(),
 
1453
                "$<" + identifier + "> expression requires literal input.");
 
1454
          return std::string();
 
1455
          }
 
1456
        }
 
1457
      result += (*it)->Evaluate(context, dagChecker);
 
1458
      if (context->HadError)
 
1459
        {
 
1460
        return std::string();
 
1461
        }
 
1462
      }
 
1463
      if ((pit + 1) != pend)
 
1464
        {
 
1465
        result += ",";
 
1466
        }
 
1467
    }
 
1468
  if (node->RequiresLiteralInput())
 
1469
    {
 
1470
    std::vector<std::string> parameters;
 
1471
    parameters.push_back(result);
 
1472
    return node->Evaluate(parameters, context, this, dagChecker);
 
1473
    }
 
1474
  return result;
 
1475
}
 
1476
 
 
1477
//----------------------------------------------------------------------------
1041
1478
std::string GeneratorExpressionContent::Evaluate(
1042
1479
                            cmGeneratorExpressionContext *context,
1043
1480
                            cmGeneratorExpressionDAGChecker *dagChecker) const
1069
1506
 
1070
1507
  if (!node->GeneratesContent())
1071
1508
    {
1072
 
    if (node->AcceptsSingleArbitraryContentParameter())
 
1509
    if (node->NumExpectedParameters() == 1
 
1510
        && node->AcceptsArbitraryContentParameter())
1073
1511
      {
1074
1512
      if (this->ParamChildren.empty())
1075
1513
        {
1086
1524
    return std::string();
1087
1525
    }
1088
1526
 
1089
 
  if (node->AcceptsSingleArbitraryContentParameter())
 
1527
  if (node->NumExpectedParameters() == 1
 
1528
        && node->AcceptsArbitraryContentParameter())
1090
1529
    {
1091
 
    std::string result;
1092
 
    std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
1093
 
                                        pit = this->ParamChildren.begin();
1094
 
    const
1095
 
    std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
1096
 
                                        pend = this->ParamChildren.end();
1097
 
    for ( ; pit != pend; ++pit)
1098
 
      {
1099
 
      if (!result.empty())
1100
 
        {
1101
 
        result += ",";
1102
 
        }
1103
 
 
1104
 
      std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
1105
 
                                                              = pit->begin();
1106
 
      const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
1107
 
                                                                = pit->end();
1108
 
      for ( ; it != end; ++it)
1109
 
        {
1110
 
        if (node->RequiresLiteralInput())
1111
 
          {
1112
 
          if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text)
1113
 
            {
1114
 
            reportError(context, this->GetOriginalExpression(),
1115
 
                  "$<" + identifier + "> expression requires literal input.");
1116
 
            return std::string();
1117
 
            }
1118
 
          }
1119
 
        result += (*it)->Evaluate(context, dagChecker);
1120
 
        if (context->HadError)
1121
 
          {
1122
 
          return std::string();
1123
 
          }
1124
 
        }
1125
 
      }
1126
 
    if (node->RequiresLiteralInput())
1127
 
      {
1128
 
      std::vector<std::string> parameters;
1129
 
      parameters.push_back(result);
1130
 
      return node->Evaluate(parameters, context, this, dagChecker);
1131
 
      }
1132
 
    return result;
 
1530
    return this->ProcessArbitraryContent(node, identifier, context,
 
1531
                                         dagChecker,
 
1532
                                         this->ParamChildren.begin());
1133
1533
    }
1134
1534
 
1135
1535
  std::vector<std::string> parameters;
1150
1550
                                cmGeneratorExpressionDAGChecker *dagChecker,
1151
1551
                                std::vector<std::string> &parameters) const
1152
1552
{
 
1553
  const int numExpected = node->NumExpectedParameters();
1153
1554
  {
1154
1555
  std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
1155
1556
                                        pit = this->ParamChildren.begin();
1156
1557
  const
1157
1558
  std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
1158
1559
                                        pend = this->ParamChildren.end();
 
1560
  const bool acceptsArbitraryContent
 
1561
                                  = node->AcceptsArbitraryContentParameter();
1159
1562
  for ( ; pit != pend; ++pit)
1160
1563
    {
1161
1564
    std::string parameter;
1172
1575
        }
1173
1576
      }
1174
1577
    parameters.push_back(parameter);
 
1578
    if (acceptsArbitraryContent
 
1579
        && parameters.size() == (unsigned int)numExpected - 1)
 
1580
      {
 
1581
      assert(pit != pend);
 
1582
      std::string lastParam = this->ProcessArbitraryContent(node, identifier,
 
1583
                                                            context,
 
1584
                                                            dagChecker,
 
1585
                                                            pit + 1);
 
1586
      parameters.push_back(lastParam);
 
1587
      return std::string();
 
1588
      }
1175
1589
    }
1176
1590
  }
1177
1591
 
1178
 
  int numExpected = node->NumExpectedParameters();
1179
 
  if ((numExpected != -1 && (unsigned int)numExpected != parameters.size()))
 
1592
  if ((numExpected > cmGeneratorExpressionNode::DynamicParameters
 
1593
      && (unsigned int)numExpected != parameters.size()))
1180
1594
    {
1181
1595
    if (numExpected == 0)
1182
1596
      {
1201
1615
    return std::string();
1202
1616
    }
1203
1617
 
1204
 
  if (numExpected == -1 && parameters.empty())
 
1618
  if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters
 
1619
      && parameters.empty())
1205
1620
    {
1206
1621
    reportError(context, this->GetOriginalExpression(), "$<" + identifier
1207
1622
                      + "> expression requires at least one parameter.");
1228
1643
  deleteAll(this->IdentifierChildren);
1229
1644
 
1230
1645
  typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
1231
 
  typedef std::vector<cmGeneratorExpressionToken> TokenVector;
1232
1646
  std::vector<EvaluatorVector>::const_iterator pit =
1233
1647
                                                  this->ParamChildren.begin();
1234
1648
  const std::vector<EvaluatorVector>::const_iterator pend =