| Line No. | Rev | Author | Line |
|---|---|---|---|
| 1 | 32 | kaklik | /********************************************************************* |
| 2 | * |
||
| 3 | * Dynamic Variable Parser Library |
||
| 4 | * |
||
| 5 | ********************************************************************* |
||
| 6 | * FileName: DynVar.cs |
||
| 7 | * Dependencies: Microsoft .NET Framework 2.0 |
||
| 8 | * Processor: x86 |
||
| 9 | * Complier: Microsoft Visual C# 2008 Express Edition |
||
| 10 | * Company: Microchip Technology, Inc. |
||
| 11 | * |
||
| 12 | * Software License Agreement |
||
| 13 | * |
||
| 14 | * This software is owned by Microchip Technology Inc. ("Microchip") |
||
| 15 | * and is supplied to you for use exclusively as described in the |
||
| 16 | * associated software agreement. This software is protected by |
||
| 17 | * software and other intellectual property laws. Any use in |
||
| 18 | * violation of the software license may subject the user to criminal |
||
| 19 | * sanctions as well as civil liability. Copyright 2008 Microchip |
||
| 20 | * Technology Inc. All rights reserved. |
||
| 21 | * |
||
| 22 | * |
||
| 23 | * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT |
||
| 24 | * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT |
||
| 25 | * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A |
||
| 26 | * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
| 27 | * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR |
||
| 28 | * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF |
||
| 29 | * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS |
||
| 30 | * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE |
||
| 31 | * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER |
||
| 32 | * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT |
||
| 33 | * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE. |
||
| 34 | * |
||
| 35 | * |
||
| 36 | * Author Date Comment |
||
| 37 | *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
| 38 | * Elliott Wood 4/17/2008 Original |
||
| 39 | ********************************************************************/ |
||
| 40 | using System; |
||
| 41 | using System.Collections.Generic; |
||
| 42 | using System.Collections.ObjectModel; |
||
| 43 | using System.Text; |
||
| 44 | using System.Text.RegularExpressions; |
||
| 45 | using System.IO; |
||
| 46 | |||
| 47 | namespace Microchip |
||
| 48 | { |
||
| 49 | |||
| 50 | public class DynamicVariableParser |
||
| 51 | { |
||
| 52 | UInt32 offSetCounter = 0; |
||
| 53 | UInt32 parseItrtn=0; |
||
| 54 | UInt32 tempFileRcrdLen=0; |
||
| 55 | |||
| 56 | #region Fields |
||
| 57 | private List<DynamicVariable> vars; |
||
| 58 | private Regex parser = new Regex(@"~(inc:[A-Za-z0-9\ \.-_\\/]{1,60}|[A-Za-z0-9_]{0,40}(\([A-Za-z0-9_,\ ]*\))?)~"); |
||
| 59 | private ASCIIEncoding ascii = new ASCIIEncoding(); |
||
| 60 | private String projectDir; |
||
| 61 | #endregion |
||
| 62 | |||
| 63 | #region String Constants |
||
| 64 | const string HTTPPRINT_H_HEADER = |
||
| 65 | "/**************************************************************\r\n" + |
||
| 66 | " * HTTPPrint.h\r\n" + |
||
| 67 | " * Provides callback headers and resolution for user\'s custom\r\n" + |
||
| 68 | " * HTTP Application.\r\n" + |
||
| 69 | " * \r\n" + |
||
| 70 | " * This file is automatically generated by the MPFS Utility\r\n" + |
||
| 71 | " * ALL MODIFICATIONS WILL BE OVERWRITTEN BY THE MPFS GENERATOR\r\n" + |
||
| 72 | " **************************************************************/\r\n\r\n" + |
||
| 73 | "#ifndef __HTTPPRINT_H\r\n" + |
||
| 74 | "#define __HTTPPRINT_H\r\n\r\n" + |
||
| 75 | "#include \"TCPIP Stack/TCPIP.h\"\r\n\r\n" + |
||
| 76 | "#if defined(STACK_USE_HTTP2_SERVER)\r\n\r\n" + |
||
| 77 | "extern HTTP_CONN curHTTP;\r\n" + |
||
| 78 | "extern HTTP_STUB httpStubs[MAX_HTTP_CONNECTIONS];\r\n" + |
||
| 79 | "extern BYTE curHTTPID;\r\n\r\n" + |
||
| 80 | "void HTTPPrint(DWORD callbackID);\r\n"; |
||
| 81 | const string HTTPPRINT_H_MIDDLE = |
||
| 82 | "\r\nvoid HTTPPrint(DWORD callbackID)\r\n" + |
||
| 83 | "{\r\n" + |
||
| 84 | " switch(callbackID)\r\n" + |
||
| 85 | " {\r\n"; |
||
| 86 | const string HTTPPRINT_H_FOOTER = |
||
| 87 | " default:\r\n" + |
||
| 88 | " // Output notification for undefined values\r\n" + |
||
| 89 | " TCPPutROMArray(sktHTTP, (ROM BYTE*)\"!DEF\", 4);\r\n" + |
||
| 90 | " }\r\n\r\n" + |
||
| 91 | " return;\r\n" + |
||
| 92 | "}\r\n\r\n" + |
||
| 93 | "void HTTPPrint_(void)\r\n" + |
||
| 94 | "{\r\n" + |
||
| 95 | " TCPPut(sktHTTP, '~');\r\n" + |
||
| 96 | " return;\r\n" + |
||
| 97 | "}\r\n\r\n#endif\r\n\r\n#endif\r\n"; |
||
| 98 | #endregion |
||
| 99 | |||
| 100 | #region Constructor |
||
| 101 | public DynamicVariableParser(String path) |
||
| 102 | { |
||
| 103 | this.projectDir = path; |
||
| 104 | vars = new List<DynamicVariable>(); |
||
| 105 | |||
| 106 | // Read previous index file if it exists. |
||
| 107 | try |
||
| 108 | { |
||
| 109 | if (File.Exists(projectDir + "HTTPPrint.idx")) |
||
| 110 | { |
||
| 111 | StreamReader fin = new StreamReader(projectDir + "HTTPPrint.idx"); |
||
| 112 | String s = fin.ReadLine(); |
||
| 113 | |||
| 114 | // Ignore old MPFS2.0 HTTPPrint.idx files |
||
| 115 | if (!s.Contains("|")) |
||
| 116 | { |
||
| 117 | while (s != null) |
||
| 118 | { |
||
| 119 | DynamicVariable dv = new DynamicVariable(s); |
||
| 120 | vars.Add(dv); |
||
| 121 | s = fin.ReadLine(); |
||
| 122 | } |
||
| 123 | } |
||
| 124 | fin.Close(); |
||
| 125 | } |
||
| 126 | } |
||
| 127 | catch |
||
| 128 | { |
||
| 129 | // do nothing...just won't have old index information |
||
| 130 | } |
||
| 131 | } |
||
| 132 | #endregion |
||
| 133 | |||
| 134 | /// <summary> |
||
| 135 | /// Parses and indexes a file for dynamic variables |
||
| 136 | /// </summary> |
||
| 137 | /// <param name="file">The MPFSFileRecord to parse</param> |
||
| 138 | /// <returns>An MPFSFileRecord of indexes, or null if no variables were found</returns> |
||
| 139 | public MPFSFileRecord Parse(MPFSFileRecord file) |
||
| 140 | { |
||
| 141 | byte[] idxData = new byte[0]; |
||
| 142 | UInt32 dynVarCntr=0; |
||
| 143 | |||
| 144 | |||
| 145 | MatchCollection matches = parser.Matches(ascii.GetString(file.data)); |
||
| 146 | foreach(Match m in matches) |
||
| 147 | { |
||
| 148 | int i = GetIndex(m.Value.Replace(" ","").Replace("~","")); |
||
| 149 | Array.Resize(ref idxData, idxData.Length + 8); |
||
| 150 | idxData[idxData.Length - 8] = (byte)m.Index; |
||
| 151 | idxData[idxData.Length - 7] = (byte)(m.Index >> 8); |
||
| 152 | idxData[idxData.Length - 6] = (byte)(m.Index >> 16); |
||
| 153 | idxData[idxData.Length - 5] = (byte)(m.Index >> 24); |
||
| 154 | idxData[idxData.Length - 4] = (byte)i; |
||
| 155 | idxData[idxData.Length - 3] = (byte)(i >> 8); |
||
| 156 | idxData[idxData.Length - 2] = (byte)(i >> 16); |
||
| 157 | idxData[idxData.Length - 1] = (byte)(i >> 24); |
||
| 158 | |||
| 159 | |||
| 160 | Array.Resize(ref file.dynVarOffsetAndIndexID, file.dynVarOffsetAndIndexID.Length + 8); |
||
| 161 | |||
| 162 | file.dynVarOffsetAndIndexID[file.dynVarOffsetAndIndexID.Length - 1] = (byte)(i >> 24); |
||
| 163 | file.dynVarOffsetAndIndexID[file.dynVarOffsetAndIndexID.Length - 2] = (byte)(i >> 16); |
||
| 164 | file.dynVarOffsetAndIndexID[file.dynVarOffsetAndIndexID.Length - 3] = (byte)(i >> 8); |
||
| 165 | file.dynVarOffsetAndIndexID[file.dynVarOffsetAndIndexID.Length - 4] = ((byte)i); |
||
| 166 | |||
| 167 | |||
| 168 | file.dynVarOffsetAndIndexID[file.dynVarOffsetAndIndexID.Length - 5] = (byte)(m.Index >> 24); |
||
| 169 | file.dynVarOffsetAndIndexID[file.dynVarOffsetAndIndexID.Length - 6] = (byte)(m.Index >> 16); |
||
| 170 | file.dynVarOffsetAndIndexID[file.dynVarOffsetAndIndexID.Length - 7] = (byte)(m.Index >> 8); |
||
| 171 | file.dynVarOffsetAndIndexID[file.dynVarOffsetAndIndexID.Length - 8] = (byte)m.Index; |
||
| 172 | |||
| 173 | file.dynVarCntr = ++dynVarCntr; |
||
| 174 | offSetCounter = offSetCounter + 8; |
||
| 175 | |||
| 176 | } |
||
| 177 | |||
| 178 | if(parseItrtn == (UInt32)0x0) |
||
| 179 | { |
||
| 180 | file.fileRecordOffset = (UInt32)0x0; |
||
| 181 | offSetCounter = (UInt32)0x0; |
||
| 182 | } |
||
| 183 | else |
||
| 184 | { |
||
| 185 | //file.fileRecordOffset=tempFileRcrdLen+1; |
||
| 186 | file.fileRecordOffset=tempFileRcrdLen; |
||
| 187 | } |
||
| 188 | |||
| 189 | file.fileRecordLength = 4 /* 4 bytes for file record length itself*/ |
||
| 190 | +2 /*To store the hasIndex/isZipped flag*/ |
||
| 191 | //+(UInt32)file.FileName.Length |
||
| 192 | + file.dynVarCntr*8; |
||
| 193 | |||
| 194 | tempFileRcrdLen += file.fileRecordLength; |
||
| 195 | |||
| 196 | parseItrtn++; |
||
| 197 | |||
| 198 | |||
| 199 | // Determine if any matches were made |
||
| 200 | if (idxData.Length == 0) |
||
| 201 | return null; |
||
| 202 | else |
||
| 203 | { |
||
| 204 | // Set up new file record |
||
| 205 | MPFSFileRecord idxFile = new MPFSFileRecord(); |
||
| 206 | idxFile.FileName = ""; |
||
| 207 | idxFile.fileDate = file.fileDate; |
||
| 208 | idxFile.isIndex = true; |
||
| 209 | idxFile.data = idxData; |
||
| 210 | return idxFile; |
||
| 211 | } |
||
| 212 | |||
| 213 | } |
||
| 214 | |||
| 215 | /// <summary> |
||
| 216 | /// Writes out HTTPPrint.h and HTTPPrint.idx if necessary |
||
| 217 | /// </summary> |
||
| 218 | /// <returns>TRUE if the files were written, FALSE if no changes are needed</returns> |
||
| 219 | public bool WriteIndices() |
||
| 220 | { |
||
| 221 | // Determine if an update is necessary |
||
| 222 | bool isChanged = false; |
||
| 223 | foreach (DynamicVariable dv in vars) |
||
| 224 | { |
||
| 225 | if ((dv.WasUsed && dv.Count == 0) || |
||
| 226 | (!dv.WasUsed && dv.Count != 0)) |
||
| 227 | { |
||
| 228 | isChanged = true; |
||
| 229 | break; |
||
| 230 | } |
||
| 231 | } |
||
| 232 | if (!isChanged) |
||
| 233 | return false; |
||
| 234 | |||
| 235 | // Write out HTTPPrint.idx |
||
| 236 | StreamWriter fout = new StreamWriter(projectDir + "HTTPPrint.idx", false); |
||
| 237 | foreach (DynamicVariable dv in vars) |
||
| 238 | { |
||
| 239 | if (dv.Count > 0) |
||
| 240 | fout.Write('+'); |
||
| 241 | fout.WriteLine(dv.Name); |
||
| 242 | } |
||
| 243 | fout.Flush(); |
||
| 244 | fout.Close(); |
||
| 245 | |||
| 246 | // Begin writing HTTPPrint.h |
||
| 247 | fout = new StreamWriter(projectDir + "HTTPPrint.h", false); |
||
| 248 | fout.Write(HTTPPRINT_H_HEADER); |
||
| 249 | |||
| 250 | // Write the prototypes |
||
| 251 | List<string> prototypes = new List<string>(); |
||
| 252 | Regex rGetParts = new Regex(@"([A-Za-z0-9_]{0,40})(\(([A-Za-z0-9_,]*)\))?"); |
||
| 253 | foreach (DynamicVariable dv in vars) |
||
| 254 | { |
||
| 255 | if (dv.Name.StartsWith("inc:") || dv.Count == 0) |
||
| 256 | continue; |
||
| 257 | Match m = rGetParts.Match(dv.Name); |
||
| 258 | if (prototypes.Contains(m.Groups[1].Value)) |
||
| 259 | continue; |
||
| 260 | |||
| 261 | // Add the prototype |
||
| 262 | prototypes.Add(m.Groups[1].Value); |
||
| 263 | fout.Write("void HTTPPrint_" + m.Groups[1].Value + "("); |
||
| 264 | if(m.Groups.Count == 4 && m.Groups[3].Value.Length > 0) |
||
| 265 | { |
||
| 266 | int numParams = m.Groups[3].Value.Split(',').Length; |
||
| 267 | for (int i = 0; i < numParams - 1; i++) |
||
| 268 | fout.Write("WORD,"); |
||
| 269 | fout.Write("WORD"); |
||
| 270 | } |
||
| 271 | else |
||
| 272 | { |
||
| 273 | fout.Write("void"); |
||
| 274 | } |
||
| 275 | fout.Write(");\r\n"); |
||
| 276 | } |
||
| 277 | |||
| 278 | // Write the function itself |
||
| 279 | fout.Write(HTTPPRINT_H_MIDDLE); |
||
| 280 | int index = 0; |
||
| 281 | foreach (DynamicVariable dv in vars) |
||
| 282 | { |
||
| 283 | if (dv.Count == 0) |
||
| 284 | { |
||
| 285 | index++; |
||
| 286 | continue; |
||
| 287 | } |
||
| 288 | |||
| 289 | fout.Write(" case 0x" + Convert.ToString(index++, 16).PadLeft(8, '0') + ":\r\n"); |
||
| 290 | |||
| 291 | // Write the actual case statement |
||
| 292 | if(dv.Name.StartsWith("inc:")) |
||
| 293 | { |
||
| 294 | fout.Write("\t\t\tHTTPIncFile((ROM BYTE*)\"" + dv.Name.Substring(4) + "\");\r\n\t\t\tbreak;\r\n"); |
||
| 295 | } |
||
| 296 | else |
||
| 297 | { |
||
| 298 | fout.Write("\t\t\tHTTPPrint_" + dv.Name); |
||
| 299 | if(!dv.Name.EndsWith(")")) |
||
| 300 | fout.Write("()"); |
||
| 301 | fout.Write(";\r\n\t\t\tbreak;\r\n"); |
||
| 302 | } |
||
| 303 | } |
||
| 304 | |||
| 305 | // Write the footer part |
||
| 306 | fout.Write(HTTPPRINT_H_FOOTER); |
||
| 307 | fout.Flush(); |
||
| 308 | fout.Close(); |
||
| 309 | |||
| 310 | return true; |
||
| 311 | } |
||
| 312 | |||
| 313 | #region Private Methods |
||
| 314 | /// <summary> |
||
| 315 | /// Finds the index of a dynamic variable, or creates a new one |
||
| 316 | /// </summary> |
||
| 317 | /// <param name="name"></param> |
||
| 318 | /// <returns>The index of the dynamic variable</returns> |
||
| 319 | private int GetIndex(String name) |
||
| 320 | { |
||
| 321 | // Search for the dynamic variable |
||
| 322 | DynamicVariable dv = new DynamicVariable(name); |
||
| 323 | int i = vars.IndexOf(dv); |
||
| 324 | |||
| 325 | // If not found, add a new one |
||
| 326 | if (i == -1) |
||
| 327 | { |
||
| 328 | vars.Add(dv); |
||
| 329 | i = vars.Count - 1; |
||
| 330 | } |
||
| 331 | |||
| 332 | // Mark as used and return the index |
||
| 333 | vars[i].Count++; |
||
| 334 | return i; |
||
| 335 | } |
||
| 336 | #endregion |
||
| 337 | |||
| 338 | } |
||
| 339 | |||
| 340 | public class DynamicVariable |
||
| 341 | { |
||
| 342 | #region Fields |
||
| 343 | private String name; |
||
| 344 | private bool wasUsed; |
||
| 345 | private int count; |
||
| 346 | #endregion |
||
| 347 | |||
| 348 | #region Properties |
||
| 349 | /// <summary> |
||
| 350 | /// Gets or sets the name of this DynamicVariable |
||
| 351 | /// </summary> |
||
| 352 | public String Name |
||
| 353 | { |
||
| 354 | get { return this.name; } |
||
| 355 | set { this.name = value; } |
||
| 356 | } |
||
| 357 | |||
| 358 | /// <summary> |
||
| 359 | /// Indicates if this specific instance was previously used |
||
| 360 | /// </summary> |
||
| 361 | public bool WasUsed |
||
| 362 | { |
||
| 363 | get { return this.wasUsed; } |
||
| 364 | set { this.wasUsed = value; } |
||
| 365 | } |
||
| 366 | |||
| 367 | /// <summary> |
||
| 368 | /// Indicates how many times this instance is used |
||
| 369 | /// </summary> |
||
| 370 | public int Count |
||
| 371 | { |
||
| 372 | get { return this.count; } |
||
| 373 | set { this.count = value; } |
||
| 374 | } |
||
| 375 | |||
| 376 | private long _offsetCntr = 0; |
||
| 377 | public long offsetCntr |
||
| 378 | { |
||
| 379 | get { return _offsetCntr; } |
||
| 380 | set { _offsetCntr = value; } |
||
| 381 | } |
||
| 382 | #endregion |
||
| 383 | |||
| 384 | #region Constructor |
||
| 385 | public DynamicVariable(String name) |
||
| 386 | { |
||
| 387 | this.wasUsed = name.StartsWith("+"); |
||
| 388 | this.name = Regex.Replace(name, @"[\ \+]", ""); |
||
| 389 | this.count = 0; |
||
| 390 | } |
||
| 391 | #endregion |
||
| 392 | |||
| 393 | public override bool Equals(object obj) |
||
| 394 | { |
||
| 395 | if (obj is DynamicVariable) |
||
| 396 | return ((DynamicVariable)obj).Name == this.name; |
||
| 397 | else |
||
| 398 | return false; |
||
| 399 | } |
||
| 400 | |||
| 401 | public override int GetHashCode() |
||
| 402 | { |
||
| 403 | return this.name.GetHashCode(); |
||
| 404 | } |
||
| 405 | } |
||
| 406 | |||
| 407 | } |
Powered by WebSVN v2.8.3