2b030ce97cdb622d7f8e26a749f605a0cca20f87
[reactos.git] / reactos / tools / rbuild / module.cpp
1 /*
2 * Copyright (C) 2005 Casper S. Hornstrup
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 #include "pch.h"
19 #include <assert.h>
20
21 #include "rbuild.h"
22
23 using std::string;
24 using std::vector;
25
26 string
27 Right ( const string& s, size_t n )
28 {
29 if ( n > s.size() )
30 return s;
31 return string ( &s[s.size()-n] );
32 }
33
34 string
35 Replace ( const string& s, const string& find, const string& with )
36 {
37 string ret;
38 const char* p = s.c_str();
39 while ( p )
40 {
41 const char* p2 = strstr ( p, find.c_str() );
42 if ( !p2 )
43 break;
44 if ( p2 > p )
45 ret += string ( p, p2-p );
46 ret += with;
47 p = p2 + find.size();
48 }
49 if ( *p )
50 ret += p;
51 return ret;
52 }
53
54 string
55 ChangeSeparator ( const string& s,
56 const char fromSeparator,
57 const char toSeparator )
58 {
59 string s2(s);
60 char* p = strchr ( &s2[0], fromSeparator );
61 while ( p )
62 {
63 *p++ = toSeparator;
64 p = strchr ( p, fromSeparator );
65 }
66 return s2;
67 }
68
69 string
70 FixSeparator ( const string& s )
71 {
72 return ChangeSeparator ( s, cBadSep, cSep );
73 }
74
75 string
76 FixSeparatorForSystemCommand ( const string& s )
77 {
78 string s2(s);
79 char* p = strchr ( &s2[0], DEF_CBAD_SEP );
80 while ( p )
81 {
82 *p++ = DEF_CSEP;
83 p = strchr ( p, DEF_CBAD_SEP );
84 }
85 return s2;
86 }
87
88 string
89 DosSeparator ( const string& s )
90 {
91 string s2(s);
92 char* p = strchr ( &s2[0], '/' );
93 while ( p )
94 {
95 *p++ = '\\';
96 p = strchr ( p, '/' );
97 }
98 return s2;
99 }
100
101 string
102 ReplaceExtension (
103 const string& filename,
104 const string& newExtension )
105 {
106 size_t index = filename.find_last_of ( '/' );
107 if ( index == string::npos )
108 index = 0;
109 size_t index2 = filename.find_last_of ( '\\' );
110 if ( index2 != string::npos && index2 > index )
111 index = index2;
112 string tmp = filename.substr( index /*, filename.size() - index*/ );
113 size_t ext_index = tmp.find_last_of( '.' );
114 if ( ext_index != string::npos )
115 return filename.substr ( 0, index + ext_index ) + newExtension;
116 return filename + newExtension;
117 }
118
119 string
120 GetSubPath (
121 const Project& project,
122 const string& location,
123 const string& path,
124 const string& att_value )
125 {
126 if ( !att_value.size() )
127 throw XMLInvalidBuildFileException (
128 location,
129 "<directory> tag has empty 'name' attribute" );
130 if ( strpbrk ( att_value.c_str (), "/\\?*:<>|" ) )
131 throw XMLInvalidBuildFileException (
132 location,
133 "<directory> tag has invalid characters in 'name' attribute" );
134 if ( !path.size() )
135 return att_value;
136
137 return FixSeparator(path + cSep + att_value);
138 }
139
140 static string
141 GetExtension ( const string& filename )
142 {
143 size_t index = filename.find_last_of ( '/' );
144 if (index == string::npos) index = 0;
145 string tmp = filename.substr( index, filename.size() - index );
146 size_t ext_index = tmp.find_last_of( '.' );
147 if (ext_index != string::npos)
148 return filename.substr ( index + ext_index, filename.size() );
149 return "";
150 }
151
152 string
153 GetExtension ( const FileLocation& file )
154 {
155 return GetExtension ( file.name );
156 }
157
158 string
159 NormalizeFilename ( const string& filename )
160 {
161 if ( filename == "" )
162 return "";
163 Path path;
164 string normalizedPath = path.Fixup ( filename, true );
165 string relativeNormalizedPath = path.RelativeFromWorkingDirectory ( normalizedPath );
166 return FixSeparator ( relativeNormalizedPath );
167 }
168
169 bool
170 GetBooleanValue ( const string& value )
171 {
172 if ( value == "1" )
173 return true;
174 else
175 return false;
176 }
177
178 string
179 ToLower ( string filename )
180 {
181 for ( size_t i = 1; i < filename.length (); i++ )
182 filename[i] = tolower ( filename[i] );
183 return filename;
184 }
185
186 IfableData::IfableData( )
187 : asmFiles ( 0 )
188 {
189 }
190
191 void IfableData::ExtractModules( std::vector<Module*> &modules )
192 {
193 size_t i;
194 for ( i = 0; i < this->modules.size (); i++ )
195 modules.push_back(this->modules[i]);
196 }
197
198 IfableData::~IfableData()
199 {
200 size_t i;
201 for ( i = 0; i < includes.size (); i++ )
202 delete includes[i];
203 for ( i = 0; i < defines.size (); i++ )
204 delete defines[i];
205 for ( i = 0; i < libraries.size (); i++ )
206 delete libraries[i];
207 for ( i = 0; i < properties.size (); i++ )
208 delete properties[i];
209 for ( i = 0; i < compilerFlags.size (); i++ )
210 delete compilerFlags[i];
211 for ( i = 0; i < modules.size(); i++ )
212 delete modules[i];
213 for ( i = 0; i < ifs.size (); i++ )
214 delete ifs[i];
215 for ( i = 0; i < compilationUnits.size (); i++ )
216 delete compilationUnits[i];
217 }
218
219 void IfableData::ProcessXML ()
220 {
221 size_t i;
222 for ( i = 0; i < includes.size (); i++ )
223 includes[i]->ProcessXML ();
224 for ( i = 0; i < defines.size (); i++ )
225 defines[i]->ProcessXML ();
226 for ( i = 0; i < libraries.size (); i++ )
227 libraries[i]->ProcessXML ();
228 for ( i = 0; i < properties.size(); i++ )
229 properties[i]->ProcessXML ();
230 for ( i = 0; i < compilerFlags.size(); i++ )
231 compilerFlags[i]->ProcessXML ();
232 for ( i = 0; i < ifs.size (); i++ )
233 ifs[i]->ProcessXML ();
234 for ( i = 0; i < compilationUnits.size (); i++ )
235 compilationUnits[i]->ProcessXML ();
236 }
237
238 Module::Module ( const Project& project,
239 const XMLElement& moduleNode,
240 const string& modulePath )
241 : project (project),
242 node (moduleNode),
243 importLibrary (NULL),
244 metadata (NULL),
245 bootstrap (NULL),
246 autoRegister(NULL),
247 linkerScript (NULL),
248 pch (NULL),
249 cplusplus (false),
250 host (HostDefault)
251 {
252 if ( node.name != "module" )
253 throw InvalidOperationException ( __FILE__,
254 __LINE__,
255 "Module created with non-<module> node" );
256
257 xmlbuildFile = FixSeparator ( Path::RelativeFromWorkingDirectory ( moduleNode.xmlFile->filename () ) );
258
259 const XMLAttribute* att = moduleNode.GetAttribute ( "name", true );
260 assert(att);
261 name = att->value;
262
263 enabled = true;
264
265 att = moduleNode.GetAttribute ( "if", false );
266 if ( att != NULL )
267 enabled = GetBooleanValue ( project.ResolveProperties ( att->value ) );
268
269 att = moduleNode.GetAttribute ( "ifnot", false );
270 if ( att != NULL )
271 enabled = !GetBooleanValue ( project.ResolveProperties ( att->value ) );
272
273 if ( !enabled && project.configuration.Verbose )
274 printf("Module '%s' has been disabled.\n", name.c_str () );
275
276 att = moduleNode.GetAttribute ( "type", true );
277 assert(att);
278 type = GetModuleType ( node.location, *att );
279
280 att = moduleNode.GetAttribute ( "extension", false );
281 if ( att != NULL )
282 extension = att->value;
283 else
284 extension = GetDefaultModuleExtension ();
285
286 att = moduleNode.GetAttribute ( "unicode", false );
287 if ( att != NULL )
288 {
289 const char* p = att->value.c_str();
290 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
291 isUnicode = true;
292 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
293 isUnicode = false;
294 else
295 {
296 throw InvalidAttributeValueException (
297 moduleNode.location,
298 "unicode",
299 att->value );
300 }
301 }
302 else
303 isUnicode = false;
304
305 if (isUnicode)
306 {
307 // Always define UNICODE and _UNICODE
308 Define* pDefine = new Define ( project, this, "UNICODE" );
309 non_if_data.defines.push_back ( pDefine );
310
311 pDefine = new Define ( project, this, "_UNICODE" );
312 non_if_data.defines.push_back ( pDefine );
313 }
314
315 att = moduleNode.GetAttribute ( "entrypoint", false );
316 if ( att != NULL )
317 {
318 if ( att->value == "" )
319 {
320 throw InvalidAttributeValueException (
321 moduleNode.location,
322 "entrypoint",
323 att->value );
324 }
325
326 entrypoint = att->value;
327 isDefaultEntryPoint = false;
328 }
329 else
330 {
331 entrypoint = GetDefaultModuleEntrypoint ();
332 isDefaultEntryPoint = true;
333 }
334
335 att = moduleNode.GetAttribute ( "baseaddress", false );
336 if ( att != NULL )
337 baseaddress = att->value;
338 else
339 baseaddress = GetDefaultModuleBaseaddress ();
340
341 att = moduleNode.GetAttribute ( "mangledsymbols", false );
342 if ( att != NULL )
343 {
344 const char* p = att->value.c_str();
345 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
346 mangledSymbols = true;
347 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
348 mangledSymbols = false;
349 else
350 {
351 throw InvalidAttributeValueException (
352 moduleNode.location,
353 "mangledsymbols",
354 att->value );
355 }
356 }
357 else
358 mangledSymbols = false;
359
360 att = moduleNode.GetAttribute ( "underscoresymbols", false );
361 if ( att != NULL )
362 underscoreSymbols = att->value == "true";
363 else
364 underscoreSymbols = false;
365
366 att = moduleNode.GetAttribute ( "host", false );
367 if ( att != NULL )
368 {
369 const char* p = att->value.c_str();
370 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
371 host = HostTrue;
372 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
373 host = HostFalse;
374 else
375 {
376 throw InvalidAttributeValueException (
377 moduleNode.location,
378 "host",
379 att->value );
380 }
381 }
382
383 att = moduleNode.GetAttribute ( "isstartuplib", false );
384 if ( att != NULL )
385 {
386 const char* p = att->value.c_str();
387 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
388 isStartupLib = true;
389 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
390 isStartupLib = false;
391 else
392 {
393 throw InvalidAttributeValueException (
394 moduleNode.location,
395 "host",
396 att->value );
397 }
398 }
399 else
400 isStartupLib = false;
401
402 att = moduleNode.GetAttribute ( "prefix", false );
403 if ( att != NULL )
404 prefix = att->value;
405
406 att = moduleNode.GetAttribute ( "installname", false );
407 if ( att != NULL )
408 {
409 const XMLAttribute* installbase = moduleNode.GetAttribute ( "installbase", false );
410 install = new FileLocation ( InstallDirectory,
411 installbase ? installbase->value : "",
412 att->value,
413 &moduleNode );
414
415 output = new FileLocation ( GetTargetDirectoryTree (),
416 modulePath,
417 att->value,
418 &moduleNode );
419 }
420 else
421 {
422 install = NULL;
423 output = new FileLocation ( GetTargetDirectoryTree (),
424 modulePath,
425 name + extension,
426 &moduleNode );
427 }
428
429 att = moduleNode.GetAttribute ( "allowwarnings", false );
430 if ( att == NULL )
431 {
432 att = moduleNode.GetAttribute ( "warnings", false );
433 if ( att != NULL )
434 {
435 printf ( "%s: WARNING: 'warnings' attribute of <module> is deprecated, use 'allowwarnings' instead\n",
436 moduleNode.location.c_str() );
437 }
438 }
439 if ( att != NULL )
440 allowWarnings = att->value == "true";
441 else
442 allowWarnings = false;
443
444 att = moduleNode.GetAttribute ( "aliasof", false );
445 if ( type == Alias && att != NULL )
446 aliasedModuleName = att->value;
447 else
448 aliasedModuleName = "";
449
450 if ( type == BootProgram )
451 {
452 att = moduleNode.GetAttribute ( "payload", true );
453 payload = att->value;
454 }
455
456 if ( type == BootProgram || type == ElfExecutable )
457 {
458 att = moduleNode.GetAttribute ( "buildtype", false );
459 if ( att != NULL )
460 {
461 buildtype = att->value;
462 }
463 else
464 {
465 buildtype = "BOOTPROG";
466 }
467 }
468
469 SetImportLibrary ( NULL );
470 }
471
472 Module::~Module ()
473 {
474 size_t i;
475 for ( i = 0; i < invocations.size(); i++ )
476 delete invocations[i];
477 for ( i = 0; i < dependencies.size(); i++ )
478 delete dependencies[i];
479 for ( i = 0; i < compilerFlags.size(); i++ )
480 delete compilerFlags[i];
481 for ( i = 0; i < linkerFlags.size(); i++ )
482 delete linkerFlags[i];
483 for ( i = 0; i < stubbedComponents.size(); i++ )
484 delete stubbedComponents[i];
485 if ( linkerScript )
486 delete linkerScript;
487 if ( pch )
488 delete pch;
489 }
490
491 void
492 Module::ProcessXML()
493 {
494 if ( type == Alias )
495 {
496 aliasedModuleName = project.ResolveProperties ( aliasedModuleName );
497 if ( aliasedModuleName == name )
498 {
499 throw XMLInvalidBuildFileException (
500 node.location,
501 "module '%s' cannot link against itself",
502 name.c_str() );
503 }
504 const Module* m = project.LocateModule ( aliasedModuleName );
505 if ( !m && enabled )
506 {
507 throw XMLInvalidBuildFileException (
508 node.location,
509 "module '%s' trying to alias non-existant module '%s'",
510 name.c_str(),
511 aliasedModuleName.c_str() );
512 }
513 }
514
515 size_t i;
516 for ( i = 0; i < node.subElements.size(); i++ )
517 {
518 ParseContext parseContext;
519 ProcessXMLSubElement ( *node.subElements[i], SourceDirectory, output->relative_path, parseContext );
520 }
521 for ( i = 0; i < invocations.size(); i++ )
522 invocations[i]->ProcessXML ();
523 for ( i = 0; i < dependencies.size(); i++ )
524 dependencies[i]->ProcessXML ();
525 for ( i = 0; i < compilerFlags.size(); i++ )
526 compilerFlags[i]->ProcessXML();
527 for ( i = 0; i < linkerFlags.size(); i++ )
528 linkerFlags[i]->ProcessXML();
529 for ( i = 0; i < stubbedComponents.size(); i++ )
530 stubbedComponents[i]->ProcessXML();
531 non_if_data.ProcessXML();
532 if ( linkerScript )
533 linkerScript->ProcessXML();
534 if ( pch )
535 pch->ProcessXML();
536 if ( autoRegister )
537 autoRegister->ProcessXML();
538 }
539
540 void
541 Module::ProcessXMLSubElement ( const XMLElement& e,
542 DirectoryLocation directory,
543 const string& relative_path,
544 ParseContext& parseContext )
545 {
546 If* pOldIf = parseContext.ifData;
547 CompilationUnit* pOldCompilationUnit = parseContext.compilationUnit;
548 bool subs_invalid = false;
549 string subpath ( relative_path );
550 DirectoryLocation subdirectory = SourceDirectory;
551 if ( e.name == "file" && e.value.size () > 0 )
552 {
553 bool first = false;
554 const XMLAttribute* att = e.GetAttribute ( "first", false );
555 if ( att != NULL )
556 {
557 if ( !stricmp ( att->value.c_str(), "true" ) )
558 first = true;
559 else if ( stricmp ( att->value.c_str(), "false" ) )
560 {
561 throw XMLInvalidBuildFileException (
562 e.location,
563 "attribute 'first' of <file> element can only be 'true' or 'false'" );
564 }
565 }
566 string switches = "";
567 att = e.GetAttribute ( "switches", false );
568 if ( att != NULL )
569 switches = att->value;
570 if ( !cplusplus )
571 {
572 // check for c++ file
573 string ext = GetExtension ( e.value );
574 if ( !stricmp ( ext.c_str(), ".cpp" ) )
575 cplusplus = true;
576 else if ( !stricmp ( ext.c_str(), ".cc" ) )
577 cplusplus = true;
578 else if ( !stricmp ( ext.c_str(), ".cxx" ) )
579 cplusplus = true;
580 }
581 File* pFile = new File ( directory,
582 relative_path,
583 e.value,
584 first,
585 switches,
586 false );
587 if ( parseContext.compilationUnit )
588 parseContext.compilationUnit->AddFile ( pFile );
589 else
590 {
591 CompilationUnit* pCompilationUnit = new CompilationUnit ( pFile );
592 if ( parseContext.ifData )
593 parseContext.ifData->data.compilationUnits.push_back ( pCompilationUnit );
594 else
595 {
596 string ext = ToLower ( GetExtension ( e.value ) );
597 if ( ext == ".idl" )
598 {
599 // put .idl files at the start of the module
600 non_if_data.compilationUnits.insert (
601 non_if_data.compilationUnits.begin(),
602 pCompilationUnit );
603 }
604 else if ( ext == ".asm" || ext == ".s" )
605 {
606 // put .asm files at the end of the module
607 non_if_data.compilationUnits.push_back ( pCompilationUnit );
608 non_if_data.asmFiles++;
609 }
610 else
611 {
612 // put other files in the middle
613 non_if_data.compilationUnits.insert (
614 non_if_data.compilationUnits.end() - non_if_data.asmFiles,
615 pCompilationUnit );
616 }
617 }
618 }
619 if ( parseContext.ifData )
620 parseContext.ifData->data.files.push_back ( pFile );
621 else
622 non_if_data.files.push_back ( pFile );
623 subs_invalid = true;
624 }
625 else if ( e.name == "library" && e.value.size () )
626 {
627 Library* pLibrary = new Library ( e, *this, e.value );
628 if ( parseContext.ifData )
629 parseContext.ifData->data.libraries.push_back ( pLibrary );
630 else
631 non_if_data.libraries.push_back ( pLibrary );
632 subs_invalid = true;
633 }
634 else if ( e.name == "directory" )
635 {
636 const XMLAttribute* att = e.GetAttribute ( "name", true );
637 const XMLAttribute* root = e.GetAttribute ( "root", false );
638 assert(att);
639 if ( root )
640 {
641 if ( root->value == "intermediate" )
642 subdirectory = IntermediateDirectory;
643 else if ( root->value == "output" )
644 subdirectory = OutputDirectory;
645 else
646 {
647 throw InvalidAttributeValueException (
648 e.location,
649 "root",
650 root->value );
651 }
652 }
653 subpath = GetSubPath ( this->project, e.location, relative_path, att->value );
654 }
655 else if ( e.name == "include" )
656 {
657 Include* include = new Include ( project, &e, this );
658 if ( parseContext.ifData )
659 parseContext.ifData->data.includes.push_back ( include );
660 else
661 non_if_data.includes.push_back ( include );
662 subs_invalid = true;
663 }
664 else if ( e.name == "define" )
665 {
666 Define* pDefine = new Define ( project, this, e );
667 if ( parseContext.ifData )
668 parseContext.ifData->data.defines.push_back ( pDefine );
669 else
670 non_if_data.defines.push_back ( pDefine );
671 subs_invalid = true;
672 }
673 else if ( e.name == "metadata" )
674 {
675 if ( parseContext.ifData )
676 {
677 throw XMLInvalidBuildFileException (
678 e.location,
679 "<metadata> is not a valid sub-element of <if>" );
680 }
681 metadata = new Metadata ( e, *this );
682 subs_invalid = false;
683 }
684 else if ( e.name == "invoke" )
685 {
686 if ( parseContext.ifData )
687 {
688 throw XMLInvalidBuildFileException (
689 e.location,
690 "<invoke> is not a valid sub-element of <if>" );
691 }
692 invocations.push_back ( new Invoke ( e, *this ) );
693 subs_invalid = false;
694 }
695 else if ( e.name == "dependency" )
696 {
697 if ( parseContext.ifData )
698 {
699 throw XMLInvalidBuildFileException (
700 e.location,
701 "<dependency> is not a valid sub-element of <if>" );
702 }
703 dependencies.push_back ( new Dependency ( e, *this ) );
704 subs_invalid = true;
705 }
706 else if ( e.name == "importlibrary" )
707 {
708 if ( parseContext.ifData )
709 {
710 throw XMLInvalidBuildFileException (
711 e.location,
712 "<importlibrary> is not a valid sub-element of <if>" );
713 }
714 if ( importLibrary )
715 {
716 throw XMLInvalidBuildFileException (
717 e.location,
718 "Only one <importlibrary> is valid per module" );
719 }
720 SetImportLibrary ( new ImportLibrary ( project, e, *this ) );
721 subs_invalid = true;
722 }
723 else if ( e.name == "if" )
724 {
725 parseContext.ifData = new If ( e, project, this );
726 if ( pOldIf )
727 pOldIf->data.ifs.push_back ( parseContext.ifData );
728 else
729 non_if_data.ifs.push_back ( parseContext.ifData );
730 subs_invalid = false;
731 }
732 else if ( e.name == "ifnot" )
733 {
734 parseContext.ifData = new If ( e, project, this, true );
735 if ( pOldIf )
736 pOldIf->data.ifs.push_back ( parseContext.ifData );
737 else
738 non_if_data.ifs.push_back ( parseContext.ifData );
739 subs_invalid = false;
740 }
741 else if ( e.name == "compilerflag" )
742 {
743 CompilerFlag* pCompilerFlag = new CompilerFlag ( project, this, e );
744 if ( parseContext.ifData )
745 parseContext.ifData->data.compilerFlags.push_back ( pCompilerFlag );
746 else
747 non_if_data.compilerFlags.push_back ( pCompilerFlag );
748 subs_invalid = true;
749 }
750 else if ( e.name == "linkerflag" )
751 {
752 linkerFlags.push_back ( new LinkerFlag ( project, this, e ) );
753 subs_invalid = true;
754 }
755 else if ( e.name == "linkerscript" )
756 {
757 if ( parseContext.ifData )
758 {
759 throw XMLInvalidBuildFileException (
760 e.location,
761 "<linkerscript> is not a valid sub-element of <if>" );
762 }
763 if ( linkerScript )
764 {
765 throw XMLInvalidBuildFileException (
766 e.location,
767 "Only one <linkerscript> is valid per module" );
768 }
769 size_t pos = e.value.find_last_of ( "/\\" );
770 if ( pos == string::npos )
771 {
772 linkerScript = new LinkerScript (
773 e, *this, FileLocation ( SourceDirectory, relative_path, e.value, &e ) );
774 }
775 else
776 {
777 string dir = e.value.substr ( 0, pos );
778 string name = e.value.substr ( pos + 1);
779 linkerScript = new LinkerScript (
780 e, *this, FileLocation ( SourceDirectory, relative_path + sSep + dir, name, &e ) );
781 }
782 subs_invalid = true;
783 }
784 else if ( e.name == "component" )
785 {
786 stubbedComponents.push_back ( new StubbedComponent ( this, e ) );
787 subs_invalid = false;
788 }
789 else if ( e.name == "property" )
790 {
791 throw XMLInvalidBuildFileException (
792 e.location,
793 "<property> is not a valid sub-element of <module>" );
794 }
795 else if ( e.name == "bootstrap" )
796 {
797 bootstrap = new Bootstrap ( project, this, e );
798 subs_invalid = true;
799 }
800 else if ( e.name == "pch" )
801 {
802 if ( parseContext.ifData )
803 {
804 throw XMLInvalidBuildFileException (
805 e.location,
806 "<pch> is not a valid sub-element of <if>" );
807 }
808 if ( pch )
809 {
810 throw XMLInvalidBuildFileException (
811 e.location,
812 "Only one <pch> is valid per module" );
813 }
814 size_t pos = e.value.find_last_of ( "/\\" );
815 if ( pos == string::npos )
816 {
817 pch = new PchFile (
818 e, *this, FileLocation ( SourceDirectory, relative_path, e.value, &e ) );
819 }
820 else
821 {
822 string dir = e.value.substr ( 0, pos );
823 string name = e.value.substr ( pos + 1);
824 pch = new PchFile (
825 e, *this, FileLocation ( SourceDirectory, relative_path + sSep + dir, name, &e ) );
826 }
827 subs_invalid = true;
828 }
829 else if ( e.name == "compilationunit" )
830 {
831 if ( project.configuration.CompilationUnitsEnabled )
832 {
833 CompilationUnit* pCompilationUnit = new CompilationUnit ( &project, this, &e );
834 if ( parseContext.ifData )
835 parseContext.ifData->data.compilationUnits.push_back ( pCompilationUnit );
836 else
837 non_if_data.compilationUnits.push_back ( pCompilationUnit );
838 parseContext.compilationUnit = pCompilationUnit;
839 }
840 subs_invalid = false;
841 }
842 else if ( e.name == "autoregister" )
843 {
844 if ( autoRegister != NULL)
845 {
846 throw XMLInvalidBuildFileException (
847 e.location,
848 "there can be only one <%s> element for a module",
849 e.name.c_str() );
850 }
851 autoRegister = new AutoRegister ( project, this, e );
852 subs_invalid = true;
853 }
854 if ( subs_invalid && e.subElements.size() > 0 )
855 {
856 throw XMLInvalidBuildFileException (
857 e.location,
858 "<%s> cannot have sub-elements",
859 e.name.c_str() );
860 }
861 for ( size_t i = 0; i < e.subElements.size (); i++ )
862 ProcessXMLSubElement ( *e.subElements[i], subdirectory, subpath, parseContext );
863 parseContext.ifData = pOldIf;
864 parseContext.compilationUnit = pOldCompilationUnit;
865 }
866
867 ModuleType
868 Module::GetModuleType ( const string& location, const XMLAttribute& attribute )
869 {
870 if ( attribute.value == "buildtool" )
871 return BuildTool;
872 if ( attribute.value == "staticlibrary" )
873 return StaticLibrary;
874 if ( attribute.value == "objectlibrary" )
875 return ObjectLibrary;
876 if ( attribute.value == "kernel" )
877 return Kernel;
878 if ( attribute.value == "kernelmodedll" )
879 return KernelModeDLL;
880 if ( attribute.value == "kernelmodedriver" )
881 return KernelModeDriver;
882 if ( attribute.value == "nativedll" )
883 return NativeDLL;
884 if ( attribute.value == "nativecui" )
885 return NativeCUI;
886 if ( attribute.value == "win32dll" )
887 return Win32DLL;
888 if ( attribute.value == "win32ocx" )
889 return Win32OCX;
890 if ( attribute.value == "win32cui" )
891 return Win32CUI;
892 if ( attribute.value == "win32gui" )
893 return Win32GUI;
894 if ( attribute.value == "win32scr" )
895 return Win32SCR;
896 if ( attribute.value == "bootloader" )
897 return BootLoader;
898 if ( attribute.value == "bootsector" )
899 return BootSector;
900 if ( attribute.value == "bootprogram" )
901 return BootProgram;
902 if ( attribute.value == "iso" )
903 return Iso;
904 if ( attribute.value == "liveiso" )
905 return LiveIso;
906 if ( attribute.value == "isoregtest" )
907 return IsoRegTest;
908 if ( attribute.value == "liveisoregtest" )
909 return LiveIsoRegTest;
910 if ( attribute.value == "test" )
911 return Test;
912 if ( attribute.value == "rpcserver" )
913 return RpcServer;
914 if ( attribute.value == "rpcclient" )
915 return RpcClient;
916 if ( attribute.value == "rpcproxy" )
917 return RpcProxy;
918 if ( attribute.value == "alias" )
919 return Alias;
920 if ( attribute.value == "idlheader" )
921 return IdlHeader;
922 if ( attribute.value == "embeddedtypelib" )
923 return EmbeddedTypeLib;
924 if ( attribute.value == "elfexecutable" )
925 return ElfExecutable;
926 throw InvalidAttributeValueException ( location,
927 attribute.name,
928 attribute.value );
929 }
930
931 DirectoryLocation
932 Module::GetTargetDirectoryTree () const
933 {
934 switch ( type )
935 {
936 case Kernel:
937 case KernelModeDLL:
938 case NativeDLL:
939 case Win32DLL:
940 case Win32OCX:
941 case KernelModeDriver:
942 case NativeCUI:
943 case Win32CUI:
944 case Test:
945 case Win32SCR:
946 case Win32GUI:
947 case BuildTool:
948 case BootLoader:
949 case BootSector:
950 case BootProgram:
951 case Iso:
952 case LiveIso:
953 case IsoRegTest:
954 case LiveIsoRegTest:
955 case EmbeddedTypeLib:
956 case ElfExecutable:
957 return OutputDirectory;
958 case StaticLibrary:
959 case ObjectLibrary:
960 case RpcServer:
961 case RpcClient:
962 case RpcProxy:
963 case Alias:
964 case IdlHeader:
965 return IntermediateDirectory;
966 case TypeDontCare:
967 break;
968 }
969 throw InvalidOperationException ( __FILE__,
970 __LINE__,
971 "Invalid module type %d.",
972 type );
973 }
974
975 string
976 Module::GetDefaultModuleExtension () const
977 {
978 switch (type)
979 {
980 case BuildTool:
981 return ExePostfix;
982 case BootProgram:
983 case StaticLibrary:
984 return ".a";
985 case ObjectLibrary:
986 return ".o";
987 case Kernel:
988 case NativeCUI:
989 case Win32CUI:
990 case Win32GUI:
991 return ".exe";
992 case Win32SCR:
993 return ".scr";
994
995 case KernelModeDLL:
996 case NativeDLL:
997 case Win32DLL:
998 return ".dll";
999 case Win32OCX:
1000 return ".ocx";
1001 case KernelModeDriver:
1002 case BootLoader:
1003 return ".sys";
1004 case BootSector:
1005 return ".o";
1006 case Iso:
1007 case LiveIso:
1008 case IsoRegTest:
1009 case LiveIsoRegTest:
1010 return ".iso";
1011 case Test:
1012 return ".exe";
1013 case RpcServer:
1014 case RpcClient:
1015 case RpcProxy:
1016 return ".o";
1017 case Alias:
1018 case ElfExecutable:
1019 case IdlHeader:
1020 return "";
1021 case EmbeddedTypeLib:
1022 return ".tlb";
1023 case TypeDontCare:
1024 break;
1025 }
1026 throw InvalidOperationException ( __FILE__,
1027 __LINE__ );
1028 }
1029
1030 string
1031 Module::GetDefaultModuleEntrypoint () const
1032 {
1033 switch ( type )
1034 {
1035 case Kernel:
1036 return "NtProcessStartup";
1037 case KernelModeDLL:
1038 case KernelModeDriver:
1039 return "DriverEntry@8";
1040 case NativeDLL:
1041 return "DllMainCRTStartup@12";
1042 case NativeCUI:
1043 return "NtProcessStartup@4";
1044 case Win32DLL:
1045 case Win32OCX:
1046 return "DllMain@12";
1047 case Win32CUI:
1048 case Test:
1049 if ( isUnicode )
1050 return "wmainCRTStartup";
1051 else
1052 return "mainCRTStartup";
1053 case Win32SCR:
1054 case Win32GUI:
1055 if ( isUnicode )
1056 return "wWinMainCRTStartup";
1057 else
1058 return "WinMainCRTStartup";
1059 case BuildTool:
1060 case StaticLibrary:
1061 case ObjectLibrary:
1062 case BootLoader:
1063 case BootSector:
1064 case Iso:
1065 case LiveIso:
1066 case IsoRegTest:
1067 case LiveIsoRegTest:
1068 case RpcServer:
1069 case RpcClient:
1070 case RpcProxy:
1071 case Alias:
1072 case BootProgram:
1073 case IdlHeader:
1074 case ElfExecutable:
1075 case EmbeddedTypeLib:
1076 return "";
1077 case TypeDontCare:
1078 break;
1079 }
1080 throw InvalidOperationException ( __FILE__,
1081 __LINE__ );
1082 }
1083
1084 string
1085 Module::GetDefaultModuleBaseaddress () const
1086 {
1087 switch ( type )
1088 {
1089 case Kernel:
1090 return "0x80800000";
1091 case Win32DLL:
1092 case Win32OCX:
1093 return "0x10000000";
1094 case NativeDLL:
1095 case NativeCUI:
1096 case Win32CUI:
1097 case Test:
1098 return "0x00400000";
1099 case Win32SCR:
1100 case Win32GUI:
1101 return "0x00400000";
1102 case KernelModeDLL:
1103 case KernelModeDriver:
1104 return "0x00010000";
1105 case ElfExecutable:
1106 return "0xe00000";
1107 case BuildTool:
1108 case StaticLibrary:
1109 case ObjectLibrary:
1110 case BootLoader:
1111 case BootSector:
1112 case Iso:
1113 case LiveIso:
1114 case IsoRegTest:
1115 case LiveIsoRegTest:
1116 case RpcServer:
1117 case RpcClient:
1118 case RpcProxy:
1119 case Alias:
1120 case BootProgram:
1121 case IdlHeader:
1122 case EmbeddedTypeLib:
1123 return "";
1124 case TypeDontCare:
1125 break;
1126 }
1127 throw InvalidOperationException ( __FILE__,
1128 __LINE__ );
1129 }
1130
1131 bool
1132 Module::HasImportLibrary () const
1133 {
1134 return importLibrary != NULL && type != StaticLibrary;
1135 }
1136
1137 bool
1138 Module::IsDLL () const
1139 {
1140 switch ( type )
1141 {
1142 case Kernel:
1143 case KernelModeDLL:
1144 case NativeDLL:
1145 case Win32DLL:
1146 case Win32OCX:
1147 case KernelModeDriver:
1148 return true;
1149 case NativeCUI:
1150 case Win32CUI:
1151 case Test:
1152 case Win32SCR:
1153 case Win32GUI:
1154 case BuildTool:
1155 case StaticLibrary:
1156 case ObjectLibrary:
1157 case BootLoader:
1158 case BootSector:
1159 case BootProgram:
1160 case Iso:
1161 case LiveIso:
1162 case IsoRegTest:
1163 case LiveIsoRegTest:
1164 case RpcServer:
1165 case RpcClient:
1166 case RpcProxy:
1167 case Alias:
1168 case IdlHeader:
1169 case EmbeddedTypeLib:
1170 case ElfExecutable:
1171 return false;
1172 case TypeDontCare:
1173 break;
1174 }
1175 throw InvalidOperationException ( __FILE__,
1176 __LINE__ );
1177 }
1178
1179 string
1180 Module::GetPathWithPrefix ( const string& prefix ) const
1181 {
1182 return output->relative_path + cSep + prefix + output->name;
1183 }
1184
1185 string
1186 Module::GetPathToBaseDir () const
1187 {
1188 string temp_path = output->relative_path;
1189 string result = "..\\";
1190 while(temp_path.find ('\\') != string::npos)
1191 {
1192 temp_path.erase (0, temp_path.find('\\')+1);
1193 result += "..\\";
1194 }
1195 return result;
1196 }
1197
1198 string
1199 Module::GetInvocationTarget ( const int index ) const
1200 {
1201 return ssprintf ( "%s_invoke_%d",
1202 name.c_str (),
1203 index );
1204 }
1205
1206 string
1207 Module::GetEntryPoint(bool leadingUnderscore) const
1208 {
1209 string result = "";
1210 if (entrypoint == "0" || entrypoint == "0x0")
1211 return "0";
1212 if (leadingUnderscore)
1213 result = "_";
1214
1215 result += entrypoint;
1216 return result;
1217 }
1218
1219 bool
1220 Module::HasFileWithExtension (
1221 const IfableData& data,
1222 const std::string& extension ) const
1223 {
1224 size_t i;
1225 for ( i = 0; i < data.compilationUnits.size (); i++ )
1226 {
1227 CompilationUnit* compilationUnit = data.compilationUnits[i];
1228 if ( compilationUnit->HasFileWithExtension ( extension ) )
1229 return true;
1230 }
1231 for ( i = 0; i < data.ifs.size (); i++ )
1232 {
1233 if ( HasFileWithExtension ( data.ifs[i]->data, extension ) )
1234 return true;
1235 }
1236 return false;
1237 }
1238
1239 void
1240 Module::InvokeModule () const
1241 {
1242 for ( size_t i = 0; i < invocations.size (); i++ )
1243 {
1244 Invoke& invoke = *invocations[i];
1245 string command = FixSeparatorForSystemCommand(invoke.invokeModule->output->relative_path + "/" + invoke.invokeModule->output->name ) + " " + invoke.GetParameters ();
1246 printf ( "Executing '%s'\n\n", command.c_str () );
1247 int exitcode = system ( command.c_str () );
1248 if ( exitcode != 0 )
1249 throw InvocationFailedException ( command,
1250 exitcode );
1251 }
1252 }
1253
1254
1255 void
1256 Module::SetImportLibrary ( ImportLibrary* importLibrary )
1257 {
1258 this->importLibrary = importLibrary;
1259 dependency = new FileLocation ( HasImportLibrary () ? IntermediateDirectory : output->directory,
1260 output->relative_path,
1261 HasImportLibrary () ? "lib" + name + ".a" : output->name );
1262 }
1263
1264
1265 File::File ( DirectoryLocation directory,
1266 const string& relative_path,
1267 const string& name,
1268 bool _first,
1269 const string& _switches,
1270 bool _isPreCompiledHeader )
1271 : file ( directory, relative_path, name ),
1272 first(_first),
1273 switches(_switches),
1274 isPreCompiledHeader(_isPreCompiledHeader)
1275 {
1276 }
1277
1278
1279 void
1280 File::ProcessXML()
1281 {
1282 }
1283
1284
1285 std::string File::GetFullPath () const
1286 {
1287 string directory ( "" );
1288 switch ( file.directory )
1289 {
1290 case SourceDirectory:
1291 break;
1292 case IntermediateDirectory:
1293 directory = Environment::GetIntermediatePath () + sSep;
1294 break;
1295 default:
1296 throw InvalidOperationException ( __FILE__,
1297 __LINE__,
1298 "Invalid directory %d.",
1299 file.directory );
1300 }
1301
1302 if ( file.relative_path.length () > 0 )
1303 directory += file.relative_path + sSep;
1304
1305
1306 return directory + file.name;
1307 }
1308
1309
1310 Library::Library ( const XMLElement& _node,
1311 const Module& _module,
1312 const string& _name )
1313 : node(&_node),
1314 module(_module),
1315 name(_name),
1316 importedModule(_module.project.LocateModule(_name))
1317 {
1318 if ( module.name == name )
1319 {
1320 throw XMLInvalidBuildFileException (
1321 node->location,
1322 "module '%s' cannot link against itself",
1323 name.c_str() );
1324 }
1325 if ( !importedModule )
1326 {
1327 throw XMLInvalidBuildFileException (
1328 node->location,
1329 "module '%s' trying to import non-existant module '%s'",
1330 module.name.c_str(),
1331 name.c_str() );
1332 }
1333 }
1334
1335 Library::Library ( const Module& _module,
1336 const string& _name )
1337 : node(NULL),
1338 module(_module),
1339 name(_name),
1340 importedModule(_module.project.LocateModule(_name))
1341 {
1342 }
1343
1344 void
1345 Library::ProcessXML()
1346 {
1347 if ( node && !module.project.LocateModule ( name ) )
1348 {
1349 throw XMLInvalidBuildFileException (
1350 node->location,
1351 "module '%s' is trying to link against non-existant module '%s'",
1352 module.name.c_str(),
1353 name.c_str() );
1354 }
1355 }
1356
1357
1358 Invoke::Invoke ( const XMLElement& _node,
1359 const Module& _module )
1360 : node (_node),
1361 module (_module)
1362 {
1363 }
1364
1365 void
1366 Invoke::ProcessXML()
1367 {
1368 const XMLAttribute* att = node.GetAttribute ( "module", false );
1369 if (att == NULL)
1370 invokeModule = &module;
1371 else
1372 {
1373 invokeModule = module.project.LocateModule ( att->value );
1374 if ( invokeModule == NULL )
1375 {
1376 throw XMLInvalidBuildFileException (
1377 node.location,
1378 "module '%s' is trying to invoke non-existant module '%s'",
1379 module.name.c_str(),
1380 att->value.c_str() );
1381 }
1382 }
1383
1384 for ( size_t i = 0; i < node.subElements.size (); i++ )
1385 ProcessXMLSubElement ( *node.subElements[i] );
1386 }
1387
1388 void
1389 Invoke::ProcessXMLSubElement ( const XMLElement& e )
1390 {
1391 bool subs_invalid = false;
1392 if ( e.name == "input" )
1393 {
1394 for ( size_t i = 0; i < e.subElements.size (); i++ )
1395 ProcessXMLSubElementInput ( *e.subElements[i] );
1396 }
1397 else if ( e.name == "output" )
1398 {
1399 for ( size_t i = 0; i < e.subElements.size (); i++ )
1400 ProcessXMLSubElementOutput ( *e.subElements[i] );
1401 }
1402 if ( subs_invalid && e.subElements.size() > 0 )
1403 {
1404 throw XMLInvalidBuildFileException (
1405 e.location,
1406 "<%s> cannot have sub-elements",
1407 e.name.c_str() );
1408 }
1409 }
1410
1411 void
1412 Invoke::ProcessXMLSubElementInput ( const XMLElement& e )
1413 {
1414 bool subs_invalid = false;
1415 if ( e.name == "inputfile" && e.value.size () > 0 )
1416 {
1417 input.push_back ( new InvokeFile (
1418 e, FixSeparator ( module.output->relative_path + cSep + e.value ) ) );
1419 subs_invalid = true;
1420 }
1421 if ( subs_invalid && e.subElements.size() > 0 )
1422 {
1423 throw XMLInvalidBuildFileException (
1424 e.location,
1425 "<%s> cannot have sub-elements",
1426 e.name.c_str() );
1427 }
1428 }
1429
1430 void
1431 Invoke::ProcessXMLSubElementOutput ( const XMLElement& e )
1432 {
1433 bool subs_invalid = false;
1434 if ( e.name == "outputfile" && e.value.size () > 0 )
1435 {
1436 output.push_back ( new InvokeFile (
1437 e, FixSeparator ( module.output->relative_path + cSep + e.value ) ) );
1438 subs_invalid = true;
1439 }
1440 if ( subs_invalid && e.subElements.size() > 0 )
1441 {
1442 throw XMLInvalidBuildFileException (
1443 e.location,
1444 "<%s> cannot have sub-elements",
1445 e.name.c_str() );
1446 }
1447 }
1448
1449 void
1450 Invoke::GetTargets ( string_list& targets ) const
1451 {
1452 for ( size_t i = 0; i < output.size (); i++ )
1453 {
1454 InvokeFile& file = *output[i];
1455 targets.push_back ( NormalizeFilename ( file.name ) );
1456 }
1457 }
1458
1459 string
1460 Invoke::GetParameters () const
1461 {
1462 string parameters ( "" );
1463 size_t i;
1464 for ( i = 0; i < output.size (); i++ )
1465 {
1466 if ( parameters.length () > 0)
1467 parameters += " ";
1468 InvokeFile& invokeFile = *output[i];
1469 if ( invokeFile.switches.length () > 0 )
1470 {
1471 parameters += invokeFile.switches + " ";
1472 }
1473 parameters += invokeFile.name;
1474 }
1475
1476 for ( i = 0; i < input.size (); i++ )
1477 {
1478 if ( parameters.length () > 0 )
1479 parameters += " ";
1480 InvokeFile& invokeFile = *input[i];
1481 if ( invokeFile.switches.length () > 0 )
1482 {
1483 parameters += invokeFile.switches;
1484 parameters += " ";
1485 }
1486 parameters += invokeFile.name ;
1487 }
1488
1489 return parameters;
1490 }
1491
1492
1493 InvokeFile::InvokeFile ( const XMLElement& _node,
1494 const string& _name )
1495 : node (_node),
1496 name (_name)
1497 {
1498 const XMLAttribute* att = _node.GetAttribute ( "switches", false );
1499 if (att != NULL)
1500 switches = att->value;
1501 else
1502 switches = "";
1503 }
1504
1505 void
1506 InvokeFile::ProcessXML()
1507 {
1508 }
1509
1510
1511 Dependency::Dependency ( const XMLElement& _node,
1512 const Module& _module )
1513 : node (_node),
1514 module (_module),
1515 dependencyModule (NULL)
1516 {
1517 }
1518
1519 void
1520 Dependency::ProcessXML()
1521 {
1522 dependencyModule = module.project.LocateModule ( node.value );
1523 if ( dependencyModule == NULL )
1524 {
1525 throw XMLInvalidBuildFileException (
1526 node.location,
1527 "module '%s' depend on non-existant module '%s'",
1528 module.name.c_str(),
1529 node.value.c_str() );
1530 }
1531 }
1532
1533
1534 Metadata::Metadata ( const XMLElement& _node,
1535 const Module& _module )
1536 : node (_node),
1537 module (_module)
1538 {
1539 /* The module name */
1540 const XMLAttribute* att = _node.GetAttribute ( "name", false );
1541 if (att != NULL)
1542 name = att->value;
1543 else
1544 name = module.name;
1545
1546 /* The module description */
1547 att = _node.GetAttribute ( "description", false );
1548 if (att != NULL)
1549 description = att->value;
1550 else
1551 description = "";
1552
1553 /* The module version */
1554 att = _node.GetAttribute ( "version", false );
1555 if (att != NULL)
1556 version = att->value;
1557 else
1558 version = "";
1559
1560 /* The module copyright */
1561 att = _node.GetAttribute ( "copyright", false );
1562 if (att != NULL)
1563 copyright = att->value;
1564 else
1565 copyright = "";
1566
1567 att = _node.GetAttribute ( "url", false );
1568 if (att != NULL)
1569 url = att->value;
1570 else
1571 url = "";
1572
1573 /* When was this module updated */
1574 att = _node.GetAttribute ( "date", false );
1575 if (att != NULL)
1576 date = att->value;
1577 else
1578 date = "?";
1579
1580 /* When was this module updated */
1581 att = _node.GetAttribute ( "owner", false );
1582 if (att != NULL)
1583 owner = att->value;
1584 else
1585 owner = "ReactOS";
1586 }
1587
1588
1589 ImportLibrary::ImportLibrary ( const Project& project,
1590 const XMLElement& node,
1591 const Module& module )
1592 : XmlNode ( project, node ),
1593 module (module)
1594 {
1595 const XMLAttribute* dllname = node.GetAttribute ( "dllname", false );
1596 const XMLAttribute* definition = node.GetAttribute ( "definition", true );
1597 assert ( definition );
1598
1599 if ( dllname )
1600 this->dllname = dllname->value;
1601 else if ( module.type == StaticLibrary )
1602 throw XMLInvalidBuildFileException (
1603 node.location,
1604 "<importlibrary> dllname attribute required." );
1605
1606 DirectoryLocation directory = SourceDirectory;
1607 size_t index = definition->value.rfind ( ".spec.def" );
1608 if ( index != string::npos )
1609 directory = IntermediateDirectory;
1610
1611 index = definition->value.find_last_of ( "/\\" );
1612 if ( index == string::npos )
1613 {
1614 source = new FileLocation ( directory,
1615 module.output->relative_path,
1616 definition->value,
1617 &node );
1618 }
1619 else
1620 {
1621 string dir = definition->value.substr ( 0, index );
1622 string name = definition->value.substr ( index + 1);
1623 source = new FileLocation ( directory,
1624 NormalizeFilename ( module.output->relative_path + sSep + dir ),
1625 name,
1626 &node );
1627 }
1628 }
1629
1630
1631 If::If ( const XMLElement& node_,
1632 const Project& project_,
1633 const Module* module_,
1634 const bool negated_ )
1635 : node(node_), project(project_), module(module_), negated(negated_)
1636 {
1637 const XMLAttribute* att;
1638
1639 att = node.GetAttribute ( "property", true );
1640 assert(att);
1641 property = att->value;
1642
1643 att = node.GetAttribute ( "value", true );
1644 assert(att);
1645 value = att->value;
1646 }
1647
1648 If::~If ()
1649 {
1650 }
1651
1652 void
1653 If::ProcessXML()
1654 {
1655
1656 }
1657
1658
1659 Property::Property ( const XMLElement& node_,
1660 const Project& project_,
1661 const Module* module_ )
1662 : project(project_), module(module_)
1663 {
1664 const XMLAttribute* att;
1665
1666 att = node_.GetAttribute ( "name", true );
1667 assert(att);
1668 name = project.ResolveProperties ( att->value );
1669
1670 att = node_.GetAttribute ( "value", true );
1671 assert(att);
1672 value = att->value;
1673 }
1674
1675 Property::Property ( const Project& project_,
1676 const Module* module_,
1677 const std::string& name_,
1678 const std::string& value_ )
1679 : project(project_), module(module_), name(name_), value(value_)
1680 {
1681 }
1682
1683 void
1684 Property::ProcessXML()
1685 {
1686 }
1687
1688
1689 PchFile::PchFile (
1690 const XMLElement& node_,
1691 const Module& module_,
1692 const FileLocation& file_ )
1693 : node(node_), module(module_), file(file_)
1694 {
1695 }
1696
1697 void
1698 PchFile::ProcessXML()
1699 {
1700 }