aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Prebuild/src/Core/Parse/Preprocessor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Prebuild/src/Core/Parse/Preprocessor.cs')
-rw-r--r--Prebuild/src/Core/Parse/Preprocessor.cs1038
1 files changed, 519 insertions, 519 deletions
diff --git a/Prebuild/src/Core/Parse/Preprocessor.cs b/Prebuild/src/Core/Parse/Preprocessor.cs
index 85e92c3..c4e1e61 100644
--- a/Prebuild/src/Core/Parse/Preprocessor.cs
+++ b/Prebuild/src/Core/Parse/Preprocessor.cs
@@ -1,519 +1,519 @@
1#region BSD License 1#region BSD License
2/* 2/*
3Copyright (c) 2004-2005 Matthew Holmes (matthew@wildfiregames.com), Dan Moorehead (dan05a@gmail.com) 3Copyright (c) 2004-2005 Matthew Holmes (matthew@wildfiregames.com), Dan Moorehead (dan05a@gmail.com)
4 4
5Redistribution and use in source and binary forms, with or without modification, are permitted 5Redistribution and use in source and binary forms, with or without modification, are permitted
6provided that the following conditions are met: 6provided that the following conditions are met:
7 7
8* Redistributions of source code must retain the above copyright notice, this list of conditions 8* Redistributions of source code must retain the above copyright notice, this list of conditions
9 and the following disclaimer. 9 and the following disclaimer.
10* Redistributions in binary form must reproduce the above copyright notice, this list of conditions 10* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
11 and the following disclaimer in the documentation and/or other materials provided with the 11 and the following disclaimer in the documentation and/or other materials provided with the
12 distribution. 12 distribution.
13* The name of the author may not be used to endorse or promote products derived from this software 13* The name of the author may not be used to endorse or promote products derived from this software
14 without specific prior written permission. 14 without specific prior written permission.
15 15
16THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 16THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
17BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 21OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
22IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23*/ 23*/
24#endregion 24#endregion
25 25
26#region CVS Information 26#region CVS Information
27/* 27/*
28 * $Source$ 28 * $Source$
29 * $Author: jendave $ 29 * $Author: jendave $
30 * $Date: 2006-09-01 19:55:06 +0200 (fr, 01 sep 2006) $ 30 * $Date: 2006-09-01 19:55:06 +0200 (fr, 01 sep 2006) $
31 * $Revision: 147 $ 31 * $Revision: 147 $
32 */ 32 */
33#endregion 33#endregion
34 34
35using System; 35using System;
36using System.Collections; 36using System.Collections;
37using System.IO; 37using System.IO;
38using System.Xml; 38using System.Xml;
39 39
40namespace Prebuild.Core.Parse 40namespace Prebuild.Core.Parse
41{ 41{
42 /// <summary> 42 /// <summary>
43 /// 43 ///
44 /// </summary> 44 /// </summary>
45 public enum OperatorSymbol 45 public enum OperatorSymbol
46 { 46 {
47 /// <summary> 47 /// <summary>
48 /// 48 ///
49 /// </summary> 49 /// </summary>
50 None, 50 None,
51 /// <summary> 51 /// <summary>
52 /// 52 ///
53 /// </summary> 53 /// </summary>
54 Equal, 54 Equal,
55 /// <summary> 55 /// <summary>
56 /// 56 ///
57 /// </summary> 57 /// </summary>
58 NotEqual, 58 NotEqual,
59 /// <summary> 59 /// <summary>
60 /// 60 ///
61 /// </summary> 61 /// </summary>
62 LessThan, 62 LessThan,
63 /// <summary> 63 /// <summary>
64 /// 64 ///
65 /// </summary> 65 /// </summary>
66 GreaterThan, 66 GreaterThan,
67 /// <summary> 67 /// <summary>
68 /// 68 ///
69 /// </summary> 69 /// </summary>
70 LessThanEqual, 70 LessThanEqual,
71 /// <summary> 71 /// <summary>
72 /// 72 ///
73 /// </summary> 73 /// </summary>
74 GreaterThanEqual 74 GreaterThanEqual
75 } 75 }
76 76
77 /// <summary> 77 /// <summary>
78 /// 78 ///
79 /// </summary> 79 /// </summary>
80 public class Preprocessor 80 public class Preprocessor
81 { 81 {
82 #region Fields 82 #region Fields
83 83
84 XmlDocument m_OutDoc; 84 XmlDocument m_OutDoc;
85 Stack m_IfStack; 85 Stack m_IfStack;
86 Hashtable m_Variables; 86 Hashtable m_Variables;
87 87
88 #endregion 88 #endregion
89 89
90 #region Constructors 90 #region Constructors
91 91
92 /// <summary> 92 /// <summary>
93 /// Initializes a new instance of the <see cref="Preprocessor"/> class. 93 /// Initializes a new instance of the <see cref="Preprocessor"/> class.
94 /// </summary> 94 /// </summary>
95 public Preprocessor() 95 public Preprocessor()
96 { 96 {
97 m_OutDoc = new XmlDocument(); 97 m_OutDoc = new XmlDocument();
98 m_IfStack = new Stack(); 98 m_IfStack = new Stack();
99 m_Variables = new Hashtable(); 99 m_Variables = new Hashtable();
100 100
101 RegisterVariable("OS", GetOS()); 101 RegisterVariable("OS", GetOS());
102 RegisterVariable("RuntimeVersion", Environment.Version.Major); 102 RegisterVariable("RuntimeVersion", Environment.Version.Major);
103 RegisterVariable("RuntimeMajor", Environment.Version.Major); 103 RegisterVariable("RuntimeMajor", Environment.Version.Major);
104 RegisterVariable("RuntimeMinor", Environment.Version.Minor); 104 RegisterVariable("RuntimeMinor", Environment.Version.Minor);
105 RegisterVariable("RuntimeRevision", Environment.Version.Revision); 105 RegisterVariable("RuntimeRevision", Environment.Version.Revision);
106 } 106 }
107 107
108 #endregion 108 #endregion
109 109
110 #region Properties 110 #region Properties
111 111
112 /// <summary> 112 /// <summary>
113 /// Gets the processed doc. 113 /// Gets the processed doc.
114 /// </summary> 114 /// </summary>
115 /// <value>The processed doc.</value> 115 /// <value>The processed doc.</value>
116 public XmlDocument ProcessedDoc 116 public XmlDocument ProcessedDoc
117 { 117 {
118 get 118 get
119 { 119 {
120 return m_OutDoc; 120 return m_OutDoc;
121 } 121 }
122 } 122 }
123 123
124 #endregion 124 #endregion
125 125
126 #region Private Methods 126 #region Private Methods
127 127
128 /// <summary> 128 /// <summary>
129 /// Parts of this code were taken from NAnt and is subject to the GPL 129 /// Parts of this code were taken from NAnt and is subject to the GPL
130 /// as per NAnt's license. Thanks to the NAnt guys for this little gem. 130 /// as per NAnt's license. Thanks to the NAnt guys for this little gem.
131 /// </summary> 131 /// </summary>
132 /// <returns></returns> 132 /// <returns></returns>
133 public static string GetOS() 133 public static string GetOS()
134 { 134 {
135 PlatformID platId = Environment.OSVersion.Platform; 135 PlatformID platId = Environment.OSVersion.Platform;
136 if(platId == PlatformID.Win32NT || platId == PlatformID.Win32Windows) 136 if(platId == PlatformID.Win32NT || platId == PlatformID.Win32Windows)
137 { 137 {
138 return "Win32"; 138 return "Win32";
139 } 139 }
140 140
141 /* 141 /*
142 * .NET 1.x, under Mono, the UNIX code is 128. Under 142 * .NET 1.x, under Mono, the UNIX code is 128. Under
143 * .NET 2.x, Mono or MS, the UNIX code is 4 143 * .NET 2.x, Mono or MS, the UNIX code is 4
144 */ 144 */
145 if(Environment.Version.Major == 1) 145 if(Environment.Version.Major == 1)
146 { 146 {
147 if((int)platId == 128) 147 if((int)platId == 128)
148 { 148 {
149 return "UNIX"; 149 return "UNIX";
150 } 150 }
151 } 151 }
152 else if((int)platId == 4) 152 else if((int)platId == 4)
153 { 153 {
154 return "UNIX"; 154 return "UNIX";
155 } 155 }
156 156
157 return "Unknown"; 157 return "Unknown";
158 } 158 }
159 159
160 private static bool CompareNum(OperatorSymbol oper, int val1, int val2) 160 private static bool CompareNum(OperatorSymbol oper, int val1, int val2)
161 { 161 {
162 switch(oper) 162 switch(oper)
163 { 163 {
164 case OperatorSymbol.Equal: 164 case OperatorSymbol.Equal:
165 return (val1 == val2); 165 return (val1 == val2);
166 case OperatorSymbol.NotEqual: 166 case OperatorSymbol.NotEqual:
167 return (val1 != val2); 167 return (val1 != val2);
168 case OperatorSymbol.LessThan: 168 case OperatorSymbol.LessThan:
169 return (val1 < val2); 169 return (val1 < val2);
170 case OperatorSymbol.LessThanEqual: 170 case OperatorSymbol.LessThanEqual:
171 return (val1 <= val2); 171 return (val1 <= val2);
172 case OperatorSymbol.GreaterThan: 172 case OperatorSymbol.GreaterThan:
173 return (val1 > val2); 173 return (val1 > val2);
174 case OperatorSymbol.GreaterThanEqual: 174 case OperatorSymbol.GreaterThanEqual:
175 return (val1 >= val2); 175 return (val1 >= val2);
176 } 176 }
177 177
178 throw new WarningException("Unknown operator type"); 178 throw new WarningException("Unknown operator type");
179 } 179 }
180 180
181 private static bool CompareStr(OperatorSymbol oper, string val1, string val2) 181 private static bool CompareStr(OperatorSymbol oper, string val1, string val2)
182 { 182 {
183 switch(oper) 183 switch(oper)
184 { 184 {
185 case OperatorSymbol.Equal: 185 case OperatorSymbol.Equal:
186 return (val1 == val2); 186 return (val1 == val2);
187 case OperatorSymbol.NotEqual: 187 case OperatorSymbol.NotEqual:
188 return (val1 != val2); 188 return (val1 != val2);
189 case OperatorSymbol.LessThan: 189 case OperatorSymbol.LessThan:
190 return (val1.CompareTo(val2) < 0); 190 return (val1.CompareTo(val2) < 0);
191 case OperatorSymbol.LessThanEqual: 191 case OperatorSymbol.LessThanEqual:
192 return (val1.CompareTo(val2) <= 0); 192 return (val1.CompareTo(val2) <= 0);
193 case OperatorSymbol.GreaterThan: 193 case OperatorSymbol.GreaterThan:
194 return (val1.CompareTo(val2) > 0); 194 return (val1.CompareTo(val2) > 0);
195 case OperatorSymbol.GreaterThanEqual: 195 case OperatorSymbol.GreaterThanEqual:
196 return (val1.CompareTo(val2) >= 0); 196 return (val1.CompareTo(val2) >= 0);
197 } 197 }
198 198
199 throw new WarningException("Unknown operator type"); 199 throw new WarningException("Unknown operator type");
200 } 200 }
201 201
202 private static char NextChar(int idx, string str) 202 private static char NextChar(int idx, string str)
203 { 203 {
204 if((idx + 1) >= str.Length) 204 if((idx + 1) >= str.Length)
205 { 205 {
206 return Char.MaxValue; 206 return Char.MaxValue;
207 } 207 }
208 208
209 return str[idx + 1]; 209 return str[idx + 1];
210 } 210 }
211 // Very very simple expression parser. Can only match expressions of the form 211 // Very very simple expression parser. Can only match expressions of the form
212 // <var> <op> <value>: 212 // <var> <op> <value>:
213 // OS = Windows 213 // OS = Windows
214 // OS != Linux 214 // OS != Linux
215 // RuntimeMinor > 0 215 // RuntimeMinor > 0
216 private bool ParseExpression(string exp) 216 private bool ParseExpression(string exp)
217 { 217 {
218 if(exp == null) 218 if(exp == null)
219 { 219 {
220 throw new ArgumentException("Invalid expression, cannot be null"); 220 throw new ArgumentException("Invalid expression, cannot be null");
221 } 221 }
222 222
223 exp = exp.Trim(); 223 exp = exp.Trim();
224 if(exp.Length < 1) 224 if(exp.Length < 1)
225 { 225 {
226 throw new ArgumentException("Invalid expression, cannot be 0 length"); 226 throw new ArgumentException("Invalid expression, cannot be 0 length");
227 } 227 }
228 228
229 string id = ""; 229 string id = "";
230 string str = ""; 230 string str = "";
231 OperatorSymbol oper = OperatorSymbol.None; 231 OperatorSymbol oper = OperatorSymbol.None;
232 bool inStr = false; 232 bool inStr = false;
233 char c; 233 char c;
234 234
235 for(int i = 0; i < exp.Length; i++) 235 for(int i = 0; i < exp.Length; i++)
236 { 236 {
237 c = exp[i]; 237 c = exp[i];
238 if(Char.IsWhiteSpace(c)) 238 if(Char.IsWhiteSpace(c))
239 { 239 {
240 continue; 240 continue;
241 } 241 }
242 242
243 if(Char.IsLetterOrDigit(c) || c == '_') 243 if(Char.IsLetterOrDigit(c) || c == '_')
244 { 244 {
245 if(inStr) 245 if(inStr)
246 { 246 {
247 str += c; 247 str += c;
248 } 248 }
249 else 249 else
250 { 250 {
251 id += c; 251 id += c;
252 } 252 }
253 } 253 }
254 else if(c == '\"') 254 else if(c == '\"')
255 { 255 {
256 inStr = !inStr; 256 inStr = !inStr;
257 if(inStr) 257 if(inStr)
258 { 258 {
259 str = ""; 259 str = "";
260 } 260 }
261 } 261 }
262 else 262 else
263 { 263 {
264 if(inStr) 264 if(inStr)
265 { 265 {
266 str += c; 266 str += c;
267 } 267 }
268 else 268 else
269 { 269 {
270 switch(c) 270 switch(c)
271 { 271 {
272 case '=': 272 case '=':
273 oper = OperatorSymbol.Equal; 273 oper = OperatorSymbol.Equal;
274 break; 274 break;
275 275
276 case '!': 276 case '!':
277 if(NextChar(i, exp) == '=') 277 if(NextChar(i, exp) == '=')
278 { 278 {
279 oper = OperatorSymbol.NotEqual; 279 oper = OperatorSymbol.NotEqual;
280 } 280 }
281 281
282 break; 282 break;
283 283
284 case '<': 284 case '<':
285 if(NextChar(i, exp) == '=') 285 if(NextChar(i, exp) == '=')
286 { 286 {
287 oper = OperatorSymbol.LessThanEqual; 287 oper = OperatorSymbol.LessThanEqual;
288 } 288 }
289 else 289 else
290 { 290 {
291 oper = OperatorSymbol.LessThan; 291 oper = OperatorSymbol.LessThan;
292 } 292 }
293 293
294 break; 294 break;
295 295
296 case '>': 296 case '>':
297 if(NextChar(i, exp) == '=') 297 if(NextChar(i, exp) == '=')
298 { 298 {
299 oper = OperatorSymbol.GreaterThanEqual; 299 oper = OperatorSymbol.GreaterThanEqual;
300 } 300 }
301 else 301 else
302 { 302 {
303 oper = OperatorSymbol.GreaterThan; 303 oper = OperatorSymbol.GreaterThan;
304 } 304 }
305 305
306 break; 306 break;
307 } 307 }
308 } 308 }
309 } 309 }
310 } 310 }
311 311
312 312
313 if(inStr) 313 if(inStr)
314 { 314 {
315 throw new WarningException("Expected end of string in expression"); 315 throw new WarningException("Expected end of string in expression");
316 } 316 }
317 317
318 if(oper == OperatorSymbol.None) 318 if(oper == OperatorSymbol.None)
319 { 319 {
320 throw new WarningException("Expected operator in expression"); 320 throw new WarningException("Expected operator in expression");
321 } 321 }
322 else if(id.Length < 1) 322 else if(id.Length < 1)
323 { 323 {
324 throw new WarningException("Expected identifier in expression"); 324 throw new WarningException("Expected identifier in expression");
325 } 325 }
326 else if(str.Length < 1) 326 else if(str.Length < 1)
327 { 327 {
328 throw new WarningException("Expected value in expression"); 328 throw new WarningException("Expected value in expression");
329 } 329 }
330 330
331 bool ret = false; 331 bool ret = false;
332 try 332 try
333 { 333 {
334 object val = m_Variables[id.ToLower()]; 334 object val = m_Variables[id.ToLower()];
335 if(val == null) 335 if(val == null)
336 { 336 {
337 throw new WarningException("Unknown identifier '{0}'", id); 337 throw new WarningException("Unknown identifier '{0}'", id);
338 } 338 }
339 339
340 int numVal, numVal2; 340 int numVal, numVal2;
341 string strVal, strVal2; 341 string strVal, strVal2;
342 Type t = val.GetType(); 342 Type t = val.GetType();
343 if(t.IsAssignableFrom(typeof(int))) 343 if(t.IsAssignableFrom(typeof(int)))
344 { 344 {
345 numVal = (int)val; 345 numVal = (int)val;
346 numVal2 = Int32.Parse(str); 346 numVal2 = Int32.Parse(str);
347 ret = CompareNum(oper, numVal, numVal2); 347 ret = CompareNum(oper, numVal, numVal2);
348 } 348 }
349 else 349 else
350 { 350 {
351 strVal = val.ToString(); 351 strVal = val.ToString();
352 strVal2 = str; 352 strVal2 = str;
353 ret = CompareStr(oper, strVal, strVal2); 353 ret = CompareStr(oper, strVal, strVal2);
354 } 354 }
355 } 355 }
356 catch(ArgumentException ex) 356 catch(ArgumentException ex)
357 { 357 {
358 ex.ToString(); 358 ex.ToString();
359 throw new WarningException("Invalid value type for system variable '{0}', expected int", id); 359 throw new WarningException("Invalid value type for system variable '{0}', expected int", id);
360 } 360 }
361 361
362 return ret; 362 return ret;
363 } 363 }
364 364
365 #endregion 365 #endregion
366 366
367 #region Public Methods 367 #region Public Methods
368 368
369 /// <summary> 369 /// <summary>
370 /// 370 ///
371 /// </summary> 371 /// </summary>
372 /// <param name="name"></param> 372 /// <param name="name"></param>
373 /// <param name="variableValue"></param> 373 /// <param name="variableValue"></param>
374 public void RegisterVariable(string name, object variableValue) 374 public void RegisterVariable(string name, object variableValue)
375 { 375 {
376 if(name == null || variableValue == null) 376 if(name == null || variableValue == null)
377 { 377 {
378 return; 378 return;
379 } 379 }
380 380
381 m_Variables[name.ToLower()] = variableValue; 381 m_Variables[name.ToLower()] = variableValue;
382 } 382 }
383 383
384 /// <summary> 384 /// <summary>
385 /// Performs validation on the xml source as well as evaluates conditional and flow expresions 385 /// Performs validation on the xml source as well as evaluates conditional and flow expresions
386 /// </summary> 386 /// </summary>
387 /// <exception cref="ArgumentException">For invalid use of conditional expressions or for invalid XML syntax. If a XmlValidatingReader is passed, then will also throw exceptions for non-schema-conforming xml</exception> 387 /// <exception cref="ArgumentException">For invalid use of conditional expressions or for invalid XML syntax. If a XmlValidatingReader is passed, then will also throw exceptions for non-schema-conforming xml</exception>
388 /// <param name="reader"></param> 388 /// <param name="reader"></param>
389 /// <returns>the output xml </returns> 389 /// <returns>the output xml </returns>
390 public string Process(XmlReader reader) 390 public string Process(XmlReader reader)
391 { 391 {
392 if(reader == null) 392 if(reader == null)
393 { 393 {
394 throw new ArgumentException("Invalid XML reader to pre-process"); 394 throw new ArgumentException("Invalid XML reader to pre-process");
395 } 395 }
396 396
397 IfContext context = new IfContext(true, true, IfState.None); 397 IfContext context = new IfContext(true, true, IfState.None);
398 StringWriter xmlText = new StringWriter(); 398 StringWriter xmlText = new StringWriter();
399 XmlTextWriter writer = new XmlTextWriter(xmlText); 399 XmlTextWriter writer = new XmlTextWriter(xmlText);
400 writer.Formatting = Formatting.Indented; 400 writer.Formatting = Formatting.Indented;
401 while(reader.Read()) 401 while(reader.Read())
402 { 402 {
403 if(reader.NodeType == XmlNodeType.ProcessingInstruction) 403 if(reader.NodeType == XmlNodeType.ProcessingInstruction)
404 { 404 {
405 bool ignore = false; 405 bool ignore = false;
406 switch(reader.LocalName) 406 switch(reader.LocalName)
407 { 407 {
408 case "if": 408 case "if":
409 m_IfStack.Push(context); 409 m_IfStack.Push(context);
410 context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If); 410 context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If);
411 ignore = true; 411 ignore = true;
412 break; 412 break;
413 413
414 case "elseif": 414 case "elseif":
415 if(m_IfStack.Count == 0) 415 if(m_IfStack.Count == 0)
416 { 416 {
417 throw new WarningException("Unexpected 'elseif' outside of 'if'"); 417 throw new WarningException("Unexpected 'elseif' outside of 'if'");
418 } 418 }
419 else if(context.State != IfState.If && context.State != IfState.ElseIf) 419 else if(context.State != IfState.If && context.State != IfState.ElseIf)
420 { 420 {
421 throw new WarningException("Unexpected 'elseif' outside of 'if'"); 421 throw new WarningException("Unexpected 'elseif' outside of 'if'");
422 } 422 }
423 423
424 context.State = IfState.ElseIf; 424 context.State = IfState.ElseIf;
425 if(!context.EverKept) 425 if(!context.EverKept)
426 { 426 {
427 context.Keep = ParseExpression(reader.Value); 427 context.Keep = ParseExpression(reader.Value);
428 } 428 }
429 else 429 else
430 { 430 {
431 context.Keep = false; 431 context.Keep = false;
432 } 432 }
433 433
434 ignore = true; 434 ignore = true;
435 break; 435 break;
436 436
437 case "else": 437 case "else":
438 if(m_IfStack.Count == 0) 438 if(m_IfStack.Count == 0)
439 { 439 {
440 throw new WarningException("Unexpected 'else' outside of 'if'"); 440 throw new WarningException("Unexpected 'else' outside of 'if'");
441 } 441 }
442 else if(context.State != IfState.If && context.State != IfState.ElseIf) 442 else if(context.State != IfState.If && context.State != IfState.ElseIf)
443 { 443 {
444 throw new WarningException("Unexpected 'else' outside of 'if'"); 444 throw new WarningException("Unexpected 'else' outside of 'if'");
445 } 445 }
446 446
447 context.State = IfState.Else; 447 context.State = IfState.Else;
448 context.Keep = !context.EverKept; 448 context.Keep = !context.EverKept;
449 ignore = true; 449 ignore = true;
450 break; 450 break;
451 451
452 case "endif": 452 case "endif":
453 if(m_IfStack.Count == 0) 453 if(m_IfStack.Count == 0)
454 { 454 {
455 throw new WarningException("Unexpected 'endif' outside of 'if'"); 455 throw new WarningException("Unexpected 'endif' outside of 'if'");
456 } 456 }
457 457
458 context = (IfContext)m_IfStack.Pop(); 458 context = (IfContext)m_IfStack.Pop();
459 ignore = true; 459 ignore = true;
460 break; 460 break;
461 } 461 }
462 462
463 if(ignore) 463 if(ignore)
464 { 464 {
465 continue; 465 continue;
466 } 466 }
467 }//end pre-proc instruction 467 }//end pre-proc instruction
468 468
469 if(!context.Active || !context.Keep) 469 if(!context.Active || !context.Keep)
470 { 470 {
471 continue; 471 continue;
472 } 472 }
473 473
474 switch(reader.NodeType) 474 switch(reader.NodeType)
475 { 475 {
476 case XmlNodeType.Element: 476 case XmlNodeType.Element:
477 bool empty = reader.IsEmptyElement; 477 bool empty = reader.IsEmptyElement;
478 writer.WriteStartElement(reader.Name); 478 writer.WriteStartElement(reader.Name);
479 479
480 while (reader.MoveToNextAttribute()) 480 while (reader.MoveToNextAttribute())
481 { 481 {
482 writer.WriteAttributeString(reader.Name, reader.Value); 482 writer.WriteAttributeString(reader.Name, reader.Value);
483 } 483 }
484 484
485 if(empty) 485 if(empty)
486 { 486 {
487 writer.WriteEndElement(); 487 writer.WriteEndElement();
488 } 488 }
489 489
490 break; 490 break;
491 491
492 case XmlNodeType.EndElement: 492 case XmlNodeType.EndElement:
493 writer.WriteEndElement(); 493 writer.WriteEndElement();
494 break; 494 break;
495 495
496 case XmlNodeType.Text: 496 case XmlNodeType.Text:
497 writer.WriteString(reader.Value); 497 writer.WriteString(reader.Value);
498 break; 498 break;
499 499
500 case XmlNodeType.CDATA: 500 case XmlNodeType.CDATA:
501 writer.WriteCData(reader.Value); 501 writer.WriteCData(reader.Value);
502 break; 502 break;
503 503
504 default: 504 default:
505 break; 505 break;
506 } 506 }
507 } 507 }
508 508
509 if(m_IfStack.Count != 0) 509 if(m_IfStack.Count != 0)
510 { 510 {
511 throw new WarningException("Mismatched 'if', 'endif' pair"); 511 throw new WarningException("Mismatched 'if', 'endif' pair");
512 } 512 }
513 513
514 return xmlText.ToString(); 514 return xmlText.ToString();
515 } 515 }
516 516
517 #endregion 517 #endregion
518 } 518 }
519} 519}