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