2 # This file is used to be the c coding style checking of ECC tool
4 # Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
5 # SPDX-License-Identifier: BSD-2-Clause-Patent
8 from __future__
import print_function
9 from __future__
import absolute_import
11 import Common
.LongFilePathOs
as os
14 from Ecc
import CodeFragmentCollector
15 from Ecc
import FileProfile
16 from CommonDataClass
import DataClass
17 from Ecc
import Database
18 from Common
import EdkLogger
19 from Ecc
.EccToolError
import *
20 from Ecc
import EccGlobalData
21 from Ecc
import MetaDataParser
23 IncludeFileListDict
= {}
24 AllIncludeFileListDict
= {}
25 IncludePathListDict
= {}
28 IgnoredKeywordList
= ['EFI_ERROR']
30 def GetIgnoredDirListPattern():
31 skipList
= list(EccGlobalData
.gConfig
.SkipDirList
) + ['.svn']
32 DirString
= '|'.join(skipList
)
33 p
= re
.compile(r
'.*[\\/](?:%s)[\\/]?.*' % DirString
)
36 def GetFuncDeclPattern():
37 p
= re
.compile(r
'(?:EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re
.DOTALL
)
40 def GetArrayPattern():
41 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
44 def GetTypedefFuncPointerPattern():
45 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
49 return EccGlobalData
.gDb
52 return EccGlobalData
.gConfig
54 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
55 Msg
= Msg
.replace('\n', '').replace('\r', '')
56 MsgPartList
= Msg
.split()
58 for Part
in MsgPartList
:
61 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
=Msg
, BelongsToTable
=TableName
, BelongsToItem
=ItemId
)
64 Type
= DataClass
.MODEL_UNKNOWN
65 Str
= Str
.replace('#', '# ')
67 if List
[1] == 'include':
68 Type
= DataClass
.MODEL_IDENTIFIER_INCLUDE
69 elif List
[1] == 'define':
70 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_DEFINE
71 elif List
[1] == 'ifdef':
72 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFDEF
73 elif List
[1] == 'ifndef':
74 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
75 elif List
[1] == 'endif':
76 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
77 elif List
[1] == 'pragma':
78 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_PROGMA
80 Type
= DataClass
.MODEL_UNKNOWN
83 def SuOccurInTypedef (Su
, TdList
):
85 if Su
.StartPos
[0] == Td
.StartPos
[0] and Su
.EndPos
[0] == Td
.EndPos
[0]:
89 def GetIdentifierList():
91 for comment
in FileProfile
.CommentList
:
92 IdComment
= DataClass
.IdentifierClass(-1, '', '', '', comment
.Content
, DataClass
.MODEL_IDENTIFIER_COMMENT
, -1, -1, comment
.StartPos
[0], comment
.StartPos
[1], comment
.EndPos
[0], comment
.EndPos
[1])
93 IdList
.append(IdComment
)
95 for pp
in FileProfile
.PPDirectiveList
:
96 Type
= GetIdType(pp
.Content
)
97 IdPP
= DataClass
.IdentifierClass(-1, '', '', '', pp
.Content
, Type
, -1, -1, pp
.StartPos
[0], pp
.StartPos
[1], pp
.EndPos
[0], pp
.EndPos
[1])
100 for pe
in FileProfile
.PredicateExpressionList
:
101 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])
104 FuncDeclPattern
= GetFuncDeclPattern()
105 ArrayPattern
= GetArrayPattern()
106 for var
in FileProfile
.VariableDeclarationList
:
107 DeclText
= var
.Declarator
.lstrip()
108 FuncPointerPattern
= GetTypedefFuncPointerPattern()
109 if FuncPointerPattern
.match(DeclText
):
111 VarNameStartLine
= var
.NameStartPos
[0]
112 VarNameStartColumn
= var
.NameStartPos
[1]
113 FirstChar
= DeclText
[0]
114 while not FirstChar
.isalpha() and FirstChar
!= '_':
117 VarNameStartColumn
+= 1
118 DeclText
= DeclText
.lstrip('*')
119 elif FirstChar
== '\r':
120 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
121 VarNameStartLine
+= 1
122 VarNameStartColumn
= 0
123 elif FirstChar
== '\n':
124 DeclText
= DeclText
.lstrip('\n')
125 VarNameStartLine
+= 1
126 VarNameStartColumn
= 0
127 elif FirstChar
== ' ':
128 DeclText
= DeclText
.lstrip(' ')
129 VarNameStartColumn
+= 1
130 elif FirstChar
== '\t':
131 DeclText
= DeclText
.lstrip('\t')
132 VarNameStartColumn
+= 8
134 DeclText
= DeclText
[1:]
135 VarNameStartColumn
+= 1
136 FirstChar
= DeclText
[0]
138 var
.Declarator
= DeclText
139 if FuncDeclPattern
.match(var
.Declarator
):
140 DeclSplitList
= var
.Declarator
.split('(')
141 FuncName
= DeclSplitList
[0].strip()
142 FuncNamePartList
= FuncName
.split()
143 if len(FuncNamePartList
) > 1:
144 FuncName
= FuncNamePartList
[-1].strip()
145 NameStart
= DeclSplitList
[0].rfind(FuncName
)
146 var
.Declarator
= var
.Declarator
[NameStart
:]
148 var
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
151 while Index
< NameStart
:
152 FirstChar
= DeclSplitList
[0][Index
]
153 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
155 VarNameStartColumn
+= 6
158 elif FirstChar
== '\r':
160 VarNameStartLine
+= 1
161 VarNameStartColumn
= 0
162 elif FirstChar
== '\n':
165 VarNameStartLine
+= 1
166 VarNameStartColumn
= 0
167 elif FirstChar
== ' ':
169 VarNameStartColumn
+= 1
170 elif FirstChar
== '\t':
172 VarNameStartColumn
+= 8
175 VarNameStartColumn
+= 1
177 IdVar
= DataClass
.IdentifierClass(-1, var
.Modifier
, '', var
.Declarator
, FuncName
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, -1, -1, var
.StartPos
[0], var
.StartPos
[1], VarNameStartLine
, VarNameStartColumn
)
181 if var
.Declarator
.find('{') == -1:
182 for decl
in var
.Declarator
.split(','):
183 DeclList
= decl
.split('=')
184 Name
= DeclList
[0].strip()
185 if ArrayPattern
.match(Name
):
186 LSBPos
= var
.Declarator
.find('[')
187 var
.Modifier
+= ' ' + Name
[LSBPos
:]
188 Name
= Name
[0:LSBPos
]
190 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
)
193 DeclList
= var
.Declarator
.split('=')
194 Name
= DeclList
[0].strip()
195 if ArrayPattern
.match(Name
):
196 LSBPos
= var
.Declarator
.find('[')
197 var
.Modifier
+= ' ' + Name
[LSBPos
:]
198 Name
= Name
[0:LSBPos
]
199 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
)
202 for enum
in FileProfile
.EnumerationDefinitionList
:
203 LBPos
= enum
.Content
.find('{')
204 RBPos
= enum
.Content
.find('}')
205 Name
= enum
.Content
[4:LBPos
].strip()
206 Value
= enum
.Content
[LBPos
+ 1:RBPos
]
207 IdEnum
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
, -1, -1, enum
.StartPos
[0], enum
.StartPos
[1], enum
.EndPos
[0], enum
.EndPos
[1])
208 IdList
.append(IdEnum
)
210 for su
in FileProfile
.StructUnionDefinitionList
:
211 if SuOccurInTypedef(su
, FileProfile
.TypedefDefinitionList
):
213 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
215 if su
.Content
.startswith('union'):
216 Type
= DataClass
.MODEL_IDENTIFIER_UNION
218 LBPos
= su
.Content
.find('{')
219 RBPos
= su
.Content
.find('}')
220 if LBPos
== -1 or RBPos
== -1:
221 Name
= su
.Content
[SkipLen
:].strip()
224 Name
= su
.Content
[SkipLen
:LBPos
].strip()
225 Value
= su
.Content
[LBPos
:RBPos
+ 1]
226 IdPE
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, Type
, -1, -1, su
.StartPos
[0], su
.StartPos
[1], su
.EndPos
[0], su
.EndPos
[1])
229 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
230 for td
in FileProfile
.TypedefDefinitionList
:
234 if TdFuncPointerPattern
.match(td
.ToType
):
235 Modifier
= td
.FromType
236 LBPos
= td
.ToType
.find('(')
237 TmpStr
= td
.ToType
[LBPos
+ 1:].strip()
238 StarPos
= TmpStr
.find('*')
240 Modifier
+= ' ' + TmpStr
[0:StarPos
]
241 while TmpStr
[StarPos
] == '*':
242 # Modifier += ' ' + '*'
244 TmpStr
= TmpStr
[StarPos
:].strip()
245 RBPos
= TmpStr
.find(')')
246 Name
= TmpStr
[0:RBPos
]
247 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
249 while Name
.startswith('*'):
251 Name
= Name
.lstrip('*').strip()
253 if Name
.find('[') != -1:
254 LBPos
= Name
.find('[')
255 RBPos
= Name
.rfind(']')
256 Value
+= Name
[LBPos
: RBPos
+ 1]
257 Name
= Name
[0 : LBPos
]
259 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])
262 for funcCall
in FileProfile
.FunctionCallingList
:
263 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])
267 def StripNonAlnumChars(Str
):
270 if Char
.isalnum() or Char
== '_':
274 def GetParamList(FuncDeclarator
, FuncNameLine
=0, FuncNameOffset
=0):
275 FuncDeclarator
= StripComments(FuncDeclarator
)
277 #DeclSplitList = FuncDeclarator.split('(')
278 LBPos
= FuncDeclarator
.find('(')
279 #if len(DeclSplitList) < 2:
282 #FuncName = DeclSplitList[0]
283 FuncName
= FuncDeclarator
[0:LBPos
]
284 #ParamStr = DeclSplitList[1].rstrip(')')
285 ParamStr
= FuncDeclarator
[LBPos
+ 1:].rstrip(')')
288 TailChar
= FuncName
[-1]
289 while not TailChar
.isalpha() and TailChar
!= '_':
292 FuncName
= FuncName
.rstrip('\r\n').rstrip('\n')
295 elif TailChar
== '\r':
296 FuncName
= FuncName
.rstrip('\r')
299 elif TailChar
== ' ':
300 FuncName
= FuncName
.rstrip(' ')
302 elif TailChar
== '\t':
303 FuncName
= FuncName
.rstrip('\t')
306 FuncName
= FuncName
[:-1]
307 TailChar
= FuncName
[-1]
309 OffsetSkipped
+= 1 #skip '('
311 for p
in ParamStr
.split(','):
315 ParamName
= ListP
[-1]
316 DeclText
= ParamName
.strip()
317 RightSpacePos
= p
.rfind(ParamName
)
318 ParamModifier
= p
[0:RightSpacePos
]
319 if ParamName
== 'OPTIONAL':
320 if ParamModifier
== '':
321 ParamModifier
+= ' ' + 'OPTIONAL'
324 ParamName
= ListP
[-2]
325 DeclText
= ParamName
.strip()
326 RightSpacePos
= p
.rfind(ParamName
)
327 ParamModifier
= p
[0:RightSpacePos
]
328 ParamModifier
+= 'OPTIONAL'
329 while DeclText
.startswith('*'):
330 ParamModifier
+= ' ' + '*'
331 DeclText
= DeclText
.lstrip('*').strip()
333 # ignore array length if exists.
334 LBIndex
= ParamName
.find('[')
336 ParamName
= ParamName
[0:LBIndex
]
338 Start
= RightSpacePos
344 if FirstChar
== '\r':
348 elif FirstChar
== '\n':
353 elif FirstChar
== ' ':
356 elif FirstChar
== '\t':
364 ParamBeginLine
= FuncNameLine
+ LineSkipped
365 ParamBeginOffset
= FuncNameOffset
+ OffsetSkipped
367 Index
= Start
+ len(ParamName
)
369 while Index
< len(p
):
372 if FirstChar
== '\r':
376 elif FirstChar
== '\n':
381 elif FirstChar
== ' ':
384 elif FirstChar
== '\t':
392 ParamEndLine
= FuncNameLine
+ LineSkipped
393 ParamEndOffset
= FuncNameOffset
+ OffsetSkipped
394 if ParamName
!= '...':
395 ParamName
= StripNonAlnumChars(ParamName
)
396 IdParam
= DataClass
.IdentifierClass(-1, ParamModifier
, '', ParamName
, '', DataClass
.MODEL_IDENTIFIER_PARAMETER
, -1, -1, ParamBeginLine
, ParamBeginOffset
, ParamEndLine
, ParamEndOffset
)
397 ParamIdList
.append(IdParam
)
399 OffsetSkipped
+= 1 #skip ','
403 def GetFunctionList():
405 for FuncDef
in FileProfile
.FunctionDefinitionList
:
407 DeclText
= FuncDef
.Declarator
.lstrip()
408 FuncNameStartLine
= FuncDef
.NamePos
[0]
409 FuncNameStartColumn
= FuncDef
.NamePos
[1]
410 FirstChar
= DeclText
[0]
411 while not FirstChar
.isalpha() and FirstChar
!= '_':
413 FuncDef
.Modifier
+= '*'
414 FuncNameStartColumn
+= 1
415 DeclText
= DeclText
.lstrip('*')
416 elif FirstChar
== '\r':
417 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
418 FuncNameStartLine
+= 1
419 FuncNameStartColumn
= 0
420 elif FirstChar
== '\n':
421 DeclText
= DeclText
.lstrip('\n')
422 FuncNameStartLine
+= 1
423 FuncNameStartColumn
= 0
424 elif FirstChar
== ' ':
425 DeclText
= DeclText
.lstrip(' ')
426 FuncNameStartColumn
+= 1
427 elif FirstChar
== '\t':
428 DeclText
= DeclText
.lstrip('\t')
429 FuncNameStartColumn
+= 8
431 DeclText
= DeclText
[1:]
432 FuncNameStartColumn
+= 1
433 FirstChar
= DeclText
[0]
435 FuncDef
.Declarator
= DeclText
436 DeclSplitList
= FuncDef
.Declarator
.split('(')
437 if len(DeclSplitList
) < 2:
440 FuncName
= DeclSplitList
[0]
441 FuncNamePartList
= FuncName
.split()
442 if len(FuncNamePartList
) > 1:
443 FuncName
= FuncNamePartList
[-1]
444 NameStart
= DeclSplitList
[0].rfind(FuncName
)
446 FuncDef
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
449 while Index
< NameStart
:
450 FirstChar
= DeclSplitList
[0][Index
]
451 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
453 FuncNameStartColumn
+= 6
456 elif FirstChar
== '\r':
458 FuncNameStartLine
+= 1
459 FuncNameStartColumn
= 0
460 elif FirstChar
== '\n':
463 FuncNameStartLine
+= 1
464 FuncNameStartColumn
= 0
465 elif FirstChar
== ' ':
467 FuncNameStartColumn
+= 1
468 elif FirstChar
== '\t':
470 FuncNameStartColumn
+= 8
473 FuncNameStartColumn
+= 1
476 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
)
477 FuncObjList
.append(FuncObj
)
481 def GetFileModificationTimeFromDB(FullFileName
):
484 SqlStatement
= """ select TimeStamp
486 where FullPath = \'%s\'
488 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
489 for Result
in ResultSet
:
490 TimeValue
= Result
[0]
493 def CollectSourceCodeDataIntoDB(RootDir
):
495 tuple = os
.walk(RootDir
)
496 IgnoredPattern
= GetIgnoredDirListPattern()
497 ParseErrorFileList
= []
498 TokenReleaceList
= EccGlobalData
.gConfig
.TokenReleaceList
499 TokenReleaceList
.extend(['L",\\\""'])
501 for dirpath
, dirnames
, filenames
in tuple:
502 if IgnoredPattern
.match(dirpath
.upper()):
506 Dirname
= os
.path
.join(dirpath
, Dir
)
507 if os
.path
.islink(Dirname
):
508 Dirname
= os
.path
.realpath(Dirname
)
509 if os
.path
.isdir(Dirname
):
510 # symlinks to directories are treated as directories
512 dirnames
.append(Dirname
)
515 if f
.lower() in EccGlobalData
.gConfig
.SkipFileList
:
518 FullName
= os
.path
.normpath(os
.path
.join(dirpath
, f
))
519 model
= DataClass
.MODEL_FILE_OTHERS
520 if os
.path
.splitext(f
)[1] in ('.h', '.c'):
521 EdkLogger
.info("Parsing " + FullName
)
522 model
= f
.endswith('c') and DataClass
.MODEL_FILE_C
or DataClass
.MODEL_FILE_H
523 collector
= CodeFragmentCollector
.CodeFragmentCollector(FullName
)
524 collector
.TokenReleaceList
= TokenReleaceList
526 collector
.ParseFile()
528 ParseErrorFileList
.append(FullName
)
529 collector
.CleanFileProfileBuffer()
530 collector
.ParseFileWithClearedPPDirective()
531 # collector.PrintFragments()
532 BaseName
= os
.path
.basename(f
)
533 DirName
= os
.path
.dirname(FullName
)
534 Ext
= os
.path
.splitext(f
)[1].lstrip('.')
535 ModifiedTime
= os
.path
.getmtime(FullName
)
536 FileObj
= DataClass
.FileClass(-1, BaseName
, Ext
, DirName
, FullName
, model
, ModifiedTime
, GetFunctionList(), GetIdentifierList(), [])
537 FileObjList
.append(FileObj
)
539 collector
.CleanFileProfileBuffer()
541 if len(ParseErrorFileList
) > 0:
542 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
545 for file in FileObjList
:
546 if file.ExtName
.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
547 Db
.InsertOneFile(file)
549 Db
.UpdateIdentifierBelongsToFunction()
551 def GetTableID(FullFileName
, ErrorMsgList
=None):
552 if ErrorMsgList
is None:
556 SqlStatement
= """ select ID
558 where FullPath like '%s'
560 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
563 for Result
in ResultSet
:
565 ErrorMsgList
.append('Duplicate file ID found in DB for file %s' % FullFileName
)
569 ErrorMsgList
.append('NO file ID found in DB for file %s' % FullFileName
)
573 def GetIncludeFileList(FullFileName
):
574 if os
.path
.splitext(FullFileName
)[1].upper() not in ('.H'):
576 IFList
= IncludeFileListDict
.get(FullFileName
)
577 if IFList
is not None:
580 FileID
= GetTableID(FullFileName
)
585 FileTable
= 'Identifier' + str(FileID
)
586 SqlStatement
= """ select Value
589 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_INCLUDE
)
590 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
591 IncludeFileListDict
[FullFileName
] = ResultSet
594 def GetFullPathOfIncludeFile(Str
, IncludePathList
):
595 for IncludePath
in IncludePathList
:
596 FullPath
= os
.path
.join(IncludePath
, Str
)
597 FullPath
= os
.path
.normpath(FullPath
)
598 if os
.path
.exists(FullPath
):
602 def GetAllIncludeFiles(FullFileName
):
603 if AllIncludeFileListDict
.get(FullFileName
) is not None:
604 return AllIncludeFileListDict
.get(FullFileName
)
606 FileDirName
= os
.path
.dirname(FullFileName
)
607 IncludePathList
= IncludePathListDict
.get(FileDirName
)
608 if IncludePathList
is None:
609 IncludePathList
= MetaDataParser
.GetIncludeListOfFile(EccGlobalData
.gWorkspace
, FullFileName
, GetDB())
610 if FileDirName
not in IncludePathList
:
611 IncludePathList
.insert(0, FileDirName
)
612 IncludePathListDict
[FileDirName
] = IncludePathList
613 IncludeFileQueue
= []
614 for IncludeFile
in GetIncludeFileList(FullFileName
):
615 FileName
= IncludeFile
[0].lstrip('#').strip()
616 FileName
= FileName
.lstrip('include').strip()
617 FileName
= FileName
.strip('\"')
618 FileName
= FileName
.lstrip('<').rstrip('>').strip()
619 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
620 if FullPath
is not None:
621 IncludeFileQueue
.append(FullPath
)
624 while i
< len(IncludeFileQueue
):
625 for IncludeFile
in GetIncludeFileList(IncludeFileQueue
[i
]):
626 FileName
= IncludeFile
[0].lstrip('#').strip()
627 FileName
= FileName
.lstrip('include').strip()
628 FileName
= FileName
.strip('\"')
629 FileName
= FileName
.lstrip('<').rstrip('>').strip()
630 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
631 if FullPath
is not None and FullPath
not in IncludeFileQueue
:
632 IncludeFileQueue
.insert(i
+ 1, FullPath
)
635 AllIncludeFileListDict
[FullFileName
] = IncludeFileQueue
636 return IncludeFileQueue
638 def GetPredicateListFromPredicateExpStr(PES
):
645 p
= GetFuncDeclPattern()
646 while i
< len(PES
) - 1:
647 if (PES
[i
].isalnum() or PES
[i
] == '_' or PES
[i
] == '*') and LogicOpPos
> PredicateBegin
:
649 if (PES
[i
] == '&' and PES
[i
+ 1] == '&') or (PES
[i
] == '|' and PES
[i
+ 1] == '|'):
651 Exp
= PES
[PredicateBegin
:i
].strip()
652 # Exp may contain '.' or '->'
653 TmpExp
= Exp
.replace('.', '').replace('->', '')
655 PredicateList
.append(Exp
)
657 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
660 if PredicateBegin
> LogicOpPos
:
661 while PredicateBegin
< len(PES
):
662 if PES
[PredicateBegin
].isalnum() or PES
[PredicateBegin
] == '_' or PES
[PredicateBegin
] == '*':
665 Exp
= PES
[PredicateBegin
:len(PES
)].strip()
666 # Exp may contain '.' or '->'
667 TmpExp
= Exp
.replace('.', '').replace('->', '')
669 PredicateList
.append(Exp
)
671 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
674 def GetCNameList(Lvalue
, StarList
=[]):
682 while SearchBegin
< len(Lvalue
):
683 while i
< len(Lvalue
):
684 if Lvalue
[i
].isalnum() or Lvalue
[i
] == '_':
690 VarList
.append(Lvalue
[VarStart
:VarEnd
+ 1])
694 if VarStart
== -1 and Lvalue
[i
] == '*':
701 DotIndex
= Lvalue
[VarEnd
:].find('.')
702 ArrowIndex
= Lvalue
[VarEnd
:].find('->')
703 if DotIndex
== -1 and ArrowIndex
== -1:
705 elif DotIndex
== -1 and ArrowIndex
!= -1:
706 SearchBegin
= VarEnd
+ ArrowIndex
707 elif ArrowIndex
== -1 and DotIndex
!= -1:
708 SearchBegin
= VarEnd
+ DotIndex
710 SearchBegin
= VarEnd
+ ((DotIndex
< ArrowIndex
) and DotIndex
or ArrowIndex
)
718 def SplitPredicateByOp(Str
, Op
, IsFuncCalling
=False):
727 while Index
< len(Str
):
728 while not LBFound
and Str
[Index
] != '_' and not Str
[Index
].isalnum():
731 while not LBFound
and (Str
[Index
].isalnum() or Str
[Index
] == '_'):
733 # maybe type-cast at the beginning, skip it.
734 RemainingStr
= Str
[Index
:].lstrip()
735 if RemainingStr
.startswith(')') and not LBFound
:
739 if RemainingStr
.startswith('(') and not LBFound
:
742 if Str
[Index
] == '(':
743 UnmatchedLBCount
+= 1
747 if Str
[Index
] == ')':
748 UnmatchedLBCount
-= 1
750 if UnmatchedLBCount
== 0:
756 if UnmatchedLBCount
> 0:
759 IndexInRemainingStr
= Str
[Index
:].find(Op
)
760 if IndexInRemainingStr
== -1:
763 Name
= Str
[0:Index
+ IndexInRemainingStr
].strip()
764 Value
= Str
[Index
+ IndexInRemainingStr
+ len(Op
):].strip().strip(')')
767 TmpStr
= Str
.rstrip(';').rstrip(')')
769 Index
= TmpStr
.rfind(Op
)
773 if Str
[Index
- 1].isalnum() or Str
[Index
- 1].isspace() or Str
[Index
- 1] == ')' or Str
[Index
- 1] == ']':
774 Name
= Str
[0:Index
].strip()
775 Value
= Str
[Index
+ len(Op
):].strip()
778 TmpStr
= Str
[0:Index
- 1]
780 def SplitPredicateStr(Str
):
782 Str
= Str
.lstrip('(')
783 IsFuncCalling
= False
784 p
= GetFuncDeclPattern()
785 TmpStr
= Str
.replace('.', '').replace('->', '')
789 PredPartList
= SplitPredicateByOp(Str
, '==', IsFuncCalling
)
790 if len(PredPartList
) > 1:
791 return [PredPartList
, '==']
793 PredPartList
= SplitPredicateByOp(Str
, '!=', IsFuncCalling
)
794 if len(PredPartList
) > 1:
795 return [PredPartList
, '!=']
797 PredPartList
= SplitPredicateByOp(Str
, '>=', IsFuncCalling
)
798 if len(PredPartList
) > 1:
799 return [PredPartList
, '>=']
801 PredPartList
= SplitPredicateByOp(Str
, '<=', IsFuncCalling
)
802 if len(PredPartList
) > 1:
803 return [PredPartList
, '<=']
805 PredPartList
= SplitPredicateByOp(Str
, '>', IsFuncCalling
)
806 if len(PredPartList
) > 1:
807 return [PredPartList
, '>']
809 PredPartList
= SplitPredicateByOp(Str
, '<', IsFuncCalling
)
810 if len(PredPartList
) > 1:
811 return [PredPartList
, '<']
813 return [[Str
, None], None]
815 def GetFuncContainsPE(ExpLine
, ResultSet
):
816 for Result
in ResultSet
:
817 if Result
[0] < ExpLine
and Result
[1] > ExpLine
:
821 def PatternInModifier(Modifier
, SubStr
):
822 PartList
= Modifier
.split()
823 for Part
in PartList
:
828 def GetDataTypeFromModifier(ModifierStr
):
829 MList
= ModifierStr
.split()
832 if M
in EccGlobalData
.gConfig
.ModifierSet
:
834 # remove array suffix
835 if M
.startswith('[') or M
.endswith(']'):
837 ReturnType
+= M
+ ' '
839 ReturnType
= ReturnType
.strip()
840 if len(ReturnType
) == 0:
844 def DiffModifier(Str1
, Str2
):
845 PartList1
= Str1
.split()
846 PartList2
= Str2
.split()
847 if PartList1
== PartList2
:
852 def GetTypedefDict(FullFileName
):
854 Dict
= ComplexTypeDict
.get(FullFileName
)
858 FileID
= GetTableID(FullFileName
)
859 FileTable
= 'Identifier' + str(FileID
)
861 SqlStatement
= """ select Modifier, Name, Value, ID
864 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
865 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
868 for Result
in ResultSet
:
869 if len(Result
[0]) == 0:
870 Dict
[Result
[1]] = Result
[2]
872 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
873 for F
in IncludeFileList
:
874 FileID
= GetTableID(F
)
878 FileTable
= 'Identifier' + str(FileID
)
879 SqlStatement
= """ select Modifier, Name, Value, ID
882 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
883 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
885 for Result
in ResultSet
:
886 if not Result
[2].startswith('FP ('):
887 Dict
[Result
[1]] = Result
[2]
889 if len(Result
[0]) == 0:
890 Dict
[Result
[1]] = 'VOID'
892 Dict
[Result
[1]] = GetDataTypeFromModifier(Result
[0])
894 ComplexTypeDict
[FullFileName
] = Dict
897 def GetSUDict(FullFileName
):
899 Dict
= SUDict
.get(FullFileName
)
903 FileID
= GetTableID(FullFileName
)
904 FileTable
= 'Identifier' + str(FileID
)
906 SqlStatement
= """ select Name, Value, ID
908 where Model = %d or Model = %d
909 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
910 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
913 for Result
in ResultSet
:
914 if len(Result
[1]) > 0:
915 Dict
[Result
[0]] = Result
[1]
917 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
918 for F
in IncludeFileList
:
919 FileID
= GetTableID(F
)
923 FileTable
= 'Identifier' + str(FileID
)
924 SqlStatement
= """ select Name, Value, ID
926 where Model = %d or Model = %d
927 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
928 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
930 for Result
in ResultSet
:
931 if len(Result
[1]) > 0:
932 Dict
[Result
[0]] = Result
[1]
934 SUDict
[FullFileName
] = Dict
937 def StripComments(Str
):
939 ListFromStr
= list(Str
)
942 DoubleSlashComment
= False
944 while Index
< len(ListFromStr
):
945 # meet new line, then no longer in a comment for //
946 if ListFromStr
[Index
] == '\n':
947 if InComment
and DoubleSlashComment
:
949 DoubleSlashComment
= False
951 # check for */ comment end
952 elif InComment
and not DoubleSlashComment
and ListFromStr
[Index
] == '*' and ListFromStr
[Index
+ 1] == '/':
953 ListFromStr
[Index
] = ' '
955 ListFromStr
[Index
] = ' '
958 # set comments to spaces
960 ListFromStr
[Index
] = ' '
962 # check for // comment
963 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '/':
965 DoubleSlashComment
= True
967 # check for /* comment start
968 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '*':
969 ListFromStr
[Index
] = ' '
971 ListFromStr
[Index
] = ' '
977 # restore from List to String
978 Str
= "".join(ListFromStr
)
979 Str
= Str
.rstrip(' ')
983 def GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
):
984 Value
= TypedefDict
.get(Type
)
986 Value
= SUDict
.get(Type
)
990 LBPos
= Value
.find('{')
992 FTList
= Value
.split()
994 if FT
not in ('struct', 'union'):
995 Value
= TypedefDict
.get(FT
)
997 Value
= SUDict
.get(FT
)
1003 LBPos
= Value
.find('{')
1005 # RBPos = Value.find('}')
1006 Fields
= Value
[LBPos
+ 1:]
1007 Fields
= StripComments(Fields
)
1008 FieldsList
= Fields
.split(';')
1009 for Field
in FieldsList
:
1010 Field
= Field
.strip()
1011 Index
= Field
.rfind(FieldName
)
1014 if not Field
[Index
- 1].isalnum():
1015 if Index
+ len(FieldName
) == len(Field
):
1016 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1019 # For the condition that the field in struct is an array with [] suffixes...
1020 if not Field
[Index
+ len(FieldName
)].isalnum():
1021 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1026 def GetRealType(Type
, TypedefDict
, TargetType
=None):
1027 if TargetType
is not None and Type
== TargetType
:
1029 while TypedefDict
.get(Type
):
1030 Type
= TypedefDict
.get(Type
)
1031 if TargetType
is not None and Type
== TargetType
:
1035 def GetTypeInfo(RefList
, Modifier
, FullFileName
, TargetType
=None):
1036 TypedefDict
= GetTypedefDict(FullFileName
)
1037 SUDict
= GetSUDict(FullFileName
)
1038 Type
= GetDataTypeFromModifier(Modifier
).replace('*', '').strip()
1040 Type
= Type
.split()[-1]
1042 while Index
< len(RefList
):
1043 FieldName
= RefList
[Index
]
1044 FromType
= GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
)
1045 if FromType
is None:
1047 # we want to determine the exact type.
1048 if TargetType
is not None:
1049 Type
= FromType
.split()[0]
1050 # we only want to check if it is a pointer
1053 if Type
.find('*') != -1 and Index
== len(RefList
) - 1:
1055 Type
= FromType
.split()[0]
1059 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1063 def GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
=False, TargetType
=None, StarList
=None):
1065 PredVar
= PredVarList
[0]
1066 FileID
= GetTableID(FullFileName
)
1069 FileTable
= 'Identifier' + str(FileID
)
1070 # search variable in include files
1072 # it is a function call, search function declarations and definitions
1074 SqlStatement
= """ select Modifier, ID
1076 where Model = %d and Value = \'%s\'
1077 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1078 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1080 for Result
in ResultSet
:
1081 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1082 TypedefDict
= GetTypedefDict(FullFileName
)
1083 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1086 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1087 for F
in IncludeFileList
:
1088 FileID
= GetTableID(F
)
1092 FileTable
= 'Identifier' + str(FileID
)
1093 SqlStatement
= """ select Modifier, ID
1095 where Model = %d and Value = \'%s\'
1096 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1097 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1099 for Result
in ResultSet
:
1100 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1101 TypedefDict
= GetTypedefDict(FullFileName
)
1102 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1105 FileID
= GetTableID(FullFileName
)
1106 SqlStatement
= """ select Modifier, ID
1108 where BelongsToFile = %d and Name = \'%s\'
1109 """ % (FileID
, PredVar
)
1110 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1112 for Result
in ResultSet
:
1113 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1114 TypedefDict
= GetTypedefDict(FullFileName
)
1115 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1118 for F
in IncludeFileList
:
1119 FileID
= GetTableID(F
)
1123 FileTable
= 'Identifier' + str(FileID
)
1124 SqlStatement
= """ select Modifier, ID
1126 where BelongsToFile = %d and Name = \'%s\'
1127 """ % (FileID
, PredVar
)
1128 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1130 for Result
in ResultSet
:
1131 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1132 TypedefDict
= GetTypedefDict(FullFileName
)
1133 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1138 # really variable, search local variable first
1139 SqlStatement
= """ select Modifier, ID
1141 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1142 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
, FuncRecord
[0], FuncRecord
[1])
1143 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1145 for Result
in ResultSet
:
1146 if len(PredVarList
) > 1:
1147 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1150 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1151 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1153 if len(TypeList
) > 1 and StarList
is not None:
1154 for Star
in StarList
:
1156 Type
= Type
.rstrip(Star
)
1157 # Get real type after de-reference pointers.
1158 if len(Type
.strip()) == 0:
1160 TypedefDict
= GetTypedefDict(FullFileName
)
1161 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1164 # search function parameters second
1165 ParamList
= GetParamList(FuncRecord
[2])
1166 for Param
in ParamList
:
1167 if Param
.Name
.strip() == PredVar
:
1168 if len(PredVarList
) > 1:
1169 Type
= GetTypeInfo(PredVarList
[1:], Param
.Modifier
, FullFileName
, TargetType
)
1172 TypeList
= GetDataTypeFromModifier(Param
.Modifier
).split()
1174 if Type
== '*' and len(TypeList
) >= 2:
1176 if len(TypeList
) > 1 and StarList
is not None:
1177 for Star
in StarList
:
1179 Type
= Type
.rstrip(Star
)
1180 # Get real type after de-reference pointers.
1181 if len(Type
.strip()) == 0:
1183 TypedefDict
= GetTypedefDict(FullFileName
)
1184 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1187 # search global variable next
1188 SqlStatement
= """ select Modifier, ID
1190 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1191 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1192 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1194 for Result
in ResultSet
:
1195 if len(PredVarList
) > 1:
1196 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1199 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1201 if len(TypeList
) > 1 and StarList
is not None:
1202 for Star
in StarList
:
1204 Type
= Type
.rstrip(Star
)
1205 # Get real type after de-reference pointers.
1206 if len(Type
.strip()) == 0:
1208 TypedefDict
= GetTypedefDict(FullFileName
)
1209 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1212 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1213 for F
in IncludeFileList
:
1214 FileID
= GetTableID(F
)
1218 FileTable
= 'Identifier' + str(FileID
)
1219 SqlStatement
= """ select Modifier, ID
1221 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1222 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1223 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1225 for Result
in ResultSet
:
1226 if len(PredVarList
) > 1:
1227 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1230 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1232 if len(TypeList
) > 1 and StarList
is not None:
1233 for Star
in StarList
:
1235 Type
= Type
.rstrip(Star
)
1236 # Get real type after de-reference pointers.
1237 if len(Type
.strip()) == 0:
1239 TypedefDict
= GetTypedefDict(FullFileName
)
1240 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1243 def GetTypeFromArray(Type
, Var
):
1244 Count
= Var
.count('[')
1248 Type
= Type
.rstrip('*')
1253 def CheckFuncLayoutReturnType(FullFileName
):
1256 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1261 FileTable
= 'Identifier' + str(FileID
)
1262 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1265 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1266 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1267 for Result
in ResultSet
:
1268 ReturnType
= GetDataTypeFromModifier(Result
[0])
1269 TypeStart
= ReturnType
.split()[0]
1270 FuncName
= Result
[5]
1271 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1274 if Result0
.upper().startswith('STATIC'):
1275 Result0
= Result0
[6:].strip()
1276 Index
= Result0
.find(TypeStart
)
1277 if Index
!= 0 or Result
[3] != 0:
1278 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1280 if Result
[2] == Result
[4]:
1281 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1283 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1285 where BelongsToFile = %d
1287 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1288 for Result
in ResultSet
:
1289 ReturnType
= GetDataTypeFromModifier(Result
[0])
1290 TypeStart
= ReturnType
.split()[0]
1291 FuncName
= Result
[5]
1292 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1295 if Result0
.upper().startswith('STATIC'):
1296 Result0
= Result0
[6:].strip()
1297 Index
= Result0
.find(TypeStart
)
1298 if Index
!= 0 or Result
[3] != 0:
1299 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1301 def CheckFuncLayoutModifier(FullFileName
):
1304 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1309 FileTable
= 'Identifier' + str(FileID
)
1310 SqlStatement
= """ select Modifier, ID
1313 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1314 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1315 for Result
in ResultSet
:
1316 ReturnType
= GetDataTypeFromModifier(Result
[0])
1317 TypeStart
= ReturnType
.split()[0]
1319 if Result0
.upper().startswith('STATIC'):
1320 Result0
= Result0
[6:].strip()
1321 Index
= Result0
.find(TypeStart
)
1323 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1325 SqlStatement
= """ select Modifier, ID
1327 where BelongsToFile = %d
1329 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1330 for Result
in ResultSet
:
1331 ReturnType
= GetDataTypeFromModifier(Result
[0])
1332 TypeStart
= ReturnType
.split()[0]
1334 if Result0
.upper().startswith('STATIC'):
1335 Result0
= Result0
[6:].strip()
1336 Index
= Result0
.find(TypeStart
)
1338 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1340 def CheckFuncLayoutName(FullFileName
):
1342 # Parameter variable format pattern.
1343 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1344 ParamIgnoreList
= ('VOID', '...')
1345 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1350 FileTable
= 'Identifier' + str(FileID
)
1351 SqlStatement
= """ select Name, ID, EndColumn, Value
1354 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1355 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1356 for Result
in ResultSet
:
1357 FuncName
= Result
[3]
1358 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1361 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1362 ParamList
= GetParamList(Result
[0])
1363 if len(ParamList
) == 0:
1366 for Param
in ParamList
:
1367 if Param
.StartLine
<= StartLine
:
1368 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1369 if Param
.StartLine
- StartLine
> 1:
1370 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1371 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
):
1372 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1373 StartLine
= Param
.StartLine
1375 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1376 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1378 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1380 where BelongsToFile = %d
1382 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1383 for Result
in ResultSet
:
1384 FuncName
= Result
[3]
1385 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1388 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1389 ParamList
= GetParamList(Result
[0])
1390 if len(ParamList
) == 0:
1393 for Param
in ParamList
:
1394 if Param
.StartLine
<= StartLine
:
1395 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1396 if Param
.StartLine
- StartLine
> 1:
1397 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1398 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
):
1399 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1400 StartLine
= Param
.StartLine
1401 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1402 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1404 def CheckFuncLayoutPrototype(FullFileName
):
1407 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1411 FileTable
= 'Identifier' + str(FileID
)
1413 SqlStatement
= """ select Modifier, Header, Name, ID
1415 where BelongsToFile = %d
1417 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1418 if len(ResultSet
) == 0:
1422 for Result
in ResultSet
:
1423 FuncDefList
.append(Result
)
1425 SqlStatement
= """ select Modifier, Name, ID
1428 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1429 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1431 for Result
in ResultSet
:
1432 FuncDeclList
.append(Result
)
1435 for FuncDef
in FuncDefList
:
1436 FuncName
= FuncDef
[2].strip()
1437 FuncModifier
= FuncDef
[0]
1438 FuncDefHeader
= FuncDef
[1]
1439 for FuncDecl
in FuncDeclList
:
1440 LBPos
= FuncDecl
[1].find('(')
1441 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1442 DeclModifier
= FuncDecl
[0]
1443 if DeclName
== FuncName
:
1444 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1445 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1446 ParamListOfDef
= GetParamList(FuncDefHeader
)
1447 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1448 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1449 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1453 while Index
< len(ParamListOfDef
):
1454 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1455 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, 'Parameter %s has different modifier with prototype in function [%s].' % (ParamListOfDef
[Index
].Name
, FuncName
), 'Function', FuncDef
[3])
1459 UndeclFuncList
.append(FuncDef
)
1461 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1463 for F
in IncludeFileList
:
1464 FileID
= GetTableID(F
, ErrorMsgList
)
1468 FileTable
= 'Identifier' + str(FileID
)
1469 SqlStatement
= """ select Modifier, Name, ID
1472 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1473 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1475 for Result
in ResultSet
:
1476 FuncDeclList
.append(Result
)
1478 for FuncDef
in UndeclFuncList
:
1479 FuncName
= FuncDef
[2].strip()
1480 FuncModifier
= FuncDef
[0]
1481 FuncDefHeader
= FuncDef
[1]
1482 for FuncDecl
in FuncDeclList
:
1483 LBPos
= FuncDecl
[1].find('(')
1484 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1485 DeclModifier
= FuncDecl
[0]
1486 if DeclName
== FuncName
:
1487 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1488 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1489 ParamListOfDef
= GetParamList(FuncDefHeader
)
1490 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1491 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1492 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1496 while Index
< len(ParamListOfDef
):
1497 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1498 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, 'Parameter %s has different modifier with prototype in function [%s].' % (ParamListOfDef
[Index
].Name
, FuncName
), 'Function', FuncDef
[3])
1502 def CheckFuncLayoutBody(FullFileName
):
1505 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1509 FileTable
= 'Identifier' + str(FileID
)
1511 SqlStatement
= """ select BodyStartColumn, EndColumn, ID, Name
1513 where BelongsToFile = %d
1515 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1516 if len(ResultSet
) == 0:
1518 for Result
in ResultSet
:
1520 if not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, Result
[3]):
1521 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
,
1522 'The open brace should be at the very beginning of a line for the function [%s].' % Result
[3],
1523 'Function', Result
[2])
1525 if not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, Result
[3]):
1526 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
,
1527 'The close brace should be at the very beginning of a line for the function [%s].' % Result
[3],
1528 'Function', Result
[2])
1530 def CheckFuncLayoutLocalVariable(FullFileName
):
1533 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1538 FileTable
= 'Identifier' + str(FileID
)
1539 SqlStatement
= """ select ID
1541 where BelongsToFile = %d
1543 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1544 if len(ResultSet
) == 0:
1547 for Result
in ResultSet
:
1551 SqlStatement
= """ select Name, Value, ID, Modifier
1553 where Model = %d and BelongsToFunction = %d
1554 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1555 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1556 if len(ResultSet
) == 0:
1559 for Result
in ResultSet
:
1560 if len(Result
[1]) > 0 and 'CONST' not in Result
[3]:
1561 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1563 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1565 # Member variable format pattern.
1566 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1568 LBPos
= Value
.find('{')
1569 RBPos
= Value
.rfind('}')
1570 if LBPos
== -1 or RBPos
== -1:
1573 Fields
= Value
[LBPos
+ 1 : RBPos
]
1574 Fields
= StripComments(Fields
).strip()
1575 NestPos
= Fields
.find ('struct')
1576 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)) and ModelId
!= DataClass
.MODEL_IDENTIFIER_UNION
:
1577 if not Fields
[NestPos
+ len('struct') + 1].isalnum():
1578 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1579 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested struct in [%s].' % (Name
), FileTable
, TdId
)
1581 NestPos
= Fields
.find ('union')
1582 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1583 if not Fields
[NestPos
+ len('union') + 1].isalnum():
1584 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1585 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested union in [%s].' % (Name
), FileTable
, TdId
)
1587 NestPos
= Fields
.find ('enum')
1588 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1589 if not Fields
[NestPos
+ len('enum') + 1].isalnum():
1590 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1591 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested enum in [%s].' % (Name
), FileTable
, TdId
)
1594 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1595 FieldsList
= Fields
.split(',')
1596 # deal with enum is pre-assigned a value by function call ( , , , ...)
1599 RemoveCurrentElement
= False
1600 while Index
< len(FieldsList
):
1601 Field
= FieldsList
[Index
]
1603 if Field
.find('(') != -1:
1605 RemoveCurrentElement
= True
1609 if Field
.find(')') != -1 and QuoteCount
> 0:
1612 if RemoveCurrentElement
:
1613 FieldsList
.remove(Field
)
1615 RemoveCurrentElement
= False
1619 RemoveCurrentElement
= False
1623 FieldsList
= Fields
.split(';')
1625 for Field
in FieldsList
:
1626 Field
= Field
.strip()
1629 # For the condition that the field in struct is an array with [] suffixes...
1630 if Field
[-1] == ']':
1631 LBPos
= Field
.find('[')
1632 Field
= Field
[0:LBPos
]
1633 # For the condition that bit field ": Number"
1634 if Field
.find(':') != -1:
1635 ColonPos
= Field
.find(':')
1636 Field
= Field
[0:ColonPos
]
1638 Field
= Field
.strip()
1641 if Field
.startswith("#"):
1643 # Enum could directly assign value to variable
1644 Field
= Field
.split('=')[0].strip()
1645 TokenList
= Field
.split()
1646 # Remove pointers before variable
1647 Token
= TokenList
[-1]
1648 if Token
in ['OPTIONAL']:
1649 Token
= TokenList
[-2]
1650 if not Pattern
.match(Token
.lstrip('*')):
1651 ErrMsgList
.append(Token
.lstrip('*'))
1655 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1658 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1663 FileTable
= 'Identifier' + str(FileID
)
1664 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1667 """ % (FileTable
, ModelId
)
1668 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1670 for Result
in ResultSet
:
1671 ResultList
.append(Result
)
1673 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1674 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1675 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1676 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1677 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1678 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1679 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1681 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1684 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1685 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1689 # Check member variable name format that from typedefs of ONLY this file.
1691 Name
= Td
[1].strip()
1692 Value
= Td
[2].strip()
1693 if Value
.startswith('enum'):
1694 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1695 elif Value
.startswith('struct'):
1696 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1697 elif Value
.startswith('union'):
1698 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1702 if ValueModelId
!= ModelId
:
1704 # Check member variable format.
1705 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1706 for ErrMsg
in ErrMsgList
:
1707 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+ '.' + ErrMsg
):
1709 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+ '.' + ErrMsg
), FileTable
, Td
[5])
1711 # First check in current file to see whether struct/union/enum is typedef-ed.
1712 UntypedefedList
= []
1713 for Result
in ResultList
:
1714 # Check member variable format.
1715 Name
= Result
[0].strip()
1716 Value
= Result
[4].strip()
1717 if Value
.startswith('enum'):
1718 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1719 elif Value
.startswith('struct'):
1720 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1721 elif Value
.startswith('union'):
1722 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1726 if ValueModelId
!= ModelId
:
1728 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1729 for ErrMsg
in ErrMsgList
:
1730 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0] + '.' + ErrMsg
):
1732 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0] + '.' + ErrMsg
), FileTable
, Result
[3])
1733 # Check whether it is typedefed.
1736 # skip function pointer
1739 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1741 if not Td
[1].isupper():
1742 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1743 if Result
[0] in Td
[2].split():
1745 if not Td
[1].isupper():
1746 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1751 UntypedefedList
.append(Result
)
1754 if len(UntypedefedList
) == 0:
1757 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1759 for F
in IncludeFileList
:
1760 FileID
= GetTableID(F
, ErrorMsgList
)
1764 IncludeFileTable
= 'Identifier' + str(FileID
)
1765 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1768 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1769 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1770 TdList
.extend(ResultSet
)
1772 for Result
in UntypedefedList
:
1774 # Check whether it is typedefed.
1780 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1782 if not Td
[1].isupper():
1783 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1784 if Result
[0] in Td
[2].split():
1786 if not Td
[1].isupper():
1787 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1792 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1795 def CheckDeclStructTypedef(FullFileName
):
1796 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1798 def CheckDeclEnumTypedef(FullFileName
):
1799 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1801 def CheckDeclUnionTypedef(FullFileName
):
1802 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1804 def CheckDeclArgModifier(FullFileName
):
1807 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1812 FileTable
= 'Identifier' + str(FileID
)
1813 SqlStatement
= """ select Modifier, Name, ID
1816 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1817 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1818 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1819 MAX_MODIFIER_LENGTH
= 100
1820 for Result
in ResultSet
:
1821 for Modifier
in ModifierTuple
:
1822 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1823 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1826 SqlStatement
= """ select Modifier, Name, ID
1829 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1830 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1831 for Result
in ResultSet
:
1832 for Modifier
in ModifierTuple
:
1833 if PatternInModifier(Result
[0], Modifier
):
1834 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1837 SqlStatement
= """ select Modifier, Header, ID
1839 where BelongsToFile = %d
1841 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1842 for Result
in ResultSet
:
1843 for Modifier
in ModifierTuple
:
1844 if PatternInModifier(Result
[0], Modifier
):
1845 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1848 def CheckDeclNoUseCType(FullFileName
):
1851 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1856 FileTable
= 'Identifier' + str(FileID
)
1857 SqlStatement
= """ select Modifier, Name, ID
1860 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1861 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1862 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1863 for Result
in ResultSet
:
1864 for Type
in CTypeTuple
:
1865 if PatternInModifier(Result
[0], Type
):
1866 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1867 Result
[0] + ' ' + Result
[1]):
1869 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1870 'Invalid variable type (%s) in definition [%s]' % (Type
, Result
[0] + ' ' + Result
[1]),
1875 SqlStatement
= """ select Modifier, Name, ID, Value
1878 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1879 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1880 for Result
in ResultSet
:
1881 ParamList
= GetParamList(Result
[1])
1882 FuncName
= Result
[3]
1883 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1885 for Type
in CTypeTuple
:
1886 if PatternInModifier(Result
[0], Type
):
1887 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1889 for Param
in ParamList
:
1890 if PatternInModifier(Param
.Modifier
, Type
):
1891 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1893 SqlStatement
= """ select Modifier, Header, ID, Name
1895 where BelongsToFile = %d
1897 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1898 for Result
in ResultSet
:
1899 ParamList
= GetParamList(Result
[1])
1900 FuncName
= Result
[3]
1901 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1903 for Type
in CTypeTuple
:
1904 if PatternInModifier(Result
[0], Type
):
1905 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1907 for Param
in ParamList
:
1908 if PatternInModifier(Param
.Modifier
, Type
):
1909 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1912 def CheckPointerNullComparison(FullFileName
):
1915 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1919 # cache the found function return type to accelerate later checking in this file.
1920 FuncReturnTypeDict
= {}
1923 FileTable
= 'Identifier' + str(FileID
)
1924 SqlStatement
= """ select Value, StartLine, ID
1927 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1928 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1929 if len(ResultSet
) == 0:
1932 for Result
in ResultSet
:
1933 PSL
.append([Result
[0], Result
[1], Result
[2]])
1935 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1937 where BelongsToFile = %d
1939 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1941 for Result
in ResultSet
:
1942 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1944 p
= GetFuncDeclPattern()
1946 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1947 if FuncRecord
is None:
1950 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1951 PredInfo
= SplitPredicateStr(Exp
)
1952 if PredInfo
[1] is None:
1953 PredVarStr
= PredInfo
[0][0].strip()
1955 SearchInCache
= False
1956 # PredVarStr may contain '.' or '->'
1957 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1959 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1960 SearchInCache
= True
1961 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1962 if TmpStr
.startswith(PredVarStr
):
1965 if PredVarStr
.strip() in IgnoredKeywordList
:
1968 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1969 # No variable found, maybe value first? like (0 == VarName)
1970 if len(PredVarList
) == 0:
1973 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1974 if Type
is not None:
1975 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1976 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1979 if PredVarStr
in FuncReturnTypeDict
:
1982 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1984 FuncReturnTypeDict
[PredVarStr
] = Type
1987 Type
= GetTypeFromArray(Type
, PredVarStr
)
1988 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1989 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1991 def CheckNonBooleanValueComparison(FullFileName
):
1994 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1998 # cache the found function return type to accelerate later checking in this file.
1999 FuncReturnTypeDict
= {}
2002 FileTable
= 'Identifier' + str(FileID
)
2003 SqlStatement
= """ select Value, StartLine, ID
2006 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2007 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2008 if len(ResultSet
) == 0:
2011 for Result
in ResultSet
:
2012 PSL
.append([Result
[0], Result
[1], Result
[2]])
2014 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2016 where BelongsToFile = %d
2018 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2020 for Result
in ResultSet
:
2021 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2023 p
= GetFuncDeclPattern()
2025 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2026 if FuncRecord
is None:
2029 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2030 PredInfo
= SplitPredicateStr(Exp
)
2031 if PredInfo
[1] is None:
2032 PredVarStr
= PredInfo
[0][0].strip()
2034 SearchInCache
= False
2035 # PredVarStr may contain '.' or '->'
2036 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2038 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2039 SearchInCache
= True
2040 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2041 if TmpStr
.startswith(PredVarStr
):
2044 if PredVarStr
.strip() in IgnoredKeywordList
:
2047 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2048 # No variable found, maybe value first? like (0 == VarName)
2049 if len(PredVarList
) == 0:
2053 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2054 if Type
is not None:
2055 if Type
.find('BOOLEAN') == -1:
2056 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2059 if PredVarStr
in FuncReturnTypeDict
:
2061 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2063 FuncReturnTypeDict
[PredVarStr
] = Type
2066 if Type
.find('BOOLEAN') == -1:
2067 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2070 def CheckBooleanValueComparison(FullFileName
):
2073 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2077 # cache the found function return type to accelerate later checking in this file.
2078 FuncReturnTypeDict
= {}
2081 FileTable
= 'Identifier' + str(FileID
)
2082 SqlStatement
= """ select Value, StartLine, ID
2085 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2086 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2087 if len(ResultSet
) == 0:
2090 for Result
in ResultSet
:
2091 PSL
.append([Result
[0], Result
[1], Result
[2]])
2093 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2095 where BelongsToFile = %d
2097 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2099 for Result
in ResultSet
:
2100 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2102 p
= GetFuncDeclPattern()
2104 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2105 if FuncRecord
is None:
2108 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2109 PredInfo
= SplitPredicateStr(Exp
)
2110 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2111 PredVarStr
= PredInfo
[0][0].strip()
2113 SearchInCache
= False
2114 # PredVarStr may contain '.' or '->'
2115 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2117 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2118 SearchInCache
= True
2119 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2120 if TmpStr
.startswith(PredVarStr
):
2123 if PredVarStr
.strip() in IgnoredKeywordList
:
2126 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2127 # No variable found, maybe value first? like (0 == VarName)
2128 if len(PredVarList
) == 0:
2132 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2133 if Type
is not None:
2134 if Type
.find('BOOLEAN') != -1:
2135 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2138 if PredVarStr
in FuncReturnTypeDict
:
2141 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2143 FuncReturnTypeDict
[PredVarStr
] = Type
2146 if Type
.find('BOOLEAN') != -1:
2147 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2150 def CheckHeaderFileData(FullFileName
, AllTypedefFun
=[]):
2153 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2158 FileTable
= 'Identifier' + str(FileID
)
2159 SqlStatement
= """ select ID, Modifier
2162 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2163 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2164 for Result
in ResultSet
:
2165 if not Result
[1].startswith('extern'):
2166 for Item
in AllTypedefFun
:
2167 if '(%s)' % Result
[1] in Item
:
2170 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2172 SqlStatement
= """ select ID
2174 where BelongsToFile = %d
2176 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2177 for Result
in ResultSet
:
2178 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2182 def CheckHeaderFileIfndef(FullFileName
):
2185 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2190 FileTable
= 'Identifier' + str(FileID
)
2191 SqlStatement
= """ select Value, StartLine
2193 where Model = %d order by StartLine
2194 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2195 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2196 if len(ResultSet
) == 0:
2197 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2199 for Result
in ResultSet
:
2200 SqlStatement
= """ select Value, EndLine
2203 """ % (FileTable
, Result
[1])
2204 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2205 for Result
in ResultSet
:
2206 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2207 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2
, '', 'File', FileID
)
2210 SqlStatement
= """ select Value
2212 where StartLine > (select max(EndLine) from %s where Model = %d)
2213 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2214 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2215 for Result
in ResultSet
:
2216 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2217 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2220 def CheckDoxygenCommand(FullFileName
):
2223 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2228 FileTable
= 'Identifier' + str(FileID
)
2229 SqlStatement
= """ select Value, ID
2231 where Model = %d or Model = %d
2232 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2233 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2234 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval',
2235 'return', 'sa', 'since', 'test', 'note', 'par', 'endcode', 'code']
2236 for Result
in ResultSet
:
2237 CommentStr
= Result
[0]
2238 CommentPartList
= CommentStr
.split()
2239 for Part
in CommentPartList
:
2240 if Part
.upper() == 'BUGBUG':
2241 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2242 if Part
.upper() == 'TODO':
2243 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2244 if Part
.startswith('@'):
2245 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2247 if not Part
.replace('@', '').strip():
2249 if Part
.lstrip('@') in ['{', '}']:
2251 if Part
.lstrip('@').isalpha():
2252 if Part
.lstrip('@') not in DoxygenCommandList
:
2253 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2255 Index
= Part
.find('[')
2257 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2258 RealCmd
= Part
[1:Index
]
2259 if RealCmd
not in DoxygenCommandList
:
2260 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2263 def CheckDoxygenTripleForwardSlash(FullFileName
):
2266 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2272 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2274 where BelongsToFile = %d
2276 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2277 if len(ResultSet
) == 0:
2281 for Result
in ResultSet
:
2282 FuncDefSet
.append(Result
)
2285 FileTable
= 'Identifier' + str(FileID
)
2286 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2290 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2291 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2294 for Result
in ResultSet
:
2295 CommentSet
.append(Result
)
2297 print('Unrecognized chars in comment of file %s', FullFileName
)
2300 for Result
in CommentSet
:
2301 CommentStr
= Result
[0]
2302 StartLine
= Result
[2]
2303 StartColumn
= Result
[3]
2305 EndColumn
= Result
[5]
2306 if not CommentStr
.startswith('///<'):
2310 for FuncDef
in FuncDefSet
:
2311 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2314 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2317 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2320 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2324 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2327 def CheckFileHeaderDoxygenComments(FullFileName
):
2330 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2335 FileTable
= 'Identifier' + str(FileID
)
2336 SqlStatement
= """ select Value, ID
2338 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2339 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2340 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2341 if len(ResultSet
) == 0:
2342 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No File License header appear at the very beginning of file.', 'File', FileID
)
2345 NoHeaderCommentStartFlag
= True
2346 NoHeaderCommentEndFlag
= True
2347 NoHeaderCommentPeriodFlag
= True
2348 NoCopyrightFlag
= True
2349 NoLicenseFlag
= True
2350 NoRevReferFlag
= True
2352 for Result
in ResultSet
:
2353 FileStartFlag
= False
2355 CommentStr
= Result
[0].strip()
2356 CommentStrListTemp
= CommentStr
.split('\n')
2357 if (len(CommentStrListTemp
) <= 1):
2359 CommentStrListTemp
= CommentStr
.split('\r')
2360 # Skip the content before the file header
2361 for CommentLine
in CommentStrListTemp
:
2362 if CommentLine
.strip().startswith('/** @file'):
2363 FileStartFlag
= True
2364 if FileStartFlag
== True:
2365 CommentStrList
.append(CommentLine
)
2369 if CommentStrList
and CommentStrList
[0].strip().startswith('/** @file'):
2370 NoHeaderCommentStartFlag
= False
2373 if CommentStrList
and CommentStrList
[-1].strip().endswith('**/'):
2374 NoHeaderCommentEndFlag
= False
2378 for CommentLine
in CommentStrList
:
2380 NextLineIndex
= Index
2381 if CommentLine
.startswith('/** @file'):
2383 if CommentLine
.startswith('**/'):
2385 # Check whether C File header Comment content start with two spaces.
2386 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentStartSpacesNum
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2387 if CommentLine
.startswith('/** @file') == False and CommentLine
.startswith('**/') == False and CommentLine
.strip() and CommentLine
.startswith(' ') == False:
2388 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment content should start with two spaces at each line', FileTable
, ID
)
2390 CommentLine
= CommentLine
.strip()
2391 if CommentLine
.startswith('Copyright') or ('Copyright' in CommentLine
and CommentLine
.lower().startswith('(c)')):
2392 NoCopyrightFlag
= False
2393 if CommentLine
.find('All rights reserved') == -1:
2394 for Copyright
in EccGlobalData
.gConfig
.Copyright
:
2395 if CommentLine
.find(Copyright
) > -1:
2396 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable
, ID
)
2398 if CommentLine
.endswith('<BR>') == -1:
2399 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'The ""<BR>"" at the end of the Copyright line is required', FileTable
, ID
)
2400 if NextLineIndex
< len(CommentStrList
) and CommentStrList
[NextLineIndex
].strip().startswith('Copyright') == False and CommentStrList
[NextLineIndex
].strip():
2401 NoLicenseFlag
= False
2402 if CommentLine
.startswith('@par Revision Reference:'):
2403 NoRevReferFlag
= False
2405 for RefLine
in CommentStrList
[NextLineIndex
:]:
2406 if RefLine
.strip() and (NextLineIndex
+ 1) < len(CommentStrList
) and CommentStrList
[NextLineIndex
+1].strip() and CommentStrList
[NextLineIndex
+1].strip().startswith('**/') == False:
2408 if RefLine
.strip() == False or RefLine
.strip().startswith('**/'):
2411 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2412 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentReferenceFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2413 if RefListFlag
== True:
2414 if RefLine
.strip() and RefLine
.strip().startswith('**/') == False and RefLine
.startswith(' -') == False:
2415 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable
, ID
)
2417 if NoHeaderCommentStartFlag
:
2418 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, ID
)
2420 if NoHeaderCommentEndFlag
:
2421 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with ""**/""', FileTable
, ID
)
2424 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment missing the ""Copyright""', FileTable
, ID
)
2425 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2426 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentLicenseFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2428 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable
, ID
)
2430 def CheckFuncHeaderDoxygenComments(FullFileName
):
2433 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2438 FileTable
= 'Identifier' + str(FileID
)
2439 SqlStatement
= """ select Value, StartLine, EndLine, ID
2442 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2444 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2447 for Result
in ResultSet
:
2448 CommentSet
.append(Result
)
2450 print('Unrecognized chars in comment of file %s', FullFileName
)
2453 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2456 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2457 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2458 for Result
in ResultSet
:
2459 FuncName
= Result
[4]
2460 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2461 if FunctionHeaderComment
:
2462 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2464 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2466 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2467 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2470 SqlStatement
= """ select Value, StartLine, EndLine, ID
2473 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2475 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2478 for Result
in ResultSet
:
2479 CommentSet
.append(Result
)
2481 print('Unrecognized chars in comment of file %s', FullFileName
)
2483 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2485 where BelongsToFile = %d
2487 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2488 for Result
in ResultSet
:
2489 FuncName
= Result
[4]
2490 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2491 if FunctionHeaderComment
:
2492 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2494 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2496 ErrorMsgList
.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2497 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), 'Function', Result
[3])
2500 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2502 for Comment
in CommentSet
:
2503 if Comment
[2] == FuncStartLine
- 1:
2507 def GetDoxygenStrFromComment(Str
):
2509 ParamTagList
= Str
.split('@param')
2510 if len(ParamTagList
) > 1:
2512 while i
< len(ParamTagList
):
2513 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2516 Str
= ParamTagList
[0]
2518 RetvalTagList
= ParamTagList
[-1].split('@retval')
2519 if len(RetvalTagList
) > 1:
2520 if len(ParamTagList
) > 1:
2521 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2523 while i
< len(RetvalTagList
):
2524 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2527 ReturnTagList
= RetvalTagList
[-1].split('@return')
2528 if len(ReturnTagList
) > 1:
2529 if len(RetvalTagList
) > 1:
2530 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2531 elif len(ParamTagList
) > 1:
2532 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2534 while i
< len(ReturnTagList
):
2535 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2538 if len(DoxygenStrList
) > 0:
2539 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2541 return DoxygenStrList
2543 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2544 #/** --*/ @retval after @param
2545 if not Str
.startswith('/**'):
2546 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2547 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2548 if not Str
.endswith('**/'):
2549 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2550 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2551 FirstRetvalIndex
= Str
.find('@retval')
2552 LastParamIndex
= Str
.rfind('@param')
2553 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2554 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2555 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2557 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2559 ParamList
= GetParamList(FuncHeader
)
2560 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2561 DescriptionStr
= CommentStr
2562 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2563 if DescriptionStr
.find('.') == -1:
2564 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2565 DoxygenTagNumber
= len(DoxygenStrList
)
2566 ParamNumber
= len(ParamList
)
2567 for Param
in ParamList
:
2568 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2571 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2572 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2573 ParamModifier
= ParamList
[Index
].Modifier
2574 ParamName
= ParamList
[Index
].Name
.strip()
2575 Tag
= DoxygenStrList
[Index
].strip(' ')
2576 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2577 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2578 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, <%s> does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2579 TagPartList
= Tag
.split()
2580 if len(TagPartList
) < 2:
2581 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2582 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2585 LBPos
= Tag
.find('[')
2586 RBPos
= Tag
.find(']')
2587 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2588 if LBPos
> 0 and len(ParamToLBContent
) == 0 and RBPos
> LBPos
:
2590 ModifierPartList
= ParamModifier
.split()
2591 for Part
in ModifierPartList
:
2592 if Part
.strip() == 'IN':
2594 if Part
.strip() == 'OUT':
2601 if Tag
.find('[' + InOutStr
+ ']') == -1:
2602 if InOutStr
!= 'in, out':
2603 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2604 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2606 if Tag
.find('[in,out]') == -1:
2607 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2608 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2611 if Tag
.find(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2612 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2613 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
)
2616 if Index
< ParamNumber
:
2617 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2618 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2619 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2620 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2622 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2623 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2624 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2625 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2627 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2628 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2629 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2631 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
2632 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2633 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need NO doxygen tags in comment ', TableName
, CommentId
)
2634 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2635 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2636 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2638 if __name__
== '__main__':
2640 # EdkLogger.Initialize()
2641 # EdkLogger.SetLevel(EdkLogger.QUIET)
2642 # CollectSourceCodeDataIntoDB(sys.argv[1])
2644 test_file
= sys
.argv
[1]
2645 except IndexError as v
:
2646 print("Usage: %s filename" % sys
.argv
[0])
2648 MsgList
= CheckFuncHeaderDoxygenComments(test_file
)