diff options
author | BlueWall | 2010-08-31 17:02:36 -0400 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2010-09-04 02:12:21 +0100 |
commit | 1e44ec84bd90ec9078027d1d9d78e83c7d305f2a (patch) | |
tree | e34db5ced4bc7bf59b98ff9fb72271dda0f25a33 /Prebuild/src/Core/Parse/Preprocessor.cs | |
parent | Merge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff) | |
download | opensim-SC-1e44ec84bd90ec9078027d1d9d78e83c7d305f2a.zip opensim-SC-1e44ec84bd90ec9078027d1d9d78e83c7d305f2a.tar.gz opensim-SC-1e44ec84bd90ec9078027d1d9d78e83c7d305f2a.tar.bz2 opensim-SC-1e44ec84bd90ec9078027d1d9d78e83c7d305f2a.tar.xz |
Build system upgrade:
Upgrading Prebuild.exe to correctly construct build solutions
for crossplatform tools such as xbuild, monodevelop and nant.
NOTE: Module prebuild files will need modification to work,
as the prebuild must correctly define the reference path for
all assemblies shipped in the OpenSimulator ./bin directory.
These include assemblies such as XMLRPC.dll, OpenMetaverse.dll,
Nini.dll, etc. . The entries should follow the form:
<Reference name="Nini" path="../../../bin/"/>
See the distributed prebuild.xml for further examples.
Crossplatform tools: xbuild and monodevelop use the
vs2008 OpenSim.sln and the .csproj files in each namespace.
Changes to the Prebuild.exe are against svn 322 and are included
in a patch attached to the mantis. And the dnpb source are
available@ svn co https://dnpb.svn.sourceforge.net/svnroot/dnpb dnpb
The patches are pending application by the dnpb team. After which,
the un-modified upstream Prebuild.exe will work as expected.
Diffstat (limited to 'Prebuild/src/Core/Parse/Preprocessor.cs')
-rw-r--r-- | Prebuild/src/Core/Parse/Preprocessor.cs | 663 |
1 files changed, 0 insertions, 663 deletions
diff --git a/Prebuild/src/Core/Parse/Preprocessor.cs b/Prebuild/src/Core/Parse/Preprocessor.cs deleted file mode 100644 index b2306e4..0000000 --- a/Prebuild/src/Core/Parse/Preprocessor.cs +++ /dev/null | |||
@@ -1,663 +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 | using System; | ||
27 | using System.Collections; | ||
28 | using System.IO; | ||
29 | using System.Text.RegularExpressions; | ||
30 | using System.Xml; | ||
31 | |||
32 | namespace Prebuild.Core.Parse | ||
33 | { | ||
34 | /// <summary> | ||
35 | /// | ||
36 | /// </summary> | ||
37 | public enum OperatorSymbol | ||
38 | { | ||
39 | /// <summary> | ||
40 | /// | ||
41 | /// </summary> | ||
42 | None, | ||
43 | /// <summary> | ||
44 | /// | ||
45 | /// </summary> | ||
46 | Equal, | ||
47 | /// <summary> | ||
48 | /// | ||
49 | /// </summary> | ||
50 | NotEqual, | ||
51 | /// <summary> | ||
52 | /// | ||
53 | /// </summary> | ||
54 | LessThan, | ||
55 | /// <summary> | ||
56 | /// | ||
57 | /// </summary> | ||
58 | GreaterThan, | ||
59 | /// <summary> | ||
60 | /// | ||
61 | /// </summary> | ||
62 | LessThanEqual, | ||
63 | /// <summary> | ||
64 | /// | ||
65 | /// </summary> | ||
66 | GreaterThanEqual | ||
67 | } | ||
68 | |||
69 | /// <summary> | ||
70 | /// | ||
71 | /// </summary> | ||
72 | public class Preprocessor | ||
73 | { | ||
74 | #region Constants | ||
75 | |||
76 | /// <summary> | ||
77 | /// Includes the regex to look for file tags in the <?include | ||
78 | /// ?> processing instruction. | ||
79 | /// </summary> | ||
80 | private static readonly Regex includeFileRegex = new Regex("file=\"(.+?)\""); | ||
81 | |||
82 | #endregion | ||
83 | |||
84 | #region Fields | ||
85 | |||
86 | XmlDocument m_OutDoc; | ||
87 | Stack m_IfStack; | ||
88 | Hashtable m_Variables; | ||
89 | |||
90 | #endregion | ||
91 | |||
92 | #region Constructors | ||
93 | |||
94 | /// <summary> | ||
95 | /// Initializes a new instance of the <see cref="Preprocessor"/> class. | ||
96 | /// </summary> | ||
97 | public Preprocessor() | ||
98 | { | ||
99 | m_OutDoc = new XmlDocument(); | ||
100 | m_IfStack = new Stack(); | ||
101 | m_Variables = new Hashtable(); | ||
102 | |||
103 | RegisterVariable("OS", GetOS()); | ||
104 | RegisterVariable("RuntimeVersion", Environment.Version.Major); | ||
105 | RegisterVariable("RuntimeMajor", Environment.Version.Major); | ||
106 | RegisterVariable("RuntimeMinor", Environment.Version.Minor); | ||
107 | RegisterVariable("RuntimeRevision", Environment.Version.Revision); | ||
108 | } | ||
109 | |||
110 | #endregion | ||
111 | |||
112 | #region Properties | ||
113 | |||
114 | /// <summary> | ||
115 | /// Gets the processed doc. | ||
116 | /// </summary> | ||
117 | /// <value>The processed doc.</value> | ||
118 | public XmlDocument ProcessedDoc | ||
119 | { | ||
120 | get | ||
121 | { | ||
122 | return m_OutDoc; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | #endregion | ||
127 | |||
128 | #region Private Methods | ||
129 | |||
130 | /// <summary> | ||
131 | /// Parts of this code were taken from NAnt and is subject to the GPL | ||
132 | /// as per NAnt's license. Thanks to the NAnt guys for this little gem. | ||
133 | /// </summary> | ||
134 | /// <returns></returns> | ||
135 | public static string GetOS() | ||
136 | { | ||
137 | PlatformID platId = Environment.OSVersion.Platform; | ||
138 | if(platId == PlatformID.Win32NT || platId == PlatformID.Win32Windows) | ||
139 | { | ||
140 | return "Win32"; | ||
141 | } | ||
142 | |||
143 | if (File.Exists("/System/Library/Frameworks/Cocoa.framework/Cocoa")) | ||
144 | { | ||
145 | return "MACOSX"; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * .NET 1.x, under Mono, the UNIX code is 128. Under | ||
150 | * .NET 2.x, Mono or MS, the UNIX code is 4 | ||
151 | */ | ||
152 | if(Environment.Version.Major == 1) | ||
153 | { | ||
154 | if((int)platId == 128) | ||
155 | { | ||
156 | return "UNIX"; | ||
157 | } | ||
158 | } | ||
159 | else if((int)platId == 4) | ||
160 | { | ||
161 | return "UNIX"; | ||
162 | } | ||
163 | |||
164 | return "Unknown"; | ||
165 | } | ||
166 | |||
167 | private static bool CompareNum(OperatorSymbol oper, int val1, int val2) | ||
168 | { | ||
169 | switch(oper) | ||
170 | { | ||
171 | case OperatorSymbol.Equal: | ||
172 | return (val1 == val2); | ||
173 | case OperatorSymbol.NotEqual: | ||
174 | return (val1 != val2); | ||
175 | case OperatorSymbol.LessThan: | ||
176 | return (val1 < val2); | ||
177 | case OperatorSymbol.LessThanEqual: | ||
178 | return (val1 <= val2); | ||
179 | case OperatorSymbol.GreaterThan: | ||
180 | return (val1 > val2); | ||
181 | case OperatorSymbol.GreaterThanEqual: | ||
182 | return (val1 >= val2); | ||
183 | } | ||
184 | |||
185 | throw new WarningException("Unknown operator type"); | ||
186 | } | ||
187 | |||
188 | private static bool CompareStr(OperatorSymbol oper, string val1, string val2) | ||
189 | { | ||
190 | switch(oper) | ||
191 | { | ||
192 | case OperatorSymbol.Equal: | ||
193 | return (val1 == val2); | ||
194 | case OperatorSymbol.NotEqual: | ||
195 | return (val1 != val2); | ||
196 | case OperatorSymbol.LessThan: | ||
197 | return (val1.CompareTo(val2) < 0); | ||
198 | case OperatorSymbol.LessThanEqual: | ||
199 | return (val1.CompareTo(val2) <= 0); | ||
200 | case OperatorSymbol.GreaterThan: | ||
201 | return (val1.CompareTo(val2) > 0); | ||
202 | case OperatorSymbol.GreaterThanEqual: | ||
203 | return (val1.CompareTo(val2) >= 0); | ||
204 | } | ||
205 | |||
206 | throw new WarningException("Unknown operator type"); | ||
207 | } | ||
208 | |||
209 | private static char NextChar(int idx, string str) | ||
210 | { | ||
211 | if((idx + 1) >= str.Length) | ||
212 | { | ||
213 | return Char.MaxValue; | ||
214 | } | ||
215 | |||
216 | return str[idx + 1]; | ||
217 | } | ||
218 | // Very very simple expression parser. Can only match expressions of the form | ||
219 | // <var> <op> <value>: | ||
220 | // OS = Windows | ||
221 | // OS != Linux | ||
222 | // RuntimeMinor > 0 | ||
223 | private bool ParseExpression(string exp) | ||
224 | { | ||
225 | if(exp == null) | ||
226 | { | ||
227 | throw new ArgumentException("Invalid expression, cannot be null"); | ||
228 | } | ||
229 | |||
230 | exp = exp.Trim(); | ||
231 | if(exp.Length < 1) | ||
232 | { | ||
233 | throw new ArgumentException("Invalid expression, cannot be 0 length"); | ||
234 | } | ||
235 | |||
236 | string id = ""; | ||
237 | string str = ""; | ||
238 | OperatorSymbol oper = OperatorSymbol.None; | ||
239 | bool inStr = false; | ||
240 | char c; | ||
241 | |||
242 | for(int i = 0; i < exp.Length; i++) | ||
243 | { | ||
244 | c = exp[i]; | ||
245 | if(Char.IsWhiteSpace(c)) | ||
246 | { | ||
247 | continue; | ||
248 | } | ||
249 | |||
250 | if(Char.IsLetterOrDigit(c) || c == '_') | ||
251 | { | ||
252 | if(inStr) | ||
253 | { | ||
254 | str += c; | ||
255 | } | ||
256 | else | ||
257 | { | ||
258 | id += c; | ||
259 | } | ||
260 | } | ||
261 | else if(c == '\"') | ||
262 | { | ||
263 | inStr = !inStr; | ||
264 | if(inStr) | ||
265 | { | ||
266 | str = ""; | ||
267 | } | ||
268 | } | ||
269 | else | ||
270 | { | ||
271 | if(inStr) | ||
272 | { | ||
273 | str += c; | ||
274 | } | ||
275 | else | ||
276 | { | ||
277 | switch(c) | ||
278 | { | ||
279 | case '=': | ||
280 | oper = OperatorSymbol.Equal; | ||
281 | break; | ||
282 | |||
283 | case '!': | ||
284 | if(NextChar(i, exp) == '=') | ||
285 | { | ||
286 | oper = OperatorSymbol.NotEqual; | ||
287 | } | ||
288 | |||
289 | break; | ||
290 | |||
291 | case '<': | ||
292 | if(NextChar(i, exp) == '=') | ||
293 | { | ||
294 | oper = OperatorSymbol.LessThanEqual; | ||
295 | } | ||
296 | else | ||
297 | { | ||
298 | oper = OperatorSymbol.LessThan; | ||
299 | } | ||
300 | |||
301 | break; | ||
302 | |||
303 | case '>': | ||
304 | if(NextChar(i, exp) == '=') | ||
305 | { | ||
306 | oper = OperatorSymbol.GreaterThanEqual; | ||
307 | } | ||
308 | else | ||
309 | { | ||
310 | oper = OperatorSymbol.GreaterThan; | ||
311 | } | ||
312 | |||
313 | break; | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | } | ||
318 | |||
319 | |||
320 | if(inStr) | ||
321 | { | ||
322 | throw new WarningException("Expected end of string in expression"); | ||
323 | } | ||
324 | |||
325 | if(oper == OperatorSymbol.None) | ||
326 | { | ||
327 | throw new WarningException("Expected operator in expression"); | ||
328 | } | ||
329 | else if(id.Length < 1) | ||
330 | { | ||
331 | throw new WarningException("Expected identifier in expression"); | ||
332 | } | ||
333 | else if(str.Length < 1) | ||
334 | { | ||
335 | throw new WarningException("Expected value in expression"); | ||
336 | } | ||
337 | |||
338 | bool ret = false; | ||
339 | try | ||
340 | { | ||
341 | object val = m_Variables[id.ToLower()]; | ||
342 | if(val == null) | ||
343 | { | ||
344 | throw new WarningException("Unknown identifier '{0}'", id); | ||
345 | } | ||
346 | |||
347 | int numVal, numVal2; | ||
348 | string strVal, strVal2; | ||
349 | Type t = val.GetType(); | ||
350 | if(t.IsAssignableFrom(typeof(int))) | ||
351 | { | ||
352 | numVal = (int)val; | ||
353 | numVal2 = Int32.Parse(str); | ||
354 | ret = CompareNum(oper, numVal, numVal2); | ||
355 | } | ||
356 | else | ||
357 | { | ||
358 | strVal = val.ToString(); | ||
359 | strVal2 = str; | ||
360 | ret = CompareStr(oper, strVal, strVal2); | ||
361 | } | ||
362 | } | ||
363 | catch(ArgumentException ex) | ||
364 | { | ||
365 | ex.ToString(); | ||
366 | throw new WarningException("Invalid value type for system variable '{0}', expected int", id); | ||
367 | } | ||
368 | |||
369 | return ret; | ||
370 | } | ||
371 | |||
372 | #endregion | ||
373 | |||
374 | #region Public Methods | ||
375 | |||
376 | /// <summary> | ||
377 | /// | ||
378 | /// </summary> | ||
379 | /// <param name="name"></param> | ||
380 | /// <param name="variableValue"></param> | ||
381 | public void RegisterVariable(string name, object variableValue) | ||
382 | { | ||
383 | if(name == null || variableValue == null) | ||
384 | { | ||
385 | return; | ||
386 | } | ||
387 | |||
388 | m_Variables[name.ToLower()] = variableValue; | ||
389 | } | ||
390 | |||
391 | /// <summary> | ||
392 | /// Performs validation on the xml source as well as evaluates conditional and flow expresions | ||
393 | /// </summary> | ||
394 | /// <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> | ||
395 | /// <param name="reader"></param> | ||
396 | /// <returns>the output xml </returns> | ||
397 | public string Process(XmlReader initialReader) | ||
398 | { | ||
399 | if(initialReader == null) | ||
400 | { | ||
401 | throw new ArgumentException("Invalid XML reader to pre-process"); | ||
402 | } | ||
403 | |||
404 | IfContext context = new IfContext(true, true, IfState.None); | ||
405 | StringWriter xmlText = new StringWriter(); | ||
406 | XmlTextWriter writer = new XmlTextWriter(xmlText); | ||
407 | writer.Formatting = Formatting.Indented; | ||
408 | |||
409 | // Create a queue of XML readers and add the initial | ||
410 | // reader to it. Then we process until we run out of | ||
411 | // readers which lets the <?include?> operation add more | ||
412 | // readers to generate a multi-file parser and not require | ||
413 | // XML fragments that a recursive version would use. | ||
414 | Stack readerStack = new Stack(); | ||
415 | readerStack.Push(initialReader); | ||
416 | |||
417 | while(readerStack.Count > 0) | ||
418 | { | ||
419 | // Pop off the next reader. | ||
420 | XmlReader reader = (XmlReader) readerStack.Pop(); | ||
421 | |||
422 | // Process through this XML reader until it is | ||
423 | // completed (or it is replaced by the include | ||
424 | // operation). | ||
425 | while(reader.Read()) | ||
426 | { | ||
427 | // The prebuild file has a series of processing | ||
428 | // instructions which allow for specific | ||
429 | // inclusions based on operating system or to | ||
430 | // include additional files. | ||
431 | if(reader.NodeType == XmlNodeType.ProcessingInstruction) | ||
432 | { | ||
433 | bool ignore = false; | ||
434 | |||
435 | switch(reader.LocalName) | ||
436 | { | ||
437 | case "include": | ||
438 | // use regular expressions to parse out the attributes. | ||
439 | MatchCollection matches = includeFileRegex.Matches(reader.Value); | ||
440 | |||
441 | // make sure there is only one file attribute. | ||
442 | if(matches.Count > 1) | ||
443 | { | ||
444 | throw new WarningException("An <?include ?> node was found, but it specified more than one file."); | ||
445 | } | ||
446 | |||
447 | if(matches.Count == 0) | ||
448 | { | ||
449 | throw new WarningException("An <?include ?> node was found, but it did not specify the file attribute."); | ||
450 | } | ||
451 | |||
452 | // Push current reader back onto the stack. | ||
453 | readerStack.Push(reader); | ||
454 | |||
455 | // Pull the file out from the regex and make sure it is a valid file before using it. | ||
456 | string filename = matches[0].Groups[1].Value; | ||
457 | |||
458 | filename = String.Join(Path.DirectorySeparatorChar.ToString(), filename.Split(new char[] { '/', '\\' })); | ||
459 | |||
460 | if (!filename.Contains("*")) | ||
461 | { | ||
462 | FileInfo includeFile = new FileInfo(filename); | ||
463 | |||
464 | if (!includeFile.Exists) | ||
465 | { | ||
466 | throw new WarningException("Cannot include file: " + includeFile.FullName); | ||
467 | } | ||
468 | |||
469 | // Create a new reader object for this file, and push it onto the stack | ||
470 | XmlReader newReader = new XmlTextReader(includeFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read)); | ||
471 | readerStack.Push(newReader); | ||
472 | } | ||
473 | else | ||
474 | { | ||
475 | WildCardInclude(readerStack, filename); | ||
476 | } | ||
477 | |||
478 | // continue reading with whatever reader is on the top of the stack | ||
479 | reader = (XmlReader)readerStack.Pop(); | ||
480 | ignore = true; | ||
481 | |||
482 | break; | ||
483 | |||
484 | case "if": | ||
485 | m_IfStack.Push(context); | ||
486 | context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If); | ||
487 | ignore = true; | ||
488 | break; | ||
489 | |||
490 | case "elseif": | ||
491 | if(m_IfStack.Count == 0) | ||
492 | { | ||
493 | throw new WarningException("Unexpected 'elseif' outside of 'if'"); | ||
494 | } | ||
495 | else if(context.State != IfState.If && context.State != IfState.ElseIf) | ||
496 | { | ||
497 | throw new WarningException("Unexpected 'elseif' outside of 'if'"); | ||
498 | } | ||
499 | |||
500 | context.State = IfState.ElseIf; | ||
501 | if(!context.EverKept) | ||
502 | { | ||
503 | context.Keep = ParseExpression(reader.Value); | ||
504 | } | ||
505 | else | ||
506 | { | ||
507 | context.Keep = false; | ||
508 | } | ||
509 | |||
510 | ignore = true; | ||
511 | break; | ||
512 | |||
513 | case "else": | ||
514 | if(m_IfStack.Count == 0) | ||
515 | { | ||
516 | throw new WarningException("Unexpected 'else' outside of 'if'"); | ||
517 | } | ||
518 | else if(context.State != IfState.If && context.State != IfState.ElseIf) | ||
519 | { | ||
520 | throw new WarningException("Unexpected 'else' outside of 'if'"); | ||
521 | } | ||
522 | |||
523 | context.State = IfState.Else; | ||
524 | context.Keep = !context.EverKept; | ||
525 | ignore = true; | ||
526 | break; | ||
527 | |||
528 | case "endif": | ||
529 | if(m_IfStack.Count == 0) | ||
530 | { | ||
531 | throw new WarningException("Unexpected 'endif' outside of 'if'"); | ||
532 | } | ||
533 | |||
534 | context = (IfContext)m_IfStack.Pop(); | ||
535 | ignore = true; | ||
536 | break; | ||
537 | } | ||
538 | |||
539 | if(ignore) | ||
540 | { | ||
541 | continue; | ||
542 | } | ||
543 | }//end pre-proc instruction | ||
544 | |||
545 | if(!context.Active || !context.Keep) | ||
546 | { | ||
547 | continue; | ||
548 | } | ||
549 | |||
550 | switch(reader.NodeType) | ||
551 | { | ||
552 | case XmlNodeType.Element: | ||
553 | bool empty = reader.IsEmptyElement; | ||
554 | writer.WriteStartElement(reader.Name); | ||
555 | |||
556 | while (reader.MoveToNextAttribute()) | ||
557 | { | ||
558 | writer.WriteAttributeString(reader.Name, reader.Value); | ||
559 | } | ||
560 | |||
561 | if(empty) | ||
562 | { | ||
563 | writer.WriteEndElement(); | ||
564 | } | ||
565 | |||
566 | break; | ||
567 | |||
568 | case XmlNodeType.EndElement: | ||
569 | writer.WriteEndElement(); | ||
570 | break; | ||
571 | |||
572 | case XmlNodeType.Text: | ||
573 | writer.WriteString(reader.Value); | ||
574 | break; | ||
575 | |||
576 | case XmlNodeType.CDATA: | ||
577 | writer.WriteCData(reader.Value); | ||
578 | break; | ||
579 | |||
580 | default: | ||
581 | break; | ||
582 | } | ||
583 | } | ||
584 | |||
585 | if(m_IfStack.Count != 0) | ||
586 | { | ||
587 | throw new WarningException("Mismatched 'if', 'endif' pair"); | ||
588 | } | ||
589 | } | ||
590 | |||
591 | return xmlText.ToString(); | ||
592 | } | ||
593 | |||
594 | private static void WildCardInclude(Stack readerStack, string include) | ||
595 | { | ||
596 | if (!include.Contains("*")) | ||
597 | { | ||
598 | return; | ||
599 | } | ||
600 | |||
601 | // Console.WriteLine("Processing {0}", include); | ||
602 | |||
603 | // Break up the include into pre and post wildcard sections | ||
604 | string preWildcard = include.Substring(0, include.IndexOf("*")); | ||
605 | string postWildcard = include.Substring(include.IndexOf("*") + 2); | ||
606 | |||
607 | // If preWildcard is a directory, recurse | ||
608 | if (Directory.Exists(preWildcard)) | ||
609 | { | ||
610 | string[] directories = Directory.GetDirectories(preWildcard); | ||
611 | Array.Sort(directories); | ||
612 | Array.Reverse(directories); | ||
613 | foreach (string dirPath in directories ) | ||
614 | { | ||
615 | Console.WriteLine("Scanning : {0}", dirPath); | ||
616 | |||
617 | string includeFile = Path.Combine(dirPath, postWildcard); | ||
618 | if (includeFile.Contains("*")) | ||
619 | { | ||
620 | // postWildcard included another wildcard, recurse. | ||
621 | WildCardInclude(readerStack, includeFile); | ||
622 | } | ||
623 | else | ||
624 | { | ||
625 | FileInfo file = new FileInfo(includeFile); | ||
626 | if (file.Exists) | ||
627 | { | ||
628 | Console.WriteLine("Including File: {0}", includeFile); | ||
629 | XmlReader newReader = new XmlTextReader(file.Open(FileMode.Open, FileAccess.Read, FileShare.Read)); | ||
630 | readerStack.Push(newReader); | ||
631 | } | ||
632 | } | ||
633 | } | ||
634 | } | ||
635 | else | ||
636 | { | ||
637 | // preWildcard is not a path to a directory, so the wildcard is in the filename | ||
638 | string searchFilename = Path.GetFileName(preWildcard.Substring(preWildcard.IndexOf("/") + 1) + "*" + postWildcard); | ||
639 | // Console.WriteLine("searchFilename: {0}", searchFilename); | ||
640 | |||
641 | string searchDirectory = Path.GetDirectoryName(preWildcard); | ||
642 | // Console.WriteLine("searchDirectory: {0}", searchDirectory); | ||
643 | |||
644 | string[] files = Directory.GetFiles(searchDirectory, searchFilename); | ||
645 | Array.Sort(files); | ||
646 | Array.Reverse(files); | ||
647 | foreach (string includeFile in files) | ||
648 | { | ||
649 | FileInfo file = new FileInfo(includeFile); | ||
650 | if (file.Exists) | ||
651 | { | ||
652 | Console.WriteLine("Including File: {0}", includeFile); | ||
653 | XmlReader newReader = new XmlTextReader(file.Open(FileMode.Open, FileAccess.Read, FileShare.Read)); | ||
654 | readerStack.Push(newReader); | ||
655 | } | ||
656 | } | ||
657 | } | ||
658 | |||
659 | } | ||
660 | |||
661 | #endregion | ||
662 | } | ||
663 | } | ||