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