]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Eot/CodeFragmentCollector.py
BaseTools: remove uncalled function
[mirror_edk2.git] / BaseTools / Source / Python / Eot / CodeFragmentCollector.py
CommitLineData
52302d4d
LG
1## @file\r
2# preprocess source file\r
3#\r
231fdbb2 4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
52302d4d 5#\r
40d841f6 6# This program and the accompanying materials\r
52302d4d
LG
7# are licensed and made available under the terms and conditions of the BSD License\r
8# which accompanies this distribution. The full text of the license may be found at\r
9# http://opensource.org/licenses/bsd-license.php\r
10#\r
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13#\r
14\r
15##\r
16# Import Modules\r
17#\r
18import re\r
1be2ed90 19import Common.LongFilePathOs as os\r
52302d4d
LG
20import sys\r
21\r
22import antlr3\r
23from CLexer import CLexer\r
24from CParser import CParser\r
25\r
26import FileProfile\r
27from CodeFragment import PP_Directive\r
28from ParserWarning import Warning\r
29\r
30\r
31##define T_CHAR_SPACE ' '\r
32##define T_CHAR_NULL '\0'\r
33##define T_CHAR_CR '\r'\r
34##define T_CHAR_TAB '\t'\r
35##define T_CHAR_LF '\n'\r
36##define T_CHAR_SLASH '/'\r
37##define T_CHAR_BACKSLASH '\\'\r
38##define T_CHAR_DOUBLE_QUOTE '\"'\r
39##define T_CHAR_SINGLE_QUOTE '\''\r
40##define T_CHAR_STAR '*'\r
41##define T_CHAR_HASH '#'\r
42\r
43(T_CHAR_SPACE, T_CHAR_NULL, T_CHAR_CR, T_CHAR_TAB, T_CHAR_LF, T_CHAR_SLASH, \\r
44T_CHAR_BACKSLASH, T_CHAR_DOUBLE_QUOTE, T_CHAR_SINGLE_QUOTE, T_CHAR_STAR, T_CHAR_HASH) = \\r
45(' ', '\0', '\r', '\t', '\n', '/', '\\', '\"', '\'', '*', '#')\r
46\r
47SEPERATOR_TUPLE = ('=', '|', ',', '{', '}')\r
48\r
49(T_COMMENT_TWO_SLASH, T_COMMENT_SLASH_STAR) = (0, 1)\r
50\r
51(T_PP_INCLUDE, T_PP_DEFINE, T_PP_OTHERS) = (0, 1, 2)\r
52\r
53## The collector for source code fragments.\r
54#\r
55# PreprocessFile method should be called prior to ParseFile\r
56#\r
57# GetNext*** procedures mean these procedures will get next token first, then make judgement.\r
58# Get*** procedures mean these procedures will make judgement on current token only.\r
59#\r
60class CodeFragmentCollector:\r
61 ## The constructor\r
62 #\r
63 # @param self The object pointer\r
64 # @param FileName The file that to be parsed\r
65 #\r
66 def __init__(self, FileName):\r
67 self.Profile = FileProfile.FileProfile(FileName)\r
68 self.Profile.FileLinesList.append(T_CHAR_LF)\r
69 self.FileName = FileName\r
70 self.CurrentLineNumber = 1\r
71 self.CurrentOffsetWithinLine = 0\r
72\r
73 self.__Token = ""\r
74 self.__SkippedChars = ""\r
75\r
52302d4d
LG
76 ## __SkipWhiteSpace() method\r
77 #\r
78 # Skip white spaces from current char, return number of chars skipped\r
79 #\r
80 # @param self The object pointer\r
81 # @retval Count The number of chars skipped\r
82 #\r
83 def __SkipWhiteSpace(self):\r
84 Count = 0\r
85 while not self.__EndOfFile():\r
86 Count += 1\r
87 if self.__CurrentChar() in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_LF, T_CHAR_SPACE, T_CHAR_TAB):\r
88 self.__SkippedChars += str(self.__CurrentChar())\r
89 self.__GetOneChar()\r
90\r
91 else:\r
92 Count = Count - 1\r
93 return Count\r
94\r
95 ## __EndOfFile() method\r
96 #\r
97 # Judge current buffer pos is at file end\r
98 #\r
99 # @param self The object pointer\r
100 # @retval True Current File buffer position is at file end\r
101 # @retval False Current File buffer position is NOT at file end\r
102 #\r
103 def __EndOfFile(self):\r
104 NumberOfLines = len(self.Profile.FileLinesList)\r
105 SizeOfLastLine = len(self.Profile.FileLinesList[-1])\r
106 if self.CurrentLineNumber == NumberOfLines and self.CurrentOffsetWithinLine >= SizeOfLastLine - 1:\r
107 return True\r
108 elif self.CurrentLineNumber > NumberOfLines:\r
109 return True\r
110 else:\r
111 return False\r
112\r
113 ## __EndOfLine() method\r
114 #\r
115 # Judge current buffer pos is at line end\r
116 #\r
117 # @param self The object pointer\r
118 # @retval True Current File buffer position is at line end\r
119 # @retval False Current File buffer position is NOT at line end\r
120 #\r
121 def __EndOfLine(self):\r
122 SizeOfCurrentLine = len(self.Profile.FileLinesList[self.CurrentLineNumber - 1])\r
123 if self.CurrentOffsetWithinLine >= SizeOfCurrentLine - 1:\r
124 return True\r
125 else:\r
126 return False\r
127\r
128 ## Rewind() method\r
129 #\r
130 # Reset file data buffer to the initial state\r
131 #\r
132 # @param self The object pointer\r
133 #\r
134 def Rewind(self):\r
135 self.CurrentLineNumber = 1\r
136 self.CurrentOffsetWithinLine = 0\r
137\r
138 ## __UndoOneChar() method\r
139 #\r
140 # Go back one char in the file buffer\r
141 #\r
142 # @param self The object pointer\r
143 # @retval True Successfully go back one char\r
144 # @retval False Not able to go back one char as file beginning reached\r
145 #\r
146 def __UndoOneChar(self):\r
147\r
148 if self.CurrentLineNumber == 1 and self.CurrentOffsetWithinLine == 0:\r
149 return False\r
150 elif self.CurrentOffsetWithinLine == 0:\r
151 self.CurrentLineNumber -= 1\r
152 self.CurrentOffsetWithinLine = len(self.__CurrentLine()) - 1\r
153 else:\r
154 self.CurrentOffsetWithinLine -= 1\r
155 return True\r
156\r
157 ## __GetOneChar() method\r
158 #\r
159 # Move forward one char in the file buffer\r
160 #\r
161 # @param self The object pointer\r
162 #\r
163 def __GetOneChar(self):\r
164 if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:\r
165 self.CurrentLineNumber += 1\r
166 self.CurrentOffsetWithinLine = 0\r
167 else:\r
168 self.CurrentOffsetWithinLine += 1\r
169\r
170 ## __CurrentChar() method\r
171 #\r
172 # Get the char pointed to by the file buffer pointer\r
173 #\r
174 # @param self The object pointer\r
175 # @retval Char Current char\r
176 #\r
177 def __CurrentChar(self):\r
178 CurrentChar = self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine]\r
179\r
180 return CurrentChar\r
181\r
182 ## __NextChar() method\r
183 #\r
184 # Get the one char pass the char pointed to by the file buffer pointer\r
185 #\r
186 # @param self The object pointer\r
187 # @retval Char Next char\r
188 #\r
189 def __NextChar(self):\r
190 if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:\r
191 return self.Profile.FileLinesList[self.CurrentLineNumber][0]\r
192 else:\r
193 return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine + 1]\r
194\r
195 ## __SetCurrentCharValue() method\r
196 #\r
197 # Modify the value of current char\r
198 #\r
199 # @param self The object pointer\r
200 # @param Value The new value of current char\r
201 #\r
202 def __SetCurrentCharValue(self, Value):\r
203 self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] = Value\r
204\r
205 ## __SetCharValue() method\r
206 #\r
207 # Modify the value of current char\r
208 #\r
209 # @param self The object pointer\r
210 # @param Value The new value of current char\r
211 #\r
212 def __SetCharValue(self, Line, Offset, Value):\r
213 self.Profile.FileLinesList[Line - 1][Offset] = Value\r
214\r
215 ## __CurrentLine() method\r
216 #\r
217 # Get the list that contains current line contents\r
218 #\r
219 # @param self The object pointer\r
220 # @retval List current line contents\r
221 #\r
222 def __CurrentLine(self):\r
223 return self.Profile.FileLinesList[self.CurrentLineNumber - 1]\r
224\r
225 ## __InsertComma() method\r
226 #\r
227 # Insert ',' to replace PP\r
228 #\r
229 # @param self The object pointer\r
230 # @retval List current line contents\r
231 #\r
232 def __InsertComma(self, Line):\r
233\r
234\r
235 if self.Profile.FileLinesList[Line - 1][0] != T_CHAR_HASH:\r
236 BeforeHashPart = str(self.Profile.FileLinesList[Line - 1]).split(T_CHAR_HASH)[0]\r
237 if BeforeHashPart.rstrip().endswith(T_CHAR_COMMA) or BeforeHashPart.rstrip().endswith(';'):\r
238 return\r
239\r
240 if Line - 2 >= 0 and str(self.Profile.FileLinesList[Line - 2]).rstrip().endswith(','):\r
241 return\r
242\r
243 if Line - 2 >= 0 and str(self.Profile.FileLinesList[Line - 2]).rstrip().endswith(';'):\r
244 return\r
245\r
246 if str(self.Profile.FileLinesList[Line]).lstrip().startswith(',') or str(self.Profile.FileLinesList[Line]).lstrip().startswith(';'):\r
247 return\r
248\r
249 self.Profile.FileLinesList[Line - 1].insert(self.CurrentOffsetWithinLine, ',')\r
250\r
251 ## PreprocessFileWithClear() method\r
252 #\r
253 # Run a preprocess for the file to clean all comments\r
254 #\r
255 # @param self The object pointer\r
256 #\r
257 def PreprocessFileWithClear(self):\r
258\r
259 self.Rewind()\r
260 InComment = False\r
261 DoubleSlashComment = False\r
262 HashComment = False\r
263 PPExtend = False\r
264 PPDirectiveObj = None\r
265 # HashComment in quoted string " " is ignored.\r
266 InString = False\r
267 InCharLiteral = False\r
268\r
269 self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesListFromFile]\r
270 while not self.__EndOfFile():\r
271\r
272 if not InComment and self.__CurrentChar() == T_CHAR_DOUBLE_QUOTE:\r
273 InString = not InString\r
274\r
275 if not InComment and self.__CurrentChar() == T_CHAR_SINGLE_QUOTE:\r
276 InCharLiteral = not InCharLiteral\r
277 # meet new line, then no longer in a comment for // and '#'\r
278 if self.__CurrentChar() == T_CHAR_LF:\r
4231a819 279 if HashComment and PPDirectiveObj is not None:\r
52302d4d
LG
280 if PPDirectiveObj.Content.rstrip(T_CHAR_CR).endswith(T_CHAR_BACKSLASH):\r
281 PPDirectiveObj.Content += T_CHAR_LF\r
282 PPExtend = True\r
283 else:\r
284 PPExtend = False\r
285\r
286 EndLinePos = (self.CurrentLineNumber, self.CurrentOffsetWithinLine)\r
287\r
288 if InComment and DoubleSlashComment:\r
289 InComment = False\r
290 DoubleSlashComment = False\r
291\r
292 if InComment and HashComment and not PPExtend:\r
293 InComment = False\r
294 HashComment = False\r
295 PPDirectiveObj.Content += T_CHAR_LF\r
296 PPDirectiveObj.EndPos = EndLinePos\r
297 FileProfile.PPDirectiveList.append(PPDirectiveObj)\r
298 PPDirectiveObj = None\r
299\r
300 if InString or InCharLiteral:\r
301 CurrentLine = "".join(self.__CurrentLine())\r
302 if CurrentLine.rstrip(T_CHAR_LF).rstrip(T_CHAR_CR).endswith(T_CHAR_BACKSLASH):\r
303 SlashIndex = CurrentLine.rindex(T_CHAR_BACKSLASH)\r
304 self.__SetCharValue(self.CurrentLineNumber, SlashIndex, T_CHAR_SPACE)\r
305\r
306 self.CurrentLineNumber += 1\r
307 self.CurrentOffsetWithinLine = 0\r
308 # check for */ comment end\r
309 elif InComment and not DoubleSlashComment and not HashComment and self.__CurrentChar() == T_CHAR_STAR and self.__NextChar() == T_CHAR_SLASH:\r
310\r
311 self.__SetCurrentCharValue(T_CHAR_SPACE)\r
312 self.__GetOneChar()\r
313 self.__SetCurrentCharValue(T_CHAR_SPACE)\r
314 self.__GetOneChar()\r
315 InComment = False\r
316 # set comments to spaces\r
317 elif InComment:\r
318 if HashComment:\r
319 # // follows hash PP directive\r
320 if self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH:\r
321 InComment = False\r
322 HashComment = False\r
323 PPDirectiveObj.EndPos = (self.CurrentLineNumber, self.CurrentOffsetWithinLine - 1)\r
324 FileProfile.PPDirectiveList.append(PPDirectiveObj)\r
325 PPDirectiveObj = None\r
326 continue\r
327 else:\r
328 PPDirectiveObj.Content += self.__CurrentChar()\r
329\r
330 self.__SetCurrentCharValue(T_CHAR_SPACE)\r
331 self.__GetOneChar()\r
332 # check for // comment\r
333 elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH:\r
334 InComment = True\r
335 DoubleSlashComment = True\r
336\r
337 # check for '#' comment\r
338 elif self.__CurrentChar() == T_CHAR_HASH and not InString and not InCharLiteral:\r
339 InComment = True\r
340 HashComment = True\r
341 PPDirectiveObj = PP_Directive('', (self.CurrentLineNumber, self.CurrentOffsetWithinLine), None)\r
342 # check for /* comment start\r
343 elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_STAR:\r
344\r
345 self.__SetCurrentCharValue( T_CHAR_SPACE)\r
346 self.__GetOneChar()\r
347 self.__SetCurrentCharValue( T_CHAR_SPACE)\r
348 self.__GetOneChar()\r
349 InComment = True\r
350 else:\r
351 self.__GetOneChar()\r
352\r
353 EndLinePos = (self.CurrentLineNumber, self.CurrentOffsetWithinLine)\r
354\r
355 if InComment and HashComment and not PPExtend:\r
356 PPDirectiveObj.EndPos = EndLinePos\r
357 FileProfile.PPDirectiveList.append(PPDirectiveObj)\r
358 self.Rewind()\r
359\r
360 ## ParseFile() method\r
361 #\r
362 # Parse the file profile buffer to extract fd, fv ... information\r
363 # Exception will be raised if syntax error found\r
364 #\r
365 # @param self The object pointer\r
366 #\r
367 def ParseFile(self):\r
368 self.PreprocessFileWithClear()\r
369 # restore from ListOfList to ListOfString\r
370 self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]\r
371 FileStringContents = ''\r
372 for fileLine in self.Profile.FileLinesList:\r
373 FileStringContents += fileLine\r
374 cStream = antlr3.StringStream(FileStringContents)\r
375 lexer = CLexer(cStream)\r
376 tStream = antlr3.CommonTokenStream(lexer)\r
377 parser = CParser(tStream)\r
378 parser.translation_unit()\r
379\r
380 ## CleanFileProfileBuffer() method\r
381 #\r
382 # Reset all contents of the profile of a file\r
383 #\r
384 def CleanFileProfileBuffer(self):\r
385\r
386 FileProfile.PPDirectiveList = []\r
387 FileProfile.AssignmentExpressionList = []\r
388 FileProfile.FunctionDefinitionList = []\r
389 FileProfile.VariableDeclarationList = []\r
390 FileProfile.EnumerationDefinitionList = []\r
391 FileProfile.StructUnionDefinitionList = []\r
392 FileProfile.TypedefDefinitionList = []\r
393 FileProfile.FunctionCallingList = []\r
394\r
395 ## PrintFragments() method\r
396 #\r
397 # Print the contents of the profile of a file\r
398 #\r
399 def PrintFragments(self):\r
400\r
401 print '################# ' + self.FileName + '#####################'\r
402\r
403 print '/****************************************/'\r
404 print '/*************** ASSIGNMENTS ***************/'\r
405 print '/****************************************/'\r
406 for asign in FileProfile.AssignmentExpressionList:\r
407 print str(asign.StartPos) + asign.Name + asign.Operator + asign.Value\r
408\r
409 print '/****************************************/'\r
410 print '/********* PREPROCESS DIRECTIVES ********/'\r
411 print '/****************************************/'\r
412 for pp in FileProfile.PPDirectiveList:\r
413 print str(pp.StartPos) + pp.Content\r
414\r
415 print '/****************************************/'\r
416 print '/********* VARIABLE DECLARATIONS ********/'\r
417 print '/****************************************/'\r
418 for var in FileProfile.VariableDeclarationList:\r
419 print str(var.StartPos) + var.Modifier + ' '+ var.Declarator\r
420\r
421 print '/****************************************/'\r
422 print '/********* FUNCTION DEFINITIONS *********/'\r
423 print '/****************************************/'\r
424 for func in FileProfile.FunctionDefinitionList:\r
425 print str(func.StartPos) + func.Modifier + ' '+ func.Declarator + ' ' + str(func.NamePos)\r
426\r
427 print '/****************************************/'\r
428 print '/************ ENUMERATIONS **************/'\r
429 print '/****************************************/'\r
430 for enum in FileProfile.EnumerationDefinitionList:\r
431 print str(enum.StartPos) + enum.Content\r
432\r
433 print '/****************************************/'\r
434 print '/*********** STRUCTS/UNIONS *************/'\r
435 print '/****************************************/'\r
436 for su in FileProfile.StructUnionDefinitionList:\r
437 print str(su.StartPos) + su.Content\r
438\r
439 print '/****************************************/'\r
440 print '/************** TYPEDEFS ****************/'\r
441 print '/****************************************/'\r
442 for typedef in FileProfile.TypedefDefinitionList:\r
443 print str(typedef.StartPos) + typedef.ToType\r
444\r
445##\r
446#\r
447# This acts like the main() function for the script, unless it is 'import'ed into another\r
448# script.\r
449#\r
450if __name__ == "__main__":\r
451\r
452 print "For Test."\r