Imported Upstream version 2.8.9
[platform/upstream/cmake.git] / Source / cmVariableWatchCommand.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "cmVariableWatchCommand.h"
13
14 #include "cmVariableWatch.h"
15
16 //----------------------------------------------------------------------------
17 static void cmVariableWatchCommandVariableAccessed(
18   const std::string& variable, int access_type, void* client_data,
19   const char* newValue, const cmMakefile* mf)
20 {
21   cmVariableWatchCommand* command
22     = static_cast<cmVariableWatchCommand*>(client_data);
23   command->VariableAccessed(variable, access_type, newValue, mf);
24 }
25
26 //----------------------------------------------------------------------------
27 cmVariableWatchCommand::cmVariableWatchCommand()
28 {
29   this->InCallback = false;
30 }
31
32 //----------------------------------------------------------------------------
33 bool cmVariableWatchCommand
34 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
35 {
36   if ( args.size() < 1 )
37     {
38     this->SetError("must be called with at least one argument.");
39     return false;
40     }
41   std::string variable = args[0];
42   if ( args.size() > 1 )
43     {
44     std::string command = args[1];
45     this->Handlers[variable].Commands.push_back(args[1]);
46     }
47   if ( variable == "CMAKE_CURRENT_LIST_FILE" )
48     {
49     cmOStringStream ostr;
50     ostr << "cannot be set on the variable: " << variable.c_str();
51     this->SetError(ostr.str().c_str());
52     return false;
53     }
54
55   this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
56     variable, cmVariableWatchCommandVariableAccessed, this);
57
58   return true;
59 }
60
61 //----------------------------------------------------------------------------
62 void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
63   int access_type, const char* newValue, const cmMakefile* mf)
64 {
65   if ( this->InCallback )
66     {
67     return;
68     }
69   this->InCallback = true;
70
71   cmListFileFunction newLFF;
72   cmVariableWatchCommandHandler *handler = &this->Handlers[variable];
73   cmVariableWatchCommandHandler::VectorOfCommands::iterator it;
74   cmListFileArgument arg;
75   bool processed = false;
76   const char* accessString = cmVariableWatch::GetAccessAsString(access_type);
77   const char* currentListFile = mf->GetDefinition("CMAKE_CURRENT_LIST_FILE");
78
79   /// Ultra bad!!
80   cmMakefile* makefile = const_cast<cmMakefile*>(mf);
81
82   std::string stack = makefile->GetProperty("LISTFILE_STACK");
83   for ( it = handler->Commands.begin(); it != handler->Commands.end();
84     ++ it )
85     {
86     std::string command = *it;
87     newLFF.Arguments.clear();
88     newLFF.Arguments.push_back(
89       cmListFileArgument(variable, true, "unknown", 9999));
90     newLFF.Arguments.push_back(
91       cmListFileArgument(accessString, true, "unknown", 9999));
92     newLFF.Arguments.push_back(
93       cmListFileArgument(newValue?newValue:"", true, "unknown", 9999));
94     newLFF.Arguments.push_back(
95       cmListFileArgument(currentListFile, true, "unknown", 9999));
96     newLFF.Arguments.push_back(
97       cmListFileArgument(stack, true, "unknown", 9999));
98     newLFF.Name = command; 
99     newLFF.FilePath = "Some weird path";
100     newLFF.Line = 9999;
101     cmExecutionStatus status;
102     if(!makefile->ExecuteCommand(newLFF,status))
103       {
104       arg.FilePath =  "Unknown";
105       arg.Line = 0;
106       cmOStringStream error;
107       error << "Error in cmake code at\n"
108         << arg.FilePath << ":" << arg.Line << ":\n"
109         << "A command failed during the invocation of callback\""
110         << command << "\".";
111       cmSystemTools::Error(error.str().c_str());
112       this->InCallback = false;
113       return;
114       }
115     processed = true;
116     }
117   if ( !processed )
118     {
119     cmOStringStream msg;
120     msg << "* Variable \"" << variable.c_str() << "\" was accessed using "
121       << accessString << " in: " << currentListFile << std::endl;
122     msg << "  The value of the variable: \"" << newValue << "\"" << std::endl;
123     msg << "  The list file stack: " << stack.c_str();
124     cmSystemTools::Message(msg.str().c_str());
125     std::vector<std::string> vars = makefile->GetDefinitions();
126     cmOStringStream msg2;
127     size_t cc;
128     for ( cc = 0; cc < vars.size(); cc ++ )
129       {
130       if ( vars[cc] == variable )
131         {
132         continue;
133         }
134       msg2 << vars[cc] << " = \""
135         << makefile->GetDefinition(vars[cc].c_str()) << "\"" << std::endl;
136       }
137     //cmSystemTools::Message(msg2.str().c_str());
138     }
139   this->InCallback = false;
140 }