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