]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/Python/Ecc/c.py
BaseTools: Unify long and int in Expression.py
[mirror_edk2.git] / BaseTools / Source / Python / Ecc / c.py
... / ...
CommitLineData
1## @file\r
2# This file is used to be the c coding style checking of ECC tool\r
3#\r
4# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
5# This program and the accompanying materials\r
6# are licensed and made available under the terms and conditions of the BSD License\r
7# which accompanies this distribution. The full text of the license may be found at\r
8# http://opensource.org/licenses/bsd-license.php\r
9#\r
10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12#\r
13\r
14from __future__ import print_function\r
15import sys\r
16import Common.LongFilePathOs as os\r
17import re\r
18import string\r
19import CodeFragmentCollector\r
20import FileProfile\r
21from CommonDataClass import DataClass\r
22import Database\r
23from Common import EdkLogger\r
24from EccToolError import *\r
25import EccGlobalData\r
26import MetaDataParser\r
27\r
28IncludeFileListDict = {}\r
29AllIncludeFileListDict = {}\r
30IncludePathListDict = {}\r
31ComplexTypeDict = {}\r
32SUDict = {}\r
33IgnoredKeywordList = ['EFI_ERROR']\r
34\r
35def GetIgnoredDirListPattern():\r
36 skipList = list(EccGlobalData.gConfig.SkipDirList) + ['.svn']\r
37 DirString = string.join(skipList, '|')\r
38 p = re.compile(r'.*[\\/](?:%s)[\\/]?.*' % DirString)\r
39 return p\r
40\r
41def 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
45def GetArrayPattern():\r
46 p = re.compile(r'[_\w]*\s*[\[.*\]]+')\r
47 return p\r
48\r
49def GetTypedefFuncPointerPattern():\r
50 p = re.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re.DOTALL)\r
51 return p\r
52\r
53def GetDB():\r
54 return EccGlobalData.gDb\r
55\r
56def GetConfig():\r
57 return EccGlobalData.gConfig\r
58\r
59def PrintErrorMsg(ErrorType, Msg, TableName, ItemId):\r
60 Msg = Msg.replace('\n', '').replace('\r', '')\r
61 MsgPartList = Msg.split()\r
62 Msg = ''\r
63 for Part in MsgPartList:\r
64 Msg += Part\r
65 Msg += ' '\r
66 GetDB().TblReport.Insert(ErrorType, OtherMsg=Msg, BelongsToTable=TableName, BelongsToItem=ItemId)\r
67\r
68def GetIdType(Str):\r
69 Type = DataClass.MODEL_UNKNOWN\r
70 Str = Str.replace('#', '# ')\r
71 List = Str.split()\r
72 if List[1] == 'include':\r
73 Type = DataClass.MODEL_IDENTIFIER_INCLUDE\r
74 elif List[1] == 'define':\r
75 Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE\r
76 elif List[1] == 'ifdef':\r
77 Type = DataClass.MODEL_IDENTIFIER_MACRO_IFDEF\r
78 elif List[1] == 'ifndef':\r
79 Type = DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF\r
80 elif List[1] == 'endif':\r
81 Type = DataClass.MODEL_IDENTIFIER_MACRO_ENDIF\r
82 elif List[1] == 'pragma':\r
83 Type = DataClass.MODEL_IDENTIFIER_MACRO_PROGMA\r
84 else:\r
85 Type = DataClass.MODEL_UNKNOWN\r
86 return Type\r
87\r
88def SuOccurInTypedef (Su, TdList):\r
89 for Td in TdList:\r
90 if Su.StartPos[0] == Td.StartPos[0] and Su.EndPos[0] == Td.EndPos[0]:\r
91 return True\r
92 return False\r
93\r
94def GetIdentifierList():\r
95 IdList = []\r
96 for comment in FileProfile.CommentList:\r
97 IdComment = DataClass.IdentifierClass(-1, '', '', '', comment.Content, DataClass.MODEL_IDENTIFIER_COMMENT, -1, -1, comment.StartPos[0], comment.StartPos[1], comment.EndPos[0], comment.EndPos[1])\r
98 IdList.append(IdComment)\r
99\r
100 for pp in FileProfile.PPDirectiveList:\r
101 Type = GetIdType(pp.Content)\r
102 IdPP = DataClass.IdentifierClass(-1, '', '', '', pp.Content, Type, -1, -1, pp.StartPos[0], pp.StartPos[1], pp.EndPos[0], pp.EndPos[1])\r
103 IdList.append(IdPP)\r
104\r
105 for pe in FileProfile.PredicateExpressionList:\r
106 IdPE = DataClass.IdentifierClass(-1, '', '', '', pe.Content, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION, -1, -1, pe.StartPos[0], pe.StartPos[1], pe.EndPos[0], pe.EndPos[1])\r
107 IdList.append(IdPE)\r
108\r
109 FuncDeclPattern = GetFuncDeclPattern()\r
110 ArrayPattern = GetArrayPattern()\r
111 for var in FileProfile.VariableDeclarationList:\r
112 DeclText = var.Declarator.lstrip()\r
113 FuncPointerPattern = GetTypedefFuncPointerPattern()\r
114 if FuncPointerPattern.match(DeclText):\r
115 continue\r
116 VarNameStartLine = var.NameStartPos[0]\r
117 VarNameStartColumn = var.NameStartPos[1]\r
118 FirstChar = DeclText[0]\r
119 while not FirstChar.isalpha() and FirstChar != '_':\r
120 if FirstChar == '*':\r
121 var.Modifier += '*'\r
122 VarNameStartColumn += 1\r
123 DeclText = DeclText.lstrip('*')\r
124 elif FirstChar == '\r':\r
125 DeclText = DeclText.lstrip('\r\n').lstrip('\r')\r
126 VarNameStartLine += 1\r
127 VarNameStartColumn = 0\r
128 elif FirstChar == '\n':\r
129 DeclText = DeclText.lstrip('\n')\r
130 VarNameStartLine += 1\r
131 VarNameStartColumn = 0\r
132 elif FirstChar == ' ':\r
133 DeclText = DeclText.lstrip(' ')\r
134 VarNameStartColumn += 1\r
135 elif FirstChar == '\t':\r
136 DeclText = DeclText.lstrip('\t')\r
137 VarNameStartColumn += 8\r
138 else:\r
139 DeclText = DeclText[1:]\r
140 VarNameStartColumn += 1\r
141 FirstChar = DeclText[0]\r
142\r
143 var.Declarator = DeclText\r
144 if FuncDeclPattern.match(var.Declarator):\r
145 DeclSplitList = var.Declarator.split('(')\r
146 FuncName = DeclSplitList[0].strip()\r
147 FuncNamePartList = FuncName.split()\r
148 if len(FuncNamePartList) > 1:\r
149 FuncName = FuncNamePartList[-1].strip()\r
150 NameStart = DeclSplitList[0].rfind(FuncName)\r
151 var.Declarator = var.Declarator[NameStart:]\r
152 if NameStart > 0:\r
153 var.Modifier += ' ' + DeclSplitList[0][0:NameStart]\r
154 Index = 0\r
155 PreChar = ''\r
156 while Index < NameStart:\r
157 FirstChar = DeclSplitList[0][Index]\r
158 if DeclSplitList[0][Index:].startswith('EFIAPI'):\r
159 Index += 6\r
160 VarNameStartColumn += 6\r
161 PreChar = ''\r
162 continue\r
163 elif FirstChar == '\r':\r
164 Index += 1\r
165 VarNameStartLine += 1\r
166 VarNameStartColumn = 0\r
167 elif FirstChar == '\n':\r
168 Index += 1\r
169 if PreChar != '\r':\r
170 VarNameStartLine += 1\r
171 VarNameStartColumn = 0\r
172 elif FirstChar == ' ':\r
173 Index += 1\r
174 VarNameStartColumn += 1\r
175 elif FirstChar == '\t':\r
176 Index += 1\r
177 VarNameStartColumn += 8\r
178 else:\r
179 Index += 1\r
180 VarNameStartColumn += 1\r
181 PreChar = FirstChar\r
182 IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', var.Declarator, FuncName, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, -1, -1, var.StartPos[0], var.StartPos[1], VarNameStartLine, VarNameStartColumn)\r
183 IdList.append(IdVar)\r
184 continue\r
185\r
186 if var.Declarator.find('{') == -1:\r
187 for decl in var.Declarator.split(','):\r
188 DeclList = decl.split('=')\r
189 Name = DeclList[0].strip()\r
190 if ArrayPattern.match(Name):\r
191 LSBPos = var.Declarator.find('[')\r
192 var.Modifier += ' ' + Name[LSBPos:]\r
193 Name = Name[0:LSBPos]\r
194\r
195 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], VarNameStartLine, VarNameStartColumn)\r
196 IdList.append(IdVar)\r
197 else:\r
198 DeclList = var.Declarator.split('=')\r
199 Name = DeclList[0].strip()\r
200 if ArrayPattern.match(Name):\r
201 LSBPos = var.Declarator.find('[')\r
202 var.Modifier += ' ' + Name[LSBPos:]\r
203 Name = Name[0:LSBPos]\r
204 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], VarNameStartLine, VarNameStartColumn)\r
205 IdList.append(IdVar)\r
206\r
207 for enum in FileProfile.EnumerationDefinitionList:\r
208 LBPos = enum.Content.find('{')\r
209 RBPos = enum.Content.find('}')\r
210 Name = enum.Content[4:LBPos].strip()\r
211 Value = enum.Content[LBPos + 1:RBPos]\r
212 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
213 IdList.append(IdEnum)\r
214\r
215 for su in FileProfile.StructUnionDefinitionList:\r
216 if SuOccurInTypedef(su, FileProfile.TypedefDefinitionList):\r
217 continue\r
218 Type = DataClass.MODEL_IDENTIFIER_STRUCTURE\r
219 SkipLen = 6\r
220 if su.Content.startswith('union'):\r
221 Type = DataClass.MODEL_IDENTIFIER_UNION\r
222 SkipLen = 5\r
223 LBPos = su.Content.find('{')\r
224 RBPos = su.Content.find('}')\r
225 if LBPos == -1 or RBPos == -1:\r
226 Name = su.Content[SkipLen:].strip()\r
227 Value = ''\r
228 else:\r
229 Name = su.Content[SkipLen:LBPos].strip()\r
230 Value = su.Content[LBPos:RBPos + 1]\r
231 IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0], su.StartPos[1], su.EndPos[0], su.EndPos[1])\r
232 IdList.append(IdPE)\r
233\r
234 TdFuncPointerPattern = GetTypedefFuncPointerPattern()\r
235 for td in FileProfile.TypedefDefinitionList:\r
236 Modifier = ''\r
237 Name = td.ToType\r
238 Value = td.FromType\r
239 if TdFuncPointerPattern.match(td.ToType):\r
240 Modifier = td.FromType\r
241 LBPos = td.ToType.find('(')\r
242 TmpStr = td.ToType[LBPos + 1:].strip()\r
243 StarPos = TmpStr.find('*')\r
244 if StarPos != -1:\r
245 Modifier += ' ' + TmpStr[0:StarPos]\r
246 while TmpStr[StarPos] == '*':\r
247# Modifier += ' ' + '*'\r
248 StarPos += 1\r
249 TmpStr = TmpStr[StarPos:].strip()\r
250 RBPos = TmpStr.find(')')\r
251 Name = TmpStr[0:RBPos]\r
252 Value = 'FP' + TmpStr[RBPos + 1:]\r
253 else:\r
254 while Name.startswith('*'):\r
255 Value += ' ' + '*'\r
256 Name = Name.lstrip('*').strip()\r
257\r
258 if Name.find('[') != -1:\r
259 LBPos = Name.find('[')\r
260 RBPos = Name.rfind(']')\r
261 Value += Name[LBPos : RBPos + 1]\r
262 Name = Name[0 : LBPos]\r
263\r
264 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
265 IdList.append(IdTd)\r
266\r
267 for funcCall in FileProfile.FunctionCallingList:\r
268 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
269 IdList.append(IdFC)\r
270 return IdList\r
271\r
272def StripNonAlnumChars(Str):\r
273 StrippedStr = ''\r
274 for Char in Str:\r
275 if Char.isalnum() or Char == '_':\r
276 StrippedStr += Char\r
277 return StrippedStr\r
278\r
279def GetParamList(FuncDeclarator, FuncNameLine=0, FuncNameOffset=0):\r
280 FuncDeclarator = StripComments(FuncDeclarator)\r
281 ParamIdList = []\r
282 #DeclSplitList = FuncDeclarator.split('(')\r
283 LBPos = FuncDeclarator.find('(')\r
284 #if len(DeclSplitList) < 2:\r
285 if LBPos == -1:\r
286 return ParamIdList\r
287 #FuncName = DeclSplitList[0]\r
288 FuncName = FuncDeclarator[0:LBPos]\r
289 #ParamStr = DeclSplitList[1].rstrip(')')\r
290 ParamStr = FuncDeclarator[LBPos + 1:].rstrip(')')\r
291 LineSkipped = 0\r
292 OffsetSkipped = 0\r
293 TailChar = FuncName[-1]\r
294 while not TailChar.isalpha() and TailChar != '_':\r
295\r
296 if TailChar == '\n':\r
297 FuncName = FuncName.rstrip('\r\n').rstrip('\n')\r
298 LineSkipped += 1\r
299 OffsetSkipped = 0\r
300 elif TailChar == '\r':\r
301 FuncName = FuncName.rstrip('\r')\r
302 LineSkipped += 1\r
303 OffsetSkipped = 0\r
304 elif TailChar == ' ':\r
305 FuncName = FuncName.rstrip(' ')\r
306 OffsetSkipped += 1\r
307 elif TailChar == '\t':\r
308 FuncName = FuncName.rstrip('\t')\r
309 OffsetSkipped += 8\r
310 else:\r
311 FuncName = FuncName[:-1]\r
312 TailChar = FuncName[-1]\r
313\r
314 OffsetSkipped += 1 #skip '('\r
315\r
316 for p in ParamStr.split(','):\r
317 ListP = p.split()\r
318 if len(ListP) == 0:\r
319 continue\r
320 ParamName = ListP[-1]\r
321 DeclText = ParamName.strip()\r
322 RightSpacePos = p.rfind(ParamName)\r
323 ParamModifier = p[0:RightSpacePos]\r
324 if ParamName == 'OPTIONAL':\r
325 if ParamModifier == '':\r
326 ParamModifier += ' ' + 'OPTIONAL'\r
327 DeclText = ''\r
328 else:\r
329 ParamName = ListP[-2]\r
330 DeclText = ParamName.strip()\r
331 RightSpacePos = p.rfind(ParamName)\r
332 ParamModifier = p[0:RightSpacePos]\r
333 ParamModifier += 'OPTIONAL'\r
334 while DeclText.startswith('*'):\r
335 ParamModifier += ' ' + '*'\r
336 DeclText = DeclText.lstrip('*').strip()\r
337 ParamName = DeclText\r
338 # ignore array length if exists.\r
339 LBIndex = ParamName.find('[')\r
340 if LBIndex != -1:\r
341 ParamName = ParamName[0:LBIndex]\r
342\r
343 Start = RightSpacePos\r
344 Index = 0\r
345 PreChar = ''\r
346 while Index < Start:\r
347 FirstChar = p[Index]\r
348\r
349 if FirstChar == '\r':\r
350 Index += 1\r
351 LineSkipped += 1\r
352 OffsetSkipped = 0\r
353 elif FirstChar == '\n':\r
354 Index += 1\r
355 if PreChar != '\r':\r
356 LineSkipped += 1\r
357 OffsetSkipped = 0\r
358 elif FirstChar == ' ':\r
359 Index += 1\r
360 OffsetSkipped += 1\r
361 elif FirstChar == '\t':\r
362 Index += 1\r
363 OffsetSkipped += 8\r
364 else:\r
365 Index += 1\r
366 OffsetSkipped += 1\r
367 PreChar = FirstChar\r
368\r
369 ParamBeginLine = FuncNameLine + LineSkipped\r
370 ParamBeginOffset = FuncNameOffset + OffsetSkipped\r
371\r
372 Index = Start + len(ParamName)\r
373 PreChar = ''\r
374 while Index < len(p):\r
375 FirstChar = p[Index]\r
376\r
377 if FirstChar == '\r':\r
378 Index += 1\r
379 LineSkipped += 1\r
380 OffsetSkipped = 0\r
381 elif FirstChar == '\n':\r
382 Index += 1\r
383 if PreChar != '\r':\r
384 LineSkipped += 1\r
385 OffsetSkipped = 0\r
386 elif FirstChar == ' ':\r
387 Index += 1\r
388 OffsetSkipped += 1\r
389 elif FirstChar == '\t':\r
390 Index += 1\r
391 OffsetSkipped += 8\r
392 else:\r
393 Index += 1\r
394 OffsetSkipped += 1\r
395 PreChar = FirstChar\r
396\r
397 ParamEndLine = FuncNameLine + LineSkipped\r
398 ParamEndOffset = FuncNameOffset + OffsetSkipped\r
399 if ParamName != '...':\r
400 ParamName = StripNonAlnumChars(ParamName)\r
401 IdParam = DataClass.IdentifierClass(-1, ParamModifier, '', ParamName, '', DataClass.MODEL_IDENTIFIER_PARAMETER, -1, -1, ParamBeginLine, ParamBeginOffset, ParamEndLine, ParamEndOffset)\r
402 ParamIdList.append(IdParam)\r
403\r
404 OffsetSkipped += 1 #skip ','\r
405\r
406 return ParamIdList\r
407\r
408def GetFunctionList():\r
409 FuncObjList = []\r
410 for FuncDef in FileProfile.FunctionDefinitionList:\r
411 ParamIdList = []\r
412 DeclText = FuncDef.Declarator.lstrip()\r
413 FuncNameStartLine = FuncDef.NamePos[0]\r
414 FuncNameStartColumn = FuncDef.NamePos[1]\r
415 FirstChar = DeclText[0]\r
416 while not FirstChar.isalpha() and FirstChar != '_':\r
417 if FirstChar == '*':\r
418 FuncDef.Modifier += '*'\r
419 FuncNameStartColumn += 1\r
420 DeclText = DeclText.lstrip('*')\r
421 elif FirstChar == '\r':\r
422 DeclText = DeclText.lstrip('\r\n').lstrip('\r')\r
423 FuncNameStartLine += 1\r
424 FuncNameStartColumn = 0\r
425 elif FirstChar == '\n':\r
426 DeclText = DeclText.lstrip('\n')\r
427 FuncNameStartLine += 1\r
428 FuncNameStartColumn = 0\r
429 elif FirstChar == ' ':\r
430 DeclText = DeclText.lstrip(' ')\r
431 FuncNameStartColumn += 1\r
432 elif FirstChar == '\t':\r
433 DeclText = DeclText.lstrip('\t')\r
434 FuncNameStartColumn += 8\r
435 else:\r
436 DeclText = DeclText[1:]\r
437 FuncNameStartColumn += 1\r
438 FirstChar = DeclText[0]\r
439\r
440 FuncDef.Declarator = DeclText\r
441 DeclSplitList = FuncDef.Declarator.split('(')\r
442 if len(DeclSplitList) < 2:\r
443 continue\r
444\r
445 FuncName = DeclSplitList[0]\r
446 FuncNamePartList = FuncName.split()\r
447 if len(FuncNamePartList) > 1:\r
448 FuncName = FuncNamePartList[-1]\r
449 NameStart = DeclSplitList[0].rfind(FuncName)\r
450 if NameStart > 0:\r
451 FuncDef.Modifier += ' ' + DeclSplitList[0][0:NameStart]\r
452 Index = 0\r
453 PreChar = ''\r
454 while Index < NameStart:\r
455 FirstChar = DeclSplitList[0][Index]\r
456 if DeclSplitList[0][Index:].startswith('EFIAPI'):\r
457 Index += 6\r
458 FuncNameStartColumn += 6\r
459 PreChar = ''\r
460 continue\r
461 elif FirstChar == '\r':\r
462 Index += 1\r
463 FuncNameStartLine += 1\r
464 FuncNameStartColumn = 0\r
465 elif FirstChar == '\n':\r
466 Index += 1\r
467 if PreChar != '\r':\r
468 FuncNameStartLine += 1\r
469 FuncNameStartColumn = 0\r
470 elif FirstChar == ' ':\r
471 Index += 1\r
472 FuncNameStartColumn += 1\r
473 elif FirstChar == '\t':\r
474 Index += 1\r
475 FuncNameStartColumn += 8\r
476 else:\r
477 Index += 1\r
478 FuncNameStartColumn += 1\r
479 PreChar = FirstChar\r
480\r
481 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, [], FuncNameStartLine, FuncNameStartColumn)\r
482 FuncObjList.append(FuncObj)\r
483\r
484 return FuncObjList\r
485\r
486def GetFileModificationTimeFromDB(FullFileName):\r
487 TimeValue = 0.0\r
488 Db = GetDB()\r
489 SqlStatement = """ select TimeStamp\r
490 from File\r
491 where FullPath = \'%s\'\r
492 """ % (FullFileName)\r
493 ResultSet = Db.TblFile.Exec(SqlStatement)\r
494 for Result in ResultSet:\r
495 TimeValue = Result[0]\r
496 return TimeValue\r
497\r
498def CollectSourceCodeDataIntoDB(RootDir):\r
499 FileObjList = []\r
500 tuple = os.walk(RootDir)\r
501 IgnoredPattern = GetIgnoredDirListPattern()\r
502 ParseErrorFileList = []\r
503\r
504 for dirpath, dirnames, filenames in tuple:\r
505 if IgnoredPattern.match(dirpath.upper()):\r
506 continue\r
507\r
508 for Dir in dirnames:\r
509 Dirname = os.path.join(dirpath, Dir)\r
510 if os.path.islink(Dirname):\r
511 Dirname = os.path.realpath(Dirname)\r
512 if os.path.isdir(Dirname):\r
513 # symlinks to directories are treated as directories\r
514 dirnames.remove(Dir)\r
515 dirnames.append(Dirname)\r
516\r
517 for f in filenames:\r
518 if f.lower() in EccGlobalData.gConfig.SkipFileList:\r
519 continue\r
520 collector = None\r
521 FullName = os.path.normpath(os.path.join(dirpath, f))\r
522 model = DataClass.MODEL_FILE_OTHERS\r
523 if os.path.splitext(f)[1] in ('.h', '.c'):\r
524 EdkLogger.info("Parsing " + FullName)\r
525 model = f.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H\r
526 collector = CodeFragmentCollector.CodeFragmentCollector(FullName)\r
527 try:\r
528 collector.ParseFile()\r
529 except UnicodeError:\r
530 ParseErrorFileList.append(FullName)\r
531 collector.CleanFileProfileBuffer()\r
532 collector.ParseFileWithClearedPPDirective()\r
533# collector.PrintFragments()\r
534 BaseName = os.path.basename(f)\r
535 DirName = os.path.dirname(FullName)\r
536 Ext = os.path.splitext(f)[1].lstrip('.')\r
537 ModifiedTime = os.path.getmtime(FullName)\r
538 FileObj = DataClass.FileClass(-1, BaseName, Ext, DirName, FullName, model, ModifiedTime, GetFunctionList(), GetIdentifierList(), [])\r
539 FileObjList.append(FileObj)\r
540 if collector:\r
541 collector.CleanFileProfileBuffer()\r
542\r
543 if len(ParseErrorFileList) > 0:\r
544 EdkLogger.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList))\r
545\r
546 Db = GetDB()\r
547 for file in FileObjList:\r
548 if file.ExtName.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:\r
549 Db.InsertOneFile(file)\r
550\r
551 Db.UpdateIdentifierBelongsToFunction()\r
552\r
553def GetTableID(FullFileName, ErrorMsgList=None):\r
554 if ErrorMsgList is None:\r
555 ErrorMsgList = []\r
556\r
557 Db = GetDB()\r
558 SqlStatement = """ select ID\r
559 from File\r
560 where FullPath like '%s'\r
561 """ % FullFileName\r
562 ResultSet = Db.TblFile.Exec(SqlStatement)\r
563\r
564 FileID = -1\r
565 for Result in ResultSet:\r
566 if FileID != -1:\r
567 ErrorMsgList.append('Duplicate file ID found in DB for file %s' % FullFileName)\r
568 return - 2\r
569 FileID = Result[0]\r
570 if FileID == -1:\r
571 ErrorMsgList.append('NO file ID found in DB for file %s' % FullFileName)\r
572 return - 1\r
573 return FileID\r
574\r
575def GetIncludeFileList(FullFileName):\r
576 if os.path.splitext(FullFileName)[1].upper() not in ('.H'):\r
577 return []\r
578 IFList = IncludeFileListDict.get(FullFileName)\r
579 if IFList is not None:\r
580 return IFList\r
581\r
582 FileID = GetTableID(FullFileName)\r
583 if FileID < 0:\r
584 return []\r
585\r
586 Db = GetDB()\r
587 FileTable = 'Identifier' + str(FileID)\r
588 SqlStatement = """ select Value\r
589 from %s\r
590 where Model = %d\r
591 """ % (FileTable, DataClass.MODEL_IDENTIFIER_INCLUDE)\r
592 ResultSet = Db.TblFile.Exec(SqlStatement)\r
593 IncludeFileListDict[FullFileName] = ResultSet\r
594 return ResultSet\r
595\r
596def GetFullPathOfIncludeFile(Str, IncludePathList):\r
597 for IncludePath in IncludePathList:\r
598 FullPath = os.path.join(IncludePath, Str)\r
599 FullPath = os.path.normpath(FullPath)\r
600 if os.path.exists(FullPath):\r
601 return FullPath\r
602 return None\r
603\r
604def GetAllIncludeFiles(FullFileName):\r
605 if AllIncludeFileListDict.get(FullFileName) is not None:\r
606 return AllIncludeFileListDict.get(FullFileName)\r
607\r
608 FileDirName = os.path.dirname(FullFileName)\r
609 IncludePathList = IncludePathListDict.get(FileDirName)\r
610 if IncludePathList is None:\r
611 IncludePathList = MetaDataParser.GetIncludeListOfFile(EccGlobalData.gWorkspace, FullFileName, GetDB())\r
612 if FileDirName not in IncludePathList:\r
613 IncludePathList.insert(0, FileDirName)\r
614 IncludePathListDict[FileDirName] = IncludePathList\r
615 IncludeFileQueue = []\r
616 for IncludeFile in GetIncludeFileList(FullFileName):\r
617 FileName = IncludeFile[0].lstrip('#').strip()\r
618 FileName = FileName.lstrip('include').strip()\r
619 FileName = FileName.strip('\"')\r
620 FileName = FileName.lstrip('<').rstrip('>').strip()\r
621 FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList)\r
622 if FullPath is not None:\r
623 IncludeFileQueue.append(FullPath)\r
624\r
625 i = 0\r
626 while i < len(IncludeFileQueue):\r
627 for IncludeFile in GetIncludeFileList(IncludeFileQueue[i]):\r
628 FileName = IncludeFile[0].lstrip('#').strip()\r
629 FileName = FileName.lstrip('include').strip()\r
630 FileName = FileName.strip('\"')\r
631 FileName = FileName.lstrip('<').rstrip('>').strip()\r
632 FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList)\r
633 if FullPath is not None and FullPath not in IncludeFileQueue:\r
634 IncludeFileQueue.insert(i + 1, FullPath)\r
635 i += 1\r
636\r
637 AllIncludeFileListDict[FullFileName] = IncludeFileQueue\r
638 return IncludeFileQueue\r
639\r
640def GetPredicateListFromPredicateExpStr(PES):\r
641\r
642 PredicateList = []\r
643 i = 0\r
644 PredicateBegin = 0\r
645 #PredicateEnd = 0\r
646 LogicOpPos = -1\r
647 p = GetFuncDeclPattern()\r
648 while i < len(PES) - 1:\r
649 if (PES[i].isalnum() or PES[i] == '_' or PES[i] == '*') and LogicOpPos > PredicateBegin:\r
650 PredicateBegin = i\r
651 if (PES[i] == '&' and PES[i + 1] == '&') or (PES[i] == '|' and PES[i + 1] == '|'):\r
652 LogicOpPos = i\r
653 Exp = PES[PredicateBegin:i].strip()\r
654 # Exp may contain '.' or '->'\r
655 TmpExp = Exp.replace('.', '').replace('->', '')\r
656 if p.match(TmpExp):\r
657 PredicateList.append(Exp)\r
658 else:\r
659 PredicateList.append(Exp.rstrip(';').rstrip(')').strip())\r
660 i += 1\r
661\r
662 if PredicateBegin > LogicOpPos:\r
663 while PredicateBegin < len(PES):\r
664 if PES[PredicateBegin].isalnum() or PES[PredicateBegin] == '_' or PES[PredicateBegin] == '*':\r
665 break\r
666 PredicateBegin += 1\r
667 Exp = PES[PredicateBegin:len(PES)].strip()\r
668 # Exp may contain '.' or '->'\r
669 TmpExp = Exp.replace('.', '').replace('->', '')\r
670 if p.match(TmpExp):\r
671 PredicateList.append(Exp)\r
672 else:\r
673 PredicateList.append(Exp.rstrip(';').rstrip(')').strip())\r
674 return PredicateList\r
675\r
676def GetCNameList(Lvalue, StarList=[]):\r
677 Lvalue += ' '\r
678 i = 0\r
679 SearchBegin = 0\r
680 VarStart = -1\r
681 VarEnd = -1\r
682 VarList = []\r
683\r
684 while SearchBegin < len(Lvalue):\r
685 while i < len(Lvalue):\r
686 if Lvalue[i].isalnum() or Lvalue[i] == '_':\r
687 if VarStart == -1:\r
688 VarStart = i\r
689 VarEnd = i\r
690 i += 1\r
691 elif VarEnd != -1:\r
692 VarList.append(Lvalue[VarStart:VarEnd + 1])\r
693 i += 1\r
694 break\r
695 else:\r
696 if VarStart == -1 and Lvalue[i] == '*':\r
697 StarList.append('*')\r
698 i += 1\r
699 if VarEnd == -1:\r
700 break\r
701\r
702\r
703 DotIndex = Lvalue[VarEnd:].find('.')\r
704 ArrowIndex = Lvalue[VarEnd:].find('->')\r
705 if DotIndex == -1 and ArrowIndex == -1:\r
706 break\r
707 elif DotIndex == -1 and ArrowIndex != -1:\r
708 SearchBegin = VarEnd + ArrowIndex\r
709 elif ArrowIndex == -1 and DotIndex != -1:\r
710 SearchBegin = VarEnd + DotIndex\r
711 else:\r
712 SearchBegin = VarEnd + ((DotIndex < ArrowIndex) and DotIndex or ArrowIndex)\r
713\r
714 i = SearchBegin\r
715 VarStart = -1\r
716 VarEnd = -1\r
717\r
718 return VarList\r
719\r
720def SplitPredicateByOp(Str, Op, IsFuncCalling=False):\r
721\r
722 Name = Str.strip()\r
723 Value = None\r
724\r
725 if IsFuncCalling:\r
726 Index = 0\r
727 LBFound = False\r
728 UnmatchedLBCount = 0\r
729 while Index < len(Str):\r
730 while not LBFound and Str[Index] != '_' and not Str[Index].isalnum():\r
731 Index += 1\r
732\r
733 while not LBFound and (Str[Index].isalnum() or Str[Index] == '_'):\r
734 Index += 1\r
735 # maybe type-cast at the begining, skip it.\r
736 RemainingStr = Str[Index:].lstrip()\r
737 if RemainingStr.startswith(')') and not LBFound:\r
738 Index += 1\r
739 continue\r
740\r
741 if RemainingStr.startswith('(') and not LBFound:\r
742 LBFound = True\r
743\r
744 if Str[Index] == '(':\r
745 UnmatchedLBCount += 1\r
746 Index += 1\r
747 continue\r
748\r
749 if Str[Index] == ')':\r
750 UnmatchedLBCount -= 1\r
751 Index += 1\r
752 if UnmatchedLBCount == 0:\r
753 break\r
754 continue\r
755\r
756 Index += 1\r
757\r
758 if UnmatchedLBCount > 0:\r
759 return [Name]\r
760\r
761 IndexInRemainingStr = Str[Index:].find(Op)\r
762 if IndexInRemainingStr == -1:\r
763 return [Name]\r
764\r
765 Name = Str[0:Index + IndexInRemainingStr].strip()\r
766 Value = Str[Index + IndexInRemainingStr + len(Op):].strip().strip(')')\r
767 return [Name, Value]\r
768\r
769 TmpStr = Str.rstrip(';').rstrip(')')\r
770 while True:\r
771 Index = TmpStr.rfind(Op)\r
772 if Index == -1:\r
773 return [Name]\r
774\r
775 if Str[Index - 1].isalnum() or Str[Index - 1].isspace() or Str[Index - 1] == ')' or Str[Index - 1] == ']':\r
776 Name = Str[0:Index].strip()\r
777 Value = Str[Index + len(Op):].strip()\r
778 return [Name, Value]\r
779\r
780 TmpStr = Str[0:Index - 1]\r
781\r
782def SplitPredicateStr(Str):\r
783\r
784 Str = Str.lstrip('(')\r
785 IsFuncCalling = False\r
786 p = GetFuncDeclPattern()\r
787 TmpStr = Str.replace('.', '').replace('->', '')\r
788 if p.match(TmpStr):\r
789 IsFuncCalling = True\r
790\r
791 PredPartList = SplitPredicateByOp(Str, '==', IsFuncCalling)\r
792 if len(PredPartList) > 1:\r
793 return [PredPartList, '==']\r
794\r
795 PredPartList = SplitPredicateByOp(Str, '!=', IsFuncCalling)\r
796 if len(PredPartList) > 1:\r
797 return [PredPartList, '!=']\r
798\r
799 PredPartList = SplitPredicateByOp(Str, '>=', IsFuncCalling)\r
800 if len(PredPartList) > 1:\r
801 return [PredPartList, '>=']\r
802\r
803 PredPartList = SplitPredicateByOp(Str, '<=', IsFuncCalling)\r
804 if len(PredPartList) > 1:\r
805 return [PredPartList, '<=']\r
806\r
807 PredPartList = SplitPredicateByOp(Str, '>', IsFuncCalling)\r
808 if len(PredPartList) > 1:\r
809 return [PredPartList, '>']\r
810\r
811 PredPartList = SplitPredicateByOp(Str, '<', IsFuncCalling)\r
812 if len(PredPartList) > 1:\r
813 return [PredPartList, '<']\r
814\r
815 return [[Str, None], None]\r
816\r
817def GetFuncContainsPE(ExpLine, ResultSet):\r
818 for Result in ResultSet:\r
819 if Result[0] < ExpLine and Result[1] > ExpLine:\r
820 return Result\r
821 return None\r
822\r
823def PatternInModifier(Modifier, SubStr):\r
824 PartList = Modifier.split()\r
825 for Part in PartList:\r
826 if Part == SubStr:\r
827 return True\r
828 return False\r
829\r
830def GetDataTypeFromModifier(ModifierStr):\r
831 MList = ModifierStr.split()\r
832 ReturnType = ''\r
833 for M in MList:\r
834 if M in EccGlobalData.gConfig.ModifierSet:\r
835 continue\r
836 # remove array sufix\r
837 if M.startswith('[') or M.endswith(']'):\r
838 continue\r
839 ReturnType += M + ' '\r
840\r
841 ReturnType = ReturnType.strip()\r
842 if len(ReturnType) == 0:\r
843 ReturnType = 'VOID'\r
844 return ReturnType\r
845\r
846def DiffModifier(Str1, Str2):\r
847 PartList1 = Str1.split()\r
848 PartList2 = Str2.split()\r
849 if PartList1 == PartList2:\r
850 return False\r
851 else:\r
852 return True\r
853\r
854def GetTypedefDict(FullFileName):\r
855\r
856 Dict = ComplexTypeDict.get(FullFileName)\r
857 if Dict is not None:\r
858 return Dict\r
859\r
860 FileID = GetTableID(FullFileName)\r
861 FileTable = 'Identifier' + str(FileID)\r
862 Db = GetDB()\r
863 SqlStatement = """ select Modifier, Name, Value, ID\r
864 from %s\r
865 where Model = %d\r
866 """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)\r
867 ResultSet = Db.TblFile.Exec(SqlStatement)\r
868\r
869 Dict = {}\r
870 for Result in ResultSet:\r
871 if len(Result[0]) == 0:\r
872 Dict[Result[1]] = Result[2]\r
873\r
874 IncludeFileList = GetAllIncludeFiles(FullFileName)\r
875 for F in IncludeFileList:\r
876 FileID = GetTableID(F)\r
877 if FileID < 0:\r
878 continue\r
879\r
880 FileTable = 'Identifier' + str(FileID)\r
881 SqlStatement = """ select Modifier, Name, Value, ID\r
882 from %s\r
883 where Model = %d\r
884 """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)\r
885 ResultSet = Db.TblFile.Exec(SqlStatement)\r
886\r
887 for Result in ResultSet:\r
888 if not Result[2].startswith('FP ('):\r
889 Dict[Result[1]] = Result[2]\r
890 else:\r
891 if len(Result[0]) == 0:\r
892 Dict[Result[1]] = 'VOID'\r
893 else:\r
894 Dict[Result[1]] = GetDataTypeFromModifier(Result[0])\r
895\r
896 ComplexTypeDict[FullFileName] = Dict\r
897 return Dict\r
898\r
899def GetSUDict(FullFileName):\r
900\r
901 Dict = SUDict.get(FullFileName)\r
902 if Dict is not None:\r
903 return Dict\r
904\r
905 FileID = GetTableID(FullFileName)\r
906 FileTable = 'Identifier' + str(FileID)\r
907 Db = GetDB()\r
908 SqlStatement = """ select Name, Value, ID\r
909 from %s\r
910 where Model = %d or Model = %d\r
911 """ % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION)\r
912 ResultSet = Db.TblFile.Exec(SqlStatement)\r
913\r
914 Dict = {}\r
915 for Result in ResultSet:\r
916 if len(Result[1]) > 0:\r
917 Dict[Result[0]] = Result[1]\r
918\r
919 IncludeFileList = GetAllIncludeFiles(FullFileName)\r
920 for F in IncludeFileList:\r
921 FileID = GetTableID(F)\r
922 if FileID < 0:\r
923 continue\r
924\r
925 FileTable = 'Identifier' + str(FileID)\r
926 SqlStatement = """ select Name, Value, ID\r
927 from %s\r
928 where Model = %d or Model = %d\r
929 """ % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION)\r
930 ResultSet = Db.TblFile.Exec(SqlStatement)\r
931\r
932 for Result in ResultSet:\r
933 if len(Result[1]) > 0:\r
934 Dict[Result[0]] = Result[1]\r
935\r
936 SUDict[FullFileName] = Dict\r
937 return Dict\r
938\r
939def StripComments(Str):\r
940 Str += ' '\r
941 ListFromStr = list(Str)\r
942\r
943 InComment = False\r
944 DoubleSlashComment = False\r
945 Index = 0\r
946 while Index < len(ListFromStr):\r
947 # meet new line, then no longer in a comment for //\r
948 if ListFromStr[Index] == '\n':\r
949 if InComment and DoubleSlashComment:\r
950 InComment = False\r
951 DoubleSlashComment = False\r
952 Index += 1\r
953 # check for */ comment end\r
954 elif InComment and not DoubleSlashComment and ListFromStr[Index] == '*' and ListFromStr[Index + 1] == '/':\r
955 ListFromStr[Index] = ' '\r
956 Index += 1\r
957 ListFromStr[Index] = ' '\r
958 Index += 1\r
959 InComment = False\r
960 # set comments to spaces\r
961 elif InComment:\r
962 ListFromStr[Index] = ' '\r
963 Index += 1\r
964 # check for // comment\r
965 elif ListFromStr[Index] == '/' and ListFromStr[Index + 1] == '/' and ListFromStr[Index + 2] != '\n':\r
966 InComment = True\r
967 DoubleSlashComment = True\r
968\r
969 # check for /* comment start\r
970 elif ListFromStr[Index] == '/' and ListFromStr[Index + 1] == '*':\r
971 ListFromStr[Index] = ' '\r
972 Index += 1\r
973 ListFromStr[Index] = ' '\r
974 Index += 1\r
975 InComment = True\r
976 else:\r
977 Index += 1\r
978\r
979 # restore from List to String\r
980 Str = "".join(ListFromStr)\r
981 Str = Str.rstrip(' ')\r
982\r
983 return Str\r
984\r
985def GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict):\r
986 Value = TypedefDict.get(Type)\r
987 if Value is None:\r
988 Value = SUDict.get(Type)\r
989 if Value is None:\r
990 return None\r
991\r
992 LBPos = Value.find('{')\r
993 while LBPos == -1:\r
994 FTList = Value.split()\r
995 for FT in FTList:\r
996 if FT not in ('struct', 'union'):\r
997 Value = TypedefDict.get(FT)\r
998 if Value is None:\r
999 Value = SUDict.get(FT)\r
1000 break\r
1001\r
1002 if Value is None:\r
1003 return None\r
1004\r
1005 LBPos = Value.find('{')\r
1006\r
1007# RBPos = Value.find('}')\r
1008 Fields = Value[LBPos + 1:]\r
1009 Fields = StripComments(Fields)\r
1010 FieldsList = Fields.split(';')\r
1011 for Field in FieldsList:\r
1012 Field = Field.strip()\r
1013 Index = Field.rfind(FieldName)\r
1014 if Index < 1:\r
1015 continue\r
1016 if not Field[Index - 1].isalnum():\r
1017 if Index + len(FieldName) == len(Field):\r
1018 Type = GetDataTypeFromModifier(Field[0:Index])\r
1019 return Type.strip()\r
1020 else:\r
1021 # For the condition that the field in struct is an array with [] sufixes...\r
1022 if not Field[Index + len(FieldName)].isalnum():\r
1023 Type = GetDataTypeFromModifier(Field[0:Index])\r
1024 return Type.strip()\r
1025\r
1026 return None\r
1027\r
1028def GetRealType(Type, TypedefDict, TargetType=None):\r
1029 if TargetType is not None and Type == TargetType:\r
1030 return Type\r
1031 while TypedefDict.get(Type):\r
1032 Type = TypedefDict.get(Type)\r
1033 if TargetType is not None and Type == TargetType:\r
1034 return Type\r
1035 return Type\r
1036\r
1037def GetTypeInfo(RefList, Modifier, FullFileName, TargetType=None):\r
1038 TypedefDict = GetTypedefDict(FullFileName)\r
1039 SUDict = GetSUDict(FullFileName)\r
1040 Type = GetDataTypeFromModifier(Modifier).replace('*', '').strip()\r
1041\r
1042 Type = Type.split()[-1]\r
1043 Index = 0\r
1044 while Index < len(RefList):\r
1045 FieldName = RefList[Index]\r
1046 FromType = GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict)\r
1047 if FromType is None:\r
1048 return None\r
1049 # we want to determine the exact type.\r
1050 if TargetType is not None:\r
1051 Type = FromType.split()[0]\r
1052 # we only want to check if it is a pointer\r
1053 else:\r
1054 Type = FromType\r
1055 if Type.find('*') != -1 and Index == len(RefList) - 1:\r
1056 return Type\r
1057 Type = FromType.split()[0]\r
1058\r
1059 Index += 1\r
1060\r
1061 Type = GetRealType(Type, TypedefDict, TargetType)\r
1062\r
1063 return Type\r
1064\r
1065def GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall=False, TargetType=None, StarList=None):\r
1066\r
1067 PredVar = PredVarList[0]\r
1068 FileID = GetTableID(FullFileName)\r
1069\r
1070 Db = GetDB()\r
1071 FileTable = 'Identifier' + str(FileID)\r
1072 # search variable in include files\r
1073\r
1074 # it is a function call, search function declarations and definitions\r
1075 if IsFuncCall:\r
1076 SqlStatement = """ select Modifier, ID\r
1077 from %s\r
1078 where Model = %d and Value = \'%s\'\r
1079 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar)\r
1080 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1081\r
1082 for Result in ResultSet:\r
1083 Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
1084 TypedefDict = GetTypedefDict(FullFileName)\r
1085 Type = GetRealType(Type, TypedefDict, TargetType)\r
1086 return Type\r
1087\r
1088 IncludeFileList = GetAllIncludeFiles(FullFileName)\r
1089 for F in IncludeFileList:\r
1090 FileID = GetTableID(F)\r
1091 if FileID < 0:\r
1092 continue\r
1093\r
1094 FileTable = 'Identifier' + str(FileID)\r
1095 SqlStatement = """ select Modifier, ID\r
1096 from %s\r
1097 where Model = %d and Value = \'%s\'\r
1098 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar)\r
1099 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1100\r
1101 for Result in ResultSet:\r
1102 Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
1103 TypedefDict = GetTypedefDict(FullFileName)\r
1104 Type = GetRealType(Type, TypedefDict, TargetType)\r
1105 return Type\r
1106\r
1107 FileID = GetTableID(FullFileName)\r
1108 SqlStatement = """ select Modifier, ID\r
1109 from Function\r
1110 where BelongsToFile = %d and Name = \'%s\'\r
1111 """ % (FileID, PredVar)\r
1112 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1113\r
1114 for Result in ResultSet:\r
1115 Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
1116 TypedefDict = GetTypedefDict(FullFileName)\r
1117 Type = GetRealType(Type, TypedefDict, TargetType)\r
1118 return Type\r
1119\r
1120 for F in IncludeFileList:\r
1121 FileID = GetTableID(F)\r
1122 if FileID < 0:\r
1123 continue\r
1124\r
1125 FileTable = 'Identifier' + str(FileID)\r
1126 SqlStatement = """ select Modifier, ID\r
1127 from Function\r
1128 where BelongsToFile = %d and Name = \'%s\'\r
1129 """ % (FileID, PredVar)\r
1130 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1131\r
1132 for Result in ResultSet:\r
1133 Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
1134 TypedefDict = GetTypedefDict(FullFileName)\r
1135 Type = GetRealType(Type, TypedefDict, TargetType)\r
1136 return Type\r
1137\r
1138 return None\r
1139\r
1140 # really variable, search local variable first\r
1141 SqlStatement = """ select Modifier, ID\r
1142 from %s\r
1143 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d\r
1144 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar, FuncRecord[0], FuncRecord[1])\r
1145 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1146 VarFound = False\r
1147 for Result in ResultSet:\r
1148 if len(PredVarList) > 1:\r
1149 Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)\r
1150 return Type\r
1151 else:\r
1152# Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
1153 TypeList = GetDataTypeFromModifier(Result[0]).split()\r
1154 Type = TypeList[-1]\r
1155 if len(TypeList) > 1 and StarList is not None:\r
1156 for Star in StarList:\r
1157 Type = Type.strip()\r
1158 Type = Type.rstrip(Star)\r
1159 # Get real type after de-reference pointers.\r
1160 if len(Type.strip()) == 0:\r
1161 Type = TypeList[-2]\r
1162 TypedefDict = GetTypedefDict(FullFileName)\r
1163 Type = GetRealType(Type, TypedefDict, TargetType)\r
1164 return Type\r
1165\r
1166 # search function parameters second\r
1167 ParamList = GetParamList(FuncRecord[2])\r
1168 for Param in ParamList:\r
1169 if Param.Name.strip() == PredVar:\r
1170 if len(PredVarList) > 1:\r
1171 Type = GetTypeInfo(PredVarList[1:], Param.Modifier, FullFileName, TargetType)\r
1172 return Type\r
1173 else:\r
1174 TypeList = GetDataTypeFromModifier(Param.Modifier).split()\r
1175 Type = TypeList[-1]\r
1176 if Type == '*' and len(TypeList) >= 2:\r
1177 Type = TypeList[-2]\r
1178 if len(TypeList) > 1 and StarList is not None:\r
1179 for Star in StarList:\r
1180 Type = Type.strip()\r
1181 Type = Type.rstrip(Star)\r
1182 # Get real type after de-reference pointers.\r
1183 if len(Type.strip()) == 0:\r
1184 Type = TypeList[-2]\r
1185 TypedefDict = GetTypedefDict(FullFileName)\r
1186 Type = GetRealType(Type, TypedefDict, TargetType)\r
1187 return Type\r
1188\r
1189 # search global variable next\r
1190 SqlStatement = """ select Modifier, ID\r
1191 from %s\r
1192 where Model = %d and Name = \'%s\' and BelongsToFunction = -1\r
1193 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar)\r
1194 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1195\r
1196 for Result in ResultSet:\r
1197 if len(PredVarList) > 1:\r
1198 Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)\r
1199 return Type\r
1200 else:\r
1201 TypeList = GetDataTypeFromModifier(Result[0]).split()\r
1202 Type = TypeList[-1]\r
1203 if len(TypeList) > 1 and StarList is not None:\r
1204 for Star in StarList:\r
1205 Type = Type.strip()\r
1206 Type = Type.rstrip(Star)\r
1207 # Get real type after de-reference pointers.\r
1208 if len(Type.strip()) == 0:\r
1209 Type = TypeList[-2]\r
1210 TypedefDict = GetTypedefDict(FullFileName)\r
1211 Type = GetRealType(Type, TypedefDict, TargetType)\r
1212 return Type\r
1213\r
1214 IncludeFileList = GetAllIncludeFiles(FullFileName)\r
1215 for F in IncludeFileList:\r
1216 FileID = GetTableID(F)\r
1217 if FileID < 0:\r
1218 continue\r
1219\r
1220 FileTable = 'Identifier' + str(FileID)\r
1221 SqlStatement = """ select Modifier, ID\r
1222 from %s\r
1223 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'\r
1224 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar)\r
1225 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1226\r
1227 for Result in ResultSet:\r
1228 if len(PredVarList) > 1:\r
1229 Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)\r
1230 return Type\r
1231 else:\r
1232 TypeList = GetDataTypeFromModifier(Result[0]).split()\r
1233 Type = TypeList[-1]\r
1234 if len(TypeList) > 1 and StarList is not None:\r
1235 for Star in StarList:\r
1236 Type = Type.strip()\r
1237 Type = Type.rstrip(Star)\r
1238 # Get real type after de-reference pointers.\r
1239 if len(Type.strip()) == 0:\r
1240 Type = TypeList[-2]\r
1241 TypedefDict = GetTypedefDict(FullFileName)\r
1242 Type = GetRealType(Type, TypedefDict, TargetType)\r
1243 return Type\r
1244\r
1245def GetTypeFromArray(Type, Var):\r
1246 Count = Var.count('[')\r
1247\r
1248 while Count > 0:\r
1249 Type = Type.strip()\r
1250 Type = Type.rstrip('*')\r
1251 Count = Count - 1\r
1252\r
1253 return Type\r
1254\r
1255def CheckFuncLayoutReturnType(FullFileName):\r
1256 ErrorMsgList = []\r
1257\r
1258 FileID = GetTableID(FullFileName, ErrorMsgList)\r
1259 if FileID < 0:\r
1260 return ErrorMsgList\r
1261\r
1262 Db = GetDB()\r
1263 FileTable = 'Identifier' + str(FileID)\r
1264 SqlStatement = """ select Modifier, ID, StartLine, StartColumn, EndLine, Value\r
1265 from %s\r
1266 where Model = %d\r
1267 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1268 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1269 for Result in ResultSet:\r
1270 ReturnType = GetDataTypeFromModifier(Result[0])\r
1271 TypeStart = ReturnType.split()[0]\r
1272 FuncName = Result[5]\r
1273 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, FuncName):\r
1274 continue\r
1275 Result0 = Result[0]\r
1276 if Result0.upper().startswith('STATIC'):\r
1277 Result0 = Result0[6:].strip()\r
1278 Index = Result0.find(TypeStart)\r
1279 if Index != 0 or Result[3] != 0:\r
1280 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, FileTable, Result[1])\r
1281\r
1282 if Result[2] == Result[4]:\r
1283 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear on its own line' % FuncName, FileTable, Result[1])\r
1284\r
1285 SqlStatement = """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name\r
1286 from Function\r
1287 where BelongsToFile = %d\r
1288 """ % (FileID)\r
1289 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1290 for Result in ResultSet:\r
1291 ReturnType = GetDataTypeFromModifier(Result[0])\r
1292 TypeStart = ReturnType.split()[0]\r
1293 FuncName = Result[5]\r
1294 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, FuncName):\r
1295 continue\r
1296 Result0 = Result[0]\r
1297 if Result0.upper().startswith('STATIC'):\r
1298 Result0 = Result0[6:].strip()\r
1299 Index = Result0.find(ReturnType)\r
1300 if Index != 0 or Result[3] != 0:\r
1301 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, 'Function', Result[1])\r
1302\r
1303def CheckFuncLayoutModifier(FullFileName):\r
1304 ErrorMsgList = []\r
1305\r
1306 FileID = GetTableID(FullFileName, ErrorMsgList)\r
1307 if FileID < 0:\r
1308 return ErrorMsgList\r
1309\r
1310 Db = GetDB()\r
1311 FileTable = 'Identifier' + str(FileID)\r
1312 SqlStatement = """ select Modifier, ID\r
1313 from %s\r
1314 where Model = %d\r
1315 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1316 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1317 for Result in ResultSet:\r
1318 ReturnType = GetDataTypeFromModifier(Result[0])\r
1319 TypeStart = ReturnType.split()[0]\r
1320 Result0 = Result[0]\r
1321 if Result0.upper().startswith('STATIC'):\r
1322 Result0 = Result0[6:].strip()\r
1323 Index = Result0.find(TypeStart)\r
1324 if Index != 0:\r
1325 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', FileTable, Result[1])\r
1326\r
1327 SqlStatement = """ select Modifier, ID\r
1328 from Function\r
1329 where BelongsToFile = %d\r
1330 """ % (FileID)\r
1331 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1332 for Result in ResultSet:\r
1333 ReturnType = GetDataTypeFromModifier(Result[0])\r
1334 TypeStart = ReturnType.split()[0]\r
1335 Result0 = Result[0]\r
1336 if Result0.upper().startswith('STATIC'):\r
1337 Result0 = Result0[6:].strip()\r
1338 Index = Result0.find(TypeStart)\r
1339 if Index != 0:\r
1340 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', 'Function', Result[1])\r
1341\r
1342def CheckFuncLayoutName(FullFileName):\r
1343 ErrorMsgList = []\r
1344 # Parameter variable format pattern.\r
1345 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')\r
1346 ParamIgnoreList = ('VOID', '...')\r
1347 FileID = GetTableID(FullFileName, ErrorMsgList)\r
1348 if FileID < 0:\r
1349 return ErrorMsgList\r
1350\r
1351 Db = GetDB()\r
1352 FileTable = 'Identifier' + str(FileID)\r
1353 SqlStatement = """ select Name, ID, EndColumn, Value\r
1354 from %s\r
1355 where Model = %d\r
1356 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1357 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1358 for Result in ResultSet:\r
1359 FuncName = Result[3]\r
1360 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName):\r
1361 continue\r
1362 if Result[2] != 0:\r
1363 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, FileTable, Result[1])\r
1364 ParamList = GetParamList(Result[0])\r
1365 if len(ParamList) == 0:\r
1366 continue\r
1367 StartLine = 0\r
1368 for Param in ParamList:\r
1369 if Param.StartLine <= StartLine:\r
1370 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, FileTable, Result[1])\r
1371 if Param.StartLine - StartLine > 1:\r
1372 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, FileTable, Result[1])\r
1373 if not Pattern.match(Param.Name) and not Param.Name in ParamIgnoreList and not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Param.Name):\r
1374 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1])\r
1375 StartLine = Param.StartLine\r
1376\r
1377 if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'):\r
1378 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', FileTable, Result[1])\r
1379\r
1380 SqlStatement = """ select Modifier, ID, FunNameStartColumn, Name\r
1381 from Function\r
1382 where BelongsToFile = %d\r
1383 """ % (FileID)\r
1384 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1385 for Result in ResultSet:\r
1386 FuncName = Result[3]\r
1387 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName):\r
1388 continue\r
1389 if Result[2] != 0:\r
1390 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, 'Function', Result[1])\r
1391 ParamList = GetParamList(Result[0])\r
1392 if len(ParamList) == 0:\r
1393 continue\r
1394 StartLine = 0\r
1395 for Param in ParamList:\r
1396 if Param.StartLine <= StartLine:\r
1397 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, 'Function', Result[1])\r
1398 if Param.StartLine - StartLine > 1:\r
1399 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, 'Function', Result[1])\r
1400 if not Pattern.match(Param.Name) and not Param.Name in ParamIgnoreList and not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Param.Name):\r
1401 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1])\r
1402 StartLine = Param.StartLine\r
1403 if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'):\r
1404 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', 'Function', Result[1])\r
1405\r
1406def CheckFuncLayoutPrototype(FullFileName):\r
1407 ErrorMsgList = []\r
1408\r
1409 FileID = GetTableID(FullFileName, ErrorMsgList)\r
1410 if FileID < 0:\r
1411 return ErrorMsgList\r
1412\r
1413 FileTable = 'Identifier' + str(FileID)\r
1414 Db = GetDB()\r
1415 SqlStatement = """ select Modifier, Header, Name, ID\r
1416 from Function\r
1417 where BelongsToFile = %d\r
1418 """ % (FileID)\r
1419 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1420 if len(ResultSet) == 0:\r
1421 return ErrorMsgList\r
1422\r
1423 FuncDefList = []\r
1424 for Result in ResultSet:\r
1425 FuncDefList.append(Result)\r
1426\r
1427 SqlStatement = """ select Modifier, Name, ID\r
1428 from %s\r
1429 where Model = %d\r
1430 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1431 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1432 FuncDeclList = []\r
1433 for Result in ResultSet:\r
1434 FuncDeclList.append(Result)\r
1435\r
1436 UndeclFuncList = []\r
1437 for FuncDef in FuncDefList:\r
1438 FuncName = FuncDef[2].strip()\r
1439 FuncModifier = FuncDef[0]\r
1440 FuncDefHeader = FuncDef[1]\r
1441 for FuncDecl in FuncDeclList:\r
1442 LBPos = FuncDecl[1].find('(')\r
1443 DeclName = FuncDecl[1][0:LBPos].strip()\r
1444 DeclModifier = FuncDecl[0]\r
1445 if DeclName == FuncName:\r
1446 if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName):\r
1447 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3])\r
1448 ParamListOfDef = GetParamList(FuncDefHeader)\r
1449 ParamListOfDecl = GetParamList(FuncDecl[1])\r
1450 if len(ParamListOfDef) != len(ParamListOfDecl) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, FuncName):\r
1451 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, 'Parameter number different in function [%s].' % FuncName, 'Function', FuncDef[3])\r
1452 break\r
1453\r
1454 Index = 0\r
1455 while Index < len(ParamListOfDef):\r
1456 if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, FuncName):\r
1457 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, 'Parameter %s has different modifier with prototype in function [%s].' % (ParamListOfDef[Index].Name, FuncName), 'Function', FuncDef[3])\r
1458 Index += 1\r
1459 break\r
1460 else:\r
1461 UndeclFuncList.append(FuncDef)\r
1462\r
1463 IncludeFileList = GetAllIncludeFiles(FullFileName)\r
1464 FuncDeclList = []\r
1465 for F in IncludeFileList:\r
1466 FileID = GetTableID(F, ErrorMsgList)\r
1467 if FileID < 0:\r
1468 continue\r
1469\r
1470 FileTable = 'Identifier' + str(FileID)\r
1471 SqlStatement = """ select Modifier, Name, ID\r
1472 from %s\r
1473 where Model = %d\r
1474 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1475 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1476\r
1477 for Result in ResultSet:\r
1478 FuncDeclList.append(Result)\r
1479\r
1480 for FuncDef in UndeclFuncList:\r
1481 FuncName = FuncDef[2].strip()\r
1482 FuncModifier = FuncDef[0]\r
1483 FuncDefHeader = FuncDef[1]\r
1484 for FuncDecl in FuncDeclList:\r
1485 LBPos = FuncDecl[1].find('(')\r
1486 DeclName = FuncDecl[1][0:LBPos].strip()\r
1487 DeclModifier = FuncDecl[0]\r
1488 if DeclName == FuncName:\r
1489 if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName):\r
1490 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3])\r
1491 ParamListOfDef = GetParamList(FuncDefHeader)\r
1492 ParamListOfDecl = GetParamList(FuncDecl[1])\r
1493 if len(ParamListOfDef) != len(ParamListOfDecl) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, FuncName):\r
1494 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, 'Parameter number different in function [%s].' % FuncName, 'Function', FuncDef[3])\r
1495 break\r
1496\r
1497 Index = 0\r
1498 while Index < len(ParamListOfDef):\r
1499 if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, FuncName):\r
1500 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, 'Parameter %s has different modifier with prototype in function [%s].' % (ParamListOfDef[Index].Name, FuncName), 'Function', FuncDef[3])\r
1501 Index += 1\r
1502 break\r
1503\r
1504def CheckFuncLayoutBody(FullFileName):\r
1505 ErrorMsgList = []\r
1506\r
1507 FileID = GetTableID(FullFileName, ErrorMsgList)\r
1508 if FileID < 0:\r
1509 return ErrorMsgList\r
1510\r
1511 FileTable = 'Identifier' + str(FileID)\r
1512 Db = GetDB()\r
1513 SqlStatement = """ select BodyStartColumn, EndColumn, ID\r
1514 from Function\r
1515 where BelongsToFile = %d\r
1516 """ % (FileID)\r
1517 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1518 if len(ResultSet) == 0:\r
1519 return ErrorMsgList\r
1520 for Result in ResultSet:\r
1521 if Result[0] != 0:\r
1522 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'open brace should be at the very beginning of a line.', 'Function', Result[2])\r
1523 if Result[1] != 0:\r
1524 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'close brace should be at the very beginning of a line.', 'Function', Result[2])\r
1525\r
1526def CheckFuncLayoutLocalVariable(FullFileName):\r
1527 ErrorMsgList = []\r
1528\r
1529 FileID = GetTableID(FullFileName, ErrorMsgList)\r
1530 if FileID < 0:\r
1531 return ErrorMsgList\r
1532\r
1533 Db = GetDB()\r
1534 FileTable = 'Identifier' + str(FileID)\r
1535 SqlStatement = """ select ID\r
1536 from Function\r
1537 where BelongsToFile = %d\r
1538 """ % (FileID)\r
1539 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1540 if len(ResultSet) == 0:\r
1541 return ErrorMsgList\r
1542 FL = []\r
1543 for Result in ResultSet:\r
1544 FL.append(Result)\r
1545\r
1546 for F in FL:\r
1547 SqlStatement = """ select Name, Value, ID, Modifier\r
1548 from %s\r
1549 where Model = %d and BelongsToFunction = %d\r
1550 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, F[0])\r
1551 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1552 if len(ResultSet) == 0:\r
1553 continue\r
1554\r
1555 for Result in ResultSet:\r
1556 if len(Result[1]) > 0 and 'CONST' not in Result[3]:\r
1557 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE, 'Variable Name: %s' % Result[0], FileTable, Result[2])\r
1558\r
1559def CheckMemberVariableFormat(Name, Value, FileTable, TdId, ModelId):\r
1560 ErrMsgList = []\r
1561 # Member variable format pattern.\r
1562 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')\r
1563\r
1564 LBPos = Value.find('{')\r
1565 RBPos = Value.rfind('}')\r
1566 if LBPos == -1 or RBPos == -1:\r
1567 return ErrMsgList\r
1568\r
1569 Fields = Value[LBPos + 1 : RBPos]\r
1570 Fields = StripComments(Fields).strip()\r
1571 NestPos = Fields.find ('struct')\r
1572 if NestPos != -1 and (NestPos + len('struct') < len(Fields)) and ModelId != DataClass.MODEL_IDENTIFIER_UNION:\r
1573 if not Fields[NestPos + len('struct') + 1].isalnum():\r
1574 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):\r
1575 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested struct in [%s].' % (Name), FileTable, TdId)\r
1576 return ErrMsgList\r
1577 NestPos = Fields.find ('union')\r
1578 if NestPos != -1 and (NestPos + len('union') < len(Fields)):\r
1579 if not Fields[NestPos + len('union') + 1].isalnum():\r
1580 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):\r
1581 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested union in [%s].' % (Name), FileTable, TdId)\r
1582 return ErrMsgList\r
1583 NestPos = Fields.find ('enum')\r
1584 if NestPos != -1 and (NestPos + len('enum') < len(Fields)):\r
1585 if not Fields[NestPos + len('enum') + 1].isalnum():\r
1586 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):\r
1587 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested enum in [%s].' % (Name), FileTable, TdId)\r
1588 return ErrMsgList\r
1589\r
1590 if ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:\r
1591 FieldsList = Fields.split(',')\r
1592 # deal with enum is pre-assigned a value by function call ( , , , ...)\r
1593 QuoteCount = 0\r
1594 Index = 0\r
1595 RemoveCurrentElement = False\r
1596 while Index < len(FieldsList):\r
1597 Field = FieldsList[Index]\r
1598\r
1599 if Field.find('(') != -1:\r
1600 QuoteCount += 1\r
1601 RemoveCurrentElement = True\r
1602 Index += 1\r
1603 continue\r
1604\r
1605 if Field.find(')') != -1 and QuoteCount > 0:\r
1606 QuoteCount -= 1\r
1607\r
1608 if RemoveCurrentElement:\r
1609 FieldsList.remove(Field)\r
1610 if QuoteCount == 0:\r
1611 RemoveCurrentElement = False\r
1612 continue\r
1613\r
1614 if QuoteCount == 0:\r
1615 RemoveCurrentElement = False\r
1616\r
1617 Index += 1\r
1618 else:\r
1619 FieldsList = Fields.split(';')\r
1620\r
1621 for Field in FieldsList:\r
1622 Field = Field.strip()\r
1623 if Field == '':\r
1624 continue\r
1625 # For the condition that the field in struct is an array with [] sufixes...\r
1626 if Field[-1] == ']':\r
1627 LBPos = Field.find('[')\r
1628 Field = Field[0:LBPos]\r
1629 # For the condition that bit field ": Number"\r
1630 if Field.find(':') != -1:\r
1631 ColonPos = Field.find(':')\r
1632 Field = Field[0:ColonPos]\r
1633\r
1634 Field = Field.strip()\r
1635 if Field == '':\r
1636 continue\r
1637 if Field.startswith("#"):\r
1638 continue\r
1639 # Enum could directly assign value to variable\r
1640 Field = Field.split('=')[0].strip()\r
1641 TokenList = Field.split()\r
1642 # Remove pointers before variable\r
1643 Token = TokenList[-1]\r
1644 if Token in ['OPTIONAL']:\r
1645 Token = TokenList[-2]\r
1646 if not Pattern.match(Token.lstrip('*')):\r
1647 ErrMsgList.append(Token.lstrip('*'))\r
1648\r
1649 return ErrMsgList\r
1650\r
1651def CheckDeclTypedefFormat(FullFileName, ModelId):\r
1652 ErrorMsgList = []\r
1653\r
1654 FileID = GetTableID(FullFileName, ErrorMsgList)\r
1655 if FileID < 0:\r
1656 return ErrorMsgList\r
1657\r
1658 Db = GetDB()\r
1659 FileTable = 'Identifier' + str(FileID)\r
1660 SqlStatement = """ select Name, StartLine, EndLine, ID, Value\r
1661 from %s\r
1662 where Model = %d\r
1663 """ % (FileTable, ModelId)\r
1664 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1665 ResultList = []\r
1666 for Result in ResultSet:\r
1667 ResultList.append(Result)\r
1668\r
1669 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ALL\r
1670 if ModelId == DataClass.MODEL_IDENTIFIER_STRUCTURE:\r
1671 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION\r
1672 elif ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:\r
1673 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE\r
1674 elif ModelId == DataClass.MODEL_IDENTIFIER_UNION:\r
1675 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE\r
1676\r
1677 SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID\r
1678 from %s\r
1679 where Model = %d\r
1680 """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)\r
1681 TdSet = Db.TblFile.Exec(SqlStatement)\r
1682 TdList = []\r
1683 for Td in TdSet:\r
1684 TdList.append(Td)\r
1685 # Check member variable name format that from typedefs of ONLY this file.\r
1686 for Td in TdList:\r
1687 Name = Td[1].strip()\r
1688 Value = Td[2].strip()\r
1689 if Value.startswith('enum'):\r
1690 ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE\r
1691 elif Value.startswith('struct'):\r
1692 ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE\r
1693 elif Value.startswith('union'):\r
1694 ValueModelId = DataClass.MODEL_IDENTIFIER_UNION\r
1695 else:\r
1696 continue\r
1697\r
1698 if ValueModelId != ModelId:\r
1699 continue\r
1700 # Check member variable format.\r
1701 ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Td[5], ModelId)\r
1702 for ErrMsg in ErrMsgList:\r
1703 if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Name + '.' + ErrMsg):\r
1704 continue\r
1705 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Name + '.' + ErrMsg), FileTable, Td[5])\r
1706\r
1707 # First check in current file to see whether struct/union/enum is typedef-ed.\r
1708 UntypedefedList = []\r
1709 for Result in ResultList:\r
1710 # Check member variable format.\r
1711 Name = Result[0].strip()\r
1712 Value = Result[4].strip()\r
1713 if Value.startswith('enum'):\r
1714 ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE\r
1715 elif Value.startswith('struct'):\r
1716 ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE\r
1717 elif Value.startswith('union'):\r
1718 ValueModelId = DataClass.MODEL_IDENTIFIER_UNION\r
1719 else:\r
1720 continue\r
1721\r
1722 if ValueModelId != ModelId:\r
1723 continue\r
1724 ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Result[3], ModelId)\r
1725 for ErrMsg in ErrMsgList:\r
1726 if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Result[0] + '.' + ErrMsg):\r
1727 continue\r
1728 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Result[0] + '.' + ErrMsg), FileTable, Result[3])\r
1729 # Check whether it is typedefed.\r
1730 Found = False\r
1731 for Td in TdList:\r
1732 # skip function pointer\r
1733 if len(Td[0]) > 0:\r
1734 continue\r
1735 if Result[1] >= Td[3] and Td[4] >= Result[2]:\r
1736 Found = True\r
1737 if not Td[1].isupper():\r
1738 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])\r
1739 if Result[0] in Td[2].split():\r
1740 Found = True\r
1741 if not Td[1].isupper():\r
1742 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])\r
1743 if Found:\r
1744 break\r
1745\r
1746 if not Found:\r
1747 UntypedefedList.append(Result)\r
1748 continue\r
1749\r
1750 if len(UntypedefedList) == 0:\r
1751 return\r
1752\r
1753 IncludeFileList = GetAllIncludeFiles(FullFileName)\r
1754 TdList = []\r
1755 for F in IncludeFileList:\r
1756 FileID = GetTableID(F, ErrorMsgList)\r
1757 if FileID < 0:\r
1758 continue\r
1759\r
1760 IncludeFileTable = 'Identifier' + str(FileID)\r
1761 SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID\r
1762 from %s\r
1763 where Model = %d\r
1764 """ % (IncludeFileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)\r
1765 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1766 TdList.extend(ResultSet)\r
1767\r
1768 for Result in UntypedefedList:\r
1769\r
1770 # Check whether it is typedefed.\r
1771 Found = False\r
1772 for Td in TdList:\r
1773\r
1774 if len(Td[0]) > 0:\r
1775 continue\r
1776 if Result[1] >= Td[3] and Td[4] >= Result[2]:\r
1777 Found = True\r
1778 if not Td[1].isupper():\r
1779 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])\r
1780 if Result[0] in Td[2].split():\r
1781 Found = True\r
1782 if not Td[1].isupper():\r
1783 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])\r
1784 if Found:\r
1785 break\r
1786\r
1787 if not Found:\r
1788 PrintErrorMsg(ErrorType, 'No Typedef for %s' % Result[0], FileTable, Result[3])\r
1789 continue\r
1790\r
1791def CheckDeclStructTypedef(FullFileName):\r
1792 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_STRUCTURE)\r
1793\r
1794def CheckDeclEnumTypedef(FullFileName):\r
1795 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_ENUMERATE)\r
1796\r
1797def CheckDeclUnionTypedef(FullFileName):\r
1798 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_UNION)\r
1799\r
1800def CheckDeclArgModifier(FullFileName):\r
1801 ErrorMsgList = []\r
1802\r
1803 FileID = GetTableID(FullFileName, ErrorMsgList)\r
1804 if FileID < 0:\r
1805 return ErrorMsgList\r
1806\r
1807 Db = GetDB()\r
1808 FileTable = 'Identifier' + str(FileID)\r
1809 SqlStatement = """ select Modifier, Name, ID\r
1810 from %s\r
1811 where Model = %d\r
1812 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)\r
1813 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1814 ModifierTuple = ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')\r
1815 MAX_MODIFIER_LENGTH = 100\r
1816 for Result in ResultSet:\r
1817 for Modifier in ModifierTuple:\r
1818 if PatternInModifier(Result[0], Modifier) and len(Result[0]) < MAX_MODIFIER_LENGTH:\r
1819 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Variable Modifier %s' % Result[0], FileTable, Result[2])\r
1820 break\r
1821\r
1822 SqlStatement = """ select Modifier, Name, ID\r
1823 from %s\r
1824 where Model = %d\r
1825 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1826 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1827 for Result in ResultSet:\r
1828 for Modifier in ModifierTuple:\r
1829 if PatternInModifier(Result[0], Modifier):\r
1830 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])\r
1831 break\r
1832\r
1833 SqlStatement = """ select Modifier, Header, ID\r
1834 from Function\r
1835 where BelongsToFile = %d\r
1836 """ % (FileID)\r
1837 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1838 for Result in ResultSet:\r
1839 for Modifier in ModifierTuple:\r
1840 if PatternInModifier(Result[0], Modifier):\r
1841 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])\r
1842 break\r
1843\r
1844def CheckDeclNoUseCType(FullFileName):\r
1845 ErrorMsgList = []\r
1846\r
1847 FileID = GetTableID(FullFileName, ErrorMsgList)\r
1848 if FileID < 0:\r
1849 return ErrorMsgList\r
1850\r
1851 Db = GetDB()\r
1852 FileTable = 'Identifier' + str(FileID)\r
1853 SqlStatement = """ select Modifier, Name, ID\r
1854 from %s\r
1855 where Model = %d\r
1856 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)\r
1857 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1858 CTypeTuple = ('int', 'unsigned', 'char', 'void', 'static', 'long')\r
1859 for Result in ResultSet:\r
1860 for Type in CTypeTuple:\r
1861 if PatternInModifier(Result[0], Type):\r
1862 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE,\r
1863 Result[0] + ' ' + Result[1]):\r
1864 continue\r
1865 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE,\r
1866 'Invalid variable type (%s) in definition [%s]' % (Type, Result[0] + ' ' + Result[1]),\r
1867 FileTable,\r
1868 Result[2])\r
1869 break\r
1870\r
1871 SqlStatement = """ select Modifier, Name, ID, Value\r
1872 from %s\r
1873 where Model = %d\r
1874 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1875 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1876 for Result in ResultSet:\r
1877 ParamList = GetParamList(Result[1])\r
1878 FuncName = Result[3]\r
1879 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):\r
1880 continue\r
1881 for Type in CTypeTuple:\r
1882 if PatternInModifier(Result[0], Type):\r
1883 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '%s Return type %s' % (FuncName, Result[0]), FileTable, Result[2])\r
1884\r
1885 for Param in ParamList:\r
1886 if PatternInModifier(Param.Modifier, Type):\r
1887 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])\r
1888\r
1889 SqlStatement = """ select Modifier, Header, ID, Name\r
1890 from Function\r
1891 where BelongsToFile = %d\r
1892 """ % (FileID)\r
1893 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1894 for Result in ResultSet:\r
1895 ParamList = GetParamList(Result[1])\r
1896 FuncName = Result[3]\r
1897 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):\r
1898 continue\r
1899 for Type in CTypeTuple:\r
1900 if PatternInModifier(Result[0], Type):\r
1901 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '[%s] Return type %s' % (FuncName, Result[0]), FileTable, Result[2])\r
1902\r
1903 for Param in ParamList:\r
1904 if PatternInModifier(Param.Modifier, Type):\r
1905 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])\r
1906\r
1907\r
1908def CheckPointerNullComparison(FullFileName):\r
1909 ErrorMsgList = []\r
1910\r
1911 FileID = GetTableID(FullFileName, ErrorMsgList)\r
1912 if FileID < 0:\r
1913 return ErrorMsgList\r
1914\r
1915 # cache the found function return type to accelerate later checking in this file.\r
1916 FuncReturnTypeDict = {}\r
1917\r
1918 Db = GetDB()\r
1919 FileTable = 'Identifier' + str(FileID)\r
1920 SqlStatement = """ select Value, StartLine, ID\r
1921 from %s\r
1922 where Model = %d\r
1923 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)\r
1924 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1925 if len(ResultSet) == 0:\r
1926 return\r
1927 PSL = []\r
1928 for Result in ResultSet:\r
1929 PSL.append([Result[0], Result[1], Result[2]])\r
1930\r
1931 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID\r
1932 from Function\r
1933 where BelongsToFile = %d\r
1934 """ % (FileID)\r
1935 ResultSet = Db.TblFile.Exec(SqlStatement)\r
1936 FL = []\r
1937 for Result in ResultSet:\r
1938 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])\r
1939\r
1940 p = GetFuncDeclPattern()\r
1941 for Str in PSL:\r
1942 FuncRecord = GetFuncContainsPE(Str[1], FL)\r
1943 if FuncRecord is None:\r
1944 continue\r
1945\r
1946 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):\r
1947 PredInfo = SplitPredicateStr(Exp)\r
1948 if PredInfo[1] is None:\r
1949 PredVarStr = PredInfo[0][0].strip()\r
1950 IsFuncCall = False\r
1951 SearchInCache = False\r
1952 # PredVarStr may contain '.' or '->'\r
1953 TmpStr = PredVarStr.replace('.', '').replace('->', '')\r
1954 if p.match(TmpStr):\r
1955 PredVarStr = PredVarStr[0:PredVarStr.find('(')]\r
1956 SearchInCache = True\r
1957 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.\r
1958 if TmpStr.startswith(PredVarStr):\r
1959 IsFuncCall = True\r
1960\r
1961 if PredVarStr.strip() in IgnoredKeywordList:\r
1962 continue\r
1963 StarList = []\r
1964 PredVarList = GetCNameList(PredVarStr, StarList)\r
1965 # No variable found, maybe value first? like (0 == VarName)\r
1966 if len(PredVarList) == 0:\r
1967 continue\r
1968 if SearchInCache:\r
1969 Type = FuncReturnTypeDict.get(PredVarStr)\r
1970 if Type is not None:\r
1971 if Type.find('*') != -1 and Type != 'BOOLEAN*':\r
1972 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
1973 continue\r
1974\r
1975 if PredVarStr in FuncReturnTypeDict:\r
1976 continue\r
1977\r
1978 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, None, StarList)\r
1979 if SearchInCache:\r
1980 FuncReturnTypeDict[PredVarStr] = Type\r
1981 if Type is None:\r
1982 continue\r
1983 Type = GetTypeFromArray(Type, PredVarStr)\r
1984 if Type.find('*') != -1 and Type != 'BOOLEAN*':\r
1985 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
1986\r
1987def CheckNonBooleanValueComparison(FullFileName):\r
1988 ErrorMsgList = []\r
1989\r
1990 FileID = GetTableID(FullFileName, ErrorMsgList)\r
1991 if FileID < 0:\r
1992 return ErrorMsgList\r
1993\r
1994 # cache the found function return type to accelerate later checking in this file.\r
1995 FuncReturnTypeDict = {}\r
1996\r
1997 Db = GetDB()\r
1998 FileTable = 'Identifier' + str(FileID)\r
1999 SqlStatement = """ select Value, StartLine, ID\r
2000 from %s\r
2001 where Model = %d\r
2002 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)\r
2003 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2004 if len(ResultSet) == 0:\r
2005 return\r
2006 PSL = []\r
2007 for Result in ResultSet:\r
2008 PSL.append([Result[0], Result[1], Result[2]])\r
2009\r
2010 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID\r
2011 from Function\r
2012 where BelongsToFile = %d\r
2013 """ % (FileID)\r
2014 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2015 FL = []\r
2016 for Result in ResultSet:\r
2017 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])\r
2018\r
2019 p = GetFuncDeclPattern()\r
2020 for Str in PSL:\r
2021 FuncRecord = GetFuncContainsPE(Str[1], FL)\r
2022 if FuncRecord is None:\r
2023 continue\r
2024\r
2025 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):\r
2026 PredInfo = SplitPredicateStr(Exp)\r
2027 if PredInfo[1] is None:\r
2028 PredVarStr = PredInfo[0][0].strip()\r
2029 IsFuncCall = False\r
2030 SearchInCache = False\r
2031 # PredVarStr may contain '.' or '->'\r
2032 TmpStr = PredVarStr.replace('.', '').replace('->', '')\r
2033 if p.match(TmpStr):\r
2034 PredVarStr = PredVarStr[0:PredVarStr.find('(')]\r
2035 SearchInCache = True\r
2036 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.\r
2037 if TmpStr.startswith(PredVarStr):\r
2038 IsFuncCall = True\r
2039\r
2040 if PredVarStr.strip() in IgnoredKeywordList:\r
2041 continue\r
2042 StarList = []\r
2043 PredVarList = GetCNameList(PredVarStr, StarList)\r
2044 # No variable found, maybe value first? like (0 == VarName)\r
2045 if len(PredVarList) == 0:\r
2046 continue\r
2047\r
2048 if SearchInCache:\r
2049 Type = FuncReturnTypeDict.get(PredVarStr)\r
2050 if Type is not None:\r
2051 if Type.find('BOOLEAN') == -1:\r
2052 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
2053 continue\r
2054\r
2055 if PredVarStr in FuncReturnTypeDict:\r
2056 continue\r
2057 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)\r
2058 if SearchInCache:\r
2059 FuncReturnTypeDict[PredVarStr] = Type\r
2060 if Type is None:\r
2061 continue\r
2062 if Type.find('BOOLEAN') == -1:\r
2063 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
2064\r
2065\r
2066def CheckBooleanValueComparison(FullFileName):\r
2067 ErrorMsgList = []\r
2068\r
2069 FileID = GetTableID(FullFileName, ErrorMsgList)\r
2070 if FileID < 0:\r
2071 return ErrorMsgList\r
2072\r
2073 # cache the found function return type to accelerate later checking in this file.\r
2074 FuncReturnTypeDict = {}\r
2075\r
2076 Db = GetDB()\r
2077 FileTable = 'Identifier' + str(FileID)\r
2078 SqlStatement = """ select Value, StartLine, ID\r
2079 from %s\r
2080 where Model = %d\r
2081 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)\r
2082 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2083 if len(ResultSet) == 0:\r
2084 return\r
2085 PSL = []\r
2086 for Result in ResultSet:\r
2087 PSL.append([Result[0], Result[1], Result[2]])\r
2088\r
2089 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID\r
2090 from Function\r
2091 where BelongsToFile = %d\r
2092 """ % (FileID)\r
2093 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2094 FL = []\r
2095 for Result in ResultSet:\r
2096 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])\r
2097\r
2098 p = GetFuncDeclPattern()\r
2099 for Str in PSL:\r
2100 FuncRecord = GetFuncContainsPE(Str[1], FL)\r
2101 if FuncRecord is None:\r
2102 continue\r
2103\r
2104 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):\r
2105 PredInfo = SplitPredicateStr(Exp)\r
2106 if PredInfo[1] in ('==', '!=') and PredInfo[0][1] in ('TRUE', 'FALSE'):\r
2107 PredVarStr = PredInfo[0][0].strip()\r
2108 IsFuncCall = False\r
2109 SearchInCache = False\r
2110 # PredVarStr may contain '.' or '->'\r
2111 TmpStr = PredVarStr.replace('.', '').replace('->', '')\r
2112 if p.match(TmpStr):\r
2113 PredVarStr = PredVarStr[0:PredVarStr.find('(')]\r
2114 SearchInCache = True\r
2115 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.\r
2116 if TmpStr.startswith(PredVarStr):\r
2117 IsFuncCall = True\r
2118\r
2119 if PredVarStr.strip() in IgnoredKeywordList:\r
2120 continue\r
2121 StarList = []\r
2122 PredVarList = GetCNameList(PredVarStr, StarList)\r
2123 # No variable found, maybe value first? like (0 == VarName)\r
2124 if len(PredVarList) == 0:\r
2125 continue\r
2126\r
2127 if SearchInCache:\r
2128 Type = FuncReturnTypeDict.get(PredVarStr)\r
2129 if Type is not None:\r
2130 if Type.find('BOOLEAN') != -1:\r
2131 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
2132 continue\r
2133\r
2134 if PredVarStr in FuncReturnTypeDict:\r
2135 continue\r
2136\r
2137 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)\r
2138 if SearchInCache:\r
2139 FuncReturnTypeDict[PredVarStr] = Type\r
2140 if Type is None:\r
2141 continue\r
2142 if Type.find('BOOLEAN') != -1:\r
2143 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
2144\r
2145\r
2146def CheckHeaderFileData(FullFileName):\r
2147 ErrorMsgList = []\r
2148\r
2149 FileID = GetTableID(FullFileName, ErrorMsgList)\r
2150 if FileID < 0:\r
2151 return ErrorMsgList\r
2152\r
2153 Db = GetDB()\r
2154 FileTable = 'Identifier' + str(FileID)\r
2155 SqlStatement = """ select ID, Modifier\r
2156 from %s\r
2157 where Model = %d\r
2158 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)\r
2159 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2160 for Result in ResultSet:\r
2161 if not Result[1].startswith('extern'):\r
2162 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Variable definition appears in header file', FileTable, Result[0])\r
2163\r
2164 SqlStatement = """ select ID\r
2165 from Function\r
2166 where BelongsToFile = %d\r
2167 """ % FileID\r
2168 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2169 for Result in ResultSet:\r
2170 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Function definition appears in header file', 'Function', Result[0])\r
2171\r
2172 return ErrorMsgList\r
2173\r
2174def CheckHeaderFileIfndef(FullFileName):\r
2175 ErrorMsgList = []\r
2176\r
2177 FileID = GetTableID(FullFileName, ErrorMsgList)\r
2178 if FileID < 0:\r
2179 return ErrorMsgList\r
2180\r
2181 Db = GetDB()\r
2182 FileTable = 'Identifier' + str(FileID)\r
2183 SqlStatement = """ select Value, StartLine\r
2184 from %s\r
2185 where Model = %d order by StartLine\r
2186 """ % (FileTable, DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF)\r
2187 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2188 if len(ResultSet) == 0:\r
2189 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1, '', 'File', FileID)\r
2190 return ErrorMsgList\r
2191 for Result in ResultSet:\r
2192 SqlStatement = """ select Value, EndLine\r
2193 from %s\r
2194 where EndLine < %d\r
2195 """ % (FileTable, Result[1])\r
2196 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2197 for Result in ResultSet:\r
2198 if not Result[0].startswith('/*') and not Result[0].startswith('//'):\r
2199 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2, '', 'File', FileID)\r
2200 break\r
2201\r
2202 SqlStatement = """ select Value\r
2203 from %s\r
2204 where StartLine > (select max(EndLine) from %s where Model = %d)\r
2205 """ % (FileTable, FileTable, DataClass.MODEL_IDENTIFIER_MACRO_ENDIF)\r
2206 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2207 for Result in ResultSet:\r
2208 if not Result[0].startswith('/*') and not Result[0].startswith('//'):\r
2209 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3, '', 'File', FileID)\r
2210 return ErrorMsgList\r
2211\r
2212def CheckDoxygenCommand(FullFileName):\r
2213 ErrorMsgList = []\r
2214\r
2215 FileID = GetTableID(FullFileName, ErrorMsgList)\r
2216 if FileID < 0:\r
2217 return ErrorMsgList\r
2218\r
2219 Db = GetDB()\r
2220 FileTable = 'Identifier' + str(FileID)\r
2221 SqlStatement = """ select Value, ID\r
2222 from %s\r
2223 where Model = %d or Model = %d\r
2224 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)\r
2225 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2226 DoxygenCommandList = ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval',\r
2227 'return', 'sa', 'since', 'test', 'note', 'par', 'endcode', 'code']\r
2228 for Result in ResultSet:\r
2229 CommentStr = Result[0]\r
2230 CommentPartList = CommentStr.split()\r
2231 for Part in CommentPartList:\r
2232 if Part.upper() == 'BUGBUG':\r
2233 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Bug should be marked with doxygen tag @bug', FileTable, Result[1])\r
2234 if Part.upper() == 'TODO':\r
2235 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'ToDo should be marked with doxygen tag @todo', FileTable, Result[1])\r
2236 if Part.startswith('@'):\r
2237 if EccGlobalData.gException.IsException(ERROR_DOXYGEN_CHECK_COMMAND, Part):\r
2238 continue\r
2239 if not Part.replace('@', '').strip():\r
2240 continue\r
2241 if Part.lstrip('@') in ['{', '}']:\r
2242 continue\r
2243 if Part.lstrip('@').isalpha():\r
2244 if Part.lstrip('@') not in DoxygenCommandList:\r
2245 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])\r
2246 else:\r
2247 Index = Part.find('[')\r
2248 if Index == -1:\r
2249 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])\r
2250 RealCmd = Part[1:Index]\r
2251 if RealCmd not in DoxygenCommandList:\r
2252 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])\r
2253\r
2254\r
2255def CheckDoxygenTripleForwardSlash(FullFileName):\r
2256 ErrorMsgList = []\r
2257\r
2258 FileID = GetTableID(FullFileName, ErrorMsgList)\r
2259 if FileID < 0:\r
2260 return ErrorMsgList\r
2261\r
2262 Db = GetDB()\r
2263\r
2264 SqlStatement = """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn\r
2265 from Function\r
2266 where BelongsToFile = %d\r
2267 """ % (FileID)\r
2268 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2269 if len(ResultSet) == 0:\r
2270 return\r
2271\r
2272 FuncDefSet = []\r
2273 for Result in ResultSet:\r
2274 FuncDefSet.append(Result)\r
2275\r
2276\r
2277 FileTable = 'Identifier' + str(FileID)\r
2278 SqlStatement = """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn\r
2279 from %s\r
2280 where Model = %d\r
2281\r
2282 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)\r
2283 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2284 CommentSet = []\r
2285 try:\r
2286 for Result in ResultSet:\r
2287 CommentSet.append(Result)\r
2288 except:\r
2289 print('Unrecognized chars in comment of file %s', FullFileName)\r
2290\r
2291\r
2292 for Result in CommentSet:\r
2293 CommentStr = Result[0]\r
2294 StartLine = Result[2]\r
2295 StartColumn = Result[3]\r
2296 EndLine = Result[4]\r
2297 EndColumn = Result[5]\r
2298 if not CommentStr.startswith('///<'):\r
2299 continue\r
2300\r
2301 Found = False\r
2302 for FuncDef in FuncDefSet:\r
2303 if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:\r
2304 Found = True\r
2305 break\r
2306 if StartLine > FuncDef[1] and EndLine < FuncDef[3]:\r
2307 Found = True\r
2308 break\r
2309 if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine < FuncDef[3]:\r
2310 Found = True\r
2311 break\r
2312 if StartLine > FuncDef[1] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:\r
2313 Found = True\r
2314 break\r
2315 if Found:\r
2316 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT, '', FileTable, Result[1])\r
2317\r
2318\r
2319def CheckFileHeaderDoxygenComments(FullFileName):\r
2320 ErrorMsgList = []\r
2321\r
2322 FileID = GetTableID(FullFileName, ErrorMsgList)\r
2323 if FileID < 0:\r
2324 return ErrorMsgList\r
2325\r
2326 Db = GetDB()\r
2327 FileTable = 'Identifier' + str(FileID)\r
2328 SqlStatement = """ select Value, ID\r
2329 from %s\r
2330 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0\r
2331 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)\r
2332 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2333 if len(ResultSet) == 0:\r
2334 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'No File License header appear at the very beginning of file.', 'File', FileID)\r
2335 return ErrorMsgList\r
2336\r
2337 NoHeaderCommentStartFlag = True\r
2338 NoHeaderCommentEndFlag = True\r
2339 NoHeaderCommentPeriodFlag = True\r
2340 NoCopyrightFlag = True\r
2341 NoLicenseFlag = True\r
2342 NoRevReferFlag = True\r
2343 NextLineIndex = 0\r
2344 for Result in ResultSet:\r
2345 FileStartFlag = False\r
2346 CommentStrList = []\r
2347 CommentStr = Result[0].strip()\r
2348 CommentStrListTemp = CommentStr.split('\n')\r
2349 if (len(CommentStrListTemp) <= 1):\r
2350 # For Mac\r
2351 CommentStrListTemp = CommentStr.split('\r')\r
2352 # Skip the content before the file header \r
2353 for CommentLine in CommentStrListTemp:\r
2354 if CommentLine.strip().startswith('/** @file'):\r
2355 FileStartFlag = True\r
2356 if FileStartFlag == True:\r
2357 CommentStrList.append(CommentLine)\r
2358 \r
2359 ID = Result[1]\r
2360 Index = 0\r
2361 if CommentStrList and CommentStrList[0].strip().startswith('/** @file'):\r
2362 NoHeaderCommentStartFlag = False\r
2363 else:\r
2364 continue\r
2365 if CommentStrList and CommentStrList[-1].strip().endswith('**/'):\r
2366 NoHeaderCommentEndFlag = False\r
2367 else:\r
2368 continue\r
2369\r
2370 for CommentLine in CommentStrList:\r
2371 Index = Index + 1\r
2372 NextLineIndex = Index\r
2373 if CommentLine.startswith('/** @file'):\r
2374 continue\r
2375 if CommentLine.startswith('**/'):\r
2376 break\r
2377 # Check whether C File header Comment content start with two spaces.\r
2378 if EccGlobalData.gConfig.HeaderCheckCFileCommentStartSpacesNum == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
2379 if CommentLine.startswith('/** @file') == False and CommentLine.startswith('**/') == False and CommentLine.strip() and CommentLine.startswith(' ') == False:\r
2380 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment content should start with two spaces at each line', FileTable, ID)\r
2381 \r
2382 CommentLine = CommentLine.strip()\r
2383 if CommentLine.startswith('Copyright'):\r
2384 NoCopyrightFlag = False\r
2385 if CommentLine.find('All rights reserved') == -1:\r
2386 for Copyright in EccGlobalData.gConfig.Copyright:\r
2387 if CommentLine.find(Copyright) > -1:\r
2388 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable, ID)\r
2389 break\r
2390 if CommentLine.endswith('<BR>') == -1:\r
2391 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'The ""<BR>"" at the end of the Copyright line is required', FileTable, ID)\r
2392 if NextLineIndex < len(CommentStrList) and CommentStrList[NextLineIndex].strip().startswith('Copyright') == False and CommentStrList[NextLineIndex].strip():\r
2393 NoLicenseFlag = False\r
2394 if CommentLine.startswith('@par Revision Reference:'):\r
2395 NoRevReferFlag = False\r
2396 RefListFlag = False\r
2397 for RefLine in CommentStrList[NextLineIndex:]:\r
2398 if RefLine.strip() and (NextLineIndex + 1) < len(CommentStrList) and CommentStrList[NextLineIndex+1].strip() and CommentStrList[NextLineIndex+1].strip().startswith('**/') == False:\r
2399 RefListFlag = True\r
2400 if RefLine.strip() == False or RefLine.strip().startswith('**/'):\r
2401 RefListFlag = False\r
2402 break\r
2403 # Check whether C File header Comment's each reference at list should begin with a bullet character.\r
2404 if EccGlobalData.gConfig.HeaderCheckCFileCommentReferenceFormat == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
2405 if RefListFlag == True:\r
2406 if RefLine.strip() and RefLine.strip().startswith('**/') == False and RefLine.startswith(' -') == False: \r
2407 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable, ID) \r
2408 \r
2409 if NoHeaderCommentStartFlag:\r
2410 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER, 'File header comment should begin with ""/** @file""', FileTable, ID)\r
2411 return\r
2412 if NoHeaderCommentEndFlag:\r
2413 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should end with ""**/""', FileTable, ID)\r
2414 return\r
2415 if NoCopyrightFlag:\r
2416 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment missing the ""Copyright""', FileTable, ID)\r
2417 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.\r
2418 if EccGlobalData.gConfig.HeaderCheckCFileCommentLicenseFormat == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':\r
2419 if NoLicenseFlag:\r
2420 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable, ID)\r
2421\r
2422def CheckFuncHeaderDoxygenComments(FullFileName):\r
2423 ErrorMsgList = []\r
2424\r
2425 FileID = GetTableID(FullFileName, ErrorMsgList)\r
2426 if FileID < 0:\r
2427 return ErrorMsgList\r
2428\r
2429 Db = GetDB()\r
2430 FileTable = 'Identifier' + str(FileID)\r
2431 SqlStatement = """ select Value, StartLine, EndLine, ID\r
2432 from %s\r
2433 where Model = %d\r
2434 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)\r
2435\r
2436 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2437 CommentSet = []\r
2438 try:\r
2439 for Result in ResultSet:\r
2440 CommentSet.append(Result)\r
2441 except:\r
2442 print('Unrecognized chars in comment of file %s', FullFileName)\r
2443\r
2444 # Func Decl check\r
2445 SqlStatement = """ select Modifier, Name, StartLine, ID, Value\r
2446 from %s\r
2447 where Model = %d\r
2448 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
2449 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2450 for Result in ResultSet:\r
2451 FuncName = Result[4]\r
2452 FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)\r
2453 if FunctionHeaderComment:\r
2454 CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)\r
2455 else:\r
2456 if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):\r
2457 continue\r
2458 ErrorMsgList.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result[2], Result[1]))\r
2459 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), FileTable, Result[3])\r
2460\r
2461 # Func Def check\r
2462 SqlStatement = """ select Value, StartLine, EndLine, ID\r
2463 from %s\r
2464 where Model = %d\r
2465 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)\r
2466\r
2467 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2468 CommentSet = []\r
2469 try:\r
2470 for Result in ResultSet:\r
2471 CommentSet.append(Result)\r
2472 except:\r
2473 print('Unrecognized chars in comment of file %s', FullFileName)\r
2474\r
2475 SqlStatement = """ select Modifier, Header, StartLine, ID, Name\r
2476 from Function\r
2477 where BelongsToFile = %d\r
2478 """ % (FileID)\r
2479 ResultSet = Db.TblFile.Exec(SqlStatement)\r
2480 for Result in ResultSet:\r
2481 FuncName = Result[4]\r
2482 FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)\r
2483 if FunctionHeaderComment:\r
2484 CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)\r
2485 else:\r
2486 if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):\r
2487 continue\r
2488 ErrorMsgList.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result[2], Result[1]))\r
2489 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), 'Function', Result[3])\r
2490 return ErrorMsgList\r
2491\r
2492def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName, FuncStartLine, CommentSet):\r
2493\r
2494 for Comment in CommentSet:\r
2495 if Comment[2] == FuncStartLine - 1:\r
2496 return Comment\r
2497 return None\r
2498\r
2499def GetDoxygenStrFromComment(Str):\r
2500 DoxygenStrList = []\r
2501 ParamTagList = Str.split('@param')\r
2502 if len(ParamTagList) > 1:\r
2503 i = 1\r
2504 while i < len(ParamTagList):\r
2505 DoxygenStrList.append('@param' + ParamTagList[i])\r
2506 i += 1\r
2507\r
2508 Str = ParamTagList[0]\r
2509\r
2510 RetvalTagList = ParamTagList[-1].split('@retval')\r
2511 if len(RetvalTagList) > 1:\r
2512 if len(ParamTagList) > 1:\r
2513 DoxygenStrList[-1] = '@param' + RetvalTagList[0]\r
2514 i = 1\r
2515 while i < len(RetvalTagList):\r
2516 DoxygenStrList.append('@retval' + RetvalTagList[i])\r
2517 i += 1\r
2518\r
2519 ReturnTagList = RetvalTagList[-1].split('@return')\r
2520 if len(ReturnTagList) > 1:\r
2521 if len(RetvalTagList) > 1:\r
2522 DoxygenStrList[-1] = '@retval' + ReturnTagList[0]\r
2523 elif len(ParamTagList) > 1:\r
2524 DoxygenStrList[-1] = '@param' + ReturnTagList[0]\r
2525 i = 1\r
2526 while i < len(ReturnTagList):\r
2527 DoxygenStrList.append('@return' + ReturnTagList[i])\r
2528 i += 1\r
2529\r
2530 if len(DoxygenStrList) > 0:\r
2531 DoxygenStrList[-1] = DoxygenStrList[-1].rstrip('--*/')\r
2532\r
2533 return DoxygenStrList\r
2534\r
2535def CheckGeneralDoxygenCommentLayout(Str, StartLine, ErrorMsgList, CommentId= -1, TableName=''):\r
2536 #/** --*/ @retval after @param\r
2537 if not Str.startswith('/**'):\r
2538 ErrorMsgList.append('Line %d : Comment does NOT have prefix /** ' % StartLine)\r
2539 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have prefix /** ', TableName, CommentId)\r
2540 if not Str.endswith('**/'):\r
2541 ErrorMsgList.append('Line %d : Comment does NOT have tail **/ ' % StartLine)\r
2542 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have tail **/ ', TableName, CommentId)\r
2543 FirstRetvalIndex = Str.find('@retval')\r
2544 LastParamIndex = Str.rfind('@param')\r
2545 if (FirstRetvalIndex > 0) and (LastParamIndex > 0) and (FirstRetvalIndex < LastParamIndex):\r
2546 ErrorMsgList.append('Line %d : @retval appear before @param ' % StartLine)\r
2547 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, @retval appear before @param ', TableName, CommentId)\r
2548\r
2549def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier, FuncHeader, FuncStartLine, CommentStr, CommentStartLine, ErrorMsgList, CommentId= -1, TableName=''):\r
2550\r
2551 ParamList = GetParamList(FuncHeader)\r
2552 CheckGeneralDoxygenCommentLayout(CommentStr, CommentStartLine, ErrorMsgList, CommentId, TableName)\r
2553 DescriptionStr = CommentStr\r
2554 DoxygenStrList = GetDoxygenStrFromComment(DescriptionStr)\r
2555 if DescriptionStr.find('.') == -1:\r
2556 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period \'.\'', TableName, CommentId)\r
2557 DoxygenTagNumber = len(DoxygenStrList)\r
2558 ParamNumber = len(ParamList)\r
2559 for Param in ParamList:\r
2560 if Param.Name.upper() == 'VOID' and ParamNumber == 1:\r
2561 ParamNumber -= 1\r
2562 Index = 0\r
2563 if ParamNumber > 0 and DoxygenTagNumber > 0:\r
2564 while Index < ParamNumber and Index < DoxygenTagNumber:\r
2565 ParamModifier = ParamList[Index].Modifier\r
2566 ParamName = ParamList[Index].Name.strip()\r
2567 Tag = DoxygenStrList[Index].strip(' ')\r
2568 if (not Tag[-1] == ('\n')) and (not Tag[-1] == ('\r')):\r
2569 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))\r
2570 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'in Comment, <%s> does NOT end with new line ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)\r
2571 TagPartList = Tag.split()\r
2572 if len(TagPartList) < 2:\r
2573 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))\r
2574 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)\r
2575 Index += 1\r
2576 continue\r
2577 LBPos = Tag.find('[')\r
2578 RBPos = Tag.find(']')\r
2579 ParamToLBContent = Tag[len('@param'):LBPos].strip()\r
2580 if LBPos > 0 and len(ParamToLBContent) == 0 and RBPos > LBPos:\r
2581 InOutStr = ''\r
2582 ModifierPartList = ParamModifier.split()\r
2583 for Part in ModifierPartList:\r
2584 if Part.strip() == 'IN':\r
2585 InOutStr += 'in'\r
2586 if Part.strip() == 'OUT':\r
2587 if InOutStr != '':\r
2588 InOutStr += ', out'\r
2589 else:\r
2590 InOutStr = 'out'\r
2591\r
2592 if InOutStr != '':\r
2593 if Tag.find('[' + InOutStr + ']') == -1:\r
2594 if InOutStr != 'in, out':\r
2595 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'))\r
2596 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT have %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'), TableName, CommentId)\r
2597 else:\r
2598 if Tag.find('[in,out]') == -1:\r
2599 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'))\r
2600 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT have %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'), TableName, CommentId)\r
2601\r
2602\r
2603 if Tag.find(ParamName) == -1 and ParamName != 'VOID' and ParamName != 'void':\r
2604 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), ParamName))\r
2605 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT consistent with parameter name %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), ParamName), TableName, CommentId)\r
2606 Index += 1\r
2607\r
2608 if Index < ParamNumber:\r
2609 ErrorMsgList.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine)\r
2610 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of doxygen tags in comment less than number of function parameters ', TableName, CommentId)\r
2611 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.\r
2612 if (FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1:\r
2613\r
2614 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'\r
2615 if Index < DoxygenTagNumber - 1 or (Index < DoxygenTagNumber and DoxygenStrList[Index].startswith('@retval')):\r
2616 ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)\r
2617 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need no doxygen tags in comment ', TableName, CommentId)\r
2618 else:\r
2619 if Index < DoxygenTagNumber and not DoxygenStrList[Index].startswith('@retval') and not DoxygenStrList[Index].startswith('@return'):\r
2620 ErrorMsgList.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine)\r
2621 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName, CommentId)\r
2622 else:\r
2623 if ParamNumber == 0 and DoxygenTagNumber != 0 and ((FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1):\r
2624 ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)\r
2625 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need NO doxygen tags in comment ', TableName, CommentId)\r
2626 if ParamNumber != 0 and DoxygenTagNumber == 0:\r
2627 ErrorMsgList.append('Line %d : No doxygen tags in comment' % CommentStartLine)\r
2628 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'No doxygen tags in comment ', TableName, CommentId)\r
2629\r
2630if __name__ == '__main__':\r
2631\r
2632# EdkLogger.Initialize()\r
2633# EdkLogger.SetLevel(EdkLogger.QUIET)\r
2634# CollectSourceCodeDataIntoDB(sys.argv[1])\r
2635 try:\r
2636 test_file = sys.argv[1]\r
2637 except IndexError as v:\r
2638 print("Usage: %s filename" % sys.argv[0])\r
2639 sys.exit(1)\r
2640 MsgList = CheckFuncHeaderDoxygenComments(test_file)\r
2641 for Msg in MsgList:\r
2642 print(Msg)\r
2643 print('Done!')\r