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