2019-09-03 11:58:42 +02:00
## @file
# This file is used to be the c coding style checking of ECC tool
#
# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
from __future__ import print_function
from __future__ import absolute_import
import sys
import Common . LongFilePathOs as os
import re
import string
from Ecc import CodeFragmentCollector
from Ecc import FileProfile
from CommonDataClass import DataClass
from Ecc import Database
from Common import EdkLogger
from Ecc . EccToolError import *
from Ecc import EccGlobalData
from Ecc import MetaDataParser
IncludeFileListDict = { }
AllIncludeFileListDict = { }
IncludePathListDict = { }
ComplexTypeDict = { }
SUDict = { }
IgnoredKeywordList = [ ' EFI_ERROR ' ]
def GetIgnoredDirListPattern ( ) :
skipList = list ( EccGlobalData . gConfig . SkipDirList ) + [ ' .svn ' ]
DirString = ' | ' . 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 ( ) or Char == ' _ ' :
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 = [ ]
TokenReleaceList = EccGlobalData . gConfig . TokenReleaceList
TokenReleaceList . extend ( [ ' L " , \\ \" " ' ] )
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 :
if f . lower ( ) in EccGlobalData . gConfig . SkipFileList :
continue
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 )
collector . TokenReleaceList = TokenReleaceList
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 is None :
ErrorMsgList = [ ]
Db = GetDB ( )
SqlStatement = """ select ID
from File
where FullPath like ' %s '
""" % F ullFileName
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 is not 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 ) is not None :
return AllIncludeFileListDict . get ( FullFileName )
FileDirName = os . path . dirname ( FullFileName )
IncludePathList = IncludePathListDict . get ( FileDirName )
if IncludePathList is 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 is not 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 is not 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 beginning, 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 . ModifierSet :
continue
# remove array suffix
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 is not 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 is not 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 ] == ' / ' :
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 is None :
Value = SUDict . get ( Type )
if Value is 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 is None :
Value = SUDict . get ( FT )
break
if Value is 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 [] suffixes...
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 is not None and Type == TargetType :
return Type
while TypedefDict . get ( Type ) :
Type = TypedefDict . get ( Type )
if TargetType is not 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 is None :
return None
# we want to determine the exact type.
if TargetType is not 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 is not 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 Type == ' * ' and len ( TypeList ) > = 2 :
Type = TypeList [ - 2 ]
if len ( TypeList ) > 1 and StarList is not 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 is not 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 is not 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
Result0 = Result [ 0 ]
if Result0 . upper ( ) . startswith ( ' STATIC ' ) :
Result0 = Result0 [ 6 : ] . strip ( )
Index = Result0 . 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
Result0 = Result [ 0 ]
if Result0 . upper ( ) . startswith ( ' STATIC ' ) :
Result0 = Result0 [ 6 : ] . strip ( )
Index = Result0 . 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 , ' 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 ]
Result0 = Result [ 0 ]
if Result0 . upper ( ) . startswith ( ' STATIC ' ) :
Result0 = Result0 [ 6 : ] . strip ( )
Index = Result0 . 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 ]
Result0 = Result [ 0 ]
if Result0 . upper ( ) . startswith ( ' STATIC ' ) :
Result0 = Result0 [ 6 : ] . strip ( )
Index = Result0 . 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, Name
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 :
if not EccGlobalData . gException . IsException ( ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY , Result [ 3 ] ) :
PrintErrorMsg ( ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY ,
' The open brace should be at the very beginning of a line for the function [ %s ]. ' % Result [ 3 ] ,
' Function ' , Result [ 2 ] )
if Result [ 1 ] != 0 :
if not EccGlobalData . gException . IsException ( ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY , Result [ 3 ] ) :
PrintErrorMsg ( ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY ,
' The close brace should be at the very beginning of a line for the function [ %s ]. ' % Result [ 3 ] ,
' 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 ) ) and ModelId != DataClass . MODEL_IDENTIFIER_UNION :
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 [] suffixes...
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
if Field . startswith ( " # " ) :
continue
# Enum could directly assign value to variable
Field = Field . split ( ' = ' ) [ 0 ] . strip ( )
TokenList = Field . split ( )
# Remove pointers before variable
Token = TokenList [ - 1 ]
if Token in [ ' OPTIONAL ' ] :
Token = TokenList [ - 2 ]
if not Pattern . match ( Token . lstrip ( ' * ' ) ) :
ErrMsgList . append ( Token . 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 )
2019-09-20 06:56:20 +02:00
CTypeTuple = ( ' int ' , ' unsigned ' , ' char ' , ' void ' , ' long ' )
2019-09-03 11:58:42 +02:00
for Result in ResultSet :
for Type in CTypeTuple :
if PatternInModifier ( Result [ 0 ] , Type ) :
if EccGlobalData . gException . IsException ( ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE ,
Result [ 0 ] + ' ' + Result [ 1 ] ) :
continue
PrintErrorMsg ( ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE ,
' Invalid variable type ( %s ) in definition [ %s ] ' % ( Type , Result [ 0 ] + ' ' + Result [ 1 ] ) ,
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 is None :
continue
for Exp in GetPredicateListFromPredicateExpStr ( Str [ 0 ] ) :
PredInfo = SplitPredicateStr ( Exp )
if PredInfo [ 1 ] is 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 is not 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 is 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 is None :
continue
for Exp in GetPredicateListFromPredicateExpStr ( Str [ 0 ] ) :
PredInfo = SplitPredicateStr ( Exp )
if PredInfo [ 1 ] is 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 is not 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 is 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 is 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 is not 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 is None :
continue
if Type . find ( ' BOOLEAN ' ) != - 1 :
PrintErrorMsg ( ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE , ' Predicate Expression: %s ' % Exp , FileTable , Str [ 2 ] )
def CheckHeaderFileData ( FullFileName , AllTypedefFun = [ ] ) :
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 ' ) :
for Item in AllTypedefFun :
if ' ( %s ) ' % Result [ 1 ] in Item :
break
else :
PrintErrorMsg ( ERROR_INCLUDE_FILE_CHECK_DATA , ' Variable definition appears in header file ' , FileTable , Result [ 0 ] )
SqlStatement = """ select ID
from Function
where BelongsToFile = % d
""" % F ileID
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 ' , ' endcode ' , ' code ' ]
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 not Part . replace ( ' @ ' , ' ' ) . strip ( ) :
continue
if Part . lstrip ( ' @ ' ) in [ ' { ' , ' } ' ] :
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 ( )
2019-09-20 06:56:20 +02:00
if CommentLine . startswith ( ' Copyright ' ) or ( ' Copyright ' in CommentLine and CommentLine . lower ( ) . startswith ( ' (c) ' ) ) :
2019-09-03 11:58:42 +02:00
NoCopyrightFlag = False
if CommentLine . find ( ' All rights reserved ' ) == - 1 :
for Copyright in EccGlobalData . gConfig . Copyright :
if CommentLine . find ( Copyright ) > - 1 :
PrintErrorMsg ( ERROR_HEADER_CHECK_FILE , ' " " All rights reserved " " announcement should be following the " " Copyright " " at the same line ' , FileTable , ID )
break
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 as v :
print ( " Usage: %s filename " % sys . argv [ 0 ] )
sys . exit ( 1 )
MsgList = CheckFuncHeaderDoxygenComments ( test_file )
for Msg in MsgList :
print ( Msg )
print ( ' Done! ' )