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
= []
499 for dirpath
, dirnames
, filenames
in tuple:
500 if IgnoredPattern
.match(dirpath
.upper()):
504 Dirname
= os
.path
.join(dirpath
, Dir
)
505 if os
.path
.islink(Dirname
):
506 Dirname
= os
.path
.realpath(Dirname
)
507 if os
.path
.isdir(Dirname
):
508 # symlinks to directories are treated as directories
510 dirnames
.append(Dirname
)
513 if f
.lower() in EccGlobalData
.gConfig
.SkipFileList
:
516 FullName
= os
.path
.normpath(os
.path
.join(dirpath
, f
))
517 model
= DataClass
.MODEL_FILE_OTHERS
518 if os
.path
.splitext(f
)[1] in ('.h', '.c'):
519 EdkLogger
.info("Parsing " + FullName
)
520 model
= f
.endswith('c') and DataClass
.MODEL_FILE_C
or DataClass
.MODEL_FILE_H
521 collector
= CodeFragmentCollector
.CodeFragmentCollector(FullName
)
523 collector
.ParseFile()
525 ParseErrorFileList
.append(FullName
)
526 collector
.CleanFileProfileBuffer()
527 collector
.ParseFileWithClearedPPDirective()
528 # collector.PrintFragments()
529 BaseName
= os
.path
.basename(f
)
530 DirName
= os
.path
.dirname(FullName
)
531 Ext
= os
.path
.splitext(f
)[1].lstrip('.')
532 ModifiedTime
= os
.path
.getmtime(FullName
)
533 FileObj
= DataClass
.FileClass(-1, BaseName
, Ext
, DirName
, FullName
, model
, ModifiedTime
, GetFunctionList(), GetIdentifierList(), [])
534 FileObjList
.append(FileObj
)
536 collector
.CleanFileProfileBuffer()
538 if len(ParseErrorFileList
) > 0:
539 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
542 for file in FileObjList
:
543 if file.ExtName
.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
544 Db
.InsertOneFile(file)
546 Db
.UpdateIdentifierBelongsToFunction()
548 def GetTableID(FullFileName
, ErrorMsgList
=None):
549 if ErrorMsgList
is None:
553 SqlStatement
= """ select ID
555 where FullPath like '%s'
557 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
560 for Result
in ResultSet
:
562 ErrorMsgList
.append('Duplicate file ID found in DB for file %s' % FullFileName
)
566 ErrorMsgList
.append('NO file ID found in DB for file %s' % FullFileName
)
570 def GetIncludeFileList(FullFileName
):
571 if os
.path
.splitext(FullFileName
)[1].upper() not in ('.H'):
573 IFList
= IncludeFileListDict
.get(FullFileName
)
574 if IFList
is not None:
577 FileID
= GetTableID(FullFileName
)
582 FileTable
= 'Identifier' + str(FileID
)
583 SqlStatement
= """ select Value
586 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_INCLUDE
)
587 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
588 IncludeFileListDict
[FullFileName
] = ResultSet
591 def GetFullPathOfIncludeFile(Str
, IncludePathList
):
592 for IncludePath
in IncludePathList
:
593 FullPath
= os
.path
.join(IncludePath
, Str
)
594 FullPath
= os
.path
.normpath(FullPath
)
595 if os
.path
.exists(FullPath
):
599 def GetAllIncludeFiles(FullFileName
):
600 if AllIncludeFileListDict
.get(FullFileName
) is not None:
601 return AllIncludeFileListDict
.get(FullFileName
)
603 FileDirName
= os
.path
.dirname(FullFileName
)
604 IncludePathList
= IncludePathListDict
.get(FileDirName
)
605 if IncludePathList
is None:
606 IncludePathList
= MetaDataParser
.GetIncludeListOfFile(EccGlobalData
.gWorkspace
, FullFileName
, GetDB())
607 if FileDirName
not in IncludePathList
:
608 IncludePathList
.insert(0, FileDirName
)
609 IncludePathListDict
[FileDirName
] = IncludePathList
610 IncludeFileQueue
= []
611 for IncludeFile
in GetIncludeFileList(FullFileName
):
612 FileName
= IncludeFile
[0].lstrip('#').strip()
613 FileName
= FileName
.lstrip('include').strip()
614 FileName
= FileName
.strip('\"')
615 FileName
= FileName
.lstrip('<').rstrip('>').strip()
616 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
617 if FullPath
is not None:
618 IncludeFileQueue
.append(FullPath
)
621 while i
< len(IncludeFileQueue
):
622 for IncludeFile
in GetIncludeFileList(IncludeFileQueue
[i
]):
623 FileName
= IncludeFile
[0].lstrip('#').strip()
624 FileName
= FileName
.lstrip('include').strip()
625 FileName
= FileName
.strip('\"')
626 FileName
= FileName
.lstrip('<').rstrip('>').strip()
627 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
628 if FullPath
is not None and FullPath
not in IncludeFileQueue
:
629 IncludeFileQueue
.insert(i
+ 1, FullPath
)
632 AllIncludeFileListDict
[FullFileName
] = IncludeFileQueue
633 return IncludeFileQueue
635 def GetPredicateListFromPredicateExpStr(PES
):
642 p
= GetFuncDeclPattern()
643 while i
< len(PES
) - 1:
644 if (PES
[i
].isalnum() or PES
[i
] == '_' or PES
[i
] == '*') and LogicOpPos
> PredicateBegin
:
646 if (PES
[i
] == '&' and PES
[i
+ 1] == '&') or (PES
[i
] == '|' and PES
[i
+ 1] == '|'):
648 Exp
= PES
[PredicateBegin
:i
].strip()
649 # Exp may contain '.' or '->'
650 TmpExp
= Exp
.replace('.', '').replace('->', '')
652 PredicateList
.append(Exp
)
654 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
657 if PredicateBegin
> LogicOpPos
:
658 while PredicateBegin
< len(PES
):
659 if PES
[PredicateBegin
].isalnum() or PES
[PredicateBegin
] == '_' or PES
[PredicateBegin
] == '*':
662 Exp
= PES
[PredicateBegin
:len(PES
)].strip()
663 # Exp may contain '.' or '->'
664 TmpExp
= Exp
.replace('.', '').replace('->', '')
666 PredicateList
.append(Exp
)
668 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
671 def GetCNameList(Lvalue
, StarList
=[]):
679 while SearchBegin
< len(Lvalue
):
680 while i
< len(Lvalue
):
681 if Lvalue
[i
].isalnum() or Lvalue
[i
] == '_':
687 VarList
.append(Lvalue
[VarStart
:VarEnd
+ 1])
691 if VarStart
== -1 and Lvalue
[i
] == '*':
698 DotIndex
= Lvalue
[VarEnd
:].find('.')
699 ArrowIndex
= Lvalue
[VarEnd
:].find('->')
700 if DotIndex
== -1 and ArrowIndex
== -1:
702 elif DotIndex
== -1 and ArrowIndex
!= -1:
703 SearchBegin
= VarEnd
+ ArrowIndex
704 elif ArrowIndex
== -1 and DotIndex
!= -1:
705 SearchBegin
= VarEnd
+ DotIndex
707 SearchBegin
= VarEnd
+ ((DotIndex
< ArrowIndex
) and DotIndex
or ArrowIndex
)
715 def SplitPredicateByOp(Str
, Op
, IsFuncCalling
=False):
724 while Index
< len(Str
):
725 while not LBFound
and Str
[Index
] != '_' and not Str
[Index
].isalnum():
728 while not LBFound
and (Str
[Index
].isalnum() or Str
[Index
] == '_'):
730 # maybe type-cast at the beginning, skip it.
731 RemainingStr
= Str
[Index
:].lstrip()
732 if RemainingStr
.startswith(')') and not LBFound
:
736 if RemainingStr
.startswith('(') and not LBFound
:
739 if Str
[Index
] == '(':
740 UnmatchedLBCount
+= 1
744 if Str
[Index
] == ')':
745 UnmatchedLBCount
-= 1
747 if UnmatchedLBCount
== 0:
753 if UnmatchedLBCount
> 0:
756 IndexInRemainingStr
= Str
[Index
:].find(Op
)
757 if IndexInRemainingStr
== -1:
760 Name
= Str
[0:Index
+ IndexInRemainingStr
].strip()
761 Value
= Str
[Index
+ IndexInRemainingStr
+ len(Op
):].strip().strip(')')
764 TmpStr
= Str
.rstrip(';').rstrip(')')
766 Index
= TmpStr
.rfind(Op
)
770 if Str
[Index
- 1].isalnum() or Str
[Index
- 1].isspace() or Str
[Index
- 1] == ')' or Str
[Index
- 1] == ']':
771 Name
= Str
[0:Index
].strip()
772 Value
= Str
[Index
+ len(Op
):].strip()
775 TmpStr
= Str
[0:Index
- 1]
777 def SplitPredicateStr(Str
):
779 Str
= Str
.lstrip('(')
780 IsFuncCalling
= False
781 p
= GetFuncDeclPattern()
782 TmpStr
= Str
.replace('.', '').replace('->', '')
786 PredPartList
= SplitPredicateByOp(Str
, '==', IsFuncCalling
)
787 if len(PredPartList
) > 1:
788 return [PredPartList
, '==']
790 PredPartList
= SplitPredicateByOp(Str
, '!=', IsFuncCalling
)
791 if len(PredPartList
) > 1:
792 return [PredPartList
, '!=']
794 PredPartList
= SplitPredicateByOp(Str
, '>=', IsFuncCalling
)
795 if len(PredPartList
) > 1:
796 return [PredPartList
, '>=']
798 PredPartList
= SplitPredicateByOp(Str
, '<=', IsFuncCalling
)
799 if len(PredPartList
) > 1:
800 return [PredPartList
, '<=']
802 PredPartList
= SplitPredicateByOp(Str
, '>', IsFuncCalling
)
803 if len(PredPartList
) > 1:
804 return [PredPartList
, '>']
806 PredPartList
= SplitPredicateByOp(Str
, '<', IsFuncCalling
)
807 if len(PredPartList
) > 1:
808 return [PredPartList
, '<']
810 return [[Str
, None], None]
812 def GetFuncContainsPE(ExpLine
, ResultSet
):
813 for Result
in ResultSet
:
814 if Result
[0] < ExpLine
and Result
[1] > ExpLine
:
818 def PatternInModifier(Modifier
, SubStr
):
819 PartList
= Modifier
.split()
820 for Part
in PartList
:
825 def GetDataTypeFromModifier(ModifierStr
):
826 MList
= ModifierStr
.split()
829 if M
in EccGlobalData
.gConfig
.ModifierSet
:
831 # remove array suffix
832 if M
.startswith('[') or M
.endswith(']'):
834 ReturnType
+= M
+ ' '
836 ReturnType
= ReturnType
.strip()
837 if len(ReturnType
) == 0:
841 def DiffModifier(Str1
, Str2
):
842 PartList1
= Str1
.split()
843 PartList2
= Str2
.split()
844 if PartList1
== PartList2
:
849 def GetTypedefDict(FullFileName
):
851 Dict
= ComplexTypeDict
.get(FullFileName
)
855 FileID
= GetTableID(FullFileName
)
856 FileTable
= 'Identifier' + str(FileID
)
858 SqlStatement
= """ select Modifier, Name, Value, ID
861 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
862 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
865 for Result
in ResultSet
:
866 if len(Result
[0]) == 0:
867 Dict
[Result
[1]] = Result
[2]
869 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
870 for F
in IncludeFileList
:
871 FileID
= GetTableID(F
)
875 FileTable
= 'Identifier' + str(FileID
)
876 SqlStatement
= """ select Modifier, Name, Value, ID
879 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
880 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
882 for Result
in ResultSet
:
883 if not Result
[2].startswith('FP ('):
884 Dict
[Result
[1]] = Result
[2]
886 if len(Result
[0]) == 0:
887 Dict
[Result
[1]] = 'VOID'
889 Dict
[Result
[1]] = GetDataTypeFromModifier(Result
[0])
891 ComplexTypeDict
[FullFileName
] = Dict
894 def GetSUDict(FullFileName
):
896 Dict
= SUDict
.get(FullFileName
)
900 FileID
= GetTableID(FullFileName
)
901 FileTable
= 'Identifier' + str(FileID
)
903 SqlStatement
= """ select Name, Value, ID
905 where Model = %d or Model = %d
906 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
907 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
910 for Result
in ResultSet
:
911 if len(Result
[1]) > 0:
912 Dict
[Result
[0]] = Result
[1]
914 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
915 for F
in IncludeFileList
:
916 FileID
= GetTableID(F
)
920 FileTable
= 'Identifier' + str(FileID
)
921 SqlStatement
= """ select Name, Value, ID
923 where Model = %d or Model = %d
924 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
925 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
927 for Result
in ResultSet
:
928 if len(Result
[1]) > 0:
929 Dict
[Result
[0]] = Result
[1]
931 SUDict
[FullFileName
] = Dict
934 def StripComments(Str
):
936 ListFromStr
= list(Str
)
939 DoubleSlashComment
= False
941 while Index
< len(ListFromStr
):
942 # meet new line, then no longer in a comment for //
943 if ListFromStr
[Index
] == '\n':
944 if InComment
and DoubleSlashComment
:
946 DoubleSlashComment
= False
948 # check for */ comment end
949 elif InComment
and not DoubleSlashComment
and ListFromStr
[Index
] == '*' and ListFromStr
[Index
+ 1] == '/':
950 ListFromStr
[Index
] = ' '
952 ListFromStr
[Index
] = ' '
955 # set comments to spaces
957 ListFromStr
[Index
] = ' '
959 # check for // comment
960 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '/':
962 DoubleSlashComment
= True
964 # check for /* comment start
965 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '*':
966 ListFromStr
[Index
] = ' '
968 ListFromStr
[Index
] = ' '
974 # restore from List to String
975 Str
= "".join(ListFromStr
)
976 Str
= Str
.rstrip(' ')
980 def GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
):
981 Value
= TypedefDict
.get(Type
)
983 Value
= SUDict
.get(Type
)
987 LBPos
= Value
.find('{')
989 FTList
= Value
.split()
991 if FT
not in ('struct', 'union'):
992 Value
= TypedefDict
.get(FT
)
994 Value
= SUDict
.get(FT
)
1000 LBPos
= Value
.find('{')
1002 # RBPos = Value.find('}')
1003 Fields
= Value
[LBPos
+ 1:]
1004 Fields
= StripComments(Fields
)
1005 FieldsList
= Fields
.split(';')
1006 for Field
in FieldsList
:
1007 Field
= Field
.strip()
1008 Index
= Field
.rfind(FieldName
)
1011 if not Field
[Index
- 1].isalnum():
1012 if Index
+ len(FieldName
) == len(Field
):
1013 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1016 # For the condition that the field in struct is an array with [] suffixes...
1017 if not Field
[Index
+ len(FieldName
)].isalnum():
1018 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1023 def GetRealType(Type
, TypedefDict
, TargetType
=None):
1024 if TargetType
is not None and Type
== TargetType
:
1026 while TypedefDict
.get(Type
):
1027 Type
= TypedefDict
.get(Type
)
1028 if TargetType
is not None and Type
== TargetType
:
1032 def GetTypeInfo(RefList
, Modifier
, FullFileName
, TargetType
=None):
1033 TypedefDict
= GetTypedefDict(FullFileName
)
1034 SUDict
= GetSUDict(FullFileName
)
1035 Type
= GetDataTypeFromModifier(Modifier
).replace('*', '').strip()
1037 Type
= Type
.split()[-1]
1039 while Index
< len(RefList
):
1040 FieldName
= RefList
[Index
]
1041 FromType
= GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
)
1042 if FromType
is None:
1044 # we want to determine the exact type.
1045 if TargetType
is not None:
1046 Type
= FromType
.split()[0]
1047 # we only want to check if it is a pointer
1050 if Type
.find('*') != -1 and Index
== len(RefList
) - 1:
1052 Type
= FromType
.split()[0]
1056 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1060 def GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
=False, TargetType
=None, StarList
=None):
1062 PredVar
= PredVarList
[0]
1063 FileID
= GetTableID(FullFileName
)
1066 FileTable
= 'Identifier' + str(FileID
)
1067 # search variable in include files
1069 # it is a function call, search function declarations and definitions
1071 SqlStatement
= """ select Modifier, ID
1073 where Model = %d and Value = \'%s\'
1074 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1075 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1077 for Result
in ResultSet
:
1078 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1079 TypedefDict
= GetTypedefDict(FullFileName
)
1080 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1083 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1084 for F
in IncludeFileList
:
1085 FileID
= GetTableID(F
)
1089 FileTable
= 'Identifier' + str(FileID
)
1090 SqlStatement
= """ select Modifier, ID
1092 where Model = %d and Value = \'%s\'
1093 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1094 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1096 for Result
in ResultSet
:
1097 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1098 TypedefDict
= GetTypedefDict(FullFileName
)
1099 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1102 FileID
= GetTableID(FullFileName
)
1103 SqlStatement
= """ select Modifier, ID
1105 where BelongsToFile = %d and Name = \'%s\'
1106 """ % (FileID
, PredVar
)
1107 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1109 for Result
in ResultSet
:
1110 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1111 TypedefDict
= GetTypedefDict(FullFileName
)
1112 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1115 for F
in IncludeFileList
:
1116 FileID
= GetTableID(F
)
1120 FileTable
= 'Identifier' + str(FileID
)
1121 SqlStatement
= """ select Modifier, ID
1123 where BelongsToFile = %d and Name = \'%s\'
1124 """ % (FileID
, PredVar
)
1125 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1127 for Result
in ResultSet
:
1128 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1129 TypedefDict
= GetTypedefDict(FullFileName
)
1130 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1135 # really variable, search local variable first
1136 SqlStatement
= """ select Modifier, ID
1138 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1139 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
, FuncRecord
[0], FuncRecord
[1])
1140 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1142 for Result
in ResultSet
:
1143 if len(PredVarList
) > 1:
1144 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1147 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1148 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1150 if len(TypeList
) > 1 and StarList
is not None:
1151 for Star
in StarList
:
1153 Type
= Type
.rstrip(Star
)
1154 # Get real type after de-reference pointers.
1155 if len(Type
.strip()) == 0:
1157 TypedefDict
= GetTypedefDict(FullFileName
)
1158 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1161 # search function parameters second
1162 ParamList
= GetParamList(FuncRecord
[2])
1163 for Param
in ParamList
:
1164 if Param
.Name
.strip() == PredVar
:
1165 if len(PredVarList
) > 1:
1166 Type
= GetTypeInfo(PredVarList
[1:], Param
.Modifier
, FullFileName
, TargetType
)
1169 TypeList
= GetDataTypeFromModifier(Param
.Modifier
).split()
1171 if Type
== '*' and len(TypeList
) >= 2:
1173 if len(TypeList
) > 1 and StarList
is not None:
1174 for Star
in StarList
:
1176 Type
= Type
.rstrip(Star
)
1177 # Get real type after de-reference pointers.
1178 if len(Type
.strip()) == 0:
1180 TypedefDict
= GetTypedefDict(FullFileName
)
1181 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1184 # search global variable next
1185 SqlStatement
= """ select Modifier, ID
1187 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1188 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1189 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1191 for Result
in ResultSet
:
1192 if len(PredVarList
) > 1:
1193 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1196 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1198 if len(TypeList
) > 1 and StarList
is not None:
1199 for Star
in StarList
:
1201 Type
= Type
.rstrip(Star
)
1202 # Get real type after de-reference pointers.
1203 if len(Type
.strip()) == 0:
1205 TypedefDict
= GetTypedefDict(FullFileName
)
1206 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1209 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1210 for F
in IncludeFileList
:
1211 FileID
= GetTableID(F
)
1215 FileTable
= 'Identifier' + str(FileID
)
1216 SqlStatement
= """ select Modifier, ID
1218 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1219 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1220 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1222 for Result
in ResultSet
:
1223 if len(PredVarList
) > 1:
1224 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1227 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1229 if len(TypeList
) > 1 and StarList
is not None:
1230 for Star
in StarList
:
1232 Type
= Type
.rstrip(Star
)
1233 # Get real type after de-reference pointers.
1234 if len(Type
.strip()) == 0:
1236 TypedefDict
= GetTypedefDict(FullFileName
)
1237 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1240 def GetTypeFromArray(Type
, Var
):
1241 Count
= Var
.count('[')
1245 Type
= Type
.rstrip('*')
1250 def CheckFuncLayoutReturnType(FullFileName
):
1253 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1258 FileTable
= 'Identifier' + str(FileID
)
1259 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1262 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1263 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1264 for Result
in ResultSet
:
1265 ReturnType
= GetDataTypeFromModifier(Result
[0])
1266 TypeStart
= ReturnType
.split()[0]
1267 FuncName
= Result
[5]
1268 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1271 if Result0
.upper().startswith('STATIC'):
1272 Result0
= Result0
[6:].strip()
1273 Index
= Result0
.find(TypeStart
)
1274 if Index
!= 0 or Result
[3] != 0:
1275 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1277 if Result
[2] == Result
[4]:
1278 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1280 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1282 where BelongsToFile = %d
1284 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1285 for Result
in ResultSet
:
1286 ReturnType
= GetDataTypeFromModifier(Result
[0])
1287 TypeStart
= ReturnType
.split()[0]
1288 FuncName
= Result
[5]
1289 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1292 if Result0
.upper().startswith('STATIC'):
1293 Result0
= Result0
[6:].strip()
1294 Index
= Result0
.find(TypeStart
)
1295 if Index
!= 0 or Result
[3] != 0:
1296 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1298 def CheckFuncLayoutModifier(FullFileName
):
1301 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1306 FileTable
= 'Identifier' + str(FileID
)
1307 SqlStatement
= """ select Modifier, ID
1310 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1311 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1312 for Result
in ResultSet
:
1313 ReturnType
= GetDataTypeFromModifier(Result
[0])
1314 TypeStart
= ReturnType
.split()[0]
1316 if Result0
.upper().startswith('STATIC'):
1317 Result0
= Result0
[6:].strip()
1318 Index
= Result0
.find(TypeStart
)
1320 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1322 SqlStatement
= """ select Modifier, ID
1324 where BelongsToFile = %d
1326 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1327 for Result
in ResultSet
:
1328 ReturnType
= GetDataTypeFromModifier(Result
[0])
1329 TypeStart
= ReturnType
.split()[0]
1331 if Result0
.upper().startswith('STATIC'):
1332 Result0
= Result0
[6:].strip()
1333 Index
= Result0
.find(TypeStart
)
1335 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1337 def CheckFuncLayoutName(FullFileName
):
1339 # Parameter variable format pattern.
1340 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1341 ParamIgnoreList
= ('VOID', '...')
1342 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1347 FileTable
= 'Identifier' + str(FileID
)
1348 SqlStatement
= """ select Name, ID, EndColumn, Value
1351 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1352 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1353 for Result
in ResultSet
:
1354 FuncName
= Result
[3]
1355 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1358 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1359 ParamList
= GetParamList(Result
[0])
1360 if len(ParamList
) == 0:
1363 for Param
in ParamList
:
1364 if Param
.StartLine
<= StartLine
:
1365 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1366 if Param
.StartLine
- StartLine
> 1:
1367 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1368 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
):
1369 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1370 StartLine
= Param
.StartLine
1372 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1373 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1375 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1377 where BelongsToFile = %d
1379 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1380 for Result
in ResultSet
:
1381 FuncName
= Result
[3]
1382 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1385 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1386 ParamList
= GetParamList(Result
[0])
1387 if len(ParamList
) == 0:
1390 for Param
in ParamList
:
1391 if Param
.StartLine
<= StartLine
:
1392 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1393 if Param
.StartLine
- StartLine
> 1:
1394 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1395 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
):
1396 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1397 StartLine
= Param
.StartLine
1398 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1399 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1401 def CheckFuncLayoutPrototype(FullFileName
):
1404 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1408 FileTable
= 'Identifier' + str(FileID
)
1410 SqlStatement
= """ select Modifier, Header, Name, ID
1412 where BelongsToFile = %d
1414 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1415 if len(ResultSet
) == 0:
1419 for Result
in ResultSet
:
1420 FuncDefList
.append(Result
)
1422 SqlStatement
= """ select Modifier, Name, ID
1425 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1426 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1428 for Result
in ResultSet
:
1429 FuncDeclList
.append(Result
)
1432 for FuncDef
in FuncDefList
:
1433 FuncName
= FuncDef
[2].strip()
1434 FuncModifier
= FuncDef
[0]
1435 FuncDefHeader
= FuncDef
[1]
1436 for FuncDecl
in FuncDeclList
:
1437 LBPos
= FuncDecl
[1].find('(')
1438 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1439 DeclModifier
= FuncDecl
[0]
1440 if DeclName
== FuncName
:
1441 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1442 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1443 ParamListOfDef
= GetParamList(FuncDefHeader
)
1444 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1445 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1446 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1450 while Index
< len(ParamListOfDef
):
1451 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1452 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])
1456 UndeclFuncList
.append(FuncDef
)
1458 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1460 for F
in IncludeFileList
:
1461 FileID
= GetTableID(F
, ErrorMsgList
)
1465 FileTable
= 'Identifier' + str(FileID
)
1466 SqlStatement
= """ select Modifier, Name, ID
1469 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1470 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1472 for Result
in ResultSet
:
1473 FuncDeclList
.append(Result
)
1475 for FuncDef
in UndeclFuncList
:
1476 FuncName
= FuncDef
[2].strip()
1477 FuncModifier
= FuncDef
[0]
1478 FuncDefHeader
= FuncDef
[1]
1479 for FuncDecl
in FuncDeclList
:
1480 LBPos
= FuncDecl
[1].find('(')
1481 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1482 DeclModifier
= FuncDecl
[0]
1483 if DeclName
== FuncName
:
1484 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1485 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1486 ParamListOfDef
= GetParamList(FuncDefHeader
)
1487 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1488 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1489 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1493 while Index
< len(ParamListOfDef
):
1494 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1495 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])
1499 def CheckFuncLayoutBody(FullFileName
):
1502 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1506 FileTable
= 'Identifier' + str(FileID
)
1508 SqlStatement
= """ select BodyStartColumn, EndColumn, ID, Name
1510 where BelongsToFile = %d
1512 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1513 if len(ResultSet
) == 0:
1515 for Result
in ResultSet
:
1517 if not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, Result
[3]):
1518 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
,
1519 'The open brace should be at the very beginning of a line for the function [%s].' % Result
[3],
1520 'Function', Result
[2])
1522 if not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, Result
[3]):
1523 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
,
1524 'The close brace should be at the very beginning of a line for the function [%s].' % Result
[3],
1525 'Function', Result
[2])
1527 def CheckFuncLayoutLocalVariable(FullFileName
):
1530 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1535 FileTable
= 'Identifier' + str(FileID
)
1536 SqlStatement
= """ select ID
1538 where BelongsToFile = %d
1540 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1541 if len(ResultSet
) == 0:
1544 for Result
in ResultSet
:
1548 SqlStatement
= """ select Name, Value, ID, Modifier
1550 where Model = %d and BelongsToFunction = %d
1551 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1552 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1553 if len(ResultSet
) == 0:
1556 for Result
in ResultSet
:
1557 if len(Result
[1]) > 0 and 'CONST' not in Result
[3]:
1558 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1560 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1562 # Member variable format pattern.
1563 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1565 LBPos
= Value
.find('{')
1566 RBPos
= Value
.rfind('}')
1567 if LBPos
== -1 or RBPos
== -1:
1570 Fields
= Value
[LBPos
+ 1 : RBPos
]
1571 Fields
= StripComments(Fields
).strip()
1572 NestPos
= Fields
.find ('struct')
1573 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)) and ModelId
!= DataClass
.MODEL_IDENTIFIER_UNION
:
1574 if not Fields
[NestPos
+ len('struct') + 1].isalnum():
1575 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1576 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested struct in [%s].' % (Name
), FileTable
, TdId
)
1578 NestPos
= Fields
.find ('union')
1579 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1580 if not Fields
[NestPos
+ len('union') + 1].isalnum():
1581 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1582 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested union in [%s].' % (Name
), FileTable
, TdId
)
1584 NestPos
= Fields
.find ('enum')
1585 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1586 if not Fields
[NestPos
+ len('enum') + 1].isalnum():
1587 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1588 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested enum in [%s].' % (Name
), FileTable
, TdId
)
1591 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1592 FieldsList
= Fields
.split(',')
1593 # deal with enum is pre-assigned a value by function call ( , , , ...)
1596 RemoveCurrentElement
= False
1597 while Index
< len(FieldsList
):
1598 Field
= FieldsList
[Index
]
1600 if Field
.find('(') != -1:
1602 RemoveCurrentElement
= True
1606 if Field
.find(')') != -1 and QuoteCount
> 0:
1609 if RemoveCurrentElement
:
1610 FieldsList
.remove(Field
)
1612 RemoveCurrentElement
= False
1616 RemoveCurrentElement
= False
1620 FieldsList
= Fields
.split(';')
1622 for Field
in FieldsList
:
1623 Field
= Field
.strip()
1626 # For the condition that the field in struct is an array with [] suffixes...
1627 if Field
[-1] == ']':
1628 LBPos
= Field
.find('[')
1629 Field
= Field
[0:LBPos
]
1630 # For the condition that bit field ": Number"
1631 if Field
.find(':') != -1:
1632 ColonPos
= Field
.find(':')
1633 Field
= Field
[0:ColonPos
]
1635 Field
= Field
.strip()
1638 if Field
.startswith("#"):
1640 # Enum could directly assign value to variable
1641 Field
= Field
.split('=')[0].strip()
1642 TokenList
= Field
.split()
1643 # Remove pointers before variable
1644 Token
= TokenList
[-1]
1645 if Token
in ['OPTIONAL']:
1646 Token
= TokenList
[-2]
1647 if not Pattern
.match(Token
.lstrip('*')):
1648 ErrMsgList
.append(Token
.lstrip('*'))
1652 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1655 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1660 FileTable
= 'Identifier' + str(FileID
)
1661 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1664 """ % (FileTable
, ModelId
)
1665 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1667 for Result
in ResultSet
:
1668 ResultList
.append(Result
)
1670 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1671 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1672 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1673 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1674 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1675 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1676 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1678 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1681 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1682 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1686 # Check member variable name format that from typedefs of ONLY this file.
1688 Name
= Td
[1].strip()
1689 Value
= Td
[2].strip()
1690 if Value
.startswith('enum'):
1691 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1692 elif Value
.startswith('struct'):
1693 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1694 elif Value
.startswith('union'):
1695 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1699 if ValueModelId
!= ModelId
:
1701 # Check member variable format.
1702 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1703 for ErrMsg
in ErrMsgList
:
1704 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+ '.' + ErrMsg
):
1706 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+ '.' + ErrMsg
), FileTable
, Td
[5])
1708 # First check in current file to see whether struct/union/enum is typedef-ed.
1709 UntypedefedList
= []
1710 for Result
in ResultList
:
1711 # Check member variable format.
1712 Name
= Result
[0].strip()
1713 Value
= Result
[4].strip()
1714 if Value
.startswith('enum'):
1715 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1716 elif Value
.startswith('struct'):
1717 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1718 elif Value
.startswith('union'):
1719 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1723 if ValueModelId
!= ModelId
:
1725 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1726 for ErrMsg
in ErrMsgList
:
1727 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0] + '.' + ErrMsg
):
1729 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0] + '.' + ErrMsg
), FileTable
, Result
[3])
1730 # Check whether it is typedefed.
1733 # skip function pointer
1736 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1738 if not Td
[1].isupper():
1739 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1740 if Result
[0] in Td
[2].split():
1742 if not Td
[1].isupper():
1743 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1748 UntypedefedList
.append(Result
)
1751 if len(UntypedefedList
) == 0:
1754 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1756 for F
in IncludeFileList
:
1757 FileID
= GetTableID(F
, ErrorMsgList
)
1761 IncludeFileTable
= 'Identifier' + str(FileID
)
1762 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1765 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1766 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1767 TdList
.extend(ResultSet
)
1769 for Result
in UntypedefedList
:
1771 # Check whether it is typedefed.
1777 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1779 if not Td
[1].isupper():
1780 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1781 if Result
[0] in Td
[2].split():
1783 if not Td
[1].isupper():
1784 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1789 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1792 def CheckDeclStructTypedef(FullFileName
):
1793 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1795 def CheckDeclEnumTypedef(FullFileName
):
1796 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1798 def CheckDeclUnionTypedef(FullFileName
):
1799 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1801 def CheckDeclArgModifier(FullFileName
):
1804 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1809 FileTable
= 'Identifier' + str(FileID
)
1810 SqlStatement
= """ select Modifier, Name, ID
1813 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1814 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1815 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1816 MAX_MODIFIER_LENGTH
= 100
1817 for Result
in ResultSet
:
1818 for Modifier
in ModifierTuple
:
1819 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1820 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1823 SqlStatement
= """ select Modifier, Name, ID
1826 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1827 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1828 for Result
in ResultSet
:
1829 for Modifier
in ModifierTuple
:
1830 if PatternInModifier(Result
[0], Modifier
):
1831 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1834 SqlStatement
= """ select Modifier, Header, ID
1836 where BelongsToFile = %d
1838 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1839 for Result
in ResultSet
:
1840 for Modifier
in ModifierTuple
:
1841 if PatternInModifier(Result
[0], Modifier
):
1842 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1845 def CheckDeclNoUseCType(FullFileName
):
1848 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1853 FileTable
= 'Identifier' + str(FileID
)
1854 SqlStatement
= """ select Modifier, Name, ID
1857 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1858 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1859 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1860 for Result
in ResultSet
:
1861 for Type
in CTypeTuple
:
1862 if PatternInModifier(Result
[0], Type
):
1863 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1864 Result
[0] + ' ' + Result
[1]):
1866 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1867 'Invalid variable type (%s) in definition [%s]' % (Type
, Result
[0] + ' ' + Result
[1]),
1872 SqlStatement
= """ select Modifier, Name, ID, Value
1875 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1876 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1877 for Result
in ResultSet
:
1878 ParamList
= GetParamList(Result
[1])
1879 FuncName
= Result
[3]
1880 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1882 for Type
in CTypeTuple
:
1883 if PatternInModifier(Result
[0], Type
):
1884 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1886 for Param
in ParamList
:
1887 if PatternInModifier(Param
.Modifier
, Type
):
1888 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1890 SqlStatement
= """ select Modifier, Header, ID, Name
1892 where BelongsToFile = %d
1894 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1895 for Result
in ResultSet
:
1896 ParamList
= GetParamList(Result
[1])
1897 FuncName
= Result
[3]
1898 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1900 for Type
in CTypeTuple
:
1901 if PatternInModifier(Result
[0], Type
):
1902 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1904 for Param
in ParamList
:
1905 if PatternInModifier(Param
.Modifier
, Type
):
1906 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1909 def CheckPointerNullComparison(FullFileName
):
1912 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1916 # cache the found function return type to accelerate later checking in this file.
1917 FuncReturnTypeDict
= {}
1920 FileTable
= 'Identifier' + str(FileID
)
1921 SqlStatement
= """ select Value, StartLine, ID
1924 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1925 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1926 if len(ResultSet
) == 0:
1929 for Result
in ResultSet
:
1930 PSL
.append([Result
[0], Result
[1], Result
[2]])
1932 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1934 where BelongsToFile = %d
1936 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1938 for Result
in ResultSet
:
1939 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1941 p
= GetFuncDeclPattern()
1943 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1944 if FuncRecord
is None:
1947 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1948 PredInfo
= SplitPredicateStr(Exp
)
1949 if PredInfo
[1] is None:
1950 PredVarStr
= PredInfo
[0][0].strip()
1952 SearchInCache
= False
1953 # PredVarStr may contain '.' or '->'
1954 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1956 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1957 SearchInCache
= True
1958 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1959 if TmpStr
.startswith(PredVarStr
):
1962 if PredVarStr
.strip() in IgnoredKeywordList
:
1965 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1966 # No variable found, maybe value first? like (0 == VarName)
1967 if len(PredVarList
) == 0:
1970 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1971 if Type
is not None:
1972 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1973 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1976 if PredVarStr
in FuncReturnTypeDict
:
1979 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1981 FuncReturnTypeDict
[PredVarStr
] = Type
1984 Type
= GetTypeFromArray(Type
, PredVarStr
)
1985 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1986 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1988 def CheckNonBooleanValueComparison(FullFileName
):
1991 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1995 # cache the found function return type to accelerate later checking in this file.
1996 FuncReturnTypeDict
= {}
1999 FileTable
= 'Identifier' + str(FileID
)
2000 SqlStatement
= """ select Value, StartLine, ID
2003 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2004 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2005 if len(ResultSet
) == 0:
2008 for Result
in ResultSet
:
2009 PSL
.append([Result
[0], Result
[1], Result
[2]])
2011 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2013 where BelongsToFile = %d
2015 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2017 for Result
in ResultSet
:
2018 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2020 p
= GetFuncDeclPattern()
2022 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2023 if FuncRecord
is None:
2026 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2027 PredInfo
= SplitPredicateStr(Exp
)
2028 if PredInfo
[1] is None:
2029 PredVarStr
= PredInfo
[0][0].strip()
2031 SearchInCache
= False
2032 # PredVarStr may contain '.' or '->'
2033 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2035 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2036 SearchInCache
= True
2037 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2038 if TmpStr
.startswith(PredVarStr
):
2041 if PredVarStr
.strip() in IgnoredKeywordList
:
2044 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2045 # No variable found, maybe value first? like (0 == VarName)
2046 if len(PredVarList
) == 0:
2050 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2051 if Type
is not None:
2052 if Type
.find('BOOLEAN') == -1:
2053 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2056 if PredVarStr
in FuncReturnTypeDict
:
2058 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2060 FuncReturnTypeDict
[PredVarStr
] = Type
2063 if Type
.find('BOOLEAN') == -1:
2064 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2067 def CheckBooleanValueComparison(FullFileName
):
2070 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2074 # cache the found function return type to accelerate later checking in this file.
2075 FuncReturnTypeDict
= {}
2078 FileTable
= 'Identifier' + str(FileID
)
2079 SqlStatement
= """ select Value, StartLine, ID
2082 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2083 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2084 if len(ResultSet
) == 0:
2087 for Result
in ResultSet
:
2088 PSL
.append([Result
[0], Result
[1], Result
[2]])
2090 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2092 where BelongsToFile = %d
2094 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2096 for Result
in ResultSet
:
2097 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2099 p
= GetFuncDeclPattern()
2101 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2102 if FuncRecord
is None:
2105 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2106 PredInfo
= SplitPredicateStr(Exp
)
2107 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2108 PredVarStr
= PredInfo
[0][0].strip()
2110 SearchInCache
= False
2111 # PredVarStr may contain '.' or '->'
2112 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2114 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2115 SearchInCache
= True
2116 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2117 if TmpStr
.startswith(PredVarStr
):
2120 if PredVarStr
.strip() in IgnoredKeywordList
:
2123 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2124 # No variable found, maybe value first? like (0 == VarName)
2125 if len(PredVarList
) == 0:
2129 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2130 if Type
is not None:
2131 if Type
.find('BOOLEAN') != -1:
2132 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2135 if PredVarStr
in FuncReturnTypeDict
:
2138 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2140 FuncReturnTypeDict
[PredVarStr
] = Type
2143 if Type
.find('BOOLEAN') != -1:
2144 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2147 def CheckHeaderFileData(FullFileName
, AllTypedefFun
=[]):
2150 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2155 FileTable
= 'Identifier' + str(FileID
)
2156 SqlStatement
= """ select ID, Modifier
2159 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2160 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2161 for Result
in ResultSet
:
2162 if not Result
[1].startswith('extern'):
2163 for Item
in AllTypedefFun
:
2164 if '(%s)' % Result
[1] in Item
:
2167 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2169 SqlStatement
= """ select ID
2171 where BelongsToFile = %d
2173 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2174 for Result
in ResultSet
:
2175 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2179 def CheckHeaderFileIfndef(FullFileName
):
2182 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2187 FileTable
= 'Identifier' + str(FileID
)
2188 SqlStatement
= """ select Value, StartLine
2190 where Model = %d order by StartLine
2191 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2192 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2193 if len(ResultSet
) == 0:
2194 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2196 for Result
in ResultSet
:
2197 SqlStatement
= """ select Value, EndLine
2200 """ % (FileTable
, Result
[1])
2201 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2202 for Result
in ResultSet
:
2203 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2204 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2
, '', 'File', FileID
)
2207 SqlStatement
= """ select Value
2209 where StartLine > (select max(EndLine) from %s where Model = %d)
2210 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2211 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2212 for Result
in ResultSet
:
2213 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2214 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2217 def CheckDoxygenCommand(FullFileName
):
2220 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2225 FileTable
= 'Identifier' + str(FileID
)
2226 SqlStatement
= """ select Value, ID
2228 where Model = %d or Model = %d
2229 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2230 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2231 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval',
2232 'return', 'sa', 'since', 'test', 'note', 'par', 'endcode', 'code']
2233 for Result
in ResultSet
:
2234 CommentStr
= Result
[0]
2235 CommentPartList
= CommentStr
.split()
2236 for Part
in CommentPartList
:
2237 if Part
.upper() == 'BUGBUG':
2238 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2239 if Part
.upper() == 'TODO':
2240 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2241 if Part
.startswith('@'):
2242 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2244 if not Part
.replace('@', '').strip():
2246 if Part
.lstrip('@') in ['{', '}']:
2248 if Part
.lstrip('@').isalpha():
2249 if Part
.lstrip('@') not in DoxygenCommandList
:
2250 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2252 Index
= Part
.find('[')
2254 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2255 RealCmd
= Part
[1:Index
]
2256 if RealCmd
not in DoxygenCommandList
:
2257 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2260 def CheckDoxygenTripleForwardSlash(FullFileName
):
2263 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2269 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2271 where BelongsToFile = %d
2273 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2274 if len(ResultSet
) == 0:
2278 for Result
in ResultSet
:
2279 FuncDefSet
.append(Result
)
2282 FileTable
= 'Identifier' + str(FileID
)
2283 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2287 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2288 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2291 for Result
in ResultSet
:
2292 CommentSet
.append(Result
)
2294 print('Unrecognized chars in comment of file %s', FullFileName
)
2297 for Result
in CommentSet
:
2298 CommentStr
= Result
[0]
2299 StartLine
= Result
[2]
2300 StartColumn
= Result
[3]
2302 EndColumn
= Result
[5]
2303 if not CommentStr
.startswith('///<'):
2307 for FuncDef
in FuncDefSet
:
2308 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2311 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2314 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2317 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2321 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2324 def CheckFileHeaderDoxygenComments(FullFileName
):
2327 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2332 FileTable
= 'Identifier' + str(FileID
)
2333 SqlStatement
= """ select Value, ID
2335 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2336 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2337 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2338 if len(ResultSet
) == 0:
2339 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No File License header appear at the very beginning of file.', 'File', FileID
)
2342 NoHeaderCommentStartFlag
= True
2343 NoHeaderCommentEndFlag
= True
2344 NoHeaderCommentPeriodFlag
= True
2345 NoCopyrightFlag
= True
2346 NoLicenseFlag
= True
2347 NoRevReferFlag
= True
2349 for Result
in ResultSet
:
2350 FileStartFlag
= False
2352 CommentStr
= Result
[0].strip()
2353 CommentStrListTemp
= CommentStr
.split('\n')
2354 if (len(CommentStrListTemp
) <= 1):
2356 CommentStrListTemp
= CommentStr
.split('\r')
2357 # Skip the content before the file header
2358 for CommentLine
in CommentStrListTemp
:
2359 if CommentLine
.strip().startswith('/** @file'):
2360 FileStartFlag
= True
2361 if FileStartFlag
== True:
2362 CommentStrList
.append(CommentLine
)
2366 if CommentStrList
and CommentStrList
[0].strip().startswith('/** @file'):
2367 NoHeaderCommentStartFlag
= False
2370 if CommentStrList
and CommentStrList
[-1].strip().endswith('**/'):
2371 NoHeaderCommentEndFlag
= False
2375 for CommentLine
in CommentStrList
:
2377 NextLineIndex
= Index
2378 if CommentLine
.startswith('/** @file'):
2380 if CommentLine
.startswith('**/'):
2382 # Check whether C File header Comment content start with two spaces.
2383 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentStartSpacesNum
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2384 if CommentLine
.startswith('/** @file') == False and CommentLine
.startswith('**/') == False and CommentLine
.strip() and CommentLine
.startswith(' ') == False:
2385 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment content should start with two spaces at each line', FileTable
, ID
)
2387 CommentLine
= CommentLine
.strip()
2388 if CommentLine
.startswith('Copyright'):
2389 NoCopyrightFlag
= False
2390 if CommentLine
.find('All rights reserved') == -1:
2391 for Copyright
in EccGlobalData
.gConfig
.Copyright
:
2392 if CommentLine
.find(Copyright
) > -1:
2393 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable
, ID
)
2395 if CommentLine
.endswith('<BR>') == -1:
2396 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'The ""<BR>"" at the end of the Copyright line is required', FileTable
, ID
)
2397 if NextLineIndex
< len(CommentStrList
) and CommentStrList
[NextLineIndex
].strip().startswith('Copyright') == False and CommentStrList
[NextLineIndex
].strip():
2398 NoLicenseFlag
= False
2399 if CommentLine
.startswith('@par Revision Reference:'):
2400 NoRevReferFlag
= False
2402 for RefLine
in CommentStrList
[NextLineIndex
:]:
2403 if RefLine
.strip() and (NextLineIndex
+ 1) < len(CommentStrList
) and CommentStrList
[NextLineIndex
+1].strip() and CommentStrList
[NextLineIndex
+1].strip().startswith('**/') == False:
2405 if RefLine
.strip() == False or RefLine
.strip().startswith('**/'):
2408 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2409 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentReferenceFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2410 if RefListFlag
== True:
2411 if RefLine
.strip() and RefLine
.strip().startswith('**/') == False and RefLine
.startswith(' -') == False:
2412 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable
, ID
)
2414 if NoHeaderCommentStartFlag
:
2415 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, ID
)
2417 if NoHeaderCommentEndFlag
:
2418 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with ""**/""', FileTable
, ID
)
2421 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment missing the ""Copyright""', FileTable
, ID
)
2422 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2423 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentLicenseFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2425 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable
, ID
)
2427 def CheckFuncHeaderDoxygenComments(FullFileName
):
2430 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2435 FileTable
= 'Identifier' + str(FileID
)
2436 SqlStatement
= """ select Value, StartLine, EndLine, ID
2439 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2441 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2444 for Result
in ResultSet
:
2445 CommentSet
.append(Result
)
2447 print('Unrecognized chars in comment of file %s', FullFileName
)
2450 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2453 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2454 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2455 for Result
in ResultSet
:
2456 FuncName
= Result
[4]
2457 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2458 if FunctionHeaderComment
:
2459 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2461 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2463 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2464 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2467 SqlStatement
= """ select Value, StartLine, EndLine, ID
2470 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2472 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2475 for Result
in ResultSet
:
2476 CommentSet
.append(Result
)
2478 print('Unrecognized chars in comment of file %s', FullFileName
)
2480 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2482 where BelongsToFile = %d
2484 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2485 for Result
in ResultSet
:
2486 FuncName
= Result
[4]
2487 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2488 if FunctionHeaderComment
:
2489 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2491 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2493 ErrorMsgList
.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2494 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), 'Function', Result
[3])
2497 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2499 for Comment
in CommentSet
:
2500 if Comment
[2] == FuncStartLine
- 1:
2504 def GetDoxygenStrFromComment(Str
):
2506 ParamTagList
= Str
.split('@param')
2507 if len(ParamTagList
) > 1:
2509 while i
< len(ParamTagList
):
2510 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2513 Str
= ParamTagList
[0]
2515 RetvalTagList
= ParamTagList
[-1].split('@retval')
2516 if len(RetvalTagList
) > 1:
2517 if len(ParamTagList
) > 1:
2518 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2520 while i
< len(RetvalTagList
):
2521 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2524 ReturnTagList
= RetvalTagList
[-1].split('@return')
2525 if len(ReturnTagList
) > 1:
2526 if len(RetvalTagList
) > 1:
2527 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2528 elif len(ParamTagList
) > 1:
2529 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2531 while i
< len(ReturnTagList
):
2532 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2535 if len(DoxygenStrList
) > 0:
2536 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2538 return DoxygenStrList
2540 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2541 #/** --*/ @retval after @param
2542 if not Str
.startswith('/**'):
2543 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2544 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2545 if not Str
.endswith('**/'):
2546 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2547 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2548 FirstRetvalIndex
= Str
.find('@retval')
2549 LastParamIndex
= Str
.rfind('@param')
2550 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2551 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2552 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2554 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2556 ParamList
= GetParamList(FuncHeader
)
2557 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2558 DescriptionStr
= CommentStr
2559 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2560 if DescriptionStr
.find('.') == -1:
2561 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2562 DoxygenTagNumber
= len(DoxygenStrList
)
2563 ParamNumber
= len(ParamList
)
2564 for Param
in ParamList
:
2565 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2568 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2569 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2570 ParamModifier
= ParamList
[Index
].Modifier
2571 ParamName
= ParamList
[Index
].Name
.strip()
2572 Tag
= DoxygenStrList
[Index
].strip(' ')
2573 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2574 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2575 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, <%s> does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2576 TagPartList
= Tag
.split()
2577 if len(TagPartList
) < 2:
2578 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2579 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2582 LBPos
= Tag
.find('[')
2583 RBPos
= Tag
.find(']')
2584 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2585 if LBPos
> 0 and len(ParamToLBContent
) == 0 and RBPos
> LBPos
:
2587 ModifierPartList
= ParamModifier
.split()
2588 for Part
in ModifierPartList
:
2589 if Part
.strip() == 'IN':
2591 if Part
.strip() == 'OUT':
2598 if Tag
.find('[' + InOutStr
+ ']') == -1:
2599 if InOutStr
!= 'in, out':
2600 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2601 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2603 if Tag
.find('[in,out]') == -1:
2604 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2605 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2608 if Tag
.find(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2609 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2610 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT consistent with parameter name %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
), TableName
, CommentId
)
2613 if Index
< ParamNumber
:
2614 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2615 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2616 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2617 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2619 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2620 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2621 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2622 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2624 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2625 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2626 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2628 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
2629 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2630 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need NO doxygen tags in comment ', TableName
, CommentId
)
2631 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2632 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2633 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2635 if __name__
== '__main__':
2637 # EdkLogger.Initialize()
2638 # EdkLogger.SetLevel(EdkLogger.QUIET)
2639 # CollectSourceCodeDataIntoDB(sys.argv[1])
2641 test_file
= sys
.argv
[1]
2642 except IndexError as v
:
2643 print("Usage: %s filename" % sys
.argv
[0])
2645 MsgList
= CheckFuncHeaderDoxygenComments(test_file
)