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