add support for <if> and <property>
[reactos.git] / reactos / tools / rbuild / project.cpp
1
2 #include "pch.h"
3 #include <assert.h>
4
5 #include "rbuild.h"
6
7 using std::string;
8 using std::vector;
9
10 /*Project::Project()
11 : node(NULL), head(NULL)
12 {
13 }*/
14
15 Project::Project ( const string& filename )
16 : xmlfile(filename), node(NULL), head(NULL)
17 {
18 ReadXml();
19 }
20
21 Project::~Project ()
22 {
23 size_t i;
24 for ( i = 0; i < modules.size (); i++ )
25 delete modules[i];
26 for ( i = 0; i < includes.size(); i++ )
27 delete includes[i];
28 for ( i = 0; i < defines.size(); i++ )
29 delete defines[i];
30 for ( i = 0; i < properties.size(); i++ )
31 delete properties[i];
32 for ( i = 0; i < ifs.size(); i++ )
33 delete ifs[i];
34 delete head;
35 }
36
37 void
38 Project::ReadXml()
39 {
40 Path path;
41 head = XMLLoadFile ( xmlfile, path );
42 node = NULL;
43 for ( size_t i = 0; i < head->subElements.size(); i++ )
44 {
45 if ( head->subElements[i]->name == "project" )
46 {
47 node = head->subElements[i];
48 this->ProcessXML ( "." );
49 return;
50 }
51 }
52
53 throw InvalidBuildFileException (
54 node->location,
55 "Document contains no 'project' tag." );
56 }
57
58 void
59 Project::ProcessXML ( const string& path )
60 {
61 const XMLAttribute *att;
62 if ( node->name != "project" )
63 throw Exception ( "internal tool error: Project::ProcessXML() called with non-<project> node" );
64
65 att = node->GetAttribute ( "name", false );
66 if ( !att )
67 name = "Unnamed";
68 else
69 name = att->value;
70
71 att = node->GetAttribute ( "makefile", true );
72 assert(att);
73 makefile = att->value;
74
75 size_t i;
76 for ( i = 0; i < node->subElements.size(); i++ )
77 ProcessXMLSubElement ( *node->subElements[i], path );
78 for ( i = 0; i < modules.size(); i++ )
79 modules[i]->ProcessXML();
80 for ( i = 0; i < includes.size(); i++ )
81 includes[i]->ProcessXML();
82 for ( i = 0; i < defines.size(); i++ )
83 defines[i]->ProcessXML();
84 for ( i = 0; i < properties.size(); i++ )
85 properties[i]->ProcessXML();
86 for ( i = 0; i < ifs.size(); i++ )
87 ifs[i]->ProcessXML();
88 }
89
90 void
91 Project::ProcessXMLSubElement ( const XMLElement& e,
92 const string& path,
93 If* pIf /*= NULL*/ )
94 {
95 bool subs_invalid = false;
96 string subpath(path);
97 if ( e.name == "module" )
98 {
99 Module* module = new Module ( *this, e, path );
100 if ( LocateModule ( module->name ) )
101 throw InvalidBuildFileException (
102 node->location,
103 "module name conflict: '%s' (originally defined at %s)",
104 module->name.c_str(),
105 module->node.location.c_str() );
106 modules.push_back ( module );
107 return; // defer processing until later
108 }
109 else if ( e.name == "directory" )
110 {
111 const XMLAttribute* att = e.GetAttribute ( "name", true );
112 assert(att);
113 subpath = path + CSEP + att->value;
114 }
115 else if ( e.name == "include" )
116 {
117 includes.push_back ( new Include ( *this, e ) );
118 subs_invalid = true;
119 }
120 else if ( e.name == "define" )
121 {
122 Define* define = new Define ( *this, e );
123 if ( pIf )
124 pIf->defines.push_back ( define );
125 else
126 defines.push_back ( define );
127 subs_invalid = true;
128 }
129 else if ( e.name == "if" )
130 {
131 If* pOldIf = pIf;
132 pIf = new If ( e, *this, NULL );
133 if ( pOldIf )
134 pOldIf->ifs.push_back ( pIf );
135 else
136 ifs.push_back ( pIf );
137 subs_invalid = false;
138 }
139 else if ( e.name == "property" )
140 {
141 Property* property = new Property ( e, *this, NULL );
142 if ( pIf )
143 pIf->properties.push_back ( property );
144 else
145 properties.push_back ( property );
146 }
147 if ( subs_invalid && e.subElements.size() )
148 throw InvalidBuildFileException (
149 e.location,
150 "<%s> cannot have sub-elements",
151 e.name.c_str() );
152 for ( size_t i = 0; i < e.subElements.size (); i++ )
153 ProcessXMLSubElement ( *e.subElements[i], subpath, pIf );
154 }
155
156 Module*
157 Project::LocateModule ( const string& name )
158 {
159 for ( size_t i = 0; i < modules.size (); i++ )
160 {
161 if (modules[i]->name == name)
162 return modules[i];
163 }
164
165 return NULL;
166 }
167
168 const Module*
169 Project::LocateModule ( const string& name ) const
170 {
171 for ( size_t i = 0; i < modules.size (); i++ )
172 {
173 if (modules[i]->name == name)
174 return modules[i];
175 }
176
177 return NULL;
178 }