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