diff options
Diffstat (limited to 'Prebuild/src/Core/Parse/Preprocessor.cs')
-rw-r--r-- | Prebuild/src/Core/Parse/Preprocessor.cs | 1088 |
1 files changed, 544 insertions, 544 deletions
diff --git a/Prebuild/src/Core/Parse/Preprocessor.cs b/Prebuild/src/Core/Parse/Preprocessor.cs index 0cd6e82..0648fad 100644 --- a/Prebuild/src/Core/Parse/Preprocessor.cs +++ b/Prebuild/src/Core/Parse/Preprocessor.cs | |||
@@ -5,16 +5,16 @@ Copyright (c) 2004-2005 Matthew Holmes (matthew@wildfiregames.com), Dan Moorehea | |||
5 | Redistribution and use in source and binary forms, with or without modification, are permitted | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted |
6 | provided that the following conditions are met: | 6 | provided 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 | ||
16 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, | 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 | 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, | 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 | 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 | 20 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
@@ -31,336 +31,336 @@ using System.Xml; | |||
31 | 31 | ||
32 | namespace Prebuild.Core.Parse | 32 | namespace Prebuild.Core.Parse |
33 | { | 33 | { |
34 | /// <summary> | 34 | /// <summary> |
35 | /// | 35 | /// |
36 | /// </summary> | 36 | /// </summary> |
37 | public enum OperatorSymbol | 37 | public enum OperatorSymbol |
38 | { | 38 | { |
39 | /// <summary> | 39 | /// <summary> |
40 | /// | 40 | /// |
41 | /// </summary> | 41 | /// </summary> |
42 | None, | 42 | None, |
43 | /// <summary> | 43 | /// <summary> |
44 | /// | 44 | /// |
45 | /// </summary> | 45 | /// </summary> |
46 | Equal, | 46 | Equal, |
47 | /// <summary> | 47 | /// <summary> |
48 | /// | 48 | /// |
49 | /// </summary> | 49 | /// </summary> |
50 | NotEqual, | 50 | NotEqual, |
51 | /// <summary> | 51 | /// <summary> |
52 | /// | 52 | /// |
53 | /// </summary> | 53 | /// </summary> |
54 | LessThan, | 54 | LessThan, |
55 | /// <summary> | 55 | /// <summary> |
56 | /// | 56 | /// |
57 | /// </summary> | 57 | /// </summary> |
58 | GreaterThan, | 58 | GreaterThan, |
59 | /// <summary> | 59 | /// <summary> |
60 | /// | 60 | /// |
61 | /// </summary> | 61 | /// </summary> |
62 | LessThanEqual, | 62 | LessThanEqual, |
63 | /// <summary> | 63 | /// <summary> |
64 | /// | 64 | /// |
65 | /// </summary> | 65 | /// </summary> |
66 | GreaterThanEqual | 66 | GreaterThanEqual |
67 | } | 67 | } |
68 | 68 | ||
69 | /// <summary> | 69 | /// <summary> |
70 | /// | 70 | /// |
71 | /// </summary> | 71 | /// </summary> |
72 | public class Preprocessor | 72 | public class Preprocessor |
73 | { | 73 | { |
74 | #region Constants | 74 | #region Constants |
75 | 75 | ||
76 | /// <summary> | 76 | /// <summary> |
77 | /// Includes the regex to look for file tags in the <?include | 77 | /// Includes the regex to look for file tags in the <?include |
78 | /// ?> processing instruction. | 78 | /// ?> processing instruction. |
79 | /// </summary> | 79 | /// </summary> |
80 | private static readonly Regex includeFileRegex = new Regex("file=\"(.+?)\""); | 80 | private static readonly Regex includeFileRegex = new Regex("file=\"(.+?)\""); |
81 | 81 | ||
82 | #endregion | 82 | #endregion |
83 | 83 | ||
84 | #region Fields | 84 | #region Fields |
85 | 85 | ||
86 | readonly XmlDocument m_OutDoc = new XmlDocument(); | 86 | readonly XmlDocument m_OutDoc = new XmlDocument(); |
87 | readonly Stack<IfContext> m_IfStack = new Stack<IfContext>(); | 87 | readonly Stack<IfContext> m_IfStack = new Stack<IfContext>(); |
88 | readonly Dictionary<string, object> m_Variables = new Dictionary<string, object>(); | 88 | readonly Dictionary<string, object> m_Variables = new Dictionary<string, object>(); |
89 | 89 | ||
90 | #endregion | 90 | #endregion |
91 | 91 | ||
92 | #region Constructors | 92 | #region Constructors |
93 | 93 | ||
94 | /// <summary> | 94 | /// <summary> |
95 | /// Initializes a new instance of the <see cref="Preprocessor"/> class. | 95 | /// Initializes a new instance of the <see cref="Preprocessor"/> class. |
96 | /// </summary> | 96 | /// </summary> |
97 | public Preprocessor() | 97 | public Preprocessor() |
98 | { | 98 | { |
99 | RegisterVariable("OS", GetOS()); | 99 | RegisterVariable("OS", GetOS()); |
100 | RegisterVariable("RuntimeVersion", Environment.Version.Major); | 100 | RegisterVariable("RuntimeVersion", Environment.Version.Major); |
101 | RegisterVariable("RuntimeMajor", Environment.Version.Major); | 101 | RegisterVariable("RuntimeMajor", Environment.Version.Major); |
102 | RegisterVariable("RuntimeMinor", Environment.Version.Minor); | 102 | RegisterVariable("RuntimeMinor", Environment.Version.Minor); |
103 | RegisterVariable("RuntimeRevision", Environment.Version.Revision); | 103 | RegisterVariable("RuntimeRevision", Environment.Version.Revision); |
104 | } | 104 | } |
105 | 105 | ||
106 | #endregion | 106 | #endregion |
107 | 107 | ||
108 | #region Properties | 108 | #region Properties |
109 | 109 | ||
110 | /// <summary> | 110 | /// <summary> |
111 | /// Gets the processed doc. | 111 | /// Gets the processed doc. |
112 | /// </summary> | 112 | /// </summary> |
113 | /// <value>The processed doc.</value> | 113 | /// <value>The processed doc.</value> |
114 | public XmlDocument ProcessedDoc | 114 | public XmlDocument ProcessedDoc |
115 | { | 115 | { |
116 | get | 116 | get |
117 | { | 117 | { |
118 | return m_OutDoc; | 118 | return m_OutDoc; |
119 | } | 119 | } |
120 | } | 120 | } |
121 | 121 | ||
122 | #endregion | 122 | #endregion |
123 | 123 | ||
124 | #region Private Methods | 124 | #region Private Methods |
125 | 125 | ||
126 | /// <summary> | 126 | /// <summary> |
127 | /// Parts of this code were taken from NAnt and is subject to the GPL | 127 | /// Parts of this code were taken from NAnt and is subject to the GPL |
128 | /// as per NAnt's license. Thanks to the NAnt guys for this little gem. | 128 | /// as per NAnt's license. Thanks to the NAnt guys for this little gem. |
129 | /// </summary> | 129 | /// </summary> |
130 | /// <returns></returns> | 130 | /// <returns></returns> |
131 | public static string GetOS() | 131 | public static string GetOS() |
132 | { | 132 | { |
133 | PlatformID platId = Environment.OSVersion.Platform; | 133 | PlatformID platId = Environment.OSVersion.Platform; |
134 | if(platId == PlatformID.Win32NT || platId == PlatformID.Win32Windows) | 134 | if(platId == PlatformID.Win32NT || platId == PlatformID.Win32Windows) |
135 | { | 135 | { |
136 | return "Win32"; | 136 | return "Win32"; |
137 | } | 137 | } |
138 | 138 | ||
139 | if (File.Exists("/System/Library/Frameworks/Cocoa.framework/Cocoa")) | 139 | if (File.Exists("/System/Library/Frameworks/Cocoa.framework/Cocoa")) |
140 | { | 140 | { |
141 | return "MACOSX"; | 141 | return "MACOSX"; |
142 | } | 142 | } |
143 | 143 | ||
144 | /* | 144 | /* |
145 | * .NET 1.x, under Mono, the UNIX code is 128. Under | 145 | * .NET 1.x, under Mono, the UNIX code is 128. Under |
146 | * .NET 2.x, Mono or MS, the UNIX code is 4 | 146 | * .NET 2.x, Mono or MS, the UNIX code is 4 |
147 | */ | 147 | */ |
148 | if(Environment.Version.Major == 1) | 148 | if(Environment.Version.Major == 1) |
149 | { | 149 | { |
150 | if((int)platId == 128) | 150 | if((int)platId == 128) |
151 | { | 151 | { |
152 | return "UNIX"; | 152 | return "UNIX"; |
153 | } | 153 | } |
154 | } | 154 | } |
155 | else if((int)platId == 4) | 155 | else if((int)platId == 4) |
156 | { | 156 | { |
157 | return "UNIX"; | 157 | return "UNIX"; |
158 | } | 158 | } |
159 | 159 | ||
160 | return "Unknown"; | 160 | return "Unknown"; |
161 | } | 161 | } |
162 | 162 | ||
163 | private static bool CompareNum(OperatorSymbol oper, int val1, int val2) | 163 | private static bool CompareNum(OperatorSymbol oper, int val1, int val2) |
164 | { | 164 | { |
165 | switch(oper) | 165 | switch(oper) |
166 | { | 166 | { |
167 | case OperatorSymbol.Equal: | 167 | case OperatorSymbol.Equal: |
168 | return (val1 == val2); | 168 | return (val1 == val2); |
169 | case OperatorSymbol.NotEqual: | 169 | case OperatorSymbol.NotEqual: |
170 | return (val1 != val2); | 170 | return (val1 != val2); |
171 | case OperatorSymbol.LessThan: | 171 | case OperatorSymbol.LessThan: |
172 | return (val1 < val2); | 172 | return (val1 < val2); |
173 | case OperatorSymbol.LessThanEqual: | 173 | case OperatorSymbol.LessThanEqual: |
174 | return (val1 <= val2); | 174 | return (val1 <= val2); |
175 | case OperatorSymbol.GreaterThan: | 175 | case OperatorSymbol.GreaterThan: |
176 | return (val1 > val2); | 176 | return (val1 > val2); |
177 | case OperatorSymbol.GreaterThanEqual: | 177 | case OperatorSymbol.GreaterThanEqual: |
178 | return (val1 >= val2); | 178 | return (val1 >= val2); |
179 | } | 179 | } |
180 | 180 | ||
181 | throw new WarningException("Unknown operator type"); | 181 | throw new WarningException("Unknown operator type"); |
182 | } | 182 | } |
183 | 183 | ||
184 | private static bool CompareStr(OperatorSymbol oper, string val1, string val2) | 184 | private static bool CompareStr(OperatorSymbol oper, string val1, string val2) |
185 | { | 185 | { |
186 | switch(oper) | 186 | switch(oper) |
187 | { | 187 | { |
188 | case OperatorSymbol.Equal: | 188 | case OperatorSymbol.Equal: |
189 | return (val1 == val2); | 189 | return (val1 == val2); |
190 | case OperatorSymbol.NotEqual: | 190 | case OperatorSymbol.NotEqual: |
191 | return (val1 != val2); | 191 | return (val1 != val2); |
192 | case OperatorSymbol.LessThan: | 192 | case OperatorSymbol.LessThan: |
193 | return (val1.CompareTo(val2) < 0); | 193 | return (val1.CompareTo(val2) < 0); |
194 | case OperatorSymbol.LessThanEqual: | 194 | case OperatorSymbol.LessThanEqual: |
195 | return (val1.CompareTo(val2) <= 0); | 195 | return (val1.CompareTo(val2) <= 0); |
196 | case OperatorSymbol.GreaterThan: | 196 | case OperatorSymbol.GreaterThan: |
197 | return (val1.CompareTo(val2) > 0); | 197 | return (val1.CompareTo(val2) > 0); |
198 | case OperatorSymbol.GreaterThanEqual: | 198 | case OperatorSymbol.GreaterThanEqual: |
199 | return (val1.CompareTo(val2) >= 0); | 199 | return (val1.CompareTo(val2) >= 0); |
200 | } | 200 | } |
201 | 201 | ||
202 | throw new WarningException("Unknown operator type"); | 202 | throw new WarningException("Unknown operator type"); |
203 | } | 203 | } |
204 | 204 | ||
205 | private static char NextChar(int idx, string str) | 205 | private static char NextChar(int idx, string str) |
206 | { | 206 | { |
207 | if((idx + 1) >= str.Length) | 207 | if((idx + 1) >= str.Length) |
208 | { | 208 | { |
209 | return Char.MaxValue; | 209 | return Char.MaxValue; |
210 | } | 210 | } |
211 | 211 | ||
212 | return str[idx + 1]; | 212 | return str[idx + 1]; |
213 | } | 213 | } |
214 | // Very very simple expression parser. Can only match expressions of the form | 214 | // Very very simple expression parser. Can only match expressions of the form |
215 | // <var> <op> <value>: | 215 | // <var> <op> <value>: |
216 | // OS = Windows | 216 | // OS = Windows |
217 | // OS != Linux | 217 | // OS != Linux |
218 | // RuntimeMinor > 0 | 218 | // RuntimeMinor > 0 |
219 | private bool ParseExpression(string exp) | 219 | private bool ParseExpression(string exp) |
220 | { | 220 | { |
221 | if(exp == null) | 221 | if(exp == null) |
222 | { | 222 | { |
223 | throw new ArgumentException("Invalid expression, cannot be null"); | 223 | throw new ArgumentException("Invalid expression, cannot be null"); |
224 | } | 224 | } |
225 | 225 | ||
226 | exp = exp.Trim(); | 226 | exp = exp.Trim(); |
227 | if(exp.Length < 1) | 227 | if(exp.Length < 1) |
228 | { | 228 | { |
229 | throw new ArgumentException("Invalid expression, cannot be 0 length"); | 229 | throw new ArgumentException("Invalid expression, cannot be 0 length"); |
230 | } | 230 | } |
231 | 231 | ||
232 | string id = ""; | 232 | string id = ""; |
233 | string str = ""; | 233 | string str = ""; |
234 | OperatorSymbol oper = OperatorSymbol.None; | 234 | OperatorSymbol oper = OperatorSymbol.None; |
235 | bool inStr = false; | 235 | bool inStr = false; |
236 | 236 | ||
237 | for(int i = 0; i < exp.Length; i++) | 237 | for(int i = 0; i < exp.Length; i++) |
238 | { | 238 | { |
239 | char c = exp[i]; | 239 | char c = exp[i]; |
240 | if(Char.IsWhiteSpace(c)) | 240 | if(Char.IsWhiteSpace(c)) |
241 | { | 241 | { |
242 | continue; | 242 | continue; |
243 | } | 243 | } |
244 | 244 | ||
245 | if(Char.IsLetterOrDigit(c) || c == '_') | 245 | if(Char.IsLetterOrDigit(c) || c == '_') |
246 | { | 246 | { |
247 | if(inStr) | 247 | if(inStr) |
248 | { | 248 | { |
249 | str += c; | 249 | str += c; |
250 | } | 250 | } |
251 | else | 251 | else |
252 | { | 252 | { |
253 | id += c; | 253 | id += c; |
254 | } | 254 | } |
255 | } | 255 | } |
256 | else if(c == '\"') | 256 | else if(c == '\"') |
257 | { | 257 | { |
258 | inStr = !inStr; | 258 | inStr = !inStr; |
259 | if(inStr) | 259 | if(inStr) |
260 | { | 260 | { |
261 | str = ""; | 261 | str = ""; |
262 | } | 262 | } |
263 | } | 263 | } |
264 | else | 264 | else |
265 | { | 265 | { |
266 | if(inStr) | 266 | if(inStr) |
267 | { | 267 | { |
268 | str += c; | 268 | str += c; |
269 | } | 269 | } |
270 | else | 270 | else |
271 | { | 271 | { |
272 | switch(c) | 272 | switch(c) |
273 | { | 273 | { |
274 | case '=': | 274 | case '=': |
275 | oper = OperatorSymbol.Equal; | 275 | oper = OperatorSymbol.Equal; |
276 | break; | 276 | break; |
277 | 277 | ||
278 | case '!': | 278 | case '!': |
279 | if(NextChar(i, exp) == '=') | 279 | if(NextChar(i, exp) == '=') |
280 | { | 280 | { |
281 | oper = OperatorSymbol.NotEqual; | 281 | oper = OperatorSymbol.NotEqual; |
282 | } | 282 | } |
283 | 283 | ||
284 | break; | 284 | break; |
285 | 285 | ||
286 | case '<': | 286 | case '<': |
287 | if(NextChar(i, exp) == '=') | 287 | if(NextChar(i, exp) == '=') |
288 | { | 288 | { |
289 | oper = OperatorSymbol.LessThanEqual; | 289 | oper = OperatorSymbol.LessThanEqual; |
290 | } | 290 | } |
291 | else | 291 | else |
292 | { | 292 | { |
293 | oper = OperatorSymbol.LessThan; | 293 | oper = OperatorSymbol.LessThan; |
294 | } | 294 | } |
295 | 295 | ||
296 | break; | 296 | break; |
297 | 297 | ||
298 | case '>': | 298 | case '>': |
299 | if(NextChar(i, exp) == '=') | 299 | if(NextChar(i, exp) == '=') |
300 | { | 300 | { |
301 | oper = OperatorSymbol.GreaterThanEqual; | 301 | oper = OperatorSymbol.GreaterThanEqual; |
302 | } | 302 | } |
303 | else | 303 | else |
304 | { | 304 | { |
305 | oper = OperatorSymbol.GreaterThan; | 305 | oper = OperatorSymbol.GreaterThan; |
306 | } | 306 | } |
307 | 307 | ||
308 | break; | 308 | break; |
309 | } | 309 | } |
310 | } | 310 | } |
311 | } | 311 | } |
312 | } | 312 | } |
313 | 313 | ||
314 | 314 | ||
315 | if(inStr) | 315 | if(inStr) |
316 | { | 316 | { |
317 | throw new WarningException("Expected end of string in expression"); | 317 | throw new WarningException("Expected end of string in expression"); |
318 | } | 318 | } |
319 | 319 | ||
320 | if(oper == OperatorSymbol.None) | 320 | if(oper == OperatorSymbol.None) |
321 | { | 321 | { |
322 | throw new WarningException("Expected operator in expression"); | 322 | throw new WarningException("Expected operator in expression"); |
323 | } | 323 | } |
324 | if(id.Length < 1) | 324 | if(id.Length < 1) |
325 | { | 325 | { |
326 | throw new WarningException("Expected identifier in expression"); | 326 | throw new WarningException("Expected identifier in expression"); |
327 | } | 327 | } |
328 | if(str.Length < 1) | 328 | if(str.Length < 1) |
329 | { | 329 | { |
330 | throw new WarningException("Expected value in expression"); | 330 | throw new WarningException("Expected value in expression"); |
331 | } | 331 | } |
332 | 332 | ||
333 | bool ret; | 333 | bool ret; |
334 | try | 334 | try |
335 | { | 335 | { |
336 | object val = m_Variables[id.ToLower()]; | 336 | object val = m_Variables[id.ToLower()]; |
337 | if(val == null) | 337 | if(val == null) |
338 | { | 338 | { |
339 | throw new WarningException("Unknown identifier '{0}'", id); | 339 | throw new WarningException("Unknown identifier '{0}'", id); |
340 | } | 340 | } |
341 | 341 | ||
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 | int numVal = (int)val; | 345 | int numVal = (int)val; |
346 | int numVal2 = Int32.Parse(str); | 346 | int 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 | string strVal = val.ToString(); | 351 | string strVal = val.ToString(); |
352 | string strVal2 = str; | 352 | string 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 | /// <summary> | 365 | /// <summary> |
366 | /// Taken from current Prebuild included in OpenSim 0.7.x | 366 | /// Taken from current Prebuild included in OpenSim 0.7.x |
@@ -376,13 +376,13 @@ namespace Prebuild.Core.Parse | |||
376 | if (!include.Contains ("*")) { | 376 | if (!include.Contains ("*")) { |
377 | return; | 377 | return; |
378 | } | 378 | } |
379 | 379 | ||
380 | // Console.WriteLine("Processing {0}", include); | 380 | // Console.WriteLine("Processing {0}", include); |
381 | 381 | ||
382 | // Break up the include into pre and post wildcard sections | 382 | // Break up the include into pre and post wildcard sections |
383 | string preWildcard = include.Substring (0, include.IndexOf ("*")); | 383 | string preWildcard = include.Substring (0, include.IndexOf ("*")); |
384 | string postWildcard = include.Substring (include.IndexOf ("*") + 2); | 384 | string postWildcard = include.Substring (include.IndexOf ("*") + 2); |
385 | 385 | ||
386 | // If preWildcard is a directory, recurse | 386 | // If preWildcard is a directory, recurse |
387 | if (Directory.Exists (preWildcard)) { | 387 | if (Directory.Exists (preWildcard)) { |
388 | string[] directories = Directory.GetDirectories (preWildcard); | 388 | string[] directories = Directory.GetDirectories (preWildcard); |
@@ -390,7 +390,7 @@ namespace Prebuild.Core.Parse | |||
390 | Array.Reverse (directories); | 390 | Array.Reverse (directories); |
391 | foreach (string dirPath in directories) { | 391 | foreach (string dirPath in directories) { |
392 | //Console.WriteLine ("Scanning : {0}", dirPath); | 392 | //Console.WriteLine ("Scanning : {0}", dirPath); |
393 | 393 | ||
394 | string includeFile = Path.Combine (dirPath, postWildcard); | 394 | string includeFile = Path.Combine (dirPath, postWildcard); |
395 | if (includeFile.Contains ("*")) { | 395 | if (includeFile.Contains ("*")) { |
396 | // postWildcard included another wildcard, recurse. | 396 | // postWildcard included another wildcard, recurse. |
@@ -408,10 +408,10 @@ namespace Prebuild.Core.Parse | |||
408 | // preWildcard is not a path to a directory, so the wildcard is in the filename | 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); | 409 | string searchFilename = Path.GetFileName (preWildcard.Substring (preWildcard.IndexOf ("/") + 1) + "*" + postWildcard); |
410 | Console.WriteLine ("searchFilename: {0}", searchFilename); | 410 | Console.WriteLine ("searchFilename: {0}", searchFilename); |
411 | 411 | ||
412 | string searchDirectory = Path.GetDirectoryName (preWildcard); | 412 | string searchDirectory = Path.GetDirectoryName (preWildcard); |
413 | Console.WriteLine ("searchDirectory: {0}", searchDirectory); | 413 | Console.WriteLine ("searchDirectory: {0}", searchDirectory); |
414 | 414 | ||
415 | string[] files = Directory.GetFiles (searchDirectory, searchFilename); | 415 | string[] files = Directory.GetFiles (searchDirectory, searchFilename); |
416 | Array.Sort (files); | 416 | Array.Sort (files); |
417 | Array.Reverse (files); | 417 | Array.Reverse (files); |
@@ -426,227 +426,227 @@ namespace Prebuild.Core.Parse | |||
426 | } | 426 | } |
427 | } | 427 | } |
428 | 428 | ||
429 | #endregion | 429 | #endregion |
430 | 430 | ||
431 | #region Public Methods | 431 | #region Public Methods |
432 | 432 | ||
433 | /// <summary> | 433 | /// <summary> |
434 | /// | 434 | /// |
435 | /// </summary> | 435 | /// </summary> |
436 | /// <param name="name"></param> | 436 | /// <param name="name"></param> |
437 | /// <param name="variableValue"></param> | 437 | /// <param name="variableValue"></param> |
438 | public void RegisterVariable(string name, object variableValue) | 438 | public void RegisterVariable(string name, object variableValue) |
439 | { | 439 | { |
440 | if(name == null || variableValue == null) | 440 | if(name == null || variableValue == null) |
441 | { | 441 | { |
442 | return; | 442 | return; |
443 | } | 443 | } |
444 | 444 | ||
445 | m_Variables[name.ToLower()] = variableValue; | 445 | m_Variables[name.ToLower()] = variableValue; |
446 | } | 446 | } |
447 | 447 | ||
448 | /// <summary> | 448 | /// <summary> |
449 | /// 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 |
450 | /// </summary> | 450 | /// </summary> |
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> | 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> |
452 | /// <param name="initialReader"></param> | 452 | /// <param name="initialReader"></param> |
453 | /// <returns>the output xml </returns> | 453 | /// <returns>the output xml </returns> |
454 | public string Process(XmlReader initialReader) | 454 | public string Process(XmlReader initialReader) |
455 | { | 455 | { |
456 | if(initialReader == null) | 456 | if(initialReader == null) |
457 | { | 457 | { |
458 | throw new ArgumentException("Invalid XML reader to pre-process"); | 458 | throw new ArgumentException("Invalid XML reader to pre-process"); |
459 | } | 459 | } |
460 | 460 | ||
461 | IfContext context = new IfContext(true, true, IfState.None); | 461 | IfContext context = new IfContext(true, true, IfState.None); |
462 | StringWriter xmlText = new StringWriter(); | 462 | StringWriter xmlText = new StringWriter(); |
463 | XmlTextWriter writer = new XmlTextWriter(xmlText); | 463 | XmlTextWriter writer = new XmlTextWriter(xmlText); |
464 | writer.Formatting = Formatting.Indented; | 464 | writer.Formatting = Formatting.Indented; |
465 | 465 | ||
466 | // Create a queue of XML readers and add the initial | 466 | // Create a queue of XML readers and add the initial |
467 | // reader to it. Then we process until we run out of | 467 | // reader to it. Then we process until we run out of |
468 | // readers which lets the <?include?> operation add more | 468 | // readers which lets the <?include?> operation add more |
469 | // readers to generate a multi-file parser and not require | 469 | // readers to generate a multi-file parser and not require |
470 | // XML fragments that a recursive version would use. | 470 | // XML fragments that a recursive version would use. |
471 | Stack<XmlReader> readerStack = new Stack<XmlReader>(); | 471 | Stack<XmlReader> readerStack = new Stack<XmlReader>(); |
472 | readerStack.Push(initialReader); | 472 | readerStack.Push(initialReader); |
473 | 473 | ||
474 | while(readerStack.Count > 0) | 474 | while(readerStack.Count > 0) |
475 | { | 475 | { |
476 | // Pop off the next reader. | 476 | // Pop off the next reader. |
477 | XmlReader reader = readerStack.Pop(); | 477 | XmlReader reader = readerStack.Pop(); |
478 | 478 | ||
479 | // Process through this XML reader until it is | 479 | // Process through this XML reader until it is |
480 | // completed (or it is replaced by the include | 480 | // completed (or it is replaced by the include |
481 | // operation). | 481 | // operation). |
482 | while(reader.Read()) | 482 | while(reader.Read()) |
483 | { | 483 | { |
484 | // The prebuild file has a series of processing | 484 | // The prebuild file has a series of processing |
485 | // instructions which allow for specific | 485 | // instructions which allow for specific |
486 | // inclusions based on operating system or to | 486 | // inclusions based on operating system or to |
487 | // include additional files. | 487 | // include additional files. |
488 | if(reader.NodeType == XmlNodeType.ProcessingInstruction) | 488 | if(reader.NodeType == XmlNodeType.ProcessingInstruction) |
489 | { | 489 | { |
490 | bool ignore = false; | 490 | bool ignore = false; |
491 | 491 | ||
492 | switch(reader.LocalName) | 492 | switch(reader.LocalName) |
493 | { | 493 | { |
494 | case "include": | 494 | case "include": |
495 | // use regular expressions to parse out the attributes. | 495 | // use regular expressions to parse out the attributes. |
496 | MatchCollection matches = includeFileRegex.Matches(reader.Value); | 496 | MatchCollection matches = includeFileRegex.Matches(reader.Value); |
497 | 497 | ||
498 | // make sure there is only one file attribute. | 498 | // make sure there is only one file attribute. |
499 | if(matches.Count > 1) | 499 | if(matches.Count > 1) |
500 | { | 500 | { |
501 | throw new WarningException("An <?include ?> node was found, but it specified more than one file."); | 501 | throw new WarningException("An <?include ?> node was found, but it specified more than one file."); |
502 | } | 502 | } |
503 | 503 | ||
504 | if(matches.Count == 0) | 504 | if(matches.Count == 0) |
505 | { | 505 | { |
506 | 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."); |
507 | } | 507 | } |
508 | 508 | ||
509 | // ***** Adding for wildcard handling | 509 | // ***** Adding for wildcard handling |
510 | // Push current reader back onto the stack. | 510 | // Push current reader back onto the stack. |
511 | readerStack.Push (reader); | 511 | readerStack.Push (reader); |
512 | 512 | ||
513 | // Pull the file out from the regex and make sure it is a valid file before using it. | 513 | // Pull the file out from the regex and make sure it is a valid file before using it. |
514 | string filename = matches[0].Groups[1].Value; | 514 | string filename = matches[0].Groups[1].Value; |
515 | 515 | ||
516 | filename = String.Join (Path.DirectorySeparatorChar.ToString (), filename.Split (new char[] { '/', '\\' })); | 516 | filename = String.Join (Path.DirectorySeparatorChar.ToString (), filename.Split (new char[] { '/', '\\' })); |
517 | 517 | ||
518 | if (!filename.Contains ("*")) { | 518 | if (!filename.Contains ("*")) { |
519 | 519 | ||
520 | FileInfo includeFile = new FileInfo (filename); | 520 | FileInfo includeFile = new FileInfo (filename); |
521 | if (!includeFile.Exists) { | 521 | if (!includeFile.Exists) { |
522 | throw new WarningException ("Cannot include file: " + includeFile.FullName); | 522 | throw new WarningException ("Cannot include file: " + includeFile.FullName); |
523 | } | 523 | } |
524 | 524 | ||
525 | // Create a new reader object for this file. Then put the old reader back on the stack and start | 525 | // Create a new reader object for this file. Then put the old reader back on the stack and start |
526 | // processing using this new XML reader. | 526 | // processing using this new XML reader. |
527 | 527 | ||
528 | XmlReader newReader = new XmlTextReader (includeFile.Open (FileMode.Open, FileAccess.Read, FileShare.Read)); | 528 | XmlReader newReader = new XmlTextReader (includeFile.Open (FileMode.Open, FileAccess.Read, FileShare.Read)); |
529 | reader = newReader; | 529 | reader = newReader; |
530 | readerStack.Push (reader); | 530 | readerStack.Push (reader); |
531 | 531 | ||
532 | } else { | 532 | } else { |
533 | WildCardInclude (readerStack, filename); | 533 | WildCardInclude (readerStack, filename); |
534 | } | 534 | } |
535 | 535 | ||
536 | reader = (XmlReader)readerStack.Pop (); | 536 | reader = (XmlReader)readerStack.Pop (); |
537 | ignore = true; | 537 | ignore = true; |
538 | break; | 538 | break; |
539 | 539 | ||
540 | case "if": | 540 | case "if": |
541 | m_IfStack.Push(context); | 541 | m_IfStack.Push(context); |
542 | context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If); | 542 | context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If); |
543 | ignore = true; | 543 | ignore = true; |
544 | break; | 544 | break; |
545 | 545 | ||
546 | case "elseif": | 546 | case "elseif": |
547 | if(m_IfStack.Count == 0) | 547 | if(m_IfStack.Count == 0) |
548 | { | 548 | { |
549 | throw new WarningException("Unexpected 'elseif' outside of 'if'"); | 549 | throw new WarningException("Unexpected 'elseif' outside of 'if'"); |
550 | } | 550 | } |
551 | if(context.State != IfState.If && context.State != IfState.ElseIf) | 551 | if(context.State != IfState.If && context.State != IfState.ElseIf) |
552 | { | 552 | { |
553 | throw new WarningException("Unexpected 'elseif' outside of 'if'"); | 553 | throw new WarningException("Unexpected 'elseif' outside of 'if'"); |
554 | } | 554 | } |
555 | 555 | ||
556 | context.State = IfState.ElseIf; | 556 | context.State = IfState.ElseIf; |
557 | if(!context.EverKept) | 557 | if(!context.EverKept) |
558 | { | 558 | { |
559 | context.Keep = ParseExpression(reader.Value); | 559 | context.Keep = ParseExpression(reader.Value); |
560 | } | 560 | } |
561 | else | 561 | else |
562 | { | 562 | { |
563 | context.Keep = false; | 563 | context.Keep = false; |
564 | } | 564 | } |
565 | 565 | ||
566 | ignore = true; | 566 | ignore = true; |
567 | break; | 567 | break; |
568 | 568 | ||
569 | case "else": | 569 | case "else": |
570 | if(m_IfStack.Count == 0) | 570 | if(m_IfStack.Count == 0) |
571 | { | 571 | { |
572 | throw new WarningException("Unexpected 'else' outside of 'if'"); | 572 | throw new WarningException("Unexpected 'else' outside of 'if'"); |
573 | } | 573 | } |
574 | if(context.State != IfState.If && context.State != IfState.ElseIf) | 574 | if(context.State != IfState.If && context.State != IfState.ElseIf) |
575 | { | 575 | { |
576 | throw new WarningException("Unexpected 'else' outside of 'if'"); | 576 | throw new WarningException("Unexpected 'else' outside of 'if'"); |
577 | } | 577 | } |
578 | 578 | ||
579 | context.State = IfState.Else; | 579 | context.State = IfState.Else; |
580 | context.Keep = !context.EverKept; | 580 | context.Keep = !context.EverKept; |
581 | ignore = true; | 581 | ignore = true; |
582 | break; | 582 | break; |
583 | 583 | ||
584 | case "endif": | 584 | case "endif": |
585 | if(m_IfStack.Count == 0) | 585 | if(m_IfStack.Count == 0) |
586 | { | 586 | { |
587 | throw new WarningException("Unexpected 'endif' outside of 'if'"); | 587 | throw new WarningException("Unexpected 'endif' outside of 'if'"); |
588 | } | 588 | } |
589 | 589 | ||
590 | context = m_IfStack.Pop(); | 590 | context = m_IfStack.Pop(); |
591 | ignore = true; | 591 | ignore = true; |
592 | break; | 592 | break; |
593 | } | 593 | } |
594 | 594 | ||
595 | if(ignore) | 595 | if(ignore) |
596 | { | 596 | { |
597 | continue; | 597 | continue; |
598 | } | 598 | } |
599 | }//end pre-proc instruction | 599 | }//end pre-proc instruction |
600 | 600 | ||
601 | if(!context.Active || !context.Keep) | 601 | if(!context.Active || !context.Keep) |
602 | { | 602 | { |
603 | continue; | 603 | continue; |
604 | } | 604 | } |
605 | 605 | ||
606 | switch(reader.NodeType) | 606 | switch(reader.NodeType) |
607 | { | 607 | { |
608 | case XmlNodeType.Element: | 608 | case XmlNodeType.Element: |
609 | bool empty = reader.IsEmptyElement; | 609 | bool empty = reader.IsEmptyElement; |
610 | writer.WriteStartElement(reader.Name); | 610 | writer.WriteStartElement(reader.Name); |
611 | 611 | ||
612 | while (reader.MoveToNextAttribute()) | 612 | while (reader.MoveToNextAttribute()) |
613 | { | 613 | { |
614 | writer.WriteAttributeString(reader.Name, reader.Value); | 614 | writer.WriteAttributeString(reader.Name, reader.Value); |
615 | } | 615 | } |
616 | 616 | ||
617 | if(empty) | 617 | if(empty) |
618 | { | 618 | { |
619 | writer.WriteEndElement(); | 619 | writer.WriteEndElement(); |
620 | } | 620 | } |
621 | 621 | ||
622 | break; | 622 | break; |
623 | 623 | ||
624 | case XmlNodeType.EndElement: | 624 | case XmlNodeType.EndElement: |
625 | writer.WriteEndElement(); | 625 | writer.WriteEndElement(); |
626 | break; | 626 | break; |
627 | 627 | ||
628 | case XmlNodeType.Text: | 628 | case XmlNodeType.Text: |
629 | writer.WriteString(reader.Value); | 629 | writer.WriteString(reader.Value); |
630 | break; | 630 | break; |
631 | 631 | ||
632 | case XmlNodeType.CDATA: | 632 | case XmlNodeType.CDATA: |
633 | writer.WriteCData(reader.Value); | 633 | writer.WriteCData(reader.Value); |
634 | break; | 634 | break; |
635 | 635 | ||
636 | default: | 636 | default: |
637 | break; | 637 | break; |
638 | } | 638 | } |
639 | } | 639 | } |
640 | 640 | ||
641 | if(m_IfStack.Count != 0) | 641 | if(m_IfStack.Count != 0) |
642 | { | 642 | { |
643 | throw new WarningException("Mismatched 'if', 'endif' pair"); | 643 | throw new WarningException("Mismatched 'if', 'endif' pair"); |
644 | } | 644 | } |
645 | } | 645 | } |
646 | 646 | ||
647 | return xmlText.ToString(); | 647 | return xmlText.ToString(); |
648 | } | 648 | } |
649 | 649 | ||
650 | #endregion | 650 | #endregion |
651 | } | 651 | } |
652 | } | 652 | } |