Imported Upstream version 2.8.9
[platform/upstream/cmake.git] / Source / cmXCodeObject.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 "cmXCodeObject.h"
13 #include "cmSystemTools.h"
14
15 #include <CoreFoundation/CoreFoundation.h> // CFUUIDCreate
16
17 //----------------------------------------------------------------------------
18 const char* cmXCodeObject::PBXTypeNames[] = {
19     "PBXGroup", "PBXBuildStyle", "PBXProject", "PBXHeadersBuildPhase", 
20     "PBXSourcesBuildPhase", "PBXFrameworksBuildPhase", "PBXNativeTarget",
21     "PBXFileReference", "PBXBuildFile", "PBXContainerItemProxy", 
22     "PBXTargetDependency", "PBXShellScriptBuildPhase", 
23     "PBXResourcesBuildPhase", "PBXApplicationReference",
24     "PBXExecutableFileReference", "PBXLibraryReference", "PBXToolTarget",
25     "PBXLibraryTarget", "PBXAggregateTarget", "XCBuildConfiguration", 
26     "XCConfigurationList",
27     "PBXCopyFilesBuildPhase",
28     "None"
29   };
30
31 //----------------------------------------------------------------------------
32 cmXCodeObject::~cmXCodeObject()
33 {
34   this->Version = 15;
35 }
36
37 //----------------------------------------------------------------------------
38 cmXCodeObject::cmXCodeObject(PBXType ptype, Type type)
39 {
40   this->Version = 15;
41   this->PBXTargetDependencyValue = 0;
42   this->Target = 0;
43   this->Object =0;
44
45   this->IsA = ptype;
46
47   if(type == OBJECT)
48     {
49     // Set the Id of an Xcode object to a unique string for each instance.
50     // However the Xcode user file references certain Ids: for those cases,
51     // override the generated Id using SetId().
52     //
53     char cUuid[40] = {0};
54     CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
55     CFStringRef s = CFUUIDCreateString(kCFAllocatorDefault, uuid);
56     CFStringGetCString(s, cUuid, sizeof(cUuid), kCFStringEncodingUTF8);
57     this->Id = cUuid;
58     CFRelease(s);
59     CFRelease(uuid);
60     }
61   else
62     {
63     this->Id =
64       "Temporary cmake object, should not be referred to in Xcode file";
65     }
66
67   cmSystemTools::ReplaceString(this->Id, "-", "");
68   if(this->Id.size() > 24)
69     {
70     this->Id = this->Id.substr(0, 24);
71     }
72
73   this->TypeValue = type;
74   if(this->TypeValue == OBJECT)
75     {
76     this->AddAttribute("isa", 0);
77     }
78 }
79
80 //----------------------------------------------------------------------------
81 void cmXCodeObject::Indent(int level, std::ostream& out)
82 {
83   while(level)
84     {
85     out << "       ";
86     level--;
87     }
88 }
89
90 //----------------------------------------------------------------------------
91 void cmXCodeObject::Print(std::ostream& out)
92 {
93   std::string separator = "\n";
94   int indentFactor = 1;
95   if(this->Version > 15 
96      && (this->IsA == PBXFileReference || this->IsA == PBXBuildFile))
97     {
98     separator = " ";
99     indentFactor = 0;
100     }
101   cmXCodeObject::Indent(2*indentFactor, out);
102   out << this->Id << " ";
103   if(!(this->IsA == PBXGroup && this->Comment.size() == 0))
104     {
105     this->PrintComment(out);
106     }
107   out << " = {";
108   if(separator == "\n")
109     {
110     out << separator;
111     }
112   std::map<cmStdString, cmXCodeObject*>::iterator i;
113   cmXCodeObject::Indent(3*indentFactor, out);
114   out << "isa = " << PBXTypeNames[this->IsA]  << ";" << separator;
115   for(i = this->ObjectAttributes.begin(); 
116       i != this->ObjectAttributes.end(); ++i)
117     { 
118     cmXCodeObject* object = i->second;
119     if(i->first != "isa")
120       { 
121       cmXCodeObject::Indent(3*indentFactor, out);
122       }
123     else
124       {
125       continue;
126       }
127     if(object->TypeValue == OBJECT_LIST)
128       {
129       out << i->first << " = (" << separator;
130       for(unsigned int k = 0; k < i->second->List.size(); k++)
131         {
132         cmXCodeObject::Indent(4*indentFactor, out);
133         out << i->second->List[k]->Id << " ";
134         i->second->List[k]->PrintComment(out);
135         out << "," << separator;
136         } 
137       cmXCodeObject::Indent(3*indentFactor, out);
138       out << ");" << separator;
139       }
140     else if(object->TypeValue == ATTRIBUTE_GROUP)
141       {
142       std::map<cmStdString, cmXCodeObject*>::iterator j;
143       out << i->first << " = {" << separator;
144       for(j = object->ObjectAttributes.begin(); j != 
145             object->ObjectAttributes.end(); ++j)
146         {
147         cmXCodeObject::Indent(4 *indentFactor, out);
148
149         if(j->second->TypeValue == STRING)
150           {
151           cmXCodeObject::PrintString(out,j->first);
152           out << " = ";
153           j->second->PrintString(out);
154           out << ";";
155           }
156         else if(j->second->TypeValue == OBJECT_LIST)
157           {
158           cmXCodeObject::PrintString(out,j->first);
159           out << " = (";
160           for(unsigned int k = 0; k < j->second->List.size(); k++)
161             {
162             if(j->second->List[k]->TypeValue == STRING)
163               {
164               j->second->List[k]->PrintString(out);
165               out << ", ";
166               }
167             else
168               {
169               out << "List_" << k << "_TypeValue_IS_NOT_STRING, ";
170               }
171             }
172           out << ");";
173           }
174         else
175           {
176           cmXCodeObject::PrintString(out,j->first);
177           out << " = error_unexpected_TypeValue_" <<
178             j->second->TypeValue << ";";
179           }
180
181         out << separator;
182         }
183       cmXCodeObject::Indent(3 *indentFactor, out);
184       out << "};" << separator;
185       }
186     else if(object->TypeValue == OBJECT_REF)
187       {
188       cmXCodeObject::PrintString(out,i->first);
189       out << " = " << object->Object->Id;
190       if(object->Object->HasComment() && i->first != "remoteGlobalIDString")
191         {
192         out << " ";
193         object->Object->PrintComment(out);
194         }
195       out << ";" << separator;
196       }
197     else if(object->TypeValue == STRING)
198       {
199       cmXCodeObject::PrintString(out,i->first);
200       out << " = ";
201       object->PrintString(out);
202       out << ";" << separator;
203       }
204     else
205       {
206       out << "what is this?? " << i->first << "\n";
207       }
208     }
209   cmXCodeObject::Indent(2*indentFactor, out);
210   out << "};\n";
211 }
212   
213 //----------------------------------------------------------------------------
214 void cmXCodeObject::PrintList(std::vector<cmXCodeObject*> const& objs,
215                               std::ostream& out)
216
217   cmXCodeObject::Indent(1, out);
218   out << "objects = {\n";
219   for(unsigned int i = 0; i < objs.size(); ++i)
220     {
221     if(objs[i]->TypeValue == OBJECT)
222       {
223       objs[i]->Print(out);
224       }
225     }
226   cmXCodeObject::Indent(1, out);
227   out << "};\n";
228 }
229
230 //----------------------------------------------------------------------------
231 void cmXCodeObject::CopyAttributes(cmXCodeObject* copy)
232 {
233   this->ObjectAttributes = copy->ObjectAttributes;
234   this->List = copy->List;
235   this->String = copy->String;
236   this->Object = copy->Object;
237 }
238
239 //----------------------------------------------------------------------------
240 void cmXCodeObject::PrintString(std::ostream& os,cmStdString String)
241 {
242   // The string needs to be quoted if it contains any characters
243   // considered special by the Xcode project file parser.
244   bool needQuote =
245     (String.empty() ||
246      String.find_first_of(" <>.+-=@$[],") != String.npos);
247   const char* quote = needQuote? "\"" : "";
248
249   // Print the string, quoted and escaped as necessary.
250   os << quote;
251   for(std::string::const_iterator i = String.begin();
252       i != String.end(); ++i)
253     {
254     if(*i == '"')
255       {
256       // Escape double-quotes.
257       os << '\\';
258       }
259     os << *i;
260     }
261   os << quote;
262 }
263
264 void cmXCodeObject::PrintString(std::ostream& os) const
265 {
266   cmXCodeObject::PrintString(os,this->String);
267 }
268
269 //----------------------------------------------------------------------------
270 void cmXCodeObject::SetString(const char* s)
271 {
272   this->String = s;
273 }