Don't mix host and targets include files
[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 if ( install )
490 delete install;
491 if ( metadata )
492 delete metadata;
493 if ( bootstrap )
494 delete bootstrap;
495 if ( importLibrary )
496 delete importLibrary;
497 delete output;
498 }
499
500 void
501 Module::ProcessXML()
502 {
503 if ( type == Alias )
504 {
505 aliasedModuleName = project.ResolveProperties ( aliasedModuleName );
506 if ( aliasedModuleName == name )
507 {
508 throw XMLInvalidBuildFileException (
509 node.location,
510 "module '%s' cannot link against itself",
511 name.c_str() );
512 }
513 const Module* m = project.LocateModule ( aliasedModuleName );
514 if ( !m && enabled )
515 {
516 throw XMLInvalidBuildFileException (
517 node.location,
518 "module '%s' trying to alias non-existant module '%s'",
519 name.c_str(),
520 aliasedModuleName.c_str() );
521 }
522 }
523
524 size_t i;
525 for ( i = 0; i < node.subElements.size(); i++ )
526 {
527 ParseContext parseContext;
528 ProcessXMLSubElement ( *node.subElements[i], SourceDirectory, output->relative_path, parseContext );
529 }
530 for ( i = 0; i < invocations.size(); i++ )
531 invocations[i]->ProcessXML ();
532 for ( i = 0; i < dependencies.size(); i++ )
533 dependencies[i]->ProcessXML ();
534 for ( i = 0; i < compilerFlags.size(); i++ )
535 compilerFlags[i]->ProcessXML();
536 for ( i = 0; i < linkerFlags.size(); i++ )
537 linkerFlags[i]->ProcessXML();
538 for ( i = 0; i < stubbedComponents.size(); i++ )
539 stubbedComponents[i]->ProcessXML();
540 non_if_data.ProcessXML();
541 if ( linkerScript )
542 linkerScript->ProcessXML();
543 if ( pch )
544 pch->ProcessXML();
545 if ( autoRegister )
546 autoRegister->ProcessXML();
547 }
548
549 void
550 Module::ProcessXMLSubElement ( const XMLElement& e,
551 DirectoryLocation directory,
552 const string& relative_path,
553 ParseContext& parseContext )
554 {
555 If* pOldIf = parseContext.ifData;
556 CompilationUnit* pOldCompilationUnit = parseContext.compilationUnit;
557 bool subs_invalid = false;
558 string subpath ( relative_path );
559 DirectoryLocation subdirectory = SourceDirectory;
560 if ( e.name == "file" && e.value.size () > 0 )
561 {
562 bool first = false;
563 const XMLAttribute* att = e.GetAttribute ( "first", false );
564 if ( att != NULL )
565 {
566 if ( !stricmp ( att->value.c_str(), "true" ) )
567 first = true;
568 else if ( stricmp ( att->value.c_str(), "false" ) )
569 {
570 throw XMLInvalidBuildFileException (
571 e.location,
572 "attribute 'first' of <file> element can only be 'true' or 'false'" );
573 }
574 }
575 string switches = "";
576 att = e.GetAttribute ( "switches", false );
577 if ( att != NULL )
578 switches = att->value;
579 if ( !cplusplus )
580 {
581 // check for c++ file
582 string ext = GetExtension ( e.value );
583 if ( !stricmp ( ext.c_str(), ".cpp" ) )
584 cplusplus = true;
585 else if ( !stricmp ( ext.c_str(), ".cc" ) )
586 cplusplus = true;
587 else if ( !stricmp ( ext.c_str(), ".cxx" ) )
588 cplusplus = true;
589 }
590 File* pFile = new File ( directory,
591 relative_path,
592 e.value,
593 first,
594 switches,
595 false );
596 if ( parseContext.compilationUnit )
597 parseContext.compilationUnit->AddFile ( pFile );
598 else
599 {
600 CompilationUnit* pCompilationUnit = new CompilationUnit ( pFile );
601 if ( parseContext.ifData )
602 parseContext.ifData->data.compilationUnits.push_back ( pCompilationUnit );
603 else
604 {
605 string ext = ToLower ( GetExtension ( e.value ) );
606 if ( ext == ".idl" )
607 {
608 // put .idl files at the start of the module
609 non_if_data.compilationUnits.insert (
610 non_if_data.compilationUnits.begin(),
611 pCompilationUnit );
612 }
613 else if ( ext == ".asm" || ext == ".s" )
614 {
615 // put .asm files at the end of the module
616 non_if_data.compilationUnits.push_back ( pCompilationUnit );
617 non_if_data.asmFiles++;
618 }
619 else
620 {
621 // put other files in the middle
622 non_if_data.compilationUnits.insert (
623 non_if_data.compilationUnits.end() - non_if_data.asmFiles,
624 pCompilationUnit );
625 }
626 }
627 }
628 if ( parseContext.ifData )
629 parseContext.ifData->data.files.push_back ( pFile );
630 else
631 non_if_data.files.push_back ( pFile );
632 subs_invalid = true;
633 }
634 else if ( e.name == "library" && e.value.size () )
635 {
636 Library* pLibrary = new Library ( e, *this, e.value );
637 if ( parseContext.ifData )
638 parseContext.ifData->data.libraries.push_back ( pLibrary );
639 else
640 non_if_data.libraries.push_back ( pLibrary );
641 subs_invalid = true;
642 }
643 else if ( e.name == "directory" )
644 {
645 const XMLAttribute* att = e.GetAttribute ( "name", true );
646 const XMLAttribute* root = e.GetAttribute ( "root", false );
647 assert(att);
648 if ( root )
649 {
650 if ( root->value == "intermediate" )
651 subdirectory = IntermediateDirectory;
652 else if ( root->value == "output" )
653 subdirectory = OutputDirectory;
654 else
655 {
656 throw InvalidAttributeValueException (
657 e.location,
658 "root",
659 root->value );
660 }
661 }
662 subpath = GetSubPath ( this->project, e.location, relative_path, att->value );
663 }
664 else if ( e.name == "include" )
665 {
666 Include* include = new Include ( project, &e, this );
667 if ( parseContext.ifData )
668 parseContext.ifData->data.includes.push_back ( include );
669 else
670 non_if_data.includes.push_back ( include );
671 subs_invalid = true;
672 }
673 else if ( e.name == "define" )
674 {
675 Define* pDefine = new Define ( project, this, e );
676 if ( parseContext.ifData )
677 parseContext.ifData->data.defines.push_back ( pDefine );
678 else
679 non_if_data.defines.push_back ( pDefine );
680 subs_invalid = true;
681 }
682 else if ( e.name == "metadata" )
683 {
684 if ( parseContext.ifData )
685 {
686 throw XMLInvalidBuildFileException (
687 e.location,
688 "<metadata> is not a valid sub-element of <if>" );
689 }
690 metadata = new Metadata ( e, *this );
691 subs_invalid = false;
692 }
693 else if ( e.name == "invoke" )
694 {
695 if ( parseContext.ifData )
696 {
697 throw XMLInvalidBuildFileException (
698 e.location,
699 "<invoke> is not a valid sub-element of <if>" );
700 }
701 invocations.push_back ( new Invoke ( e, *this ) );
702 subs_invalid = false;
703 }
704 else if ( e.name == "dependency" )
705 {
706 if ( parseContext.ifData )
707 {
708 throw XMLInvalidBuildFileException (
709 e.location,
710 "<dependency> is not a valid sub-element of <if>" );
711 }
712 dependencies.push_back ( new Dependency ( e, *this ) );
713 subs_invalid = true;
714 }
715 else if ( e.name == "importlibrary" )
716 {
717 if ( parseContext.ifData )
718 {
719 throw XMLInvalidBuildFileException (
720 e.location,
721 "<importlibrary> is not a valid sub-element of <if>" );
722 }
723 if ( importLibrary )
724 {
725 throw XMLInvalidBuildFileException (
726 e.location,
727 "Only one <importlibrary> is valid per module" );
728 }
729 SetImportLibrary ( new ImportLibrary ( project, e, *this ) );
730 subs_invalid = true;
731 }
732 else if ( e.name == "if" )
733 {
734 parseContext.ifData = new If ( e, project, this );
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 == "ifnot" )
742 {
743 parseContext.ifData = new If ( e, project, this, true );
744 if ( pOldIf )
745 pOldIf->data.ifs.push_back ( parseContext.ifData );
746 else
747 non_if_data.ifs.push_back ( parseContext.ifData );
748 subs_invalid = false;
749 }
750 else if ( e.name == "compilerflag" )
751 {
752 CompilerFlag* pCompilerFlag = new CompilerFlag ( project, this, e );
753 if ( parseContext.ifData )
754 parseContext.ifData->data.compilerFlags.push_back ( pCompilerFlag );
755 else
756 non_if_data.compilerFlags.push_back ( pCompilerFlag );
757 subs_invalid = true;
758 }
759 else if ( e.name == "linkerflag" )
760 {
761 linkerFlags.push_back ( new LinkerFlag ( project, this, e ) );
762 subs_invalid = true;
763 }
764 else if ( e.name == "linkerscript" )
765 {
766 if ( parseContext.ifData )
767 {
768 throw XMLInvalidBuildFileException (
769 e.location,
770 "<linkerscript> is not a valid sub-element of <if>" );
771 }
772 if ( linkerScript )
773 {
774 throw XMLInvalidBuildFileException (
775 e.location,
776 "Only one <linkerscript> is valid per module" );
777 }
778 size_t pos = e.value.find_last_of ( "/\\" );
779 if ( pos == string::npos )
780 {
781 linkerScript = new LinkerScript (
782 e, *this, new FileLocation ( SourceDirectory, relative_path, e.value, &e ) );
783 }
784 else
785 {
786 string dir = e.value.substr ( 0, pos );
787 string name = e.value.substr ( pos + 1);
788 linkerScript = new LinkerScript (
789 e, *this, new FileLocation ( SourceDirectory, relative_path + sSep + dir, name, &e ) );
790 }
791 subs_invalid = true;
792 }
793 else if ( e.name == "component" )
794 {
795 stubbedComponents.push_back ( new StubbedComponent ( this, e ) );
796 subs_invalid = false;
797 }
798 else if ( e.name == "property" )
799 {
800 throw XMLInvalidBuildFileException (
801 e.location,
802 "<property> is not a valid sub-element of <module>" );
803 }
804 else if ( e.name == "bootstrap" )
805 {
806 bootstrap = new Bootstrap ( project, this, e );
807 subs_invalid = true;
808 }
809 else if ( e.name == "pch" )
810 {
811 if ( parseContext.ifData )
812 {
813 throw XMLInvalidBuildFileException (
814 e.location,
815 "<pch> is not a valid sub-element of <if>" );
816 }
817 if ( pch )
818 {
819 throw XMLInvalidBuildFileException (
820 e.location,
821 "Only one <pch> is valid per module" );
822 }
823 size_t pos = e.value.find_last_of ( "/\\" );
824 if ( pos == string::npos )
825 {
826 pch = new PchFile (
827 e, *this, new FileLocation ( SourceDirectory, relative_path, e.value, &e ) );
828 }
829 else
830 {
831 string dir = e.value.substr ( 0, pos );
832 string name = e.value.substr ( pos + 1);
833 pch = new PchFile (
834 e, *this, new FileLocation ( SourceDirectory, relative_path + sSep + dir, name, &e ) );
835 }
836 subs_invalid = true;
837 }
838 else if ( e.name == "compilationunit" )
839 {
840 if ( project.configuration.CompilationUnitsEnabled )
841 {
842 CompilationUnit* pCompilationUnit = new CompilationUnit ( &project, this, &e );
843 if ( parseContext.ifData )
844 parseContext.ifData->data.compilationUnits.push_back ( pCompilationUnit );
845 else
846 non_if_data.compilationUnits.push_back ( pCompilationUnit );
847 parseContext.compilationUnit = pCompilationUnit;
848 }
849 subs_invalid = false;
850 }
851 else if ( e.name == "autoregister" )
852 {
853 if ( autoRegister != NULL)
854 {
855 throw XMLInvalidBuildFileException (
856 e.location,
857 "there can be only one <%s> element for a module",
858 e.name.c_str() );
859 }
860 autoRegister = new AutoRegister ( project, this, e );
861 subs_invalid = true;
862 }
863 if ( subs_invalid && e.subElements.size() > 0 )
864 {
865 throw XMLInvalidBuildFileException (
866 e.location,
867 "<%s> cannot have sub-elements",
868 e.name.c_str() );
869 }
870 for ( size_t i = 0; i < e.subElements.size (); i++ )
871 ProcessXMLSubElement ( *e.subElements[i], subdirectory, subpath, parseContext );
872 parseContext.ifData = pOldIf;
873 parseContext.compilationUnit = pOldCompilationUnit;
874 }
875
876 ModuleType
877 Module::GetModuleType ( const string& location, const XMLAttribute& attribute )
878 {
879 if ( attribute.value == "buildtool" )
880 return BuildTool;
881 if ( attribute.value == "staticlibrary" )
882 return StaticLibrary;
883 if ( attribute.value == "hoststaticlibrary" )
884 return HostStaticLibrary;
885 if ( attribute.value == "objectlibrary" )
886 return ObjectLibrary;
887 if ( attribute.value == "kernel" )
888 return Kernel;
889 if ( attribute.value == "kernelmodedll" )
890 return KernelModeDLL;
891 if ( attribute.value == "kernelmodedriver" )
892 return KernelModeDriver;
893 if ( attribute.value == "nativedll" )
894 return NativeDLL;
895 if ( attribute.value == "nativecui" )
896 return NativeCUI;
897 if ( attribute.value == "win32dll" )
898 return Win32DLL;
899 if ( attribute.value == "win32ocx" )
900 return Win32OCX;
901 if ( attribute.value == "win32cui" )
902 return Win32CUI;
903 if ( attribute.value == "win32gui" )
904 return Win32GUI;
905 if ( attribute.value == "win32scr" )
906 return Win32SCR;
907 if ( attribute.value == "bootloader" )
908 return BootLoader;
909 if ( attribute.value == "bootsector" )
910 return BootSector;
911 if ( attribute.value == "bootprogram" )
912 return BootProgram;
913 if ( attribute.value == "iso" )
914 return Iso;
915 if ( attribute.value == "liveiso" )
916 return LiveIso;
917 if ( attribute.value == "isoregtest" )
918 return IsoRegTest;
919 if ( attribute.value == "liveisoregtest" )
920 return LiveIsoRegTest;
921 if ( attribute.value == "test" )
922 return Test;
923 if ( attribute.value == "rpcserver" )
924 return RpcServer;
925 if ( attribute.value == "rpcclient" )
926 return RpcClient;
927 if ( attribute.value == "rpcproxy" )
928 return RpcProxy;
929 if ( attribute.value == "alias" )
930 return Alias;
931 if ( attribute.value == "idlheader" )
932 return IdlHeader;
933 if ( attribute.value == "embeddedtypelib" )
934 return EmbeddedTypeLib;
935 if ( attribute.value == "elfexecutable" )
936 return ElfExecutable;
937 throw InvalidAttributeValueException ( location,
938 attribute.name,
939 attribute.value );
940 }
941
942 DirectoryLocation
943 Module::GetTargetDirectoryTree () const
944 {
945 switch ( type )
946 {
947 case Kernel:
948 case KernelModeDLL:
949 case NativeDLL:
950 case Win32DLL:
951 case Win32OCX:
952 case KernelModeDriver:
953 case NativeCUI:
954 case Win32CUI:
955 case Test:
956 case Win32SCR:
957 case Win32GUI:
958 case BuildTool:
959 case BootLoader:
960 case BootSector:
961 case BootProgram:
962 case Iso:
963 case LiveIso:
964 case IsoRegTest:
965 case LiveIsoRegTest:
966 case EmbeddedTypeLib:
967 case ElfExecutable:
968 return OutputDirectory;
969 case StaticLibrary:
970 case HostStaticLibrary:
971 case ObjectLibrary:
972 case RpcServer:
973 case RpcClient:
974 case RpcProxy:
975 case Alias:
976 case IdlHeader:
977 return IntermediateDirectory;
978 case TypeDontCare:
979 break;
980 }
981 throw InvalidOperationException ( __FILE__,
982 __LINE__,
983 "Invalid module type %d.",
984 type );
985 }
986
987 string
988 Module::GetDefaultModuleExtension () const
989 {
990 switch (type)
991 {
992 case BuildTool:
993 return ExePostfix;
994 case BootProgram:
995 case StaticLibrary:
996 case HostStaticLibrary:
997 return ".a";
998 case ObjectLibrary:
999 return ".o";
1000 case Kernel:
1001 case NativeCUI:
1002 case Win32CUI:
1003 case Win32GUI:
1004 return ".exe";
1005 case Win32SCR:
1006 return ".scr";
1007
1008 case KernelModeDLL:
1009 case NativeDLL:
1010 case Win32DLL:
1011 return ".dll";
1012 case Win32OCX:
1013 return ".ocx";
1014 case KernelModeDriver:
1015 case BootLoader:
1016 return ".sys";
1017 case BootSector:
1018 return ".o";
1019 case Iso:
1020 case LiveIso:
1021 case IsoRegTest:
1022 case LiveIsoRegTest:
1023 return ".iso";
1024 case Test:
1025 return ".exe";
1026 case RpcServer:
1027 case RpcClient:
1028 case RpcProxy:
1029 return ".o";
1030 case Alias:
1031 case ElfExecutable:
1032 case IdlHeader:
1033 return "";
1034 case EmbeddedTypeLib:
1035 return ".tlb";
1036 case TypeDontCare:
1037 break;
1038 }
1039 throw InvalidOperationException ( __FILE__,
1040 __LINE__ );
1041 }
1042
1043 string
1044 Module::GetDefaultModuleEntrypoint () const
1045 {
1046 switch ( type )
1047 {
1048 case Kernel:
1049 return "KiSystemStartup";
1050 case KernelModeDLL:
1051 case KernelModeDriver:
1052 return "DriverEntry@8";
1053 case NativeDLL:
1054 return "DllMainCRTStartup@12";
1055 case NativeCUI:
1056 return "NtProcessStartup@4";
1057 case Win32DLL:
1058 case Win32OCX:
1059 return "DllMain@12";
1060 case Win32CUI:
1061 case Test:
1062 if ( isUnicode )
1063 return "wmainCRTStartup";
1064 else
1065 return "mainCRTStartup";
1066 case Win32SCR:
1067 case Win32GUI:
1068 if ( isUnicode )
1069 return "wWinMainCRTStartup";
1070 else
1071 return "WinMainCRTStartup";
1072 case BuildTool:
1073 case StaticLibrary:
1074 case HostStaticLibrary:
1075 case ObjectLibrary:
1076 case BootLoader:
1077 case BootSector:
1078 case Iso:
1079 case LiveIso:
1080 case IsoRegTest:
1081 case LiveIsoRegTest:
1082 case RpcServer:
1083 case RpcClient:
1084 case RpcProxy:
1085 case Alias:
1086 case BootProgram:
1087 case IdlHeader:
1088 case ElfExecutable:
1089 case EmbeddedTypeLib:
1090 return "";
1091 case TypeDontCare:
1092 break;
1093 }
1094 throw InvalidOperationException ( __FILE__,
1095 __LINE__ );
1096 }
1097
1098 string
1099 Module::GetDefaultModuleBaseaddress () const
1100 {
1101 switch ( type )
1102 {
1103 case Kernel:
1104 return "0x80800000";
1105 case Win32DLL:
1106 case Win32OCX:
1107 return "0x10000000";
1108 case NativeDLL:
1109 case NativeCUI:
1110 case Win32CUI:
1111 case Test:
1112 return "0x00400000";
1113 case Win32SCR:
1114 case Win32GUI:
1115 return "0x00400000";
1116 case KernelModeDLL:
1117 case KernelModeDriver:
1118 return "0x00010000";
1119 case ElfExecutable:
1120 return "0xe00000";
1121 case BuildTool:
1122 case StaticLibrary:
1123 case HostStaticLibrary:
1124 case ObjectLibrary:
1125 case BootLoader:
1126 case BootSector:
1127 case Iso:
1128 case LiveIso:
1129 case IsoRegTest:
1130 case LiveIsoRegTest:
1131 case RpcServer:
1132 case RpcClient:
1133 case RpcProxy:
1134 case Alias:
1135 case BootProgram:
1136 case IdlHeader:
1137 case EmbeddedTypeLib:
1138 return "";
1139 case TypeDontCare:
1140 break;
1141 }
1142 throw InvalidOperationException ( __FILE__,
1143 __LINE__ );
1144 }
1145
1146 bool
1147 Module::HasImportLibrary () const
1148 {
1149 return importLibrary != NULL && type != StaticLibrary && type != HostStaticLibrary;
1150 }
1151
1152 bool
1153 Module::IsDLL () const
1154 {
1155 switch ( type )
1156 {
1157 case Kernel:
1158 case KernelModeDLL:
1159 case NativeDLL:
1160 case Win32DLL:
1161 case Win32OCX:
1162 case KernelModeDriver:
1163 return true;
1164 case NativeCUI:
1165 case Win32CUI:
1166 case Test:
1167 case Win32SCR:
1168 case Win32GUI:
1169 case BuildTool:
1170 case StaticLibrary:
1171 case HostStaticLibrary:
1172 case ObjectLibrary:
1173 case BootLoader:
1174 case BootSector:
1175 case BootProgram:
1176 case Iso:
1177 case LiveIso:
1178 case IsoRegTest:
1179 case LiveIsoRegTest:
1180 case RpcServer:
1181 case RpcClient:
1182 case RpcProxy:
1183 case Alias:
1184 case IdlHeader:
1185 case EmbeddedTypeLib:
1186 case ElfExecutable:
1187 return false;
1188 case TypeDontCare:
1189 break;
1190 }
1191 throw InvalidOperationException ( __FILE__,
1192 __LINE__ );
1193 }
1194
1195 string
1196 Module::GetPathWithPrefix ( const string& prefix ) const
1197 {
1198 return output->relative_path + cSep + prefix + output->name;
1199 }
1200
1201 string
1202 Module::GetPathToBaseDir () const
1203 {
1204 string temp_path = output->relative_path;
1205 string result = "..\\";
1206 while(temp_path.find ('\\') != string::npos)
1207 {
1208 temp_path.erase (0, temp_path.find('\\')+1);
1209 result += "..\\";
1210 }
1211 return result;
1212 }
1213
1214 string
1215 Module::GetInvocationTarget ( const int index ) const
1216 {
1217 return ssprintf ( "%s_invoke_%d",
1218 name.c_str (),
1219 index );
1220 }
1221
1222 string
1223 Module::GetEntryPoint(bool leadingUnderscore) const
1224 {
1225 string result = "";
1226 if (entrypoint == "0" || entrypoint == "0x0")
1227 return "0";
1228 if (leadingUnderscore)
1229 result = "_";
1230
1231 result += entrypoint;
1232 return result;
1233 }
1234
1235 bool
1236 Module::HasFileWithExtension (
1237 const IfableData& data,
1238 const std::string& extension ) const
1239 {
1240 size_t i;
1241 for ( i = 0; i < data.compilationUnits.size (); i++ )
1242 {
1243 CompilationUnit* compilationUnit = data.compilationUnits[i];
1244 if ( compilationUnit->HasFileWithExtension ( extension ) )
1245 return true;
1246 }
1247 for ( i = 0; i < data.ifs.size (); i++ )
1248 {
1249 if ( HasFileWithExtension ( data.ifs[i]->data, extension ) )
1250 return true;
1251 }
1252 return false;
1253 }
1254
1255 void
1256 Module::InvokeModule () const
1257 {
1258 for ( size_t i = 0; i < invocations.size (); i++ )
1259 {
1260 Invoke& invoke = *invocations[i];
1261 string command = FixSeparatorForSystemCommand(invoke.invokeModule->output->relative_path + "/" + invoke.invokeModule->output->name ) + " " + invoke.GetParameters ();
1262 printf ( "Executing '%s'\n\n", command.c_str () );
1263 int exitcode = system ( command.c_str () );
1264 if ( exitcode != 0 )
1265 throw InvocationFailedException ( command,
1266 exitcode );
1267 }
1268 }
1269
1270
1271 void
1272 Module::SetImportLibrary ( ImportLibrary* importLibrary )
1273 {
1274 this->importLibrary = importLibrary;
1275 dependency = new FileLocation ( HasImportLibrary () ? IntermediateDirectory : output->directory,
1276 output->relative_path,
1277 HasImportLibrary () ? "lib" + name + ".a" : output->name );
1278 }
1279
1280
1281 File::File ( DirectoryLocation directory,
1282 const string& relative_path,
1283 const string& name,
1284 bool _first,
1285 const string& _switches,
1286 bool _isPreCompiledHeader )
1287 : file ( directory, relative_path, name ),
1288 first(_first),
1289 switches(_switches),
1290 isPreCompiledHeader(_isPreCompiledHeader)
1291 {
1292 }
1293
1294
1295 void
1296 File::ProcessXML()
1297 {
1298 }
1299
1300
1301 std::string File::GetFullPath () const
1302 {
1303 string directory ( "" );
1304 switch ( file.directory )
1305 {
1306 case SourceDirectory:
1307 break;
1308 case IntermediateDirectory:
1309 directory = Environment::GetIntermediatePath () + sSep;
1310 break;
1311 default:
1312 throw InvalidOperationException ( __FILE__,
1313 __LINE__,
1314 "Invalid directory %d.",
1315 file.directory );
1316 }
1317
1318 if ( file.relative_path.length () > 0 )
1319 directory += file.relative_path + sSep;
1320
1321
1322 return directory + file.name;
1323 }
1324
1325
1326 Library::Library ( const XMLElement& _node,
1327 const Module& _module,
1328 const string& _name )
1329 : node(&_node),
1330 module(_module),
1331 name(_name),
1332 importedModule(_module.project.LocateModule(_name))
1333 {
1334 if ( module.name == name )
1335 {
1336 throw XMLInvalidBuildFileException (
1337 node->location,
1338 "module '%s' cannot link against itself",
1339 name.c_str() );
1340 }
1341 if ( !importedModule )
1342 {
1343 throw XMLInvalidBuildFileException (
1344 node->location,
1345 "module '%s' trying to import non-existant module '%s'",
1346 module.name.c_str(),
1347 name.c_str() );
1348 }
1349 }
1350
1351 Library::Library ( const Module& _module,
1352 const string& _name )
1353 : node(NULL),
1354 module(_module),
1355 name(_name),
1356 importedModule(_module.project.LocateModule(_name))
1357 {
1358 }
1359
1360 void
1361 Library::ProcessXML()
1362 {
1363 if ( node && !module.project.LocateModule ( name ) )
1364 {
1365 throw XMLInvalidBuildFileException (
1366 node->location,
1367 "module '%s' is trying to link against non-existant module '%s'",
1368 module.name.c_str(),
1369 name.c_str() );
1370 }
1371 }
1372
1373
1374 Invoke::Invoke ( const XMLElement& _node,
1375 const Module& _module )
1376 : node (_node),
1377 module (_module)
1378 {
1379 }
1380
1381 void
1382 Invoke::ProcessXML()
1383 {
1384 const XMLAttribute* att = node.GetAttribute ( "module", false );
1385 if (att == NULL)
1386 invokeModule = &module;
1387 else
1388 {
1389 invokeModule = module.project.LocateModule ( att->value );
1390 if ( invokeModule == NULL )
1391 {
1392 throw XMLInvalidBuildFileException (
1393 node.location,
1394 "module '%s' is trying to invoke non-existant module '%s'",
1395 module.name.c_str(),
1396 att->value.c_str() );
1397 }
1398 }
1399
1400 for ( size_t i = 0; i < node.subElements.size (); i++ )
1401 ProcessXMLSubElement ( *node.subElements[i] );
1402 }
1403
1404 void
1405 Invoke::ProcessXMLSubElement ( const XMLElement& e )
1406 {
1407 bool subs_invalid = false;
1408 if ( e.name == "input" )
1409 {
1410 for ( size_t i = 0; i < e.subElements.size (); i++ )
1411 ProcessXMLSubElementInput ( *e.subElements[i] );
1412 }
1413 else if ( e.name == "output" )
1414 {
1415 for ( size_t i = 0; i < e.subElements.size (); i++ )
1416 ProcessXMLSubElementOutput ( *e.subElements[i] );
1417 }
1418 if ( subs_invalid && e.subElements.size() > 0 )
1419 {
1420 throw XMLInvalidBuildFileException (
1421 e.location,
1422 "<%s> cannot have sub-elements",
1423 e.name.c_str() );
1424 }
1425 }
1426
1427 void
1428 Invoke::ProcessXMLSubElementInput ( const XMLElement& e )
1429 {
1430 bool subs_invalid = false;
1431 if ( e.name == "inputfile" && e.value.size () > 0 )
1432 {
1433 input.push_back ( new InvokeFile (
1434 e, FixSeparator ( module.output->relative_path + cSep + e.value ) ) );
1435 subs_invalid = true;
1436 }
1437 if ( subs_invalid && e.subElements.size() > 0 )
1438 {
1439 throw XMLInvalidBuildFileException (
1440 e.location,
1441 "<%s> cannot have sub-elements",
1442 e.name.c_str() );
1443 }
1444 }
1445
1446 void
1447 Invoke::ProcessXMLSubElementOutput ( const XMLElement& e )
1448 {
1449 bool subs_invalid = false;
1450 if ( e.name == "outputfile" && e.value.size () > 0 )
1451 {
1452 output.push_back ( new InvokeFile (
1453 e, FixSeparator ( module.output->relative_path + cSep + e.value ) ) );
1454 subs_invalid = true;
1455 }
1456 if ( subs_invalid && e.subElements.size() > 0 )
1457 {
1458 throw XMLInvalidBuildFileException (
1459 e.location,
1460 "<%s> cannot have sub-elements",
1461 e.name.c_str() );
1462 }
1463 }
1464
1465 void
1466 Invoke::GetTargets ( string_list& targets ) const
1467 {
1468 for ( size_t i = 0; i < output.size (); i++ )
1469 {
1470 InvokeFile& file = *output[i];
1471 targets.push_back ( NormalizeFilename ( file.name ) );
1472 }
1473 }
1474
1475 string
1476 Invoke::GetParameters () const
1477 {
1478 string parameters ( "" );
1479 size_t i;
1480 for ( i = 0; i < output.size (); i++ )
1481 {
1482 if ( parameters.length () > 0)
1483 parameters += " ";
1484 InvokeFile& invokeFile = *output[i];
1485 if ( invokeFile.switches.length () > 0 )
1486 {
1487 parameters += invokeFile.switches + " ";
1488 }
1489 parameters += invokeFile.name;
1490 }
1491
1492 for ( i = 0; i < input.size (); i++ )
1493 {
1494 if ( parameters.length () > 0 )
1495 parameters += " ";
1496 InvokeFile& invokeFile = *input[i];
1497 if ( invokeFile.switches.length () > 0 )
1498 {
1499 parameters += invokeFile.switches;
1500 parameters += " ";
1501 }
1502 parameters += invokeFile.name ;
1503 }
1504
1505 return parameters;
1506 }
1507
1508
1509 InvokeFile::InvokeFile ( const XMLElement& _node,
1510 const string& _name )
1511 : node (_node),
1512 name (_name)
1513 {
1514 const XMLAttribute* att = _node.GetAttribute ( "switches", false );
1515 if (att != NULL)
1516 switches = att->value;
1517 else
1518 switches = "";
1519 }
1520
1521 void
1522 InvokeFile::ProcessXML()
1523 {
1524 }
1525
1526
1527 Dependency::Dependency ( const XMLElement& _node,
1528 const Module& _module )
1529 : node (_node),
1530 module (_module),
1531 dependencyModule (NULL)
1532 {
1533 }
1534
1535 void
1536 Dependency::ProcessXML()
1537 {
1538 dependencyModule = module.project.LocateModule ( node.value );
1539 if ( dependencyModule == NULL )
1540 {
1541 throw XMLInvalidBuildFileException (
1542 node.location,
1543 "module '%s' depend on non-existant module '%s'",
1544 module.name.c_str(),
1545 node.value.c_str() );
1546 }
1547 }
1548
1549
1550 Metadata::Metadata ( const XMLElement& _node,
1551 const Module& _module )
1552 : node (_node),
1553 module (_module)
1554 {
1555 /* The module name */
1556 const XMLAttribute* att = _node.GetAttribute ( "name", false );
1557 if (att != NULL)
1558 name = att->value;
1559 else
1560 name = module.name;
1561
1562 /* The module description */
1563 att = _node.GetAttribute ( "description", false );
1564 if (att != NULL)
1565 description = att->value;
1566 else
1567 description = "";
1568
1569 /* The module version */
1570 att = _node.GetAttribute ( "version", false );
1571 if (att != NULL)
1572 version = att->value;
1573 else
1574 version = "";
1575
1576 /* The module copyright */
1577 att = _node.GetAttribute ( "copyright", false );
1578 if (att != NULL)
1579 copyright = att->value;
1580 else
1581 copyright = "";
1582
1583 att = _node.GetAttribute ( "url", false );
1584 if (att != NULL)
1585 url = att->value;
1586 else
1587 url = "";
1588
1589 /* When was this module updated */
1590 att = _node.GetAttribute ( "date", false );
1591 if (att != NULL)
1592 date = att->value;
1593 else
1594 date = "?";
1595
1596 /* When was this module updated */
1597 att = _node.GetAttribute ( "owner", false );
1598 if (att != NULL)
1599 owner = att->value;
1600 else
1601 owner = "ReactOS";
1602 }
1603
1604
1605 ImportLibrary::~ImportLibrary ()
1606 {
1607 delete source;
1608 }
1609
1610
1611 ImportLibrary::ImportLibrary ( const Project& project,
1612 const XMLElement& node,
1613 const Module& module )
1614 : XmlNode ( project, node ),
1615 module (module)
1616 {
1617 const XMLAttribute* dllname = node.GetAttribute ( "dllname", false );
1618 const XMLAttribute* definition = node.GetAttribute ( "definition", true );
1619 assert ( definition );
1620
1621 if ( dllname )
1622 this->dllname = dllname->value;
1623 else if ( module.type == StaticLibrary || module.type == HostStaticLibrary )
1624 throw XMLInvalidBuildFileException (
1625 node.location,
1626 "<importlibrary> dllname attribute required." );
1627
1628 DirectoryLocation directory = SourceDirectory;
1629 size_t index = definition->value.rfind ( ".spec.def" );
1630 if ( index != string::npos )
1631 directory = IntermediateDirectory;
1632
1633 index = definition->value.find_last_of ( "/\\" );
1634 if ( index == string::npos )
1635 {
1636 source = new FileLocation ( directory,
1637 module.output->relative_path,
1638 definition->value,
1639 &node );
1640 }
1641 else
1642 {
1643 string dir = definition->value.substr ( 0, index );
1644 string name = definition->value.substr ( index + 1);
1645 source = new FileLocation ( directory,
1646 NormalizeFilename ( module.output->relative_path + sSep + dir ),
1647 name,
1648 &node );
1649 }
1650 }
1651
1652
1653 If::If ( const XMLElement& node_,
1654 const Project& project_,
1655 const Module* module_,
1656 const bool negated_ )
1657 : node(node_), project(project_), module(module_), negated(negated_)
1658 {
1659 const XMLAttribute* att;
1660
1661 att = node.GetAttribute ( "property", true );
1662 assert(att);
1663 property = att->value;
1664
1665 att = node.GetAttribute ( "value", true );
1666 assert(att);
1667 value = att->value;
1668 }
1669
1670 If::~If ()
1671 {
1672 }
1673
1674 void
1675 If::ProcessXML()
1676 {
1677
1678 }
1679
1680
1681 Property::Property ( const XMLElement& node_,
1682 const Project& project_,
1683 const Module* module_ )
1684 : project(project_), module(module_)
1685 {
1686 const XMLAttribute* att;
1687
1688 att = node_.GetAttribute ( "name", true );
1689 assert(att);
1690 name = project.ResolveProperties ( att->value );
1691
1692 att = node_.GetAttribute ( "value", true );
1693 assert(att);
1694 value = att->value;
1695 }
1696
1697 Property::Property ( const Project& project_,
1698 const Module* module_,
1699 const std::string& name_,
1700 const std::string& value_ )
1701 : project(project_), module(module_), name(name_), value(value_)
1702 {
1703 }
1704
1705 void
1706 Property::ProcessXML()
1707 {
1708 }
1709
1710
1711 PchFile::PchFile (
1712 const XMLElement& node_,
1713 const Module& module_,
1714 const FileLocation *file_ )
1715 : node(node_), module(module_), file(file_)
1716 {
1717 }
1718
1719 PchFile::~PchFile()
1720 {
1721 delete file;
1722 }
1723
1724 void
1725 PchFile::ProcessXML()
1726 {
1727 }