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