audk/BaseTools/Source/Python/Ecc/c.py

2504 lines
104 KiB
Python
Raw Normal View History

import sys
import os
import re
import string
import CodeFragmentCollector
import FileProfile
from CommonDataClass import DataClass
import Database
from Common import EdkLogger
from EccToolError import *
import EccGlobalData
import MetaDataParser
IncludeFileListDict = {}
AllIncludeFileListDict = {}
IncludePathListDict = {}
ComplexTypeDict = {}
SUDict = {}
IgnoredKeywordList = ['EFI_ERROR']
def GetIgnoredDirListPattern():
skipList = list(EccGlobalData.gConfig.SkipDirList) + ['.svn']
DirString = string.join(skipList, '|')
p = re.compile(r'.*[\\/](?:%s)[\\/]?.*' % DirString)
return p
def GetFuncDeclPattern():
p = re.compile(r'(?:EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re.DOTALL)
return p
def GetArrayPattern():
p = re.compile(r'[_\w]*\s*[\[.*\]]+')
return p
def GetTypedefFuncPointerPattern():
p = re.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re.DOTALL)
return p
def GetDB():
return EccGlobalData.gDb
def GetConfig():
return EccGlobalData.gConfig
def PrintErrorMsg(ErrorType, Msg, TableName, ItemId):
Msg = Msg.replace('\n', '').replace('\r', '')
MsgPartList = Msg.split()
Msg = ''
for Part in MsgPartList:
Msg += Part
Msg += ' '
GetDB().TblReport.Insert(ErrorType, OtherMsg = Msg, BelongsToTable = TableName, BelongsToItem = ItemId)
def GetIdType(Str):
Type = DataClass.MODEL_UNKNOWN
Str = Str.replace('#', '# ')
List = Str.split()
if List[1] == 'include':
Type = DataClass.MODEL_IDENTIFIER_INCLUDE
elif List[1] == 'define':
Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE
elif List[1] == 'ifdef':
Type = DataClass.MODEL_IDENTIFIER_MACRO_IFDEF
elif List[1] == 'ifndef':
Type = DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF
elif List[1] == 'endif':
Type = DataClass.MODEL_IDENTIFIER_MACRO_ENDIF
elif List[1] == 'pragma':
Type = DataClass.MODEL_IDENTIFIER_MACRO_PROGMA
else:
Type = DataClass.MODEL_UNKNOWN
return Type
def SuOccurInTypedef (Su, TdList):
for Td in TdList:
if Su.StartPos[0] == Td.StartPos[0] and Su.EndPos[0] == Td.EndPos[0]:
return True
return False
def GetIdentifierList():
IdList = []
for comment in FileProfile.CommentList:
IdComment = DataClass.IdentifierClass(-1, '', '', '', comment.Content, DataClass.MODEL_IDENTIFIER_COMMENT, -1, -1, comment.StartPos[0],comment.StartPos[1],comment.EndPos[0],comment.EndPos[1])
IdList.append(IdComment)
for pp in FileProfile.PPDirectiveList:
Type = GetIdType(pp.Content)
IdPP = DataClass.IdentifierClass(-1, '', '', '', pp.Content, Type, -1, -1, pp.StartPos[0],pp.StartPos[1],pp.EndPos[0],pp.EndPos[1])
IdList.append(IdPP)
for pe in FileProfile.PredicateExpressionList:
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])
IdList.append(IdPE)
FuncDeclPattern = GetFuncDeclPattern()
ArrayPattern = GetArrayPattern()
for var in FileProfile.VariableDeclarationList:
DeclText = var.Declarator.lstrip()
FuncPointerPattern = GetTypedefFuncPointerPattern()
if FuncPointerPattern.match(DeclText):
continue
VarNameStartLine = var.NameStartPos[0]
VarNameStartColumn = var.NameStartPos[1]
FirstChar = DeclText[0]
while not FirstChar.isalpha() and FirstChar != '_':
if FirstChar == '*':
var.Modifier += '*'
VarNameStartColumn += 1
DeclText = DeclText.lstrip('*')
elif FirstChar == '\r':
DeclText = DeclText.lstrip('\r\n').lstrip('\r')
VarNameStartLine += 1
VarNameStartColumn = 0
elif FirstChar == '\n':
DeclText = DeclText.lstrip('\n')
VarNameStartLine += 1
VarNameStartColumn = 0
elif FirstChar == ' ':
DeclText = DeclText.lstrip(' ')
VarNameStartColumn += 1
elif FirstChar == '\t':
DeclText = DeclText.lstrip('\t')
VarNameStartColumn += 8
else:
DeclText = DeclText[1:]
VarNameStartColumn += 1
FirstChar = DeclText[0]
var.Declarator = DeclText
if FuncDeclPattern.match(var.Declarator):
DeclSplitList = var.Declarator.split('(')
FuncName = DeclSplitList[0].strip()
FuncNamePartList = FuncName.split()
if len(FuncNamePartList) > 1:
FuncName = FuncNamePartList[-1].strip()
NameStart = DeclSplitList[0].rfind(FuncName)
var.Declarator = var.Declarator[NameStart:]
if NameStart > 0:
var.Modifier += ' ' + DeclSplitList[0][0:NameStart]
Index = 0
PreChar = ''
while Index < NameStart:
FirstChar = DeclSplitList[0][Index]
if DeclSplitList[0][Index:].startswith('EFIAPI'):
Index += 6
VarNameStartColumn += 6
PreChar = ''
continue
elif FirstChar == '\r':
Index += 1
VarNameStartLine += 1
VarNameStartColumn = 0
elif FirstChar == '\n':
Index += 1
if PreChar != '\r':
VarNameStartLine += 1
VarNameStartColumn = 0
elif FirstChar == ' ':
Index += 1
VarNameStartColumn += 1
elif FirstChar == '\t':
Index += 1
VarNameStartColumn += 8
else:
Index += 1
VarNameStartColumn += 1
PreChar = FirstChar
IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', var.Declarator, FuncName, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, -1, -1, var.StartPos[0], var.StartPos[1], VarNameStartLine, VarNameStartColumn)
IdList.append(IdVar)
continue
if var.Declarator.find('{') == -1:
for decl in var.Declarator.split(','):
DeclList = decl.split('=')
Name = DeclList[0].strip()
if ArrayPattern.match(Name):
LSBPos = var.Declarator.find('[')
var.Modifier += ' ' + Name[LSBPos:]
Name = Name[0:LSBPos]
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)
IdList.append(IdVar)
else:
DeclList = var.Declarator.split('=')
Name = DeclList[0].strip()
if ArrayPattern.match(Name):
LSBPos = var.Declarator.find('[')
var.Modifier += ' ' + Name[LSBPos:]
Name = Name[0:LSBPos]
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)
IdList.append(IdVar)
for enum in FileProfile.EnumerationDefinitionList:
LBPos = enum.Content.find('{')
RBPos = enum.Content.find('}')
Name = enum.Content[4:LBPos].strip()
Value = enum.Content[LBPos+1:RBPos]
IdEnum = DataClass.IdentifierClass(-1, '', '', Name, Value, DataClass.MODEL_IDENTIFIER_ENUMERATE, -1, -1, enum.StartPos[0],enum.StartPos[1],enum.EndPos[0],enum.EndPos[1])
IdList.append(IdEnum)
for su in FileProfile.StructUnionDefinitionList:
if SuOccurInTypedef(su, FileProfile.TypedefDefinitionList):
continue
Type = DataClass.MODEL_IDENTIFIER_STRUCTURE
SkipLen = 6
if su.Content.startswith('union'):
Type = DataClass.MODEL_IDENTIFIER_UNION
SkipLen = 5
LBPos = su.Content.find('{')
RBPos = su.Content.find('}')
if LBPos == -1 or RBPos == -1:
Name = su.Content[SkipLen:].strip()
Value = ''
else:
Name = su.Content[SkipLen:LBPos].strip()
Value = su.Content[LBPos:RBPos+1]
IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0],su.StartPos[1],su.EndPos[0],su.EndPos[1])
IdList.append(IdPE)
TdFuncPointerPattern = GetTypedefFuncPointerPattern()
for td in FileProfile.TypedefDefinitionList:
Modifier = ''
Name = td.ToType
Value = td.FromType
if TdFuncPointerPattern.match(td.ToType):
Modifier = td.FromType
LBPos = td.ToType.find('(')
TmpStr = td.ToType[LBPos+1:].strip()
StarPos = TmpStr.find('*')
if StarPos != -1:
Modifier += ' ' + TmpStr[0:StarPos]
while TmpStr[StarPos] == '*':
# Modifier += ' ' + '*'
StarPos += 1
TmpStr = TmpStr[StarPos:].strip()
RBPos = TmpStr.find(')')
Name = TmpStr[0:RBPos]
Value = 'FP' + TmpStr[RBPos + 1:]
else:
while Name.startswith('*'):
Value += ' ' + '*'
Name = Name.lstrip('*').strip()
if Name.find('[') != -1:
LBPos = Name.find('[')
RBPos = Name.rfind(']')
Value += Name[LBPos : RBPos + 1]
Name = Name[0 : LBPos]
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])
IdList.append(IdTd)
for funcCall in FileProfile.FunctionCallingList:
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])
IdList.append(IdFC)
return IdList
def StripNonAlnumChars(Str):
StrippedStr = ''
for Char in Str:
if Char.isalnum():
StrippedStr += Char
return StrippedStr
def GetParamList(FuncDeclarator, FuncNameLine = 0, FuncNameOffset = 0):
FuncDeclarator = StripComments(FuncDeclarator)
ParamIdList = []
#DeclSplitList = FuncDeclarator.split('(')
LBPos = FuncDeclarator.find('(')
#if len(DeclSplitList) < 2:
if LBPos == -1:
return ParamIdList
#FuncName = DeclSplitList[0]
FuncName = FuncDeclarator[0:LBPos]
#ParamStr = DeclSplitList[1].rstrip(')')
ParamStr = FuncDeclarator[LBPos + 1:].rstrip(')')
LineSkipped = 0
OffsetSkipped = 0
TailChar = FuncName[-1]
while not TailChar.isalpha() and TailChar != '_':
if TailChar == '\n':
FuncName = FuncName.rstrip('\r\n').rstrip('\n')
LineSkipped += 1
OffsetSkipped = 0
elif TailChar == '\r':
FuncName = FuncName.rstrip('\r')
LineSkipped += 1
OffsetSkipped = 0
elif TailChar == ' ':
FuncName = FuncName.rstrip(' ')
OffsetSkipped += 1
elif TailChar == '\t':
FuncName = FuncName.rstrip('\t')
OffsetSkipped += 8
else:
FuncName = FuncName[:-1]
TailChar = FuncName[-1]
OffsetSkipped += 1 #skip '('
for p in ParamStr.split(','):
ListP = p.split()
if len(ListP) == 0:
continue
ParamName = ListP[-1]
DeclText = ParamName.strip()
RightSpacePos = p.rfind(ParamName)
ParamModifier = p[0:RightSpacePos]
if ParamName == 'OPTIONAL':
if ParamModifier == '':
ParamModifier += ' ' + 'OPTIONAL'
DeclText = ''
else:
ParamName = ListP[-2]
DeclText = ParamName.strip()
RightSpacePos = p.rfind(ParamName)
ParamModifier = p[0:RightSpacePos]
ParamModifier += 'OPTIONAL'
while DeclText.startswith('*'):
ParamModifier += ' ' + '*'
DeclText = DeclText.lstrip('*').strip()
ParamName = DeclText
# ignore array length if exists.
LBIndex = ParamName.find('[')
if LBIndex != -1:
ParamName = ParamName[0:LBIndex]
Start = RightSpacePos
Index = 0
PreChar = ''
while Index < Start:
FirstChar = p[Index]
if FirstChar == '\r':
Index += 1
LineSkipped += 1
OffsetSkipped = 0
elif FirstChar == '\n':
Index += 1
if PreChar != '\r':
LineSkipped += 1
OffsetSkipped = 0
elif FirstChar == ' ':
Index += 1
OffsetSkipped += 1
elif FirstChar == '\t':
Index += 1
OffsetSkipped += 8
else:
Index += 1
OffsetSkipped += 1
PreChar = FirstChar
ParamBeginLine = FuncNameLine + LineSkipped
ParamBeginOffset = FuncNameOffset + OffsetSkipped
Index = Start + len(ParamName)
PreChar = ''
while Index < len(p):
FirstChar = p[Index]
if FirstChar == '\r':
Index += 1
LineSkipped += 1
OffsetSkipped = 0
elif FirstChar == '\n':
Index += 1
if PreChar != '\r':
LineSkipped += 1
OffsetSkipped = 0
elif FirstChar == ' ':
Index += 1
OffsetSkipped += 1
elif FirstChar == '\t':
Index += 1
OffsetSkipped += 8
else:
Index += 1
OffsetSkipped += 1
PreChar = FirstChar
ParamEndLine = FuncNameLine + LineSkipped
ParamEndOffset = FuncNameOffset + OffsetSkipped
if ParamName != '...':
ParamName = StripNonAlnumChars(ParamName)
IdParam = DataClass.IdentifierClass(-1, ParamModifier, '', ParamName, '', DataClass.MODEL_IDENTIFIER_PARAMETER, -1, -1, ParamBeginLine, ParamBeginOffset, ParamEndLine, ParamEndOffset)
ParamIdList.append(IdParam)
OffsetSkipped += 1 #skip ','
return ParamIdList
def GetFunctionList():
FuncObjList = []
for FuncDef in FileProfile.FunctionDefinitionList:
ParamIdList = []
DeclText = FuncDef.Declarator.lstrip()
FuncNameStartLine = FuncDef.NamePos[0]
FuncNameStartColumn = FuncDef.NamePos[1]
FirstChar = DeclText[0]
while not FirstChar.isalpha() and FirstChar != '_':
if FirstChar == '*':
FuncDef.Modifier += '*'
FuncNameStartColumn += 1
DeclText = DeclText.lstrip('*')
elif FirstChar == '\r':
DeclText = DeclText.lstrip('\r\n').lstrip('\r')
FuncNameStartLine += 1
FuncNameStartColumn = 0
elif FirstChar == '\n':
DeclText = DeclText.lstrip('\n')
FuncNameStartLine += 1
FuncNameStartColumn = 0
elif FirstChar == ' ':
DeclText = DeclText.lstrip(' ')
FuncNameStartColumn += 1
elif FirstChar == '\t':
DeclText = DeclText.lstrip('\t')
FuncNameStartColumn += 8
else:
DeclText = DeclText[1:]
FuncNameStartColumn += 1
FirstChar = DeclText[0]
FuncDef.Declarator = DeclText
DeclSplitList = FuncDef.Declarator.split('(')
if len(DeclSplitList) < 2:
continue
FuncName = DeclSplitList[0]
FuncNamePartList = FuncName.split()
if len(FuncNamePartList) > 1:
FuncName = FuncNamePartList[-1]
NameStart = DeclSplitList[0].rfind(FuncName)
if NameStart > 0:
FuncDef.Modifier += ' ' + DeclSplitList[0][0:NameStart]
Index = 0
PreChar = ''
while Index < NameStart:
FirstChar = DeclSplitList[0][Index]
if DeclSplitList[0][Index:].startswith('EFIAPI'):
Index += 6
FuncNameStartColumn += 6
PreChar = ''
continue
elif FirstChar == '\r':
Index += 1
FuncNameStartLine += 1
FuncNameStartColumn = 0
elif FirstChar == '\n':
Index += 1
if PreChar != '\r':
FuncNameStartLine += 1
FuncNameStartColumn = 0
elif FirstChar == ' ':
Index += 1
FuncNameStartColumn += 1
elif FirstChar == '\t':
Index += 1
FuncNameStartColumn += 8
else:
Index += 1
FuncNameStartColumn += 1
PreChar = FirstChar
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)
FuncObjList.append(FuncObj)
return FuncObjList
def GetFileModificationTimeFromDB(FullFileName):
TimeValue = 0.0
Db = GetDB()
SqlStatement = """ select TimeStamp
from File
where FullPath = \'%s\'
""" % (FullFileName)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
TimeValue = Result[0]
return TimeValue
def CollectSourceCodeDataIntoDB(RootDir):
FileObjList = []
tuple = os.walk(RootDir)
IgnoredPattern = GetIgnoredDirListPattern()
ParseErrorFileList = []
for dirpath, dirnames, filenames in tuple:
if IgnoredPattern.match(dirpath.upper()):
continue
for Dir in dirnames:
Dirname = os.path.join(dirpath, Dir)
if os.path.islink(Dirname):
Dirname = os.path.realpath(Dirname)
if os.path.isdir(Dirname):
# symlinks to directories are treated as directories
dirnames.remove(Dir)
dirnames.append(Dirname)
for f in filenames:
FullName = os.path.normpath(os.path.join(dirpath, f))
if os.path.splitext(f)[1] in ('.h', '.c'):
EdkLogger.info("Parsing " + FullName)
model = f.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H
collector = CodeFragmentCollector.CodeFragmentCollector(FullName)
try:
collector.ParseFile()
except UnicodeError:
ParseErrorFileList.append(FullName)
collector.CleanFileProfileBuffer()
collector.ParseFileWithClearedPPDirective()
# collector.PrintFragments()
BaseName = os.path.basename(f)
DirName = os.path.dirname(FullName)
Ext = os.path.splitext(f)[1].lstrip('.')
ModifiedTime = os.path.getmtime(FullName)
FileObj = DataClass.FileClass(-1, BaseName, Ext, DirName, FullName, model, ModifiedTime, GetFunctionList(), GetIdentifierList(), [])
FileObjList.append(FileObj)
collector.CleanFileProfileBuffer()
if len(ParseErrorFileList) > 0:
EdkLogger.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList))
Db = GetDB()
for file in FileObjList:
Db.InsertOneFile(file)
Db.UpdateIdentifierBelongsToFunction()
def GetTableID(FullFileName, ErrorMsgList = None):
if ErrorMsgList == None:
ErrorMsgList = []
Db = GetDB()
SqlStatement = """ select ID
from File
where FullPath like '%s'
""" % FullFileName
ResultSet = Db.TblFile.Exec(SqlStatement)
FileID = -1
for Result in ResultSet:
if FileID != -1:
ErrorMsgList.append('Duplicate file ID found in DB for file %s' % FullFileName)
return -2
FileID = Result[0]
if FileID == -1:
ErrorMsgList.append('NO file ID found in DB for file %s' % FullFileName)
return -1
return FileID
def GetIncludeFileList(FullFileName):
IFList = IncludeFileListDict.get(FullFileName)
if IFList != None:
return IFList
FileID = GetTableID(FullFileName)
if FileID < 0:
return []
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Value
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_INCLUDE)
ResultSet = Db.TblFile.Exec(SqlStatement)
IncludeFileListDict[FullFileName] = ResultSet
return ResultSet
def GetFullPathOfIncludeFile(Str, IncludePathList):
for IncludePath in IncludePathList:
FullPath = os.path.join(IncludePath, Str)
FullPath = os.path.normpath(FullPath)
if os.path.exists(FullPath):
return FullPath
return None
def GetAllIncludeFiles(FullFileName):
if AllIncludeFileListDict.get(FullFileName) != None:
return AllIncludeFileListDict.get(FullFileName)
FileDirName = os.path.dirname(FullFileName)
IncludePathList = IncludePathListDict.get(FileDirName)
if IncludePathList == None:
IncludePathList = MetaDataParser.GetIncludeListOfFile(EccGlobalData.gWorkspace, FullFileName, GetDB())
if FileDirName not in IncludePathList:
IncludePathList.insert(0, FileDirName)
IncludePathListDict[FileDirName] = IncludePathList
IncludeFileQueue = []
for IncludeFile in GetIncludeFileList(FullFileName):
FileName = IncludeFile[0].lstrip('#').strip()
FileName = FileName.lstrip('include').strip()
FileName = FileName.strip('\"')
FileName = FileName.lstrip('<').rstrip('>').strip()
FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList)
if FullPath != None:
IncludeFileQueue.append(FullPath)
i = 0
while i < len(IncludeFileQueue):
for IncludeFile in GetIncludeFileList(IncludeFileQueue[i]):
FileName = IncludeFile[0].lstrip('#').strip()
FileName = FileName.lstrip('include').strip()
FileName = FileName.strip('\"')
FileName = FileName.lstrip('<').rstrip('>').strip()
FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList)
if FullPath != None and FullPath not in IncludeFileQueue:
IncludeFileQueue.insert(i + 1, FullPath)
i += 1
AllIncludeFileListDict[FullFileName] = IncludeFileQueue
return IncludeFileQueue
def GetPredicateListFromPredicateExpStr(PES):
PredicateList = []
i = 0
PredicateBegin = 0
#PredicateEnd = 0
LogicOpPos = -1
p = GetFuncDeclPattern()
while i < len(PES) - 1:
if (PES[i].isalnum() or PES[i] == '_' or PES[i] == '*') and LogicOpPos > PredicateBegin:
PredicateBegin = i
if (PES[i] == '&' and PES[i+1] == '&') or (PES[i] == '|' and PES[i+1] == '|'):
LogicOpPos = i
Exp = PES[PredicateBegin:i].strip()
# Exp may contain '.' or '->'
TmpExp = Exp.replace('.', '').replace('->', '')
if p.match(TmpExp):
PredicateList.append(Exp)
else:
PredicateList.append(Exp.rstrip(';').rstrip(')').strip())
i += 1
if PredicateBegin > LogicOpPos:
while PredicateBegin < len(PES):
if PES[PredicateBegin].isalnum() or PES[PredicateBegin] == '_' or PES[PredicateBegin] == '*':
break
PredicateBegin += 1
Exp = PES[PredicateBegin:len(PES)].strip()
# Exp may contain '.' or '->'
TmpExp = Exp.replace('.', '').replace('->', '')
if p.match(TmpExp):
PredicateList.append(Exp)
else:
PredicateList.append(Exp.rstrip(';').rstrip(')').strip())
return PredicateList
def GetCNameList(Lvalue, StarList = []):
Lvalue += ' '
i = 0
SearchBegin = 0
VarStart = -1
VarEnd = -1
VarList = []
while SearchBegin < len(Lvalue):
while i < len(Lvalue):
if Lvalue[i].isalnum() or Lvalue[i] == '_':
if VarStart == -1:
VarStart = i
VarEnd = i
i += 1
elif VarEnd != -1:
VarList.append(Lvalue[VarStart:VarEnd+1])
i += 1
break
else:
if VarStart == -1 and Lvalue[i] == '*':
StarList.append('*')
i += 1
if VarEnd == -1:
break
DotIndex = Lvalue[VarEnd:].find('.')
ArrowIndex = Lvalue[VarEnd:].find('->')
if DotIndex == -1 and ArrowIndex == -1:
break
elif DotIndex == -1 and ArrowIndex != -1:
SearchBegin = VarEnd + ArrowIndex
elif ArrowIndex == -1 and DotIndex != -1:
SearchBegin = VarEnd + DotIndex
else:
SearchBegin = VarEnd + ((DotIndex < ArrowIndex) and DotIndex or ArrowIndex)
i = SearchBegin
VarStart = -1
VarEnd = -1
return VarList
def SplitPredicateByOp(Str, Op, IsFuncCalling = False):
Name = Str.strip()
Value = None
if IsFuncCalling:
Index = 0
LBFound = False
UnmatchedLBCount = 0
while Index < len(Str):
while not LBFound and Str[Index] != '_' and not Str[Index].isalnum():
Index += 1
while not LBFound and (Str[Index].isalnum() or Str[Index] == '_'):
Index += 1
# maybe type-cast at the begining, skip it.
RemainingStr = Str[Index:].lstrip()
if RemainingStr.startswith(')') and not LBFound:
Index += 1
continue
if RemainingStr.startswith('(') and not LBFound:
LBFound = True
if Str[Index] == '(':
UnmatchedLBCount += 1
Index += 1
continue
if Str[Index] == ')':
UnmatchedLBCount -= 1
Index += 1
if UnmatchedLBCount == 0:
break
continue
Index += 1
if UnmatchedLBCount > 0:
return [Name]
IndexInRemainingStr = Str[Index:].find(Op)
if IndexInRemainingStr == -1:
return [Name]
Name = Str[0:Index + IndexInRemainingStr].strip()
Value = Str[Index+IndexInRemainingStr+len(Op):].strip()
return [Name, Value]
TmpStr = Str.rstrip(';').rstrip(')')
while True:
Index = TmpStr.rfind(Op)
if Index == -1:
return [Name]
if Str[Index - 1].isalnum() or Str[Index - 1].isspace() or Str[Index - 1] == ')':
Name = Str[0:Index].strip()
Value = Str[Index + len(Op):].strip()
return [Name, Value]
TmpStr = Str[0:Index - 1]
def SplitPredicateStr(Str):
IsFuncCalling = False
p = GetFuncDeclPattern()
TmpStr = Str.replace('.', '').replace('->', '')
if p.match(TmpStr):
IsFuncCalling = True
PredPartList = SplitPredicateByOp(Str, '==', IsFuncCalling)
if len(PredPartList) > 1:
return [PredPartList, '==']
PredPartList = SplitPredicateByOp(Str, '!=', IsFuncCalling)
if len(PredPartList) > 1:
return [PredPartList, '!=']
PredPartList = SplitPredicateByOp(Str, '>=', IsFuncCalling)
if len(PredPartList) > 1:
return [PredPartList, '>=']
PredPartList = SplitPredicateByOp(Str, '<=', IsFuncCalling)
if len(PredPartList) > 1:
return [PredPartList, '<=']
PredPartList = SplitPredicateByOp(Str, '>', IsFuncCalling)
if len(PredPartList) > 1:
return [PredPartList, '>']
PredPartList = SplitPredicateByOp(Str, '<', IsFuncCalling)
if len(PredPartList) > 1:
return [PredPartList, '<']
return [[Str, None], None]
def GetFuncContainsPE(ExpLine, ResultSet):
for Result in ResultSet:
if Result[0] < ExpLine and Result[1] > ExpLine:
return Result
return None
def PatternInModifier(Modifier, SubStr):
PartList = Modifier.split()
for Part in PartList:
if Part == SubStr:
return True
return False
def GetDataTypeFromModifier(ModifierStr):
MList = ModifierStr.split()
for M in MList:
if M in EccGlobalData.gConfig.ModifierList:
MList.remove(M)
# remove array sufix
if M.startswith('['):
MList.remove(M)
ReturnType = ''
for M in MList:
ReturnType += M + ' '
ReturnType = ReturnType.strip()
if len(ReturnType) == 0:
ReturnType = 'VOID'
return ReturnType
def DiffModifier(Str1, Str2):
PartList1 = Str1.split()
PartList2 = Str2.split()
if PartList1 == PartList2:
return False
else:
return True
def GetTypedefDict(FullFileName):
Dict = ComplexTypeDict.get(FullFileName)
if Dict != None:
return Dict
FileID = GetTableID(FullFileName)
FileTable = 'Identifier' + str(FileID)
Db = GetDB()
SqlStatement = """ select Modifier, Name, Value, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
ResultSet = Db.TblFile.Exec(SqlStatement)
Dict = {}
for Result in ResultSet:
if len(Result[0]) == 0:
Dict[Result[1]] = Result[2]
IncludeFileList = GetAllIncludeFiles(FullFileName)
for F in IncludeFileList:
FileID = GetTableID(F)
if FileID < 0:
continue
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Modifier, Name, Value, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
if not Result[2].startswith('FP ('):
Dict[Result[1]] = Result[2]
else:
if len(Result[0]) == 0:
Dict[Result[1]] = 'VOID'
else:
Dict[Result[1]] = GetDataTypeFromModifier(Result[0])
ComplexTypeDict[FullFileName] = Dict
return Dict
def GetSUDict(FullFileName):
Dict = SUDict.get(FullFileName)
if Dict != None:
return Dict
FileID = GetTableID(FullFileName)
FileTable = 'Identifier' + str(FileID)
Db = GetDB()
SqlStatement = """ select Name, Value, ID
from %s
where Model = %d or Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION)
ResultSet = Db.TblFile.Exec(SqlStatement)
Dict = {}
for Result in ResultSet:
if len(Result[1]) > 0:
Dict[Result[0]] = Result[1]
IncludeFileList = GetAllIncludeFiles(FullFileName)
for F in IncludeFileList:
FileID = GetTableID(F)
if FileID < 0:
continue
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Name, Value, ID
from %s
where Model = %d or Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
if len(Result[1]) > 0:
Dict[Result[0]] = Result[1]
SUDict[FullFileName] = Dict
return Dict
def StripComments(Str):
Str += ' '
ListFromStr = list(Str)
InComment = False
DoubleSlashComment = False
Index = 0
while Index < len(ListFromStr):
# meet new line, then no longer in a comment for //
if ListFromStr[Index] == '\n':
if InComment and DoubleSlashComment:
InComment = False
DoubleSlashComment = False
Index += 1
# check for */ comment end
elif InComment and not DoubleSlashComment and ListFromStr[Index] == '*' and ListFromStr[Index+1] == '/':
ListFromStr[Index] = ' '
Index += 1
ListFromStr[Index] = ' '
Index += 1
InComment = False
# set comments to spaces
elif InComment:
ListFromStr[Index] = ' '
Index += 1
# check for // comment
elif ListFromStr[Index] == '/' and ListFromStr[Index+1] == '/' and ListFromStr[Index+2] != '\n':
InComment = True
DoubleSlashComment = True
# check for /* comment start
elif ListFromStr[Index] == '/' and ListFromStr[Index+1] == '*':
ListFromStr[Index] = ' '
Index += 1
ListFromStr[Index] = ' '
Index += 1
InComment = True
else:
Index += 1
# restore from List to String
Str = "".join(ListFromStr)
Str = Str.rstrip(' ')
return Str
def GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict):
Value = TypedefDict.get(Type)
if Value == None:
Value = SUDict.get(Type)
if Value == None:
return None
LBPos = Value.find('{')
while LBPos == -1:
FTList = Value.split()
for FT in FTList:
if FT not in ('struct', 'union'):
Value = TypedefDict.get(FT)
if Value == None:
Value = SUDict.get(FT)
break
if Value == None:
return None
LBPos = Value.find('{')
# RBPos = Value.find('}')
Fields = Value[LBPos + 1:]
Fields = StripComments(Fields)
FieldsList = Fields.split(';')
for Field in FieldsList:
Field = Field.strip()
Index = Field.rfind(FieldName)
if Index < 1:
continue
if not Field[Index - 1].isalnum():
if Index + len(FieldName) == len(Field):
Type = GetDataTypeFromModifier(Field[0:Index])
return Type.strip()
else:
# For the condition that the field in struct is an array with [] sufixes...
if not Field[Index + len(FieldName)].isalnum():
Type = GetDataTypeFromModifier(Field[0:Index])
return Type.strip()
return None
def GetRealType(Type, TypedefDict, TargetType = None):
if TargetType != None and Type == TargetType:
return Type
while TypedefDict.get(Type):
Type = TypedefDict.get(Type)
if TargetType != None and Type == TargetType:
return Type
return Type
def GetTypeInfo(RefList, Modifier, FullFileName, TargetType = None):
TypedefDict = GetTypedefDict(FullFileName)
SUDict = GetSUDict(FullFileName)
Type = GetDataTypeFromModifier(Modifier).replace('*', '').strip()
Type = Type.split()[-1]
Index = 0
while Index < len(RefList):
FieldName = RefList[Index]
FromType = GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict)
if FromType == None:
return None
# we want to determine the exact type.
if TargetType != None:
Type = FromType.split()[0]
# we only want to check if it is a pointer
else:
Type = FromType
if Type.find('*') != -1 and Index == len(RefList)-1:
return Type
Type = FromType.split()[0]
Index += 1
Type = GetRealType(Type, TypedefDict, TargetType)
return Type
def GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall = False, TargetType = None, StarList = None):
PredVar = PredVarList[0]
FileID = GetTableID(FullFileName)
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
# search variable in include files
# it is a function call, search function declarations and definitions
if IsFuncCall:
SqlStatement = """ select Modifier, ID
from %s
where Model = %d and Value = \'%s\'
""" % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
Type = GetDataTypeFromModifier(Result[0]).split()[-1]
TypedefDict = GetTypedefDict(FullFileName)
Type = GetRealType(Type, TypedefDict, TargetType)
return Type
IncludeFileList = GetAllIncludeFiles(FullFileName)
for F in IncludeFileList:
FileID = GetTableID(F)
if FileID < 0:
continue
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Modifier, ID
from %s
where Model = %d and Value = \'%s\'
""" % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
Type = GetDataTypeFromModifier(Result[0]).split()[-1]
TypedefDict = GetTypedefDict(FullFileName)
Type = GetRealType(Type, TypedefDict, TargetType)
return Type
FileID = GetTableID(FullFileName)
SqlStatement = """ select Modifier, ID
from Function
where BelongsToFile = %d and Name = \'%s\'
""" % (FileID, PredVar)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
Type = GetDataTypeFromModifier(Result[0]).split()[-1]
TypedefDict = GetTypedefDict(FullFileName)
Type = GetRealType(Type, TypedefDict, TargetType)
return Type
for F in IncludeFileList:
FileID = GetTableID(F)
if FileID < 0:
continue
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Modifier, ID
from Function
where BelongsToFile = %d and Name = \'%s\'
""" % (FileID, PredVar)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
Type = GetDataTypeFromModifier(Result[0]).split()[-1]
TypedefDict = GetTypedefDict(FullFileName)
Type = GetRealType(Type, TypedefDict, TargetType)
return Type
return None
# really variable, search local variable first
SqlStatement = """ select Modifier, ID
from %s
where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar, FuncRecord[0], FuncRecord[1])
ResultSet = Db.TblFile.Exec(SqlStatement)
VarFound = False
for Result in ResultSet:
if len(PredVarList) > 1:
Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)
return Type
else:
# Type = GetDataTypeFromModifier(Result[0]).split()[-1]
TypeList = GetDataTypeFromModifier(Result[0]).split()
Type = TypeList[-1]
if len(TypeList) > 1 and StarList != None:
for Star in StarList:
Type = Type.strip()
Type = Type.rstrip(Star)
# Get real type after de-reference pointers.
if len(Type.strip()) == 0:
Type = TypeList[-2]
TypedefDict = GetTypedefDict(FullFileName)
Type = GetRealType(Type, TypedefDict, TargetType)
return Type
# search function parameters second
ParamList = GetParamList(FuncRecord[2])
for Param in ParamList:
if Param.Name.strip() == PredVar:
if len(PredVarList) > 1:
Type = GetTypeInfo(PredVarList[1:], Param.Modifier, FullFileName, TargetType)
return Type
else:
TypeList = GetDataTypeFromModifier(Param.Modifier).split()
Type = TypeList[-1]
if len(TypeList) > 1 and StarList != None:
for Star in StarList:
Type = Type.strip()
Type = Type.rstrip(Star)
# Get real type after de-reference pointers.
if len(Type.strip()) == 0:
Type = TypeList[-2]
TypedefDict = GetTypedefDict(FullFileName)
Type = GetRealType(Type, TypedefDict, TargetType)
return Type
# search global variable next
SqlStatement = """ select Modifier, ID
from %s
where Model = %d and Name = \'%s\' and BelongsToFunction = -1
""" % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
if len(PredVarList) > 1:
Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)
return Type
else:
TypeList = GetDataTypeFromModifier(Result[0]).split()
Type = TypeList[-1]
if len(TypeList) > 1 and StarList != None:
for Star in StarList:
Type = Type.strip()
Type = Type.rstrip(Star)
# Get real type after de-reference pointers.
if len(Type.strip()) == 0:
Type = TypeList[-2]
TypedefDict = GetTypedefDict(FullFileName)
Type = GetRealType(Type, TypedefDict, TargetType)
return Type
IncludeFileList = GetAllIncludeFiles(FullFileName)
for F in IncludeFileList:
FileID = GetTableID(F)
if FileID < 0:
continue
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Modifier, ID
from %s
where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
""" % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
if len(PredVarList) > 1:
Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)
return Type
else:
TypeList = GetDataTypeFromModifier(Result[0]).split()
Type = TypeList[-1]
if len(TypeList) > 1 and StarList != None:
for Star in StarList:
Type = Type.strip()
Type = Type.rstrip(Star)
# Get real type after de-reference pointers.
if len(Type.strip()) == 0:
Type = TypeList[-2]
TypedefDict = GetTypedefDict(FullFileName)
Type = GetRealType(Type, TypedefDict, TargetType)
return Type
def CheckFuncLayoutReturnType(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
ReturnType = GetDataTypeFromModifier(Result[0])
TypeStart = ReturnType.split()[0]
FuncName = Result[5]
if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, FuncName):
continue
Index = Result[0].find(TypeStart)
if Index != 0 or Result[3] != 0:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, FileTable, Result[1])
if Result[2] == Result[4]:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear on its own line' % FuncName, FileTable, Result[1])
SqlStatement = """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
ReturnType = GetDataTypeFromModifier(Result[0])
TypeStart = ReturnType.split()[0]
FuncName = Result[5]
if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, FuncName):
continue
Index = Result[0].find(ReturnType)
if Index != 0 or Result[3] != 0:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, 'Function', Result[1])
if Result[2] == Result[4]:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear on its own line' % FuncName, 'Function', Result[1])
def CheckFuncLayoutModifier(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Modifier, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
ReturnType = GetDataTypeFromModifier(Result[0])
TypeStart = ReturnType.split()[0]
# if len(ReturnType) == 0:
# continue
Index = Result[0].find(TypeStart)
if Index != 0:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', FileTable, Result[1])
SqlStatement = """ select Modifier, ID
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
ReturnType = GetDataTypeFromModifier(Result[0])
TypeStart = ReturnType.split()[0]
# if len(ReturnType) == 0:
# continue
Index = Result[0].find(TypeStart)
if Index != 0:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', 'Function', Result[1])
def CheckFuncLayoutName(FullFileName):
ErrorMsgList = []
# Parameter variable format pattern.
Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
ParamIgnoreList = ('VOID', '...')
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Name, ID, EndColumn, Value
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
FuncName = Result[3]
if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName):
continue
if Result[2] != 0:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, FileTable, Result[1])
ParamList = GetParamList(Result[0])
if len(ParamList) == 0:
continue
StartLine = 0
for Param in ParamList:
if Param.StartLine <= StartLine:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, FileTable, Result[1])
if Param.StartLine - StartLine > 1:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, FileTable, Result[1])
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):
PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1])
StartLine = Param.StartLine
if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'):
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', FileTable, Result[1])
SqlStatement = """ select Modifier, ID, FunNameStartColumn, Name
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
FuncName = Result[3]
if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName):
continue
if Result[2] != 0:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, 'Function', Result[1])
ParamList = GetParamList(Result[0])
if len(ParamList) == 0:
continue
StartLine = 0
for Param in ParamList:
if Param.StartLine <= StartLine:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, 'Function', Result[1])
if Param.StartLine - StartLine > 1:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, 'Function', Result[1])
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):
PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1])
StartLine = Param.StartLine
if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'):
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', 'Function', Result[1])
def CheckFuncLayoutPrototype(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
FileTable = 'Identifier' + str(FileID)
Db = GetDB()
SqlStatement = """ select Modifier, Header, Name, ID
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
if len(ResultSet) == 0:
return ErrorMsgList
FuncDefList = []
for Result in ResultSet:
FuncDefList.append(Result)
SqlStatement = """ select Modifier, Name, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
ResultSet = Db.TblFile.Exec(SqlStatement)
FuncDeclList = []
for Result in ResultSet:
FuncDeclList.append(Result)
UndeclFuncList = []
for FuncDef in FuncDefList:
FuncName = FuncDef[2].strip()
FuncModifier = FuncDef[0]
FuncDefHeader = FuncDef[1]
for FuncDecl in FuncDeclList:
LBPos = FuncDecl[1].find('(')
DeclName = FuncDecl[1][0:LBPos].strip()
DeclModifier = FuncDecl[0]
if DeclName == FuncName:
if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName):
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3])
ParamListOfDef = GetParamList(FuncDefHeader)
ParamListOfDecl = GetParamList(FuncDecl[1])
if len(ParamListOfDef) != len(ParamListOfDecl):
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Parameter number different.', 'Function', FuncDef[3])
break
Index = 0
while Index < len(ParamListOfDef):
if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier):
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Parameter %s has different modifier with prototype.' % ParamListOfDef[Index].Name, 'Function', FuncDef[3])
Index += 1
break
else:
UndeclFuncList.append(FuncDef)
IncludeFileList = GetAllIncludeFiles(FullFileName)
FuncDeclList = []
for F in IncludeFileList:
FileID = GetTableID(F, ErrorMsgList)
if FileID < 0:
continue
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Modifier, Name, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
FuncDeclList.append(Result)
for FuncDef in UndeclFuncList:
FuncName = FuncDef[2].strip()
FuncModifier = FuncDef[0]
FuncDefHeader = FuncDef[1]
for FuncDecl in FuncDeclList:
LBPos = FuncDecl[1].find('(')
DeclName = FuncDecl[1][0:LBPos].strip()
DeclModifier = FuncDecl[0]
if DeclName == FuncName:
if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName):
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3])
ParamListOfDef = GetParamList(FuncDefHeader)
ParamListOfDecl = GetParamList(FuncDecl[1])
if len(ParamListOfDef) != len(ParamListOfDecl):
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Parameter number different.', 'Function', FuncDef[3])
break
Index = 0
while Index < len(ParamListOfDef):
if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier):
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Parameter %s has different modifier with prototype.' % ParamListOfDef[Index].Name, 'Function', FuncDef[3])
Index += 1
break
def CheckFuncLayoutBody(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
FileTable = 'Identifier' + str(FileID)
Db = GetDB()
SqlStatement = """ select BodyStartColumn, EndColumn, ID
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
if len(ResultSet) == 0:
return ErrorMsgList
for Result in ResultSet:
if Result[0] != 0:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'open brace should be at the very beginning of a line.', 'Function', Result[2])
if Result[1] != 0:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'close brace should be at the very beginning of a line.', 'Function', Result[2])
def CheckFuncLayoutLocalVariable(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select ID
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
if len(ResultSet) == 0:
return ErrorMsgList
FL = []
for Result in ResultSet:
FL.append(Result)
for F in FL:
SqlStatement = """ select Name, Value, ID
from %s
where Model = %d and BelongsToFunction = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, F[0])
ResultSet = Db.TblFile.Exec(SqlStatement)
if len(ResultSet) == 0:
continue
for Result in ResultSet:
if len(Result[1]) > 0:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE, 'Variable Name: %s' % Result[0], FileTable, Result[2])
def CheckMemberVariableFormat(Name, Value, FileTable, TdId, ModelId):
ErrMsgList = []
# Member variable format pattern.
Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
LBPos = Value.find('{')
RBPos = Value.rfind('}')
if LBPos == -1 or RBPos == -1:
return ErrMsgList
Fields = Value[LBPos + 1 : RBPos]
Fields = StripComments(Fields).strip()
NestPos = Fields.find ('struct')
if NestPos != -1 and (NestPos + len('struct') < len(Fields)):
if not Fields[NestPos + len('struct') + 1].isalnum():
if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested struct in [%s].' % (Name), FileTable, TdId)
return ErrMsgList
NestPos = Fields.find ('union')
if NestPos != -1 and (NestPos + len('union') < len(Fields)):
if not Fields[NestPos + len('union') + 1].isalnum():
if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested union in [%s].' % (Name), FileTable, TdId)
return ErrMsgList
NestPos = Fields.find ('enum')
if NestPos != -1 and (NestPos + len('enum') < len(Fields)):
if not Fields[NestPos + len('enum') + 1].isalnum():
if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested enum in [%s].' % (Name), FileTable, TdId)
return ErrMsgList
if ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:
FieldsList = Fields.split(',')
# deal with enum is pre-assigned a value by function call ( , , , ...)
QuoteCount = 0
Index = 0
RemoveCurrentElement = False
while Index < len(FieldsList):
Field = FieldsList[Index]
if Field.find('(') != -1:
QuoteCount += 1
RemoveCurrentElement = True
Index += 1
continue
if Field.find(')') != -1 and QuoteCount > 0:
QuoteCount -= 1
if RemoveCurrentElement:
FieldsList.remove(Field)
if QuoteCount == 0:
RemoveCurrentElement = False
continue
if QuoteCount == 0:
RemoveCurrentElement = False
Index += 1
else:
FieldsList = Fields.split(';')
for Field in FieldsList:
Field = Field.strip()
if Field == '':
continue
# For the condition that the field in struct is an array with [] sufixes...
if Field[-1] == ']':
LBPos = Field.find('[')
Field = Field[0:LBPos]
# For the condition that bit field ": Number"
if Field.find(':') != -1:
ColonPos = Field.find(':')
Field = Field[0:ColonPos]
Field = Field.strip()
if Field == '':
continue
# Enum could directly assign value to variable
Field = Field.split('=')[0].strip()
TokenList = Field.split()
# Remove pointers before variable
if not Pattern.match(TokenList[-1].lstrip('*')):
ErrMsgList.append(TokenList[-1].lstrip('*'))
return ErrMsgList
def CheckDeclTypedefFormat(FullFileName, ModelId):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Name, StartLine, EndLine, ID, Value
from %s
where Model = %d
""" % (FileTable, ModelId)
ResultSet = Db.TblFile.Exec(SqlStatement)
ResultList = []
for Result in ResultSet:
ResultList.append(Result)
ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
if ModelId == DataClass.MODEL_IDENTIFIER_STRUCTURE:
ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
elif ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:
ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
elif ModelId == DataClass.MODEL_IDENTIFIER_UNION:
ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
TdSet = Db.TblFile.Exec(SqlStatement)
TdList = []
for Td in TdSet:
TdList.append(Td)
# Check member variable name format that from typedefs of ONLY this file.
for Td in TdList:
Name = Td[1].strip()
Value = Td[2].strip()
if Value.startswith('enum'):
ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE
elif Value.startswith('struct'):
ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE
elif Value.startswith('union'):
ValueModelId = DataClass.MODEL_IDENTIFIER_UNION
else:
continue
if ValueModelId != ModelId:
continue
# Check member variable format.
ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Td[5], ModelId)
for ErrMsg in ErrMsgList:
if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Name+'.'+ErrMsg):
continue
PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Name+'.'+ErrMsg), FileTable, Td[5])
# First check in current file to see whether struct/union/enum is typedef-ed.
UntypedefedList = []
for Result in ResultList:
# Check member variable format.
Name = Result[0].strip()
Value = Result[4].strip()
if Value.startswith('enum'):
ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE
elif Value.startswith('struct'):
ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE
elif Value.startswith('union'):
ValueModelId = DataClass.MODEL_IDENTIFIER_UNION
else:
continue
if ValueModelId != ModelId:
continue
ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Result[3], ModelId)
for ErrMsg in ErrMsgList:
if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Result[0]+'.'+ErrMsg):
continue
PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Result[0]+'.'+ErrMsg), FileTable, Result[3])
# Check whether it is typedefed.
Found = False
for Td in TdList:
# skip function pointer
if len(Td[0]) > 0:
continue
if Result[1] >= Td[3] and Td[4] >= Result[2]:
Found = True
if not Td[1].isupper():
PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
if Result[0] in Td[2].split():
Found = True
if not Td[1].isupper():
PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
if Found:
break
if not Found:
UntypedefedList.append(Result)
continue
if len(UntypedefedList) == 0:
return
IncludeFileList = GetAllIncludeFiles(FullFileName)
TdList = []
for F in IncludeFileList:
FileID = GetTableID(F, ErrorMsgList)
if FileID < 0:
continue
IncludeFileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID
from %s
where Model = %d
""" % (IncludeFileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
ResultSet = Db.TblFile.Exec(SqlStatement)
TdList.extend(ResultSet)
for Result in UntypedefedList:
# Check whether it is typedefed.
Found = False
for Td in TdList:
if len(Td[0]) > 0:
continue
if Result[1] >= Td[3] and Td[4] >= Result[2]:
Found = True
if not Td[1].isupper():
PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
if Result[0] in Td[2].split():
Found = True
if not Td[1].isupper():
PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
if Found:
break
if not Found:
PrintErrorMsg(ErrorType, 'No Typedef for %s' % Result[0], FileTable, Result[3])
continue
def CheckDeclStructTypedef(FullFileName):
CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_STRUCTURE)
def CheckDeclEnumTypedef(FullFileName):
CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_ENUMERATE)
def CheckDeclUnionTypedef(FullFileName):
CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_UNION)
def CheckDeclArgModifier(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Modifier, Name, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
ResultSet = Db.TblFile.Exec(SqlStatement)
ModifierTuple = ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
MAX_MODIFIER_LENGTH = 100
for Result in ResultSet:
for Modifier in ModifierTuple:
if PatternInModifier(Result[0], Modifier) and len(Result[0]) < MAX_MODIFIER_LENGTH:
PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Variable Modifier %s' % Result[0], FileTable, Result[2])
break
SqlStatement = """ select Modifier, Name, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
for Modifier in ModifierTuple:
if PatternInModifier(Result[0], Modifier):
PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])
break
SqlStatement = """ select Modifier, Header, ID
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
for Modifier in ModifierTuple:
if PatternInModifier(Result[0], Modifier):
PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])
break
def CheckDeclNoUseCType(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Modifier, Name, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
ResultSet = Db.TblFile.Exec(SqlStatement)
CTypeTuple = ('int', 'unsigned', 'char', 'void', 'static', 'long')
for Result in ResultSet:
for Type in CTypeTuple:
if PatternInModifier(Result[0], Type):
PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Variable type %s' % Type, FileTable, Result[2])
break
SqlStatement = """ select Modifier, Name, ID, Value
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
ParamList = GetParamList(Result[1])
FuncName = Result[3]
if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):
continue
for Type in CTypeTuple:
if PatternInModifier(Result[0], Type):
PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '%s Return type %s' % (FuncName, Result[0]), FileTable, Result[2])
for Param in ParamList:
if PatternInModifier(Param.Modifier, Type):
PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])
SqlStatement = """ select Modifier, Header, ID, Name
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
ParamList = GetParamList(Result[1])
FuncName = Result[3]
if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):
continue
for Type in CTypeTuple:
if PatternInModifier(Result[0], Type):
PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '[%s] Return type %s' % (FuncName, Result[0]), FileTable, Result[2])
for Param in ParamList:
if PatternInModifier(Param.Modifier, Type):
PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])
def CheckPointerNullComparison(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
# cache the found function return type to accelerate later checking in this file.
FuncReturnTypeDict = {}
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Value, StartLine, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
ResultSet = Db.TblFile.Exec(SqlStatement)
if len(ResultSet) == 0:
return
PSL = []
for Result in ResultSet:
PSL.append([Result[0], Result[1], Result[2]])
SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
FL = []
for Result in ResultSet:
FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
p = GetFuncDeclPattern()
for Str in PSL:
FuncRecord = GetFuncContainsPE(Str[1], FL)
if FuncRecord == None:
continue
for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
PredInfo = SplitPredicateStr(Exp)
if PredInfo[1] == None:
PredVarStr = PredInfo[0][0].strip()
IsFuncCall = False
SearchInCache = False
# PredVarStr may contain '.' or '->'
TmpStr = PredVarStr.replace('.', '').replace('->', '')
if p.match(TmpStr):
PredVarStr = PredVarStr[0:PredVarStr.find('(')]
SearchInCache = True
# Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
if TmpStr.startswith(PredVarStr):
IsFuncCall = True
if PredVarStr.strip() in IgnoredKeywordList:
continue
StarList = []
PredVarList = GetCNameList(PredVarStr, StarList)
# No variable found, maybe value first? like (0 == VarName)
if len(PredVarList) == 0:
continue
if SearchInCache:
Type = FuncReturnTypeDict.get(PredVarStr)
if Type != None:
if Type.find('*') != -1:
PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
continue
if PredVarStr in FuncReturnTypeDict:
continue
Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, None, StarList)
if SearchInCache:
FuncReturnTypeDict[PredVarStr] = Type
if Type == None:
continue
if Type.find('*') != -1:
PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
def CheckNonBooleanValueComparison(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
# cache the found function return type to accelerate later checking in this file.
FuncReturnTypeDict = {}
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Value, StartLine, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
ResultSet = Db.TblFile.Exec(SqlStatement)
if len(ResultSet) == 0:
return
PSL = []
for Result in ResultSet:
PSL.append([Result[0], Result[1], Result[2]])
SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
FL = []
for Result in ResultSet:
FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
p = GetFuncDeclPattern()
for Str in PSL:
FuncRecord = GetFuncContainsPE(Str[1], FL)
if FuncRecord == None:
continue
for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
# if p.match(Exp):
# continue
PredInfo = SplitPredicateStr(Exp)
if PredInfo[1] == None:
PredVarStr = PredInfo[0][0].strip()
IsFuncCall = False
SearchInCache = False
# PredVarStr may contain '.' or '->'
TmpStr = PredVarStr.replace('.', '').replace('->', '')
if p.match(TmpStr):
PredVarStr = PredVarStr[0:PredVarStr.find('(')]
SearchInCache = True
# Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
if TmpStr.startswith(PredVarStr):
IsFuncCall = True
if PredVarStr.strip() in IgnoredKeywordList:
continue
StarList = []
PredVarList = GetCNameList(PredVarStr, StarList)
# No variable found, maybe value first? like (0 == VarName)
if len(PredVarList) == 0:
continue
if SearchInCache:
Type = FuncReturnTypeDict.get(PredVarStr)
if Type != None:
if Type.find('BOOLEAN') == -1:
PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
continue
if PredVarStr in FuncReturnTypeDict:
continue
Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)
if SearchInCache:
FuncReturnTypeDict[PredVarStr] = Type
if Type == None:
continue
if Type.find('BOOLEAN') == -1:
PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
def CheckBooleanValueComparison(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
# cache the found function return type to accelerate later checking in this file.
FuncReturnTypeDict = {}
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Value, StartLine, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
ResultSet = Db.TblFile.Exec(SqlStatement)
if len(ResultSet) == 0:
return
PSL = []
for Result in ResultSet:
PSL.append([Result[0], Result[1], Result[2]])
SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
FL = []
for Result in ResultSet:
FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
p = GetFuncDeclPattern()
for Str in PSL:
FuncRecord = GetFuncContainsPE(Str[1], FL)
if FuncRecord == None:
continue
for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
PredInfo = SplitPredicateStr(Exp)
if PredInfo[1] in ('==', '!=') and PredInfo[0][1] in ('TRUE', 'FALSE'):
PredVarStr = PredInfo[0][0].strip()
IsFuncCall = False
SearchInCache = False
# PredVarStr may contain '.' or '->'
TmpStr = PredVarStr.replace('.', '').replace('->', '')
if p.match(TmpStr):
PredVarStr = PredVarStr[0:PredVarStr.find('(')]
SearchInCache = True
# Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
if TmpStr.startswith(PredVarStr):
IsFuncCall = True
if PredVarStr.strip() in IgnoredKeywordList:
continue
StarList = []
PredVarList = GetCNameList(PredVarStr, StarList)
# No variable found, maybe value first? like (0 == VarName)
if len(PredVarList) == 0:
continue
if SearchInCache:
Type = FuncReturnTypeDict.get(PredVarStr)
if Type != None:
if Type.find('BOOLEAN') != -1:
PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
continue
if PredVarStr in FuncReturnTypeDict:
continue
Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)
if SearchInCache:
FuncReturnTypeDict[PredVarStr] = Type
if Type == None:
continue
if Type.find('BOOLEAN') != -1:
PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
def CheckHeaderFileData(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select ID, Modifier
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
if not Result[1].startswith('extern'):
PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Variable definition appears in header file', FileTable, Result[0])
SqlStatement = """ select ID
from Function
where BelongsToFile = %d
""" % FileID
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Function definition appears in header file', 'Function', Result[0])
return ErrorMsgList
def CheckHeaderFileIfndef(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Value, StartLine
from %s
where Model = %d order by StartLine
""" % (FileTable, DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF)
ResultSet = Db.TblFile.Exec(SqlStatement)
if len(ResultSet) == 0:
PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1, '', 'File', FileID)
return ErrorMsgList
for Result in ResultSet:
SqlStatement = """ select Value, EndLine
from %s
where EndLine < %d
""" % (FileTable, Result[1])
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
if not Result[0].startswith('/*') and not Result[0].startswith('//'):
PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2, '', 'File', FileID)
break
SqlStatement = """ select Value
from %s
where StartLine > (select max(EndLine) from %s where Model = %d)
""" % (FileTable, FileTable, DataClass.MODEL_IDENTIFIER_MACRO_ENDIF)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
if not Result[0].startswith('/*') and not Result[0].startswith('//'):
PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3, '', 'File', FileID)
return ErrorMsgList
def CheckDoxygenCommand(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Value, ID
from %s
where Model = %d or Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)
ResultSet = Db.TblFile.Exec(SqlStatement)
DoxygenCommandList = ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval', 'return', 'sa', 'since', 'test', 'note', 'par']
for Result in ResultSet:
CommentStr = Result[0]
CommentPartList = CommentStr.split()
for Part in CommentPartList:
if Part.upper() == 'BUGBUG':
PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Bug should be marked with doxygen tag @bug', FileTable, Result[1])
if Part.upper() == 'TODO':
PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'ToDo should be marked with doxygen tag @todo', FileTable, Result[1])
if Part.startswith('@'):
if EccGlobalData.gException.IsException(ERROR_DOXYGEN_CHECK_COMMAND, Part):
continue
if Part.lstrip('@').isalpha():
if Part.lstrip('@') not in DoxygenCommandList:
PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
else:
Index = Part.find('[')
if Index == -1:
PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
RealCmd = Part[1:Index]
if RealCmd not in DoxygenCommandList:
PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
def CheckDoxygenTripleForwardSlash(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
SqlStatement = """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
if len(ResultSet) == 0:
return
FuncDefSet = []
for Result in ResultSet:
FuncDefSet.append(Result)
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
ResultSet = Db.TblFile.Exec(SqlStatement)
CommentSet = []
try:
for Result in ResultSet:
CommentSet.append(Result)
except:
print 'Unrecognized chars in comment of file %s', FullFileName
for Result in CommentSet:
CommentStr = Result[0]
StartLine = Result[2]
StartColumn = Result[3]
EndLine = Result[4]
EndColumn = Result[5]
if not CommentStr.startswith('///<'):
continue
Found = False
for FuncDef in FuncDefSet:
if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:
Found = True
break
if StartLine > FuncDef[1] and EndLine < FuncDef[3]:
Found = True
break
if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine < FuncDef[3]:
Found = True
break
if StartLine > FuncDef[1] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:
Found = True
break
if Found:
PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT, '', FileTable, Result[1])
def CheckFileHeaderDoxygenComments(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Value, ID
from %s
where Model = %d and StartLine = 1 and StartColumn = 0
""" % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
ResultSet = Db.TblFile.Exec(SqlStatement)
if len(ResultSet) == 0:
PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'No Comment appear at the very beginning of file.', 'File', FileID)
return ErrorMsgList
for Result in ResultSet:
CommentStr = Result[0]
if not CommentStr.startswith('/** @file'):
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER, 'File header comment should begin with ""/** @file""', FileTable, Result[1])
if not CommentStr.endswith('**/'):
PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should end with **/', FileTable, Result[1])
if CommentStr.find('.') == -1:
PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period \'.\'', FileTable, Result[1])
def CheckFuncHeaderDoxygenComments(FullFileName):
ErrorMsgList = []
FileID = GetTableID(FullFileName, ErrorMsgList)
if FileID < 0:
return ErrorMsgList
Db = GetDB()
FileTable = 'Identifier' + str(FileID)
SqlStatement = """ select Value, StartLine, EndLine, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
ResultSet = Db.TblFile.Exec(SqlStatement)
CommentSet = []
try:
for Result in ResultSet:
CommentSet.append(Result)
except:
print 'Unrecognized chars in comment of file %s', FullFileName
# Func Decl check
SqlStatement = """ select Modifier, Name, StartLine, ID, Value
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
FuncName = Result[4]
FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)
if FunctionHeaderComment:
CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)
else:
if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):
continue
ErrorMsgList.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result[2], Result[1]))
PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), FileTable, Result[3])
# Func Def check
SqlStatement = """ select Value, StartLine, EndLine, ID
from %s
where Model = %d
""" % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)
ResultSet = Db.TblFile.Exec(SqlStatement)
CommentSet = []
try:
for Result in ResultSet:
CommentSet.append(Result)
except:
print 'Unrecognized chars in comment of file %s', FullFileName
SqlStatement = """ select Modifier, Header, StartLine, ID, Name
from Function
where BelongsToFile = %d
""" % (FileID)
ResultSet = Db.TblFile.Exec(SqlStatement)
for Result in ResultSet:
FuncName = Result[4]
FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)
if FunctionHeaderComment:
CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)
else:
if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):
continue
ErrorMsgList.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result[2], Result[1]))
PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), 'Function', Result[3])
return ErrorMsgList
def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName, FuncStartLine, CommentSet):
for Comment in CommentSet:
if Comment[2] == FuncStartLine - 1:
return Comment
return None
def GetDoxygenStrFromComment(Str):
DoxygenStrList = []
ParamTagList = Str.split('@param')
if len(ParamTagList) > 1:
i = 1
while i < len(ParamTagList):
DoxygenStrList.append('@param' + ParamTagList[i])
i += 1
Str = ParamTagList[0]
RetvalTagList = ParamTagList[-1].split('@retval')
if len(RetvalTagList) > 1:
if len(ParamTagList) > 1:
DoxygenStrList[-1] = '@param' + RetvalTagList[0]
i = 1
while i < len(RetvalTagList):
DoxygenStrList.append('@retval' + RetvalTagList[i])
i += 1
ReturnTagList = RetvalTagList[-1].split('@return')
if len(ReturnTagList) > 1:
if len(RetvalTagList) > 1:
DoxygenStrList[-1] = '@retval' + ReturnTagList[0]
elif len(ParamTagList) > 1:
DoxygenStrList[-1] = '@param' + ReturnTagList[0]
i = 1
while i < len(ReturnTagList):
DoxygenStrList.append('@return' + ReturnTagList[i])
i += 1
if len(DoxygenStrList) > 0:
DoxygenStrList[-1] = DoxygenStrList[-1].rstrip('--*/')
return DoxygenStrList
def CheckGeneralDoxygenCommentLayout(Str, StartLine, ErrorMsgList, CommentId = -1, TableName = ''):
#/** --*/ @retval after @param
if not Str.startswith('/**'):
ErrorMsgList.append('Line %d : Comment does NOT have prefix /** ' % StartLine)
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have prefix /** ', TableName, CommentId)
if not Str.endswith('**/'):
ErrorMsgList.append('Line %d : Comment does NOT have tail **/ ' % StartLine)
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have tail **/ ', TableName, CommentId)
FirstRetvalIndex = Str.find('@retval')
LastParamIndex = Str.rfind('@param')
if (FirstRetvalIndex > 0) and (LastParamIndex > 0) and (FirstRetvalIndex < LastParamIndex):
ErrorMsgList.append('Line %d : @retval appear before @param ' % StartLine)
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, @retval appear before @param ', TableName, CommentId)
def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier, FuncHeader, FuncStartLine, CommentStr, CommentStartLine, ErrorMsgList, CommentId = -1, TableName = ''):
ParamList = GetParamList(FuncHeader)
CheckGeneralDoxygenCommentLayout(CommentStr, CommentStartLine, ErrorMsgList, CommentId, TableName)
DescriptionStr = CommentStr
DoxygenStrList = GetDoxygenStrFromComment(DescriptionStr)
if DescriptionStr.find('.') == -1:
PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period \'.\'', TableName, CommentId)
DoxygenTagNumber = len(DoxygenStrList)
ParamNumber = len(ParamList)
for Param in ParamList:
if Param.Name.upper() == 'VOID' and ParamNumber == 1:
ParamNumber -= 1
Index = 0
if ParamNumber > 0 and DoxygenTagNumber > 0:
while Index < ParamNumber and Index < DoxygenTagNumber:
ParamModifier = ParamList[Index].Modifier
ParamName = ParamList[Index].Name.strip()
Tag = DoxygenStrList[Index].strip(' ')
if (not Tag[-1] == ('\n')) and (not Tag[-1] == ('\r')):
ErrorMsgList.append('Line %d : in Comment, \"%s\" does NOT end with new line ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))
PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'in Comment, \"%s\" does NOT end with new line ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)
TagPartList = Tag.split()
if len(TagPartList) < 2:
ErrorMsgList.append('Line %d : in Comment, \"%s\" does NOT contain doxygen contents ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, \"%s\" does NOT contain doxygen contents ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)
Index += 1
continue
LBPos = Tag.find('[')
RBPos = Tag.find(']')
ParamToLBContent = Tag[len('@param'):LBPos].strip()
if LBPos > 0 and len(ParamToLBContent)==0 and RBPos > LBPos:
InOutStr = ''
ModifierPartList = ParamModifier.split()
for Part in ModifierPartList:
if Part.strip() == 'IN':
InOutStr += 'in'
if Part.strip() == 'OUT':
if InOutStr != '':
InOutStr += ', out'
else:
InOutStr = 'out'
if InOutStr != '':
if Tag.find('['+InOutStr+']') == -1:
ErrorMsgList.append('Line %d : in Comment, \"%s\" does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' +TagPartList[1]).replace('\n', '').replace('\r', ''), '['+InOutStr+']'))
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, \"%s\" does NOT have %s ' % ((TagPartList[0] + ' ' +TagPartList[1]).replace('\n', '').replace('\r', ''), '['+InOutStr+']'), TableName, CommentId)
if Tag.find(ParamName) == -1 and ParamName != 'VOID' and ParamName != 'void':
ErrorMsgList.append('Line %d : in Comment, \"%s\" does NOT consistent with parameter name %s ' % (CommentStartLine, (TagPartList[0] + ' ' +TagPartList[1]).replace('\n', '').replace('\r', ''), ParamName))
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)
Index += 1
if Index < ParamNumber:
ErrorMsgList.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine)
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of doxygen tags in comment less than number of function parameters ', TableName, CommentId)
# VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
if (FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1:
# assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
if Index < DoxygenTagNumber - 1 or (Index < DoxygenTagNumber and DoxygenStrList[Index].startswith('@retval')):
ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need no doxygen tags in comment ', TableName, CommentId)
else:
if Index < DoxygenTagNumber and not DoxygenStrList[Index].startswith('@retval') and not DoxygenStrList[Index].startswith('@return'):
ErrorMsgList.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine)
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName, CommentId)
else:
if ParamNumber == 0 and DoxygenTagNumber != 0 and ((FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1):
ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need NO doxygen tags in comment ', TableName, CommentId)
if ParamNumber != 0 and DoxygenTagNumber == 0:
ErrorMsgList.append('Line %d : No doxygen tags in comment' % CommentStartLine)
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'No doxygen tags in comment ', TableName, CommentId)
if __name__ == '__main__':
# EdkLogger.Initialize()
# EdkLogger.SetLevel(EdkLogger.QUIET)
# CollectSourceCodeDataIntoDB(sys.argv[1])
MsgList = CheckFuncHeaderDoxygenComments('C:\\Combo\\R9\\LakeportX64Dev\\FlashDevicePkg\\Library\\SpiFlashChipM25P64\\SpiFlashChipM25P64.c')
for Msg in MsgList:
print Msg
print 'Done!'