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