added validation for <directory>'s name attribute
[reactos.git] / reactos / tools / rbuild / module.cpp
1 #include "pch.h"
2 #include <assert.h>
3
4 #include "rbuild.h"
5
6 using std::string;
7 using std::vector;
8
9 string
10 FixSeparator ( const string& s )
11 {
12 string s2(s);
13 char* p = strchr ( &s2[0], CBAD_SEP );
14 while ( p )
15 {
16 *p++ = CSEP;
17 p = strchr ( p, CBAD_SEP );
18 }
19 return s2;
20 }
21
22 string
23 GetSubPath (
24 const string& location,
25 const string& path,
26 const string& att_value )
27 {
28 if ( !att_value.size() )
29 throw InvalidBuildFileException (
30 location,
31 "<directory> tag has empty 'name' attribute" );
32 if ( strpbrk ( att_value.c_str (), "/\\?*:<>|" ) )
33 throw InvalidBuildFileException (
34 location,
35 "<directory> tag has invalid characters in 'name' attribute" );
36 if ( !path.size() )
37 return att_value;
38 return FixSeparator(path + CSEP + att_value);
39 }
40
41 string
42 GetExtension ( const string& filename )
43 {
44 size_t index = filename.find_last_of ( '/' );
45 if (index == string::npos) index = 0;
46 string tmp = filename.substr( index, filename.size() - index );
47 size_t ext_index = tmp.find_last_of( '.' );
48 if (ext_index != string::npos)
49 return filename.substr ( index + ext_index, filename.size() );
50 return "";
51 }
52
53 string
54 GetDirectory ( const string& filename )
55 {
56 size_t index = filename.find_last_of ( CSEP );
57 if ( index == string::npos )
58 return filename;
59 else
60 return filename.substr ( 0, index );
61 }
62
63 string
64 NormalizeFilename ( const string& filename )
65 {
66 Path path;
67 string normalizedPath = path.Fixup ( filename, true );
68 string relativeNormalizedPath = path.RelativeFromWorkingDirectory ( normalizedPath );
69 return FixSeparator ( relativeNormalizedPath );
70 }
71
72 IfableData::~IfableData()
73 {
74 size_t i;
75 for ( i = 0; i < files.size(); i++ )
76 delete files[i];
77 for ( i = 0; i < includes.size(); i++ )
78 delete includes[i];
79 for ( i = 0; i < defines.size(); i++ )
80 delete defines[i];
81 for ( i = 0; i < libraries.size(); i++ )
82 delete libraries[i];
83 for ( i = 0; i < properties.size(); i++ )
84 delete properties[i];
85 for ( i = 0; i < ifs.size(); i++ )
86 delete ifs[i];
87 }
88
89 void IfableData::ProcessXML ()
90 {
91 size_t i;
92 for ( i = 0; i < files.size (); i++ )
93 files[i]->ProcessXML ();
94 for ( i = 0; i < includes.size (); i++ )
95 includes[i]->ProcessXML ();
96 for ( i = 0; i < defines.size (); i++ )
97 defines[i]->ProcessXML ();
98 for ( i = 0; i < libraries.size (); i++ )
99 libraries[i]->ProcessXML ();
100 for ( i = 0; i < properties.size(); i++ )
101 properties[i]->ProcessXML ();
102 for ( i = 0; i < ifs.size (); i++ )
103 ifs[i]->ProcessXML ();
104 }
105
106 Module::Module ( const Project& project,
107 const XMLElement& moduleNode,
108 const string& modulePath )
109 : project (project),
110 node (moduleNode),
111 importLibrary (NULL),
112 bootstrap (NULL),
113 pch (NULL),
114 cplusplus (false),
115 host (HostDefault)
116 {
117 if ( node.name != "module" )
118 throw Exception ( "internal tool error: Module created with non-<module> node" );
119
120 path = FixSeparator ( modulePath );
121
122 const XMLAttribute* att = moduleNode.GetAttribute ( "name", true );
123 assert(att);
124 name = att->value;
125
126 att = moduleNode.GetAttribute ( "type", true );
127 assert(att);
128 type = GetModuleType ( node.location, *att );
129
130 att = moduleNode.GetAttribute ( "extension", false );
131 if ( att != NULL )
132 extension = att->value;
133 else
134 extension = GetDefaultModuleExtension ();
135
136 att = moduleNode.GetAttribute ( "entrypoint", false );
137 if ( att != NULL )
138 entrypoint = att->value;
139 else
140 entrypoint = GetDefaultModuleEntrypoint ();
141
142 att = moduleNode.GetAttribute ( "baseaddress", false );
143 if ( att != NULL )
144 baseaddress = att->value;
145 else
146 baseaddress = GetDefaultModuleBaseaddress ();
147
148 att = moduleNode.GetAttribute ( "mangledsymbols", false );
149 if ( att != NULL )
150 {
151 const char* p = att->value.c_str();
152 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
153 mangledSymbols = true;
154 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
155 mangledSymbols = false;
156 else
157 {
158 throw InvalidAttributeValueException (
159 moduleNode.location,
160 "mangledsymbols",
161 att->value );
162 }
163 }
164 else
165 mangledSymbols = false;
166
167 att = moduleNode.GetAttribute ( "host", false );
168 if ( att != NULL )
169 {
170 const char* p = att->value.c_str();
171 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
172 host = HostTrue;
173 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
174 host = HostFalse;
175 else
176 {
177 throw InvalidAttributeValueException (
178 moduleNode.location,
179 "host",
180 att->value );
181 }
182 }
183
184 att = moduleNode.GetAttribute ( "prefix", false );
185 if ( att != NULL )
186 prefix = att->value;
187 }
188
189 Module::~Module ()
190 {
191 size_t i;
192 for ( i = 0; i < invocations.size(); i++ )
193 delete invocations[i];
194 for ( i = 0; i < dependencies.size(); i++ )
195 delete dependencies[i];
196 for ( i = 0; i < compilerFlags.size(); i++ )
197 delete compilerFlags[i];
198 for ( i = 0; i < linkerFlags.size(); i++ )
199 delete linkerFlags[i];
200 if ( pch )
201 delete pch;
202 }
203
204 void
205 Module::ProcessXML()
206 {
207 size_t i;
208 for ( i = 0; i < node.subElements.size(); i++ )
209 ProcessXMLSubElement ( *node.subElements[i], path );
210 for ( i = 0; i < invocations.size(); i++ )
211 invocations[i]->ProcessXML ();
212 for ( i = 0; i < dependencies.size(); i++ )
213 dependencies[i]->ProcessXML ();
214 for ( i = 0; i < compilerFlags.size(); i++ )
215 compilerFlags[i]->ProcessXML();
216 for ( i = 0; i < linkerFlags.size(); i++ )
217 linkerFlags[i]->ProcessXML();
218 non_if_data.ProcessXML();
219 if ( pch )
220 pch->ProcessXML();
221 }
222
223 void
224 Module::ProcessXMLSubElement ( const XMLElement& e,
225 const string& path,
226 If* pIf /*= NULL*/ )
227 {
228 bool subs_invalid = false;
229 string subpath ( path );
230 if ( e.name == "file" && e.value.size () > 0 )
231 {
232 bool first = false;
233 const XMLAttribute* att = e.GetAttribute ( "first", false );
234 if ( att )
235 {
236 if ( !stricmp ( att->value.c_str(), "true" ) )
237 first = true;
238 else if ( stricmp ( att->value.c_str(), "false" ) )
239 throw InvalidBuildFileException (
240 e.location,
241 "attribute 'first' of <file> element can only be 'true' or 'false'" );
242 }
243 if ( !cplusplus )
244 {
245 // check for c++ file
246 string ext = GetExtension ( e.value );
247 if ( !stricmp ( ext.c_str(), ".cpp" ) )
248 cplusplus = true;
249 else if ( !stricmp ( ext.c_str(), ".cc" ) )
250 cplusplus = true;
251 else if ( !stricmp ( ext.c_str(), ".cxx" ) )
252 cplusplus = true;
253 }
254 File* pFile = new File ( FixSeparator ( path + CSEP + e.value ), first );
255 if ( pIf )
256 pIf->data.files.push_back ( pFile );
257 else
258 non_if_data.files.push_back ( pFile );
259 subs_invalid = true;
260 }
261 else if ( e.name == "library" && e.value.size () )
262 {
263 Library* pLibrary = new Library ( e, *this, e.value );
264 if ( pIf )
265 pIf->data.libraries.push_back ( pLibrary );
266 else
267 non_if_data.libraries.push_back ( pLibrary );
268 subs_invalid = true;
269 }
270 else if ( e.name == "directory" )
271 {
272 const XMLAttribute* att = e.GetAttribute ( "name", true );
273 assert(att);
274 subpath = GetSubPath ( e.location, path, att->value );
275 }
276 else if ( e.name == "include" )
277 {
278 Include* include = new Include ( project, this, e );
279 if ( pIf )
280 pIf->data.includes.push_back ( include );
281 else
282 non_if_data.includes.push_back ( include );
283 subs_invalid = true;
284 }
285 else if ( e.name == "define" )
286 {
287 Define* pDefine = new Define ( project, this, e );
288 if ( pIf )
289 pIf->data.defines.push_back ( pDefine );
290 else
291 non_if_data.defines.push_back ( pDefine );
292 subs_invalid = true;
293 }
294 else if ( e.name == "invoke" )
295 {
296 if ( pIf )
297 throw InvalidBuildFileException (
298 e.location,
299 "<invoke> is not a valid sub-element of <if>" );
300 invocations.push_back ( new Invoke ( e, *this ) );
301 subs_invalid = false;
302 }
303 else if ( e.name == "dependency" )
304 {
305 if ( pIf )
306 throw InvalidBuildFileException (
307 e.location,
308 "<dependency> is not a valid sub-element of <if>" );
309 dependencies.push_back ( new Dependency ( e, *this ) );
310 subs_invalid = true;
311 }
312 else if ( e.name == "importlibrary" )
313 {
314 if ( pIf )
315 throw InvalidBuildFileException (
316 e.location,
317 "<importlibrary> is not a valid sub-element of <if>" );
318 if ( importLibrary )
319 throw InvalidBuildFileException (
320 e.location,
321 "Only one <importlibrary> is valid per module" );
322 importLibrary = new ImportLibrary ( e, *this );
323 subs_invalid = true;
324 }
325 else if ( e.name == "if" )
326 {
327 If* pOldIf = pIf;
328 pIf = new If ( e, project, this );
329 if ( pOldIf )
330 pOldIf->data.ifs.push_back ( pIf );
331 else
332 non_if_data.ifs.push_back ( pIf );
333 subs_invalid = false;
334 }
335 else if ( e.name == "compilerflag" )
336 {
337 compilerFlags.push_back ( new CompilerFlag ( project, this, e ) );
338 subs_invalid = true;
339 }
340 else if ( e.name == "linkerflag" )
341 {
342 linkerFlags.push_back ( new LinkerFlag ( project, this, e ) );
343 subs_invalid = true;
344 }
345 else if ( e.name == "property" )
346 {
347 throw InvalidBuildFileException (
348 e.location,
349 "<property> is not a valid sub-element of <module>" );
350 }
351 else if ( e.name == "bootstrap" )
352 {
353 bootstrap = new Bootstrap ( project, this, e );
354 subs_invalid = true;
355 }
356 else if ( e.name == "pch" )
357 {
358 if ( pIf )
359 throw InvalidBuildFileException (
360 e.location,
361 "<pch> is not a valid sub-element of <if>" );
362 if ( pch )
363 throw InvalidBuildFileException (
364 e.location,
365 "Only one <pch> is valid per module" );
366 pch = new PchFile (
367 e, *this, FixSeparator ( path + CSEP + e.value ) );
368 subs_invalid = true;
369 }
370 if ( subs_invalid && e.subElements.size() > 0 )
371 throw InvalidBuildFileException (
372 e.location,
373 "<%s> cannot have sub-elements",
374 e.name.c_str() );
375 for ( size_t i = 0; i < e.subElements.size (); i++ )
376 ProcessXMLSubElement ( *e.subElements[i], subpath, pIf );
377 }
378
379 ModuleType
380 Module::GetModuleType ( const string& location, const XMLAttribute& attribute )
381 {
382 if ( attribute.value == "buildtool" )
383 return BuildTool;
384 if ( attribute.value == "staticlibrary" )
385 return StaticLibrary;
386 if ( attribute.value == "objectlibrary" )
387 return ObjectLibrary;
388 if ( attribute.value == "kernel" )
389 return Kernel;
390 if ( attribute.value == "kernelmodedll" )
391 return KernelModeDLL;
392 if ( attribute.value == "kernelmodedriver" )
393 return KernelModeDriver;
394 if ( attribute.value == "nativedll" )
395 return NativeDLL;
396 if ( attribute.value == "nativecui" )
397 return NativeCUI;
398 if ( attribute.value == "win32dll" )
399 return Win32DLL;
400 if ( attribute.value == "win32cui" )
401 return Win32CUI;
402 if ( attribute.value == "win32gui" )
403 return Win32GUI;
404 if ( attribute.value == "bootloader" )
405 return BootLoader;
406 if ( attribute.value == "bootsector" )
407 return BootSector;
408 if ( attribute.value == "iso" )
409 return Iso;
410 throw InvalidAttributeValueException ( location,
411 attribute.name,
412 attribute.value );
413 }
414
415 string
416 Module::GetDefaultModuleExtension () const
417 {
418 switch (type)
419 {
420 case BuildTool:
421 return EXEPOSTFIX;
422 case StaticLibrary:
423 return ".a";
424 case ObjectLibrary:
425 return ".o";
426 case Kernel:
427 case NativeCUI:
428 case Win32CUI:
429 case Win32GUI:
430 return ".exe";
431 case KernelModeDLL:
432 case NativeDLL:
433 case Win32DLL:
434 return ".dll";
435 case KernelModeDriver:
436 case BootLoader:
437 return ".sys";
438 case BootSector:
439 return ".o";
440 case Iso:
441 return ".iso";
442 }
443 throw InvalidOperationException ( __FILE__,
444 __LINE__ );
445 }
446
447 string
448 Module::GetDefaultModuleEntrypoint () const
449 {
450 switch (type)
451 {
452 case Kernel:
453 return "_NtProcessStartup";
454 case KernelModeDLL:
455 return "_DriverEntry@8";
456 case NativeDLL:
457 return "_DllMainCRTStartup@12";
458 case NativeCUI:
459 return "_NtProcessStartup@4";
460 case Win32DLL:
461 return "_DllMain@12";
462 case Win32CUI:
463 return "_mainCRTStartup";
464 case Win32GUI:
465 return "_WinMainCRTStartup";
466 case KernelModeDriver:
467 return "_DriverEntry@8";
468 case BuildTool:
469 case StaticLibrary:
470 case ObjectLibrary:
471 case BootLoader:
472 case BootSector:
473 case Iso:
474 return "";
475 }
476 throw InvalidOperationException ( __FILE__,
477 __LINE__ );
478 }
479
480 string
481 Module::GetDefaultModuleBaseaddress () const
482 {
483 switch (type)
484 {
485 case Kernel:
486 return "0xc0000000";
487 case KernelModeDLL:
488 return "0x10000";
489 case NativeDLL:
490 return "0x10000";
491 case NativeCUI:
492 return "0x10000";
493 case Win32DLL:
494 return "0x10000";
495 case Win32CUI:
496 return "0x00400000";
497 case Win32GUI:
498 return "0x00400000";
499 case KernelModeDriver:
500 return "0x10000";
501 case BuildTool:
502 case StaticLibrary:
503 case ObjectLibrary:
504 case BootLoader:
505 case BootSector:
506 case Iso:
507 return "";
508 }
509 throw InvalidOperationException ( __FILE__,
510 __LINE__ );
511 }
512
513 bool
514 Module::HasImportLibrary () const
515 {
516 return importLibrary != NULL;
517 }
518
519 string
520 Module::GetTargetName () const
521 {
522 return name + extension;
523 }
524
525 string
526 Module::GetDependencyPath () const
527 {
528 if ( HasImportLibrary () )
529 {
530 return ssprintf ( "dk%cnkm%clib%clib%s.a",
531 CSEP,
532 CSEP,
533 CSEP,
534 name.c_str () );
535 }
536 else
537 return GetPath();
538 }
539
540 string
541 Module::GetBasePath () const
542 {
543 return path;
544 }
545
546 string
547 Module::GetPath () const
548 {
549 return path + CSEP + GetTargetName ();
550 }
551
552 string
553 Module::GetPathWithPrefix ( const string& prefix ) const
554 {
555 return path + CSEP + prefix + GetTargetName ();
556 }
557
558 string
559 Module::GetTargets () const
560 {
561 if ( invocations.size () > 0 )
562 {
563 string targets ( "" );
564 for ( size_t i = 0; i < invocations.size (); i++ )
565 {
566 Invoke& invoke = *invocations[i];
567 if ( targets.length () > 0 )
568 targets += " ";
569 targets += invoke.GetTargets ();
570 }
571 return targets;
572 }
573 else
574 return GetPath ();
575 }
576
577 string
578 Module::GetInvocationTarget ( const int index ) const
579 {
580 return ssprintf ( "%s_invoke_%d",
581 name.c_str (),
582 index );
583 }
584
585 bool
586 Module::HasFileWithExtension (
587 const IfableData& data,
588 const std::string& extension ) const
589 {
590 size_t i;
591 for ( i = 0; i < data.files.size (); i++ )
592 {
593 File& file = *data.files[i];
594 string file_ext = GetExtension ( file.name );
595 if ( !stricmp ( file_ext.c_str (), extension.c_str () ) )
596 return true;
597 }
598 for ( i = 0; i < data.ifs.size (); i++ )
599 {
600 if ( HasFileWithExtension ( data.ifs[i]->data, extension ) )
601 return true;
602 }
603 return false;
604 }
605
606 void
607 Module::InvokeModule () const
608 {
609 for ( size_t i = 0; i < invocations.size (); i++ )
610 {
611 Invoke& invoke = *invocations[i];
612 string command = invoke.invokeModule->GetPath () + " " + invoke.GetParameters ();
613 printf ( "Executing '%s'\n\n", command.c_str () );
614 int exitcode = system ( command.c_str () );
615 if ( exitcode != 0 )
616 throw InvocationFailedException ( command,
617 exitcode );
618 }
619 }
620
621
622 File::File ( const string& _name, bool _first )
623 : name(_name), first(_first)
624 {
625 }
626
627 void
628 File::ProcessXML()
629 {
630 }
631
632
633 Library::Library ( const XMLElement& _node,
634 const Module& _module,
635 const string& _name )
636 : node(_node),
637 module(_module),
638 name(_name),
639 imported_module(_module.project.LocateModule(_name))
640 {
641 if ( module.name == name )
642 throw InvalidBuildFileException (
643 node.location,
644 "module '%s' cannot link against itself",
645 name.c_str() );
646 if ( !imported_module )
647 throw InvalidBuildFileException (
648 node.location,
649 "module '%s' trying to import non-existant module '%s'",
650 module.name.c_str(),
651 name.c_str() );
652 }
653
654 void
655 Library::ProcessXML()
656 {
657 if ( !module.project.LocateModule ( name ) )
658 throw InvalidBuildFileException (
659 node.location,
660 "module '%s' is trying to link against non-existant module '%s'",
661 module.name.c_str(),
662 name.c_str() );
663 }
664
665
666 Invoke::Invoke ( const XMLElement& _node,
667 const Module& _module )
668 : node (_node),
669 module (_module)
670 {
671 }
672
673 void
674 Invoke::ProcessXML()
675 {
676 const XMLAttribute* att = node.GetAttribute ( "module", false );
677 if (att == NULL)
678 invokeModule = &module;
679 else
680 {
681 invokeModule = module.project.LocateModule ( att->value );
682 if ( invokeModule == NULL )
683 throw InvalidBuildFileException (
684 node.location,
685 "module '%s' is trying to invoke non-existant module '%s'",
686 module.name.c_str(),
687 att->value.c_str() );
688 }
689
690 for ( size_t i = 0; i < node.subElements.size (); i++ )
691 ProcessXMLSubElement ( *node.subElements[i] );
692 }
693
694 void
695 Invoke::ProcessXMLSubElement ( const XMLElement& e )
696 {
697 bool subs_invalid = false;
698 if ( e.name == "input" )
699 {
700 for ( size_t i = 0; i < e.subElements.size (); i++ )
701 ProcessXMLSubElementInput ( *e.subElements[i] );
702 }
703 else if ( e.name == "output" )
704 {
705 for ( size_t i = 0; i < e.subElements.size (); i++ )
706 ProcessXMLSubElementOutput ( *e.subElements[i] );
707 }
708 if ( subs_invalid && e.subElements.size() > 0 )
709 throw InvalidBuildFileException ( e.location,
710 "<%s> cannot have sub-elements",
711 e.name.c_str() );
712 }
713
714 void
715 Invoke::ProcessXMLSubElementInput ( const XMLElement& e )
716 {
717 bool subs_invalid = false;
718 if ( e.name == "inputfile" && e.value.size () > 0 )
719 {
720 input.push_back ( new InvokeFile ( e, FixSeparator ( module.path + CSEP + e.value ) ) );
721 subs_invalid = true;
722 }
723 if ( subs_invalid && e.subElements.size() > 0 )
724 throw InvalidBuildFileException ( e.location,
725 "<%s> cannot have sub-elements",
726 e.name.c_str() );
727 }
728
729 void
730 Invoke::ProcessXMLSubElementOutput ( const XMLElement& e )
731 {
732 bool subs_invalid = false;
733 if ( e.name == "outputfile" && e.value.size () > 0 )
734 {
735 output.push_back ( new InvokeFile ( e, FixSeparator ( module.path + CSEP + e.value ) ) );
736 subs_invalid = true;
737 }
738 if ( subs_invalid && e.subElements.size() > 0 )
739 throw InvalidBuildFileException ( e.location,
740 "<%s> cannot have sub-elements",
741 e.name.c_str() );
742 }
743
744 string
745 Invoke::GetTargets () const
746 {
747 string targets ( "" );
748 for ( size_t i = 0; i < output.size (); i++ )
749 {
750 InvokeFile& file = *output[i];
751 if ( targets.length () > 0 )
752 targets += " ";
753 targets += NormalizeFilename ( file.name );
754 }
755 return targets;
756 }
757
758 string
759 Invoke::GetParameters () const
760 {
761 string parameters ( "" );
762 size_t i;
763 for ( i = 0; i < output.size (); i++ )
764 {
765 if ( parameters.length () > 0)
766 parameters += " ";
767 InvokeFile& invokeFile = *output[i];
768 if ( invokeFile.switches.length () > 0 )
769 {
770 parameters += invokeFile.switches;
771 parameters += " ";
772 }
773 parameters += invokeFile.name;
774 }
775
776 for ( i = 0; i < input.size (); i++ )
777 {
778 if ( parameters.length () > 0 )
779 parameters += " ";
780 InvokeFile& invokeFile = *input[i];
781 if ( invokeFile.switches.length () > 0 )
782 {
783 parameters += invokeFile.switches;
784 parameters += " ";
785 }
786 parameters += invokeFile.name ;
787 }
788
789 return parameters;
790 }
791
792
793 InvokeFile::InvokeFile ( const XMLElement& _node,
794 const string& _name )
795 : node (_node),
796 name (_name)
797 {
798 const XMLAttribute* att = _node.GetAttribute ( "switches", false );
799 if (att != NULL)
800 switches = att->value;
801 else
802 switches = "";
803 }
804
805 void
806 InvokeFile::ProcessXML()
807 {
808 }
809
810
811 Dependency::Dependency ( const XMLElement& _node,
812 const Module& _module )
813 : node (_node),
814 module (_module),
815 dependencyModule (NULL)
816 {
817 }
818
819 void
820 Dependency::ProcessXML()
821 {
822 dependencyModule = module.project.LocateModule ( node.value );
823 if ( dependencyModule == NULL )
824 throw InvalidBuildFileException ( node.location,
825 "module '%s' depend on non-existant module '%s'",
826 module.name.c_str(),
827 node.value.c_str() );
828 }
829
830
831 ImportLibrary::ImportLibrary ( const XMLElement& _node,
832 const Module& _module )
833 : node (_node),
834 module (_module)
835 {
836 const XMLAttribute* att = _node.GetAttribute ( "basename", false );
837 if (att != NULL)
838 basename = att->value;
839 else
840 basename = module.name;
841
842 att = _node.GetAttribute ( "definition", true );
843 assert (att);
844 definition = FixSeparator(att->value);
845 }
846
847
848 If::If ( const XMLElement& node_,
849 const Project& project_,
850 const Module* module_ )
851 : node(node_), project(project_), module(module_)
852 {
853 const XMLAttribute* att;
854
855 att = node.GetAttribute ( "property", true );
856 assert(att);
857 property = att->value;
858
859 att = node.GetAttribute ( "value", true );
860 assert(att);
861 value = att->value;
862 }
863
864 If::~If ()
865 {
866 }
867
868 void
869 If::ProcessXML()
870 {
871 }
872
873
874 Property::Property ( const XMLElement& node_,
875 const Project& project_,
876 const Module* module_ )
877 : node(node_), project(project_), module(module_)
878 {
879 const XMLAttribute* att;
880
881 att = node.GetAttribute ( "name", true );
882 assert(att);
883 name = att->value;
884
885 att = node.GetAttribute ( "value", true );
886 assert(att);
887 value = att->value;
888 }
889
890 void
891 Property::ProcessXML()
892 {
893 }
894
895
896 PchFile::PchFile (
897 const XMLElement& node_,
898 const Module& module_,
899 const string& header_ )
900 : node(node_), module(module_), header(header_)
901 {
902 }
903
904 void
905 PchFile::ProcessXML()
906 {
907 }