]>
Commit | Line | Data |
---|---|---|
52302d4d LG |
1 | ## @file\r |
2 | # preprocess source file\r | |
3 | #\r | |
1be2ed90 | 4 | # Copyright (c) 2007 - 2014, 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 | 18 | from __future__ import print_function\r |
52302d4d | 19 | import sys\r |
1be2ed90 | 20 | import Common.LongFilePathOs as os\r |
52302d4d LG |
21 | import re\r |
22 | import CodeFragmentCollector\r | |
23 | import FileProfile\r | |
24 | from CommonDataClass import DataClass\r | |
25 | from Common import EdkLogger\r | |
26 | from EotToolError import *\r | |
27 | import EotGlobalData\r | |
28 | \r | |
29 | # Global Dicts\r | |
30 | IncludeFileListDict = {}\r | |
31 | IncludePathListDict = {}\r | |
32 | ComplexTypeDict = {}\r | |
33 | SUDict = {}\r | |
34 | \r | |
52302d4d LG |
35 | ## GetFuncDeclPattern() method\r |
36 | #\r | |
37 | # Get the pattern of function declaration\r | |
38 | #\r | |
39 | # @return p: the pattern of function declaration\r | |
40 | #\r | |
41 | def GetFuncDeclPattern():\r | |
42 | p = re.compile(r'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re.DOTALL)\r | |
43 | return p\r | |
44 | \r | |
45 | ## GetArrayPattern() method\r | |
46 | #\r | |
47 | # Get the pattern of array\r | |
48 | #\r | |
49 | # @return p: the pattern of array\r | |
50 | #\r | |
51 | def GetArrayPattern():\r | |
52 | p = re.compile(r'[_\w]*\s*[\[.*\]]+')\r | |
53 | return p\r | |
54 | \r | |
55 | ## GetTypedefFuncPointerPattern() method\r | |
56 | #\r | |
57 | # Get the pattern of function pointer\r | |
58 | #\r | |
59 | # @return p: the pattern of function pointer\r | |
60 | #\r | |
61 | def GetTypedefFuncPointerPattern():\r | |
62 | p = re.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re.DOTALL)\r | |
63 | return p\r | |
64 | \r | |
65 | ## GetDB() method\r | |
66 | #\r | |
67 | # Get global database instance\r | |
68 | #\r | |
69 | # @return EotGlobalData.gDb: the global database instance\r | |
70 | #\r | |
71 | def GetDB():\r | |
72 | return EotGlobalData.gDb\r | |
73 | \r | |
74 | ## PrintErrorMsg() method\r | |
75 | #\r | |
76 | # print error message\r | |
77 | #\r | |
78 | # @param ErrorType: Type of error\r | |
79 | # @param Msg: Error message\r | |
80 | # @param TableName: table name of error found\r | |
81 | # @param ItemId: id of item\r | |
82 | #\r | |
83 | def PrintErrorMsg(ErrorType, Msg, TableName, ItemId):\r | |
84 | Msg = Msg.replace('\n', '').replace('\r', '')\r | |
85 | MsgPartList = Msg.split()\r | |
86 | Msg = ''\r | |
87 | for Part in MsgPartList:\r | |
88 | Msg += Part\r | |
89 | Msg += ' '\r | |
90 | GetDB().TblReport.Insert(ErrorType, OtherMsg = Msg, BelongsToTable = TableName, BelongsToItem = ItemId)\r | |
91 | \r | |
92 | ## GetIdType() method\r | |
93 | #\r | |
94 | # Find type of input string\r | |
95 | #\r | |
96 | # @param Str: String to be parsed\r | |
97 | #\r | |
98 | # @return Type: The type of the string\r | |
99 | #\r | |
100 | def GetIdType(Str):\r | |
101 | Type = DataClass.MODEL_UNKNOWN\r | |
102 | Str = Str.replace('#', '# ')\r | |
103 | List = Str.split()\r | |
104 | if List[1] == 'include':\r | |
105 | Type = DataClass.MODEL_IDENTIFIER_INCLUDE\r | |
106 | elif List[1] == 'define':\r | |
107 | Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE\r | |
108 | elif List[1] == 'ifdef':\r | |
109 | Type = DataClass.MODEL_IDENTIFIER_MACRO_IFDEF\r | |
110 | elif List[1] == 'ifndef':\r | |
111 | Type = DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF\r | |
112 | elif List[1] == 'endif':\r | |
113 | Type = DataClass.MODEL_IDENTIFIER_MACRO_ENDIF\r | |
114 | elif List[1] == 'pragma':\r | |
115 | Type = DataClass.MODEL_IDENTIFIER_MACRO_PROGMA\r | |
116 | else:\r | |
117 | Type = DataClass.MODEL_UNKNOWN\r | |
118 | return Type\r | |
119 | \r | |
120 | ## GetIdentifierList() method\r | |
121 | #\r | |
122 | # Get id of all files\r | |
123 | #\r | |
124 | # @return IdList: The list of all id of files\r | |
125 | #\r | |
126 | def GetIdentifierList():\r | |
127 | IdList = []\r | |
128 | \r | |
129 | for pp in FileProfile.PPDirectiveList:\r | |
130 | Type = GetIdType(pp.Content)\r | |
131 | IdPP = DataClass.IdentifierClass(-1, '', '', '', pp.Content, Type, -1, -1, pp.StartPos[0],pp.StartPos[1],pp.EndPos[0],pp.EndPos[1])\r | |
132 | IdList.append(IdPP)\r | |
133 | \r | |
134 | for ae in FileProfile.AssignmentExpressionList:\r | |
135 | IdAE = DataClass.IdentifierClass(-1, ae.Operator, '', ae.Name, ae.Value, DataClass.MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION, -1, -1, ae.StartPos[0],ae.StartPos[1],ae.EndPos[0],ae.EndPos[1])\r | |
136 | IdList.append(IdAE)\r | |
137 | \r | |
138 | FuncDeclPattern = GetFuncDeclPattern()\r | |
139 | ArrayPattern = GetArrayPattern()\r | |
140 | for var in FileProfile.VariableDeclarationList:\r | |
141 | DeclText = var.Declarator.strip()\r | |
142 | while DeclText.startswith('*'):\r | |
143 | var.Modifier += '*'\r | |
144 | DeclText = DeclText.lstrip('*').strip()\r | |
145 | var.Declarator = DeclText\r | |
146 | if FuncDeclPattern.match(var.Declarator):\r | |
147 | DeclSplitList = var.Declarator.split('(')\r | |
148 | FuncName = DeclSplitList[0]\r | |
149 | FuncNamePartList = FuncName.split()\r | |
150 | if len(FuncNamePartList) > 1:\r | |
151 | FuncName = FuncNamePartList[-1]\r | |
152 | Index = 0\r | |
153 | while Index < len(FuncNamePartList) - 1:\r | |
154 | var.Modifier += ' ' + FuncNamePartList[Index]\r | |
155 | var.Declarator = var.Declarator.lstrip().lstrip(FuncNamePartList[Index])\r | |
156 | Index += 1\r | |
157 | IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', var.Declarator, '', DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, -1, -1, var.StartPos[0],var.StartPos[1],var.EndPos[0],var.EndPos[1])\r | |
158 | IdList.append(IdVar)\r | |
159 | continue\r | |
160 | \r | |
161 | if var.Declarator.find('{') == -1:\r | |
162 | for decl in var.Declarator.split(','):\r | |
163 | DeclList = decl.split('=')\r | |
164 | Name = DeclList[0].strip()\r | |
165 | if ArrayPattern.match(Name):\r | |
166 | LSBPos = var.Declarator.find('[')\r | |
167 | var.Modifier += ' ' + Name[LSBPos:]\r | |
168 | Name = Name[0:LSBPos]\r | |
169 | \r | |
170 | IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', Name, (len(DeclList) > 1 and [DeclList[1]]or [''])[0], DataClass.MODEL_IDENTIFIER_VARIABLE, -1, -1, var.StartPos[0],var.StartPos[1],var.EndPos[0],var.EndPos[1])\r | |
171 | IdList.append(IdVar)\r | |
172 | else:\r | |
173 | DeclList = var.Declarator.split('=')\r | |
174 | Name = DeclList[0].strip()\r | |
175 | if ArrayPattern.match(Name):\r | |
176 | LSBPos = var.Declarator.find('[')\r | |
177 | var.Modifier += ' ' + Name[LSBPos:]\r | |
178 | Name = Name[0:LSBPos]\r | |
179 | IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', Name, (len(DeclList) > 1 and [DeclList[1]]or [''])[0], DataClass.MODEL_IDENTIFIER_VARIABLE, -1, -1, var.StartPos[0],var.StartPos[1],var.EndPos[0],var.EndPos[1])\r | |
180 | IdList.append(IdVar)\r | |
181 | \r | |
182 | for enum in FileProfile.EnumerationDefinitionList:\r | |
183 | LBPos = enum.Content.find('{')\r | |
184 | RBPos = enum.Content.find('}')\r | |
185 | Name = enum.Content[4:LBPos].strip()\r | |
186 | Value = enum.Content[LBPos+1:RBPos]\r | |
187 | IdEnum = DataClass.IdentifierClass(-1, '', '', Name, Value, DataClass.MODEL_IDENTIFIER_ENUMERATE, -1, -1, enum.StartPos[0],enum.StartPos[1],enum.EndPos[0],enum.EndPos[1])\r | |
188 | IdList.append(IdEnum)\r | |
189 | \r | |
190 | for su in FileProfile.StructUnionDefinitionList:\r | |
191 | Type = DataClass.MODEL_IDENTIFIER_STRUCTURE\r | |
192 | SkipLen = 6\r | |
193 | if su.Content.startswith('union'):\r | |
194 | Type = DataClass.MODEL_IDENTIFIER_UNION\r | |
195 | SkipLen = 5\r | |
196 | LBPos = su.Content.find('{')\r | |
197 | RBPos = su.Content.find('}')\r | |
198 | if LBPos == -1 or RBPos == -1:\r | |
199 | Name = su.Content[SkipLen:].strip()\r | |
200 | Value = ''\r | |
201 | else:\r | |
202 | Name = su.Content[SkipLen:LBPos].strip()\r | |
203 | Value = su.Content[LBPos+1:RBPos]\r | |
204 | IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0],su.StartPos[1],su.EndPos[0],su.EndPos[1])\r | |
205 | IdList.append(IdPE)\r | |
206 | \r | |
207 | TdFuncPointerPattern = GetTypedefFuncPointerPattern()\r | |
208 | for td in FileProfile.TypedefDefinitionList:\r | |
209 | Modifier = ''\r | |
210 | Name = td.ToType\r | |
211 | Value = td.FromType\r | |
212 | if TdFuncPointerPattern.match(td.ToType):\r | |
213 | Modifier = td.FromType\r | |
214 | LBPos = td.ToType.find('(')\r | |
215 | TmpStr = td.ToType[LBPos+1:].strip()\r | |
216 | StarPos = TmpStr.find('*')\r | |
217 | if StarPos != -1:\r | |
218 | Modifier += ' ' + TmpStr[0:StarPos]\r | |
219 | while TmpStr[StarPos] == '*':\r | |
220 | Modifier += ' ' + '*'\r | |
221 | StarPos += 1\r | |
222 | TmpStr = TmpStr[StarPos:].strip()\r | |
223 | RBPos = TmpStr.find(')')\r | |
224 | Name = TmpStr[0:RBPos]\r | |
225 | Value = 'FP' + TmpStr[RBPos + 1:]\r | |
226 | \r | |
227 | IdTd = DataClass.IdentifierClass(-1, Modifier, '', Name, Value, DataClass.MODEL_IDENTIFIER_TYPEDEF, -1, -1, td.StartPos[0],td.StartPos[1],td.EndPos[0],td.EndPos[1])\r | |
228 | IdList.append(IdTd)\r | |
229 | \r | |
230 | for funcCall in FileProfile.FunctionCallingList:\r | |
231 | IdFC = DataClass.IdentifierClass(-1, '', '', funcCall.FuncName, funcCall.ParamList, DataClass.MODEL_IDENTIFIER_FUNCTION_CALLING, -1, -1, funcCall.StartPos[0],funcCall.StartPos[1],funcCall.EndPos[0],funcCall.EndPos[1])\r | |
232 | IdList.append(IdFC)\r | |
233 | return IdList\r | |
234 | \r | |
235 | ## GetParamList() method\r | |
236 | #\r | |
237 | # Get a list of parameters\r | |
238 | #\r | |
239 | # @param FuncDeclarator: Function declarator\r | |
240 | # @param FuncNameLine: Line number of function name\r | |
241 | # @param FuncNameOffset: Offset of function name\r | |
242 | #\r | |
243 | # @return ParamIdList: A list of parameters\r | |
244 | #\r | |
245 | def GetParamList(FuncDeclarator, FuncNameLine = 0, FuncNameOffset = 0):\r | |
246 | ParamIdList = []\r | |
247 | DeclSplitList = FuncDeclarator.split('(')\r | |
248 | if len(DeclSplitList) < 2:\r | |
249 | return ParamIdList\r | |
250 | FuncName = DeclSplitList[0]\r | |
251 | ParamStr = DeclSplitList[1].rstrip(')')\r | |
252 | LineSkipped = 0\r | |
253 | OffsetSkipped = 0\r | |
254 | Start = 0\r | |
255 | while FuncName.find('\n', Start) != -1:\r | |
256 | LineSkipped += 1\r | |
257 | OffsetSkipped = 0\r | |
258 | Start += FuncName.find('\n', Start)\r | |
259 | Start += 1\r | |
260 | OffsetSkipped += len(FuncName[Start:])\r | |
261 | OffsetSkipped += 1 #skip '('\r | |
262 | ParamBeginLine = FuncNameLine + LineSkipped\r | |
263 | ParamBeginOffset = OffsetSkipped\r | |
264 | for p in ParamStr.split(','):\r | |
265 | ListP = p.split()\r | |
266 | if len(ListP) == 0:\r | |
267 | continue\r | |
268 | ParamName = ListP[-1]\r | |
269 | DeclText = ParamName.strip()\r | |
270 | RightSpacePos = p.rfind(ParamName)\r | |
271 | ParamModifier = p[0:RightSpacePos]\r | |
272 | if ParamName == 'OPTIONAL':\r | |
273 | if ParamModifier == '':\r | |
274 | ParamModifier += ' ' + 'OPTIONAL'\r | |
275 | DeclText = ''\r | |
276 | else:\r | |
277 | ParamName = ListP[-2]\r | |
278 | DeclText = ParamName.strip()\r | |
279 | RightSpacePos = p.rfind(ParamName)\r | |
280 | ParamModifier = p[0:RightSpacePos]\r | |
281 | ParamModifier += 'OPTIONAL'\r | |
282 | while DeclText.startswith('*'):\r | |
283 | ParamModifier += ' ' + '*'\r | |
284 | DeclText = DeclText.lstrip('*').strip()\r | |
285 | ParamName = DeclText\r | |
286 | \r | |
287 | Start = 0\r | |
288 | while p.find('\n', Start) != -1:\r | |
289 | LineSkipped += 1\r | |
290 | OffsetSkipped = 0\r | |
291 | Start += p.find('\n', Start)\r | |
292 | Start += 1\r | |
293 | OffsetSkipped += len(p[Start:])\r | |
294 | \r | |
295 | ParamEndLine = ParamBeginLine + LineSkipped\r | |
296 | ParamEndOffset = OffsetSkipped\r | |
297 | IdParam = DataClass.IdentifierClass(-1, ParamModifier, '', ParamName, '', DataClass.MODEL_IDENTIFIER_PARAMETER, -1, -1, ParamBeginLine, ParamBeginOffset, ParamEndLine, ParamEndOffset)\r | |
298 | ParamIdList.append(IdParam)\r | |
299 | ParamBeginLine = ParamEndLine\r | |
300 | ParamBeginOffset = OffsetSkipped + 1 #skip ','\r | |
301 | \r | |
302 | return ParamIdList\r | |
303 | \r | |
304 | ## GetFunctionList()\r | |
305 | #\r | |
306 | # Get a list of functions\r | |
307 | #\r | |
308 | # @return FuncObjList: A list of function objects\r | |
309 | #\r | |
310 | def GetFunctionList():\r | |
311 | FuncObjList = []\r | |
312 | for FuncDef in FileProfile.FunctionDefinitionList:\r | |
313 | ParamIdList = []\r | |
314 | DeclText = FuncDef.Declarator.strip()\r | |
315 | while DeclText.startswith('*'):\r | |
316 | FuncDef.Modifier += '*'\r | |
317 | DeclText = DeclText.lstrip('*').strip()\r | |
318 | \r | |
319 | FuncDef.Declarator = FuncDef.Declarator.lstrip('*')\r | |
320 | DeclSplitList = FuncDef.Declarator.split('(')\r | |
321 | if len(DeclSplitList) < 2:\r | |
322 | continue\r | |
323 | \r | |
324 | FuncName = DeclSplitList[0]\r | |
325 | FuncNamePartList = FuncName.split()\r | |
326 | if len(FuncNamePartList) > 1:\r | |
327 | FuncName = FuncNamePartList[-1]\r | |
328 | Index = 0\r | |
329 | while Index < len(FuncNamePartList) - 1:\r | |
330 | FuncDef.Modifier += ' ' + FuncNamePartList[Index]\r | |
331 | Index += 1\r | |
332 | \r | |
333 | FuncObj = DataClass.FunctionClass(-1, FuncDef.Declarator, FuncDef.Modifier, FuncName.strip(), '', FuncDef.StartPos[0],FuncDef.StartPos[1],FuncDef.EndPos[0],FuncDef.EndPos[1], FuncDef.LeftBracePos[0], FuncDef.LeftBracePos[1], -1, ParamIdList, [])\r | |
334 | FuncObjList.append(FuncObj)\r | |
335 | \r | |
336 | return FuncObjList\r | |
337 | \r | |
338 | ## CreateCCodeDB() method\r | |
339 | #\r | |
340 | # Create database for all c code\r | |
341 | #\r | |
342 | # @param FileNameList: A list of all c code file names\r | |
343 | #\r | |
344 | def CreateCCodeDB(FileNameList):\r | |
345 | FileObjList = []\r | |
346 | ParseErrorFileList = []\r | |
40d841f6 | 347 | ParsedFiles = {}\r |
52302d4d LG |
348 | for FullName in FileNameList:\r |
349 | if os.path.splitext(FullName)[1] in ('.h', '.c'):\r | |
40d841f6 LG |
350 | if FullName.lower() in ParsedFiles:\r |
351 | continue\r | |
352 | ParsedFiles[FullName.lower()] = 1\r | |
52302d4d LG |
353 | EdkLogger.info("Parsing " + FullName)\r |
354 | model = FullName.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H\r | |
355 | collector = CodeFragmentCollector.CodeFragmentCollector(FullName)\r | |
356 | try:\r | |
357 | collector.ParseFile()\r | |
79714906 | 358 | except:\r |
52302d4d LG |
359 | ParseErrorFileList.append(FullName)\r |
360 | BaseName = os.path.basename(FullName)\r | |
361 | DirName = os.path.dirname(FullName)\r | |
362 | Ext = os.path.splitext(BaseName)[1].lstrip('.')\r | |
363 | ModifiedTime = os.path.getmtime(FullName)\r | |
364 | FileObj = DataClass.FileClass(-1, BaseName, Ext, DirName, FullName, model, ModifiedTime, GetFunctionList(), GetIdentifierList(), [])\r | |
365 | FileObjList.append(FileObj)\r | |
366 | collector.CleanFileProfileBuffer()\r | |
367 | \r | |
368 | if len(ParseErrorFileList) > 0:\r | |
369 | EdkLogger.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList))\r | |
370 | \r | |
371 | Db = EotGlobalData.gDb\r | |
372 | for file in FileObjList:\r | |
373 | Db.InsertOneFile(file)\r | |
374 | \r | |
375 | Db.UpdateIdentifierBelongsToFunction()\r | |
376 | \r | |
377 | ##\r | |
378 | #\r | |
379 | # This acts like the main() function for the script, unless it is 'import'ed into another\r | |
380 | # script.\r | |
381 | #\r | |
382 | if __name__ == '__main__':\r | |
383 | \r | |
384 | EdkLogger.Initialize()\r | |
385 | EdkLogger.SetLevel(EdkLogger.QUIET)\r | |
386 | CollectSourceCodeDataIntoDB(sys.argv[1])\r | |
387 | \r | |
72443dd2 | 388 | print('Done!')\r |