mirror of
https://github.com/acidanthera/audk.git
synced 2025-04-08 17:05:09 +02:00
1. Support use expression as DSC file PCD value. 2. Update FDF parser to fix bug to get complete macro value. 3. Fix bug to replace SET statement macro and evaluate SET statement PCD value in FDF file. 4. Fix a bug for MACRO defined in conditional block cannot be processed correctly Signed-off-by: lgao4 Reviewed-by: gikidy git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12827 6f19259b-4bc3-4df7-8a09-765794883524
2615 lines
109 KiB
Python
2615 lines
109 KiB
Python
## @file
|
|
# This file is used to be the c coding style checking of ECC tool
|
|
#
|
|
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
|
# This program and the accompanying materials
|
|
# are licensed and made available under the terms and conditions of the BSD License
|
|
# which accompanies this distribution. The full text of the license may be found at
|
|
# http://opensource.org/licenses/bsd-license.php
|
|
#
|
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
#
|
|
|
|
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:
|
|
collector = None
|
|
FullName = os.path.normpath(os.path.join(dirpath, f))
|
|
model = DataClass.MODEL_FILE_OTHERS
|
|
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)
|
|
if collector:
|
|
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:
|
|
if file.ExtName.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
|
|
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):
|
|
if os.path.splitext(FullFileName)[1].upper() not in ('.H'):
|
|
return []
|
|
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().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] == ')' 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):
|
|
|
|
Str = Str.lstrip('(')
|
|
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()
|
|
ReturnType = ''
|
|
for M in MList:
|
|
if M in EccGlobalData.gConfig.ModifierList:
|
|
continue
|
|
# remove array sufix
|
|
if M.startswith('[') or M.endswith(']'):
|
|
continue
|
|
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 GetTypeFromArray(Type, Var):
|
|
Count = Var.count('[')
|
|
|
|
while Count > 0:
|
|
Type = Type.strip()
|
|
Type = Type.rstrip('*')
|
|
Count = Count - 1
|
|
|
|
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) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, FuncName):
|
|
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, 'Parameter number different in function [%s].' % FuncName, 'Function', FuncDef[3])
|
|
break
|
|
|
|
Index = 0
|
|
while Index < len(ParamListOfDef):
|
|
if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, FuncName):
|
|
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])
|
|
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) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, FuncName):
|
|
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, 'Parameter number different in function [%s].' % FuncName, 'Function', FuncDef[3])
|
|
break
|
|
|
|
Index = 0
|
|
while Index < len(ParamListOfDef):
|
|
if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, FuncName):
|
|
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])
|
|
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, Modifier
|
|
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 and 'CONST' not in Result[3]:
|
|
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 and Type != 'BOOLEAN*':
|
|
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
|
|
Type = GetTypeFromArray(Type, PredVarStr)
|
|
if Type.find('*') != -1 and Type != 'BOOLEAN*':
|
|
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]):
|
|
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 or StartLine = 7 or StartLine = 8) and StartColumn = 0
|
|
""" % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
|
|
ResultSet = Db.TblFile.Exec(SqlStatement)
|
|
if len(ResultSet) == 0:
|
|
PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'No File License header appear at the very beginning of file.', 'File', FileID)
|
|
return ErrorMsgList
|
|
|
|
NoHeaderCommentStartFlag = True
|
|
NoHeaderCommentEndFlag = True
|
|
NoHeaderCommentPeriodFlag = True
|
|
NoCopyrightFlag = True
|
|
NoLicenseFlag = True
|
|
NoRevReferFlag = True
|
|
NextLineIndex = 0
|
|
for Result in ResultSet:
|
|
FileStartFlag = False
|
|
CommentStrList = []
|
|
CommentStr = Result[0].strip()
|
|
CommentStrListTemp = CommentStr.split('\n')
|
|
if (len(CommentStrListTemp) <= 1):
|
|
# For Mac
|
|
CommentStrListTemp = CommentStr.split('\r')
|
|
# Skip the content before the file header
|
|
for CommentLine in CommentStrListTemp:
|
|
if CommentLine.strip().startswith('/** @file'):
|
|
FileStartFlag = True
|
|
if FileStartFlag == True:
|
|
CommentStrList.append(CommentLine)
|
|
|
|
ID = Result[1]
|
|
Index = 0
|
|
if CommentStrList and CommentStrList[0].strip().startswith('/** @file'):
|
|
NoHeaderCommentStartFlag = False
|
|
else:
|
|
continue
|
|
if CommentStrList and CommentStrList[-1].strip().endswith('**/'):
|
|
NoHeaderCommentEndFlag = False
|
|
else:
|
|
continue
|
|
|
|
for CommentLine in CommentStrList:
|
|
Index = Index + 1
|
|
NextLineIndex = Index
|
|
if CommentLine.startswith('/** @file'):
|
|
continue
|
|
if CommentLine.startswith('**/'):
|
|
break
|
|
# Check whether C File header Comment content start with two spaces.
|
|
if EccGlobalData.gConfig.HeaderCheckCFileCommentStartSpacesNum == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
|
|
if CommentLine.startswith('/** @file') == False and CommentLine.startswith('**/') == False and CommentLine.strip() and CommentLine.startswith(' ') == False:
|
|
PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment content should start with two spaces at each line', FileTable, ID)
|
|
|
|
CommentLine = CommentLine.strip()
|
|
if CommentLine.startswith('Copyright'):
|
|
NoCopyrightFlag = False
|
|
if CommentLine.find('All rights reserved') == -1:
|
|
PrintErrorMsg(ERROR_HEADER_CHECK_FILE, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable, ID)
|
|
if CommentLine.endswith('<BR>') == -1:
|
|
PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'The ""<BR>"" at the end of the Copyright line is required', FileTable, ID)
|
|
if NextLineIndex < len(CommentStrList) and CommentStrList[NextLineIndex].strip().startswith('Copyright') == False and CommentStrList[NextLineIndex].strip():
|
|
NoLicenseFlag = False
|
|
if CommentLine.startswith('@par Revision Reference:'):
|
|
NoRevReferFlag = False
|
|
RefListFlag = False
|
|
for RefLine in CommentStrList[NextLineIndex:]:
|
|
if RefLine.strip() and (NextLineIndex + 1) < len(CommentStrList) and CommentStrList[NextLineIndex+1].strip() and CommentStrList[NextLineIndex+1].strip().startswith('**/') == False:
|
|
RefListFlag = True
|
|
if RefLine.strip() == False or RefLine.strip().startswith('**/'):
|
|
RefListFlag = False
|
|
break
|
|
# Check whether C File header Comment's each reference at list should begin with a bullet character.
|
|
if EccGlobalData.gConfig.HeaderCheckCFileCommentReferenceFormat == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
|
|
if RefListFlag == True:
|
|
if RefLine.strip() and RefLine.strip().startswith('**/') == False and RefLine.startswith(' -') == False:
|
|
PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable, ID)
|
|
|
|
if NoHeaderCommentStartFlag:
|
|
PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER, 'File header comment should begin with ""/** @file""', FileTable, ID)
|
|
return
|
|
if NoHeaderCommentEndFlag:
|
|
PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should end with ""**/""', FileTable, ID)
|
|
return
|
|
if NoCopyrightFlag:
|
|
PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment missing the ""Copyright""', FileTable, ID)
|
|
#Check whether C File header Comment have the License immediately after the ""Copyright"" line.
|
|
if EccGlobalData.gConfig.HeaderCheckCFileCommentLicenseFormat == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
|
|
if NoLicenseFlag:
|
|
PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable, ID)
|
|
|
|
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:
|
|
if InOutStr != 'in, out':
|
|
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)
|
|
else:
|
|
if Tag.find('[in,out]') == -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])
|
|
try:
|
|
test_file = sys.argv[1]
|
|
except IndexError, v:
|
|
print "Usage: %s filename" % sys.argv[0]
|
|
sys.exit(1)
|
|
MsgList = CheckFuncHeaderDoxygenComments(test_file)
|
|
for Msg in MsgList:
|
|
print Msg
|
|
print 'Done!'
|