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.cs267
1 files changed, 128 insertions, 139 deletions
diff --git a/Prebuild/src/Core/Parse/Preprocessor.cs b/Prebuild/src/Core/Parse/Preprocessor.cs
index b2306e4..0648fad 100644
--- a/Prebuild/src/Core/Parse/Preprocessor.cs
+++ b/Prebuild/src/Core/Parse/Preprocessor.cs
@@ -24,7 +24,7 @@ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY O
24#endregion 24#endregion
25 25
26using System; 26using System;
27using System.Collections; 27using System.Collections.Generic;
28using System.IO; 28using System.IO;
29using System.Text.RegularExpressions; 29using System.Text.RegularExpressions;
30using System.Xml; 30using System.Xml;
@@ -83,9 +83,9 @@ namespace Prebuild.Core.Parse
83 83
84 #region Fields 84 #region Fields
85 85
86 XmlDocument m_OutDoc; 86 readonly XmlDocument m_OutDoc = new XmlDocument();
87 Stack m_IfStack; 87 readonly Stack<IfContext> m_IfStack = new Stack<IfContext>();
88 Hashtable m_Variables; 88 readonly Dictionary<string, object> m_Variables = new Dictionary<string, object>();
89 89
90 #endregion 90 #endregion
91 91
@@ -96,10 +96,6 @@ namespace Prebuild.Core.Parse
96 /// </summary> 96 /// </summary>
97 public Preprocessor() 97 public Preprocessor()
98 { 98 {
99 m_OutDoc = new XmlDocument();
100 m_IfStack = new Stack();
101 m_Variables = new Hashtable();
102
103 RegisterVariable("OS", GetOS()); 99 RegisterVariable("OS", GetOS());
104 RegisterVariable("RuntimeVersion", Environment.Version.Major); 100 RegisterVariable("RuntimeVersion", Environment.Version.Major);
105 RegisterVariable("RuntimeMajor", Environment.Version.Major); 101 RegisterVariable("RuntimeMajor", Environment.Version.Major);
@@ -237,11 +233,10 @@ namespace Prebuild.Core.Parse
237 string str = ""; 233 string str = "";
238 OperatorSymbol oper = OperatorSymbol.None; 234 OperatorSymbol oper = OperatorSymbol.None;
239 bool inStr = false; 235 bool inStr = false;
240 char c; 236
241 237 for(int i = 0; i < exp.Length; i++)
242 for(int i = 0; i < exp.Length; i++)
243 { 238 {
244 c = exp[i]; 239 char c = exp[i];
245 if(Char.IsWhiteSpace(c)) 240 if(Char.IsWhiteSpace(c))
246 { 241 {
247 continue; 242 continue;
@@ -326,16 +321,16 @@ namespace Prebuild.Core.Parse
326 { 321 {
327 throw new WarningException("Expected operator in expression"); 322 throw new WarningException("Expected operator in expression");
328 } 323 }
329 else if(id.Length < 1) 324 if(id.Length < 1)
330 { 325 {
331 throw new WarningException("Expected identifier in expression"); 326 throw new WarningException("Expected identifier in expression");
332 } 327 }
333 else if(str.Length < 1) 328 if(str.Length < 1)
334 { 329 {
335 throw new WarningException("Expected value in expression"); 330 throw new WarningException("Expected value in expression");
336 } 331 }
337 332
338 bool ret = false; 333 bool ret;
339 try 334 try
340 { 335 {
341 object val = m_Variables[id.ToLower()]; 336 object val = m_Variables[id.ToLower()];
@@ -344,19 +339,17 @@ namespace Prebuild.Core.Parse
344 throw new WarningException("Unknown identifier '{0}'", id); 339 throw new WarningException("Unknown identifier '{0}'", id);
345 } 340 }
346 341
347 int numVal, numVal2; 342 Type t = val.GetType();
348 string strVal, strVal2;
349 Type t = val.GetType();
350 if(t.IsAssignableFrom(typeof(int))) 343 if(t.IsAssignableFrom(typeof(int)))
351 { 344 {
352 numVal = (int)val; 345 int numVal = (int)val;
353 numVal2 = Int32.Parse(str); 346 int numVal2 = Int32.Parse(str);
354 ret = CompareNum(oper, numVal, numVal2); 347 ret = CompareNum(oper, numVal, numVal2);
355 } 348 }
356 else 349 else
357 { 350 {
358 strVal = val.ToString(); 351 string strVal = val.ToString();
359 strVal2 = str; 352 string strVal2 = str;
360 ret = CompareStr(oper, strVal, strVal2); 353 ret = CompareStr(oper, strVal, strVal2);
361 } 354 }
362 } 355 }
@@ -369,6 +362,70 @@ namespace Prebuild.Core.Parse
369 return ret; 362 return ret;
370 } 363 }
371 364
365 /// <summary>
366 /// Taken from current Prebuild included in OpenSim 0.7.x
367 /// </summary>
368 /// <param name="readerStack">
369 /// A <see cref="Stack<XmlReader>"/>
370 /// </param>
371 /// <param name="include">
372 /// A <see cref="System.String"/>
373 /// </param>
374 private static void WildCardInclude (Stack<XmlReader> readerStack, string include)
375 {
376 if (!include.Contains ("*")) {
377 return;
378 }
379
380 // Console.WriteLine("Processing {0}", include);
381
382 // Break up the include into pre and post wildcard sections
383 string preWildcard = include.Substring (0, include.IndexOf ("*"));
384 string postWildcard = include.Substring (include.IndexOf ("*") + 2);
385
386 // If preWildcard is a directory, recurse
387 if (Directory.Exists (preWildcard)) {
388 string[] directories = Directory.GetDirectories (preWildcard);
389 Array.Sort (directories);
390 Array.Reverse (directories);
391 foreach (string dirPath in directories) {
392 //Console.WriteLine ("Scanning : {0}", dirPath);
393
394 string includeFile = Path.Combine (dirPath, postWildcard);
395 if (includeFile.Contains ("*")) {
396 // postWildcard included another wildcard, recurse.
397 WildCardInclude (readerStack, includeFile);
398 } else {
399 FileInfo file = new FileInfo (includeFile);
400 if (file.Exists) {
401 //Console.WriteLine ("Including File: {0}", includeFile);
402 XmlReader newReader = new XmlTextReader (file.Open (FileMode.Open, FileAccess.Read, FileShare.Read));
403 readerStack.Push (newReader);
404 }
405 }
406 }
407 } else {
408 // preWildcard is not a path to a directory, so the wildcard is in the filename
409 string searchFilename = Path.GetFileName (preWildcard.Substring (preWildcard.IndexOf ("/") + 1) + "*" + postWildcard);
410 Console.WriteLine ("searchFilename: {0}", searchFilename);
411
412 string searchDirectory = Path.GetDirectoryName (preWildcard);
413 Console.WriteLine ("searchDirectory: {0}", searchDirectory);
414
415 string[] files = Directory.GetFiles (searchDirectory, searchFilename);
416 Array.Sort (files);
417 Array.Reverse (files);
418 foreach (string includeFile in files) {
419 FileInfo file = new FileInfo (includeFile);
420 if (file.Exists) {
421 // Console.WriteLine ("Including File: {0}", includeFile);
422 XmlReader newReader = new XmlTextReader (file.Open (FileMode.Open, FileAccess.Read, FileShare.Read));
423 readerStack.Push (newReader);
424 }
425 }
426 }
427 }
428
372 #endregion 429 #endregion
373 430
374 #region Public Methods 431 #region Public Methods
@@ -392,7 +449,7 @@ namespace Prebuild.Core.Parse
392 /// Performs validation on the xml source as well as evaluates conditional and flow expresions 449 /// Performs validation on the xml source as well as evaluates conditional and flow expresions
393 /// </summary> 450 /// </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> 451 /// <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> 452 /// <param name="initialReader"></param>
396 /// <returns>the output xml </returns> 453 /// <returns>the output xml </returns>
397 public string Process(XmlReader initialReader) 454 public string Process(XmlReader initialReader)
398 { 455 {
@@ -411,13 +468,13 @@ namespace Prebuild.Core.Parse
411 // readers which lets the <?include?> operation add more 468 // readers which lets the <?include?> operation add more
412 // readers to generate a multi-file parser and not require 469 // readers to generate a multi-file parser and not require
413 // XML fragments that a recursive version would use. 470 // XML fragments that a recursive version would use.
414 Stack readerStack = new Stack(); 471 Stack<XmlReader> readerStack = new Stack<XmlReader>();
415 readerStack.Push(initialReader); 472 readerStack.Push(initialReader);
416 473
417 while(readerStack.Count > 0) 474 while(readerStack.Count > 0)
418 { 475 {
419 // Pop off the next reader. 476 // Pop off the next reader.
420 XmlReader reader = (XmlReader) readerStack.Pop(); 477 XmlReader reader = readerStack.Pop();
421 478
422 // Process through this XML reader until it is 479 // Process through this XML reader until it is
423 // completed (or it is replaced by the include 480 // completed (or it is replaced by the include
@@ -437,7 +494,7 @@ namespace Prebuild.Core.Parse
437 case "include": 494 case "include":
438 // use regular expressions to parse out the attributes. 495 // use regular expressions to parse out the attributes.
439 MatchCollection matches = includeFileRegex.Matches(reader.Value); 496 MatchCollection matches = includeFileRegex.Matches(reader.Value);
440 497
441 // make sure there is only one file attribute. 498 // make sure there is only one file attribute.
442 if(matches.Count > 1) 499 if(matches.Count > 1)
443 { 500 {
@@ -448,38 +505,37 @@ namespace Prebuild.Core.Parse
448 { 505 {
449 throw new WarningException("An <?include ?> node was found, but it did not specify the file attribute."); 506 throw new WarningException("An <?include ?> node was found, but it did not specify the file attribute.");
450 } 507 }
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 508
458 filename = String.Join(Path.DirectorySeparatorChar.ToString(), filename.Split(new char[] { '/', '\\' })); 509 // ***** Adding for wildcard handling
459 510 // Push current reader back onto the stack.
460 if (!filename.Contains("*")) 511 readerStack.Push (reader);
461 { 512
462 FileInfo includeFile = new FileInfo(filename); 513 // Pull the file out from the regex and make sure it is a valid file before using it.
463 514 string filename = matches[0].Groups[1].Value;
464 if (!includeFile.Exists) 515
465 { 516 filename = String.Join (Path.DirectorySeparatorChar.ToString (), filename.Split (new char[] { '/', '\\' }));
466 throw new WarningException("Cannot include file: " + includeFile.FullName); 517
518 if (!filename.Contains ("*")) {
519
520 FileInfo includeFile = new FileInfo (filename);
521 if (!includeFile.Exists) {
522 throw new WarningException ("Cannot include file: " + includeFile.FullName);
467 } 523 }
468 524
469 // Create a new reader object for this file, and push it onto the stack 525 // Create a new reader object for this file. Then put the old reader back on the stack and start
470 XmlReader newReader = new XmlTextReader(includeFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read)); 526 // processing using this new XML reader.
471 readerStack.Push(newReader); 527
472 } 528 XmlReader newReader = new XmlTextReader (includeFile.Open (FileMode.Open, FileAccess.Read, FileShare.Read));
473 else 529 reader = newReader;
474 { 530 readerStack.Push (reader);
475 WildCardInclude(readerStack, filename); 531
532 } else {
533 WildCardInclude (readerStack, filename);
476 } 534 }
477 535
478 // continue reading with whatever reader is on the top of the stack 536 reader = (XmlReader)readerStack.Pop ();
479 reader = (XmlReader)readerStack.Pop();
480 ignore = true; 537 ignore = true;
481 538 break;
482 break;
483 539
484 case "if": 540 case "if":
485 m_IfStack.Push(context); 541 m_IfStack.Push(context);
@@ -492,12 +548,12 @@ namespace Prebuild.Core.Parse
492 { 548 {
493 throw new WarningException("Unexpected 'elseif' outside of 'if'"); 549 throw new WarningException("Unexpected 'elseif' outside of 'if'");
494 } 550 }
495 else if(context.State != IfState.If && context.State != IfState.ElseIf) 551 if(context.State != IfState.If && context.State != IfState.ElseIf)
496 { 552 {
497 throw new WarningException("Unexpected 'elseif' outside of 'if'"); 553 throw new WarningException("Unexpected 'elseif' outside of 'if'");
498 } 554 }
499 555
500 context.State = IfState.ElseIf; 556 context.State = IfState.ElseIf;
501 if(!context.EverKept) 557 if(!context.EverKept)
502 { 558 {
503 context.Keep = ParseExpression(reader.Value); 559 context.Keep = ParseExpression(reader.Value);
@@ -515,12 +571,12 @@ namespace Prebuild.Core.Parse
515 { 571 {
516 throw new WarningException("Unexpected 'else' outside of 'if'"); 572 throw new WarningException("Unexpected 'else' outside of 'if'");
517 } 573 }
518 else if(context.State != IfState.If && context.State != IfState.ElseIf) 574 if(context.State != IfState.If && context.State != IfState.ElseIf)
519 { 575 {
520 throw new WarningException("Unexpected 'else' outside of 'if'"); 576 throw new WarningException("Unexpected 'else' outside of 'if'");
521 } 577 }
522 578
523 context.State = IfState.Else; 579 context.State = IfState.Else;
524 context.Keep = !context.EverKept; 580 context.Keep = !context.EverKept;
525 ignore = true; 581 ignore = true;
526 break; 582 break;
@@ -531,7 +587,7 @@ namespace Prebuild.Core.Parse
531 throw new WarningException("Unexpected 'endif' outside of 'if'"); 587 throw new WarningException("Unexpected 'endif' outside of 'if'");
532 } 588 }
533 589
534 context = (IfContext)m_IfStack.Pop(); 590 context = m_IfStack.Pop();
535 ignore = true; 591 ignore = true;
536 break; 592 break;
537 } 593 }
@@ -591,73 +647,6 @@ namespace Prebuild.Core.Parse
591 return xmlText.ToString(); 647 return xmlText.ToString();
592 } 648 }
593 649
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 650 #endregion
662 } 651 }
663} 652}