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