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