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 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 from __future__
import print_function
15 from __future__
import absolute_import
17 import Common
.LongFilePathOs
as os
20 from Ecc
import CodeFragmentCollector
21 from Ecc
import FileProfile
22 from CommonDataClass
import DataClass
23 from Ecc
import Database
24 from Common
import EdkLogger
25 from Ecc
.EccToolError
import *
26 from Ecc
import EccGlobalData
27 from Ecc
import MetaDataParser
29 IncludeFileListDict
= {}
30 AllIncludeFileListDict
= {}
31 IncludePathListDict
= {}
34 IgnoredKeywordList
= ['EFI_ERROR']
36 def GetIgnoredDirListPattern():
37 skipList
= list(EccGlobalData
.gConfig
.SkipDirList
) + ['.svn']
38 DirString
= '|'.join(skipList
)
39 p
= re
.compile(r
'.*[\\/](?:%s)[\\/]?.*' % DirString
)
42 def GetFuncDeclPattern():
43 p
= re
.compile(r
'(?:EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re
.DOTALL
)
46 def GetArrayPattern():
47 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
50 def GetTypedefFuncPointerPattern():
51 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
55 return EccGlobalData
.gDb
58 return EccGlobalData
.gConfig
60 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
61 Msg
= Msg
.replace('\n', '').replace('\r', '')
62 MsgPartList
= Msg
.split()
64 for Part
in MsgPartList
:
67 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
=Msg
, BelongsToTable
=TableName
, BelongsToItem
=ItemId
)
70 Type
= DataClass
.MODEL_UNKNOWN
71 Str
= Str
.replace('#', '# ')
73 if List
[1] == 'include':
74 Type
= DataClass
.MODEL_IDENTIFIER_INCLUDE
75 elif List
[1] == 'define':
76 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_DEFINE
77 elif List
[1] == 'ifdef':
78 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFDEF
79 elif List
[1] == 'ifndef':
80 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
81 elif List
[1] == 'endif':
82 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
83 elif List
[1] == 'pragma':
84 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_PROGMA
86 Type
= DataClass
.MODEL_UNKNOWN
89 def SuOccurInTypedef (Su
, TdList
):
91 if Su
.StartPos
[0] == Td
.StartPos
[0] and Su
.EndPos
[0] == Td
.EndPos
[0]:
95 def GetIdentifierList():
97 for comment
in FileProfile
.CommentList
:
98 IdComment
= DataClass
.IdentifierClass(-1, '', '', '', comment
.Content
, DataClass
.MODEL_IDENTIFIER_COMMENT
, -1, -1, comment
.StartPos
[0], comment
.StartPos
[1], comment
.EndPos
[0], comment
.EndPos
[1])
99 IdList
.append(IdComment
)
101 for pp
in FileProfile
.PPDirectiveList
:
102 Type
= GetIdType(pp
.Content
)
103 IdPP
= DataClass
.IdentifierClass(-1, '', '', '', pp
.Content
, Type
, -1, -1, pp
.StartPos
[0], pp
.StartPos
[1], pp
.EndPos
[0], pp
.EndPos
[1])
106 for pe
in FileProfile
.PredicateExpressionList
:
107 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])
110 FuncDeclPattern
= GetFuncDeclPattern()
111 ArrayPattern
= GetArrayPattern()
112 for var
in FileProfile
.VariableDeclarationList
:
113 DeclText
= var
.Declarator
.lstrip()
114 FuncPointerPattern
= GetTypedefFuncPointerPattern()
115 if FuncPointerPattern
.match(DeclText
):
117 VarNameStartLine
= var
.NameStartPos
[0]
118 VarNameStartColumn
= var
.NameStartPos
[1]
119 FirstChar
= DeclText
[0]
120 while not FirstChar
.isalpha() and FirstChar
!= '_':
123 VarNameStartColumn
+= 1
124 DeclText
= DeclText
.lstrip('*')
125 elif FirstChar
== '\r':
126 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
127 VarNameStartLine
+= 1
128 VarNameStartColumn
= 0
129 elif FirstChar
== '\n':
130 DeclText
= DeclText
.lstrip('\n')
131 VarNameStartLine
+= 1
132 VarNameStartColumn
= 0
133 elif FirstChar
== ' ':
134 DeclText
= DeclText
.lstrip(' ')
135 VarNameStartColumn
+= 1
136 elif FirstChar
== '\t':
137 DeclText
= DeclText
.lstrip('\t')
138 VarNameStartColumn
+= 8
140 DeclText
= DeclText
[1:]
141 VarNameStartColumn
+= 1
142 FirstChar
= DeclText
[0]
144 var
.Declarator
= DeclText
145 if FuncDeclPattern
.match(var
.Declarator
):
146 DeclSplitList
= var
.Declarator
.split('(')
147 FuncName
= DeclSplitList
[0].strip()
148 FuncNamePartList
= FuncName
.split()
149 if len(FuncNamePartList
) > 1:
150 FuncName
= FuncNamePartList
[-1].strip()
151 NameStart
= DeclSplitList
[0].rfind(FuncName
)
152 var
.Declarator
= var
.Declarator
[NameStart
:]
154 var
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
157 while Index
< NameStart
:
158 FirstChar
= DeclSplitList
[0][Index
]
159 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
161 VarNameStartColumn
+= 6
164 elif FirstChar
== '\r':
166 VarNameStartLine
+= 1
167 VarNameStartColumn
= 0
168 elif FirstChar
== '\n':
171 VarNameStartLine
+= 1
172 VarNameStartColumn
= 0
173 elif FirstChar
== ' ':
175 VarNameStartColumn
+= 1
176 elif FirstChar
== '\t':
178 VarNameStartColumn
+= 8
181 VarNameStartColumn
+= 1
183 IdVar
= DataClass
.IdentifierClass(-1, var
.Modifier
, '', var
.Declarator
, FuncName
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, -1, -1, var
.StartPos
[0], var
.StartPos
[1], VarNameStartLine
, VarNameStartColumn
)
187 if var
.Declarator
.find('{') == -1:
188 for decl
in var
.Declarator
.split(','):
189 DeclList
= decl
.split('=')
190 Name
= DeclList
[0].strip()
191 if ArrayPattern
.match(Name
):
192 LSBPos
= var
.Declarator
.find('[')
193 var
.Modifier
+= ' ' + Name
[LSBPos
:]
194 Name
= Name
[0:LSBPos
]
196 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
)
199 DeclList
= var
.Declarator
.split('=')
200 Name
= DeclList
[0].strip()
201 if ArrayPattern
.match(Name
):
202 LSBPos
= var
.Declarator
.find('[')
203 var
.Modifier
+= ' ' + Name
[LSBPos
:]
204 Name
= Name
[0:LSBPos
]
205 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
)
208 for enum
in FileProfile
.EnumerationDefinitionList
:
209 LBPos
= enum
.Content
.find('{')
210 RBPos
= enum
.Content
.find('}')
211 Name
= enum
.Content
[4:LBPos
].strip()
212 Value
= enum
.Content
[LBPos
+ 1:RBPos
]
213 IdEnum
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
, -1, -1, enum
.StartPos
[0], enum
.StartPos
[1], enum
.EndPos
[0], enum
.EndPos
[1])
214 IdList
.append(IdEnum
)
216 for su
in FileProfile
.StructUnionDefinitionList
:
217 if SuOccurInTypedef(su
, FileProfile
.TypedefDefinitionList
):
219 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
221 if su
.Content
.startswith('union'):
222 Type
= DataClass
.MODEL_IDENTIFIER_UNION
224 LBPos
= su
.Content
.find('{')
225 RBPos
= su
.Content
.find('}')
226 if LBPos
== -1 or RBPos
== -1:
227 Name
= su
.Content
[SkipLen
:].strip()
230 Name
= su
.Content
[SkipLen
:LBPos
].strip()
231 Value
= su
.Content
[LBPos
:RBPos
+ 1]
232 IdPE
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, Type
, -1, -1, su
.StartPos
[0], su
.StartPos
[1], su
.EndPos
[0], su
.EndPos
[1])
235 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
236 for td
in FileProfile
.TypedefDefinitionList
:
240 if TdFuncPointerPattern
.match(td
.ToType
):
241 Modifier
= td
.FromType
242 LBPos
= td
.ToType
.find('(')
243 TmpStr
= td
.ToType
[LBPos
+ 1:].strip()
244 StarPos
= TmpStr
.find('*')
246 Modifier
+= ' ' + TmpStr
[0:StarPos
]
247 while TmpStr
[StarPos
] == '*':
248 # Modifier += ' ' + '*'
250 TmpStr
= TmpStr
[StarPos
:].strip()
251 RBPos
= TmpStr
.find(')')
252 Name
= TmpStr
[0:RBPos
]
253 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
255 while Name
.startswith('*'):
257 Name
= Name
.lstrip('*').strip()
259 if Name
.find('[') != -1:
260 LBPos
= Name
.find('[')
261 RBPos
= Name
.rfind(']')
262 Value
+= Name
[LBPos
: RBPos
+ 1]
263 Name
= Name
[0 : LBPos
]
265 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])
268 for funcCall
in FileProfile
.FunctionCallingList
:
269 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])
273 def StripNonAlnumChars(Str
):
276 if Char
.isalnum() or Char
== '_':
280 def GetParamList(FuncDeclarator
, FuncNameLine
=0, FuncNameOffset
=0):
281 FuncDeclarator
= StripComments(FuncDeclarator
)
283 #DeclSplitList = FuncDeclarator.split('(')
284 LBPos
= FuncDeclarator
.find('(')
285 #if len(DeclSplitList) < 2:
288 #FuncName = DeclSplitList[0]
289 FuncName
= FuncDeclarator
[0:LBPos
]
290 #ParamStr = DeclSplitList[1].rstrip(')')
291 ParamStr
= FuncDeclarator
[LBPos
+ 1:].rstrip(')')
294 TailChar
= FuncName
[-1]
295 while not TailChar
.isalpha() and TailChar
!= '_':
298 FuncName
= FuncName
.rstrip('\r\n').rstrip('\n')
301 elif TailChar
== '\r':
302 FuncName
= FuncName
.rstrip('\r')
305 elif TailChar
== ' ':
306 FuncName
= FuncName
.rstrip(' ')
308 elif TailChar
== '\t':
309 FuncName
= FuncName
.rstrip('\t')
312 FuncName
= FuncName
[:-1]
313 TailChar
= FuncName
[-1]
315 OffsetSkipped
+= 1 #skip '('
317 for p
in ParamStr
.split(','):
321 ParamName
= ListP
[-1]
322 DeclText
= ParamName
.strip()
323 RightSpacePos
= p
.rfind(ParamName
)
324 ParamModifier
= p
[0:RightSpacePos
]
325 if ParamName
== 'OPTIONAL':
326 if ParamModifier
== '':
327 ParamModifier
+= ' ' + 'OPTIONAL'
330 ParamName
= ListP
[-2]
331 DeclText
= ParamName
.strip()
332 RightSpacePos
= p
.rfind(ParamName
)
333 ParamModifier
= p
[0:RightSpacePos
]
334 ParamModifier
+= 'OPTIONAL'
335 while DeclText
.startswith('*'):
336 ParamModifier
+= ' ' + '*'
337 DeclText
= DeclText
.lstrip('*').strip()
339 # ignore array length if exists.
340 LBIndex
= ParamName
.find('[')
342 ParamName
= ParamName
[0:LBIndex
]
344 Start
= RightSpacePos
350 if FirstChar
== '\r':
354 elif FirstChar
== '\n':
359 elif FirstChar
== ' ':
362 elif FirstChar
== '\t':
370 ParamBeginLine
= FuncNameLine
+ LineSkipped
371 ParamBeginOffset
= FuncNameOffset
+ OffsetSkipped
373 Index
= Start
+ len(ParamName
)
375 while Index
< len(p
):
378 if FirstChar
== '\r':
382 elif FirstChar
== '\n':
387 elif FirstChar
== ' ':
390 elif FirstChar
== '\t':
398 ParamEndLine
= FuncNameLine
+ LineSkipped
399 ParamEndOffset
= FuncNameOffset
+ OffsetSkipped
400 if ParamName
!= '...':
401 ParamName
= StripNonAlnumChars(ParamName
)
402 IdParam
= DataClass
.IdentifierClass(-1, ParamModifier
, '', ParamName
, '', DataClass
.MODEL_IDENTIFIER_PARAMETER
, -1, -1, ParamBeginLine
, ParamBeginOffset
, ParamEndLine
, ParamEndOffset
)
403 ParamIdList
.append(IdParam
)
405 OffsetSkipped
+= 1 #skip ','
409 def GetFunctionList():
411 for FuncDef
in FileProfile
.FunctionDefinitionList
:
413 DeclText
= FuncDef
.Declarator
.lstrip()
414 FuncNameStartLine
= FuncDef
.NamePos
[0]
415 FuncNameStartColumn
= FuncDef
.NamePos
[1]
416 FirstChar
= DeclText
[0]
417 while not FirstChar
.isalpha() and FirstChar
!= '_':
419 FuncDef
.Modifier
+= '*'
420 FuncNameStartColumn
+= 1
421 DeclText
= DeclText
.lstrip('*')
422 elif FirstChar
== '\r':
423 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
424 FuncNameStartLine
+= 1
425 FuncNameStartColumn
= 0
426 elif FirstChar
== '\n':
427 DeclText
= DeclText
.lstrip('\n')
428 FuncNameStartLine
+= 1
429 FuncNameStartColumn
= 0
430 elif FirstChar
== ' ':
431 DeclText
= DeclText
.lstrip(' ')
432 FuncNameStartColumn
+= 1
433 elif FirstChar
== '\t':
434 DeclText
= DeclText
.lstrip('\t')
435 FuncNameStartColumn
+= 8
437 DeclText
= DeclText
[1:]
438 FuncNameStartColumn
+= 1
439 FirstChar
= DeclText
[0]
441 FuncDef
.Declarator
= DeclText
442 DeclSplitList
= FuncDef
.Declarator
.split('(')
443 if len(DeclSplitList
) < 2:
446 FuncName
= DeclSplitList
[0]
447 FuncNamePartList
= FuncName
.split()
448 if len(FuncNamePartList
) > 1:
449 FuncName
= FuncNamePartList
[-1]
450 NameStart
= DeclSplitList
[0].rfind(FuncName
)
452 FuncDef
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
455 while Index
< NameStart
:
456 FirstChar
= DeclSplitList
[0][Index
]
457 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
459 FuncNameStartColumn
+= 6
462 elif FirstChar
== '\r':
464 FuncNameStartLine
+= 1
465 FuncNameStartColumn
= 0
466 elif FirstChar
== '\n':
469 FuncNameStartLine
+= 1
470 FuncNameStartColumn
= 0
471 elif FirstChar
== ' ':
473 FuncNameStartColumn
+= 1
474 elif FirstChar
== '\t':
476 FuncNameStartColumn
+= 8
479 FuncNameStartColumn
+= 1
482 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
)
483 FuncObjList
.append(FuncObj
)
487 def GetFileModificationTimeFromDB(FullFileName
):
490 SqlStatement
= """ select TimeStamp
492 where FullPath = \'%s\'
494 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
495 for Result
in ResultSet
:
496 TimeValue
= Result
[0]
499 def CollectSourceCodeDataIntoDB(RootDir
):
501 tuple = os
.walk(RootDir
)
502 IgnoredPattern
= GetIgnoredDirListPattern()
503 ParseErrorFileList
= []
505 for dirpath
, dirnames
, filenames
in tuple:
506 if IgnoredPattern
.match(dirpath
.upper()):
510 Dirname
= os
.path
.join(dirpath
, Dir
)
511 if os
.path
.islink(Dirname
):
512 Dirname
= os
.path
.realpath(Dirname
)
513 if os
.path
.isdir(Dirname
):
514 # symlinks to directories are treated as directories
516 dirnames
.append(Dirname
)
519 if f
.lower() in EccGlobalData
.gConfig
.SkipFileList
:
522 FullName
= os
.path
.normpath(os
.path
.join(dirpath
, f
))
523 model
= DataClass
.MODEL_FILE_OTHERS
524 if os
.path
.splitext(f
)[1] in ('.h', '.c'):
525 EdkLogger
.info("Parsing " + FullName
)
526 model
= f
.endswith('c') and DataClass
.MODEL_FILE_C
or DataClass
.MODEL_FILE_H
527 collector
= CodeFragmentCollector
.CodeFragmentCollector(FullName
)
529 collector
.ParseFile()
531 ParseErrorFileList
.append(FullName
)
532 collector
.CleanFileProfileBuffer()
533 collector
.ParseFileWithClearedPPDirective()
534 # collector.PrintFragments()
535 BaseName
= os
.path
.basename(f
)
536 DirName
= os
.path
.dirname(FullName
)
537 Ext
= os
.path
.splitext(f
)[1].lstrip('.')
538 ModifiedTime
= os
.path
.getmtime(FullName
)
539 FileObj
= DataClass
.FileClass(-1, BaseName
, Ext
, DirName
, FullName
, model
, ModifiedTime
, GetFunctionList(), GetIdentifierList(), [])
540 FileObjList
.append(FileObj
)
542 collector
.CleanFileProfileBuffer()
544 if len(ParseErrorFileList
) > 0:
545 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
548 for file in FileObjList
:
549 if file.ExtName
.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
550 Db
.InsertOneFile(file)
552 Db
.UpdateIdentifierBelongsToFunction()
554 def GetTableID(FullFileName
, ErrorMsgList
=None):
555 if ErrorMsgList
is None:
559 SqlStatement
= """ select ID
561 where FullPath like '%s'
563 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
566 for Result
in ResultSet
:
568 ErrorMsgList
.append('Duplicate file ID found in DB for file %s' % FullFileName
)
572 ErrorMsgList
.append('NO file ID found in DB for file %s' % FullFileName
)
576 def GetIncludeFileList(FullFileName
):
577 if os
.path
.splitext(FullFileName
)[1].upper() not in ('.H'):
579 IFList
= IncludeFileListDict
.get(FullFileName
)
580 if IFList
is not None:
583 FileID
= GetTableID(FullFileName
)
588 FileTable
= 'Identifier' + str(FileID
)
589 SqlStatement
= """ select Value
592 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_INCLUDE
)
593 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
594 IncludeFileListDict
[FullFileName
] = ResultSet
597 def GetFullPathOfIncludeFile(Str
, IncludePathList
):
598 for IncludePath
in IncludePathList
:
599 FullPath
= os
.path
.join(IncludePath
, Str
)
600 FullPath
= os
.path
.normpath(FullPath
)
601 if os
.path
.exists(FullPath
):
605 def GetAllIncludeFiles(FullFileName
):
606 if AllIncludeFileListDict
.get(FullFileName
) is not None:
607 return AllIncludeFileListDict
.get(FullFileName
)
609 FileDirName
= os
.path
.dirname(FullFileName
)
610 IncludePathList
= IncludePathListDict
.get(FileDirName
)
611 if IncludePathList
is None:
612 IncludePathList
= MetaDataParser
.GetIncludeListOfFile(EccGlobalData
.gWorkspace
, FullFileName
, GetDB())
613 if FileDirName
not in IncludePathList
:
614 IncludePathList
.insert(0, FileDirName
)
615 IncludePathListDict
[FileDirName
] = IncludePathList
616 IncludeFileQueue
= []
617 for IncludeFile
in GetIncludeFileList(FullFileName
):
618 FileName
= IncludeFile
[0].lstrip('#').strip()
619 FileName
= FileName
.lstrip('include').strip()
620 FileName
= FileName
.strip('\"')
621 FileName
= FileName
.lstrip('<').rstrip('>').strip()
622 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
623 if FullPath
is not None:
624 IncludeFileQueue
.append(FullPath
)
627 while i
< len(IncludeFileQueue
):
628 for IncludeFile
in GetIncludeFileList(IncludeFileQueue
[i
]):
629 FileName
= IncludeFile
[0].lstrip('#').strip()
630 FileName
= FileName
.lstrip('include').strip()
631 FileName
= FileName
.strip('\"')
632 FileName
= FileName
.lstrip('<').rstrip('>').strip()
633 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
634 if FullPath
is not None and FullPath
not in IncludeFileQueue
:
635 IncludeFileQueue
.insert(i
+ 1, FullPath
)
638 AllIncludeFileListDict
[FullFileName
] = IncludeFileQueue
639 return IncludeFileQueue
641 def GetPredicateListFromPredicateExpStr(PES
):
648 p
= GetFuncDeclPattern()
649 while i
< len(PES
) - 1:
650 if (PES
[i
].isalnum() or PES
[i
] == '_' or PES
[i
] == '*') and LogicOpPos
> PredicateBegin
:
652 if (PES
[i
] == '&' and PES
[i
+ 1] == '&') or (PES
[i
] == '|' and PES
[i
+ 1] == '|'):
654 Exp
= PES
[PredicateBegin
:i
].strip()
655 # Exp may contain '.' or '->'
656 TmpExp
= Exp
.replace('.', '').replace('->', '')
658 PredicateList
.append(Exp
)
660 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
663 if PredicateBegin
> LogicOpPos
:
664 while PredicateBegin
< len(PES
):
665 if PES
[PredicateBegin
].isalnum() or PES
[PredicateBegin
] == '_' or PES
[PredicateBegin
] == '*':
668 Exp
= PES
[PredicateBegin
:len(PES
)].strip()
669 # Exp may contain '.' or '->'
670 TmpExp
= Exp
.replace('.', '').replace('->', '')
672 PredicateList
.append(Exp
)
674 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
677 def GetCNameList(Lvalue
, StarList
=[]):
685 while SearchBegin
< len(Lvalue
):
686 while i
< len(Lvalue
):
687 if Lvalue
[i
].isalnum() or Lvalue
[i
] == '_':
693 VarList
.append(Lvalue
[VarStart
:VarEnd
+ 1])
697 if VarStart
== -1 and Lvalue
[i
] == '*':
704 DotIndex
= Lvalue
[VarEnd
:].find('.')
705 ArrowIndex
= Lvalue
[VarEnd
:].find('->')
706 if DotIndex
== -1 and ArrowIndex
== -1:
708 elif DotIndex
== -1 and ArrowIndex
!= -1:
709 SearchBegin
= VarEnd
+ ArrowIndex
710 elif ArrowIndex
== -1 and DotIndex
!= -1:
711 SearchBegin
= VarEnd
+ DotIndex
713 SearchBegin
= VarEnd
+ ((DotIndex
< ArrowIndex
) and DotIndex
or ArrowIndex
)
721 def SplitPredicateByOp(Str
, Op
, IsFuncCalling
=False):
730 while Index
< len(Str
):
731 while not LBFound
and Str
[Index
] != '_' and not Str
[Index
].isalnum():
734 while not LBFound
and (Str
[Index
].isalnum() or Str
[Index
] == '_'):
736 # maybe type-cast at the beginning, skip it.
737 RemainingStr
= Str
[Index
:].lstrip()
738 if RemainingStr
.startswith(')') and not LBFound
:
742 if RemainingStr
.startswith('(') and not LBFound
:
745 if Str
[Index
] == '(':
746 UnmatchedLBCount
+= 1
750 if Str
[Index
] == ')':
751 UnmatchedLBCount
-= 1
753 if UnmatchedLBCount
== 0:
759 if UnmatchedLBCount
> 0:
762 IndexInRemainingStr
= Str
[Index
:].find(Op
)
763 if IndexInRemainingStr
== -1:
766 Name
= Str
[0:Index
+ IndexInRemainingStr
].strip()
767 Value
= Str
[Index
+ IndexInRemainingStr
+ len(Op
):].strip().strip(')')
770 TmpStr
= Str
.rstrip(';').rstrip(')')
772 Index
= TmpStr
.rfind(Op
)
776 if Str
[Index
- 1].isalnum() or Str
[Index
- 1].isspace() or Str
[Index
- 1] == ')' or Str
[Index
- 1] == ']':
777 Name
= Str
[0:Index
].strip()
778 Value
= Str
[Index
+ len(Op
):].strip()
781 TmpStr
= Str
[0:Index
- 1]
783 def SplitPredicateStr(Str
):
785 Str
= Str
.lstrip('(')
786 IsFuncCalling
= False
787 p
= GetFuncDeclPattern()
788 TmpStr
= Str
.replace('.', '').replace('->', '')
792 PredPartList
= SplitPredicateByOp(Str
, '==', IsFuncCalling
)
793 if len(PredPartList
) > 1:
794 return [PredPartList
, '==']
796 PredPartList
= SplitPredicateByOp(Str
, '!=', IsFuncCalling
)
797 if len(PredPartList
) > 1:
798 return [PredPartList
, '!=']
800 PredPartList
= SplitPredicateByOp(Str
, '>=', IsFuncCalling
)
801 if len(PredPartList
) > 1:
802 return [PredPartList
, '>=']
804 PredPartList
= SplitPredicateByOp(Str
, '<=', IsFuncCalling
)
805 if len(PredPartList
) > 1:
806 return [PredPartList
, '<=']
808 PredPartList
= SplitPredicateByOp(Str
, '>', IsFuncCalling
)
809 if len(PredPartList
) > 1:
810 return [PredPartList
, '>']
812 PredPartList
= SplitPredicateByOp(Str
, '<', IsFuncCalling
)
813 if len(PredPartList
) > 1:
814 return [PredPartList
, '<']
816 return [[Str
, None], None]
818 def GetFuncContainsPE(ExpLine
, ResultSet
):
819 for Result
in ResultSet
:
820 if Result
[0] < ExpLine
and Result
[1] > ExpLine
:
824 def PatternInModifier(Modifier
, SubStr
):
825 PartList
= Modifier
.split()
826 for Part
in PartList
:
831 def GetDataTypeFromModifier(ModifierStr
):
832 MList
= ModifierStr
.split()
835 if M
in EccGlobalData
.gConfig
.ModifierSet
:
837 # remove array suffix
838 if M
.startswith('[') or M
.endswith(']'):
840 ReturnType
+= M
+ ' '
842 ReturnType
= ReturnType
.strip()
843 if len(ReturnType
) == 0:
847 def DiffModifier(Str1
, Str2
):
848 PartList1
= Str1
.split()
849 PartList2
= Str2
.split()
850 if PartList1
== PartList2
:
855 def GetTypedefDict(FullFileName
):
857 Dict
= ComplexTypeDict
.get(FullFileName
)
861 FileID
= GetTableID(FullFileName
)
862 FileTable
= 'Identifier' + str(FileID
)
864 SqlStatement
= """ select Modifier, Name, Value, ID
867 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
868 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
871 for Result
in ResultSet
:
872 if len(Result
[0]) == 0:
873 Dict
[Result
[1]] = Result
[2]
875 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
876 for F
in IncludeFileList
:
877 FileID
= GetTableID(F
)
881 FileTable
= 'Identifier' + str(FileID
)
882 SqlStatement
= """ select Modifier, Name, Value, ID
885 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
886 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
888 for Result
in ResultSet
:
889 if not Result
[2].startswith('FP ('):
890 Dict
[Result
[1]] = Result
[2]
892 if len(Result
[0]) == 0:
893 Dict
[Result
[1]] = 'VOID'
895 Dict
[Result
[1]] = GetDataTypeFromModifier(Result
[0])
897 ComplexTypeDict
[FullFileName
] = Dict
900 def GetSUDict(FullFileName
):
902 Dict
= SUDict
.get(FullFileName
)
906 FileID
= GetTableID(FullFileName
)
907 FileTable
= 'Identifier' + str(FileID
)
909 SqlStatement
= """ select Name, Value, ID
911 where Model = %d or Model = %d
912 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
913 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
916 for Result
in ResultSet
:
917 if len(Result
[1]) > 0:
918 Dict
[Result
[0]] = Result
[1]
920 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
921 for F
in IncludeFileList
:
922 FileID
= GetTableID(F
)
926 FileTable
= 'Identifier' + str(FileID
)
927 SqlStatement
= """ select Name, Value, ID
929 where Model = %d or Model = %d
930 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
931 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
933 for Result
in ResultSet
:
934 if len(Result
[1]) > 0:
935 Dict
[Result
[0]] = Result
[1]
937 SUDict
[FullFileName
] = Dict
940 def StripComments(Str
):
942 ListFromStr
= list(Str
)
945 DoubleSlashComment
= False
947 while Index
< len(ListFromStr
):
948 # meet new line, then no longer in a comment for //
949 if ListFromStr
[Index
] == '\n':
950 if InComment
and DoubleSlashComment
:
952 DoubleSlashComment
= False
954 # check for */ comment end
955 elif InComment
and not DoubleSlashComment
and ListFromStr
[Index
] == '*' and ListFromStr
[Index
+ 1] == '/':
956 ListFromStr
[Index
] = ' '
958 ListFromStr
[Index
] = ' '
961 # set comments to spaces
963 ListFromStr
[Index
] = ' '
965 # check for // comment
966 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '/':
968 DoubleSlashComment
= True
970 # check for /* comment start
971 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '*':
972 ListFromStr
[Index
] = ' '
974 ListFromStr
[Index
] = ' '
980 # restore from List to String
981 Str
= "".join(ListFromStr
)
982 Str
= Str
.rstrip(' ')
986 def GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
):
987 Value
= TypedefDict
.get(Type
)
989 Value
= SUDict
.get(Type
)
993 LBPos
= Value
.find('{')
995 FTList
= Value
.split()
997 if FT
not in ('struct', 'union'):
998 Value
= TypedefDict
.get(FT
)
1000 Value
= SUDict
.get(FT
)
1006 LBPos
= Value
.find('{')
1008 # RBPos = Value.find('}')
1009 Fields
= Value
[LBPos
+ 1:]
1010 Fields
= StripComments(Fields
)
1011 FieldsList
= Fields
.split(';')
1012 for Field
in FieldsList
:
1013 Field
= Field
.strip()
1014 Index
= Field
.rfind(FieldName
)
1017 if not Field
[Index
- 1].isalnum():
1018 if Index
+ len(FieldName
) == len(Field
):
1019 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1022 # For the condition that the field in struct is an array with [] suffixes...
1023 if not Field
[Index
+ len(FieldName
)].isalnum():
1024 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1029 def GetRealType(Type
, TypedefDict
, TargetType
=None):
1030 if TargetType
is not None and Type
== TargetType
:
1032 while TypedefDict
.get(Type
):
1033 Type
= TypedefDict
.get(Type
)
1034 if TargetType
is not None and Type
== TargetType
:
1038 def GetTypeInfo(RefList
, Modifier
, FullFileName
, TargetType
=None):
1039 TypedefDict
= GetTypedefDict(FullFileName
)
1040 SUDict
= GetSUDict(FullFileName
)
1041 Type
= GetDataTypeFromModifier(Modifier
).replace('*', '').strip()
1043 Type
= Type
.split()[-1]
1045 while Index
< len(RefList
):
1046 FieldName
= RefList
[Index
]
1047 FromType
= GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
)
1048 if FromType
is None:
1050 # we want to determine the exact type.
1051 if TargetType
is not None:
1052 Type
= FromType
.split()[0]
1053 # we only want to check if it is a pointer
1056 if Type
.find('*') != -1 and Index
== len(RefList
) - 1:
1058 Type
= FromType
.split()[0]
1062 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1066 def GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
=False, TargetType
=None, StarList
=None):
1068 PredVar
= PredVarList
[0]
1069 FileID
= GetTableID(FullFileName
)
1072 FileTable
= 'Identifier' + str(FileID
)
1073 # search variable in include files
1075 # it is a function call, search function declarations and definitions
1077 SqlStatement
= """ select Modifier, ID
1079 where Model = %d and Value = \'%s\'
1080 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1081 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1083 for Result
in ResultSet
:
1084 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1085 TypedefDict
= GetTypedefDict(FullFileName
)
1086 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1089 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1090 for F
in IncludeFileList
:
1091 FileID
= GetTableID(F
)
1095 FileTable
= 'Identifier' + str(FileID
)
1096 SqlStatement
= """ select Modifier, ID
1098 where Model = %d and Value = \'%s\'
1099 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1100 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1102 for Result
in ResultSet
:
1103 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1104 TypedefDict
= GetTypedefDict(FullFileName
)
1105 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1108 FileID
= GetTableID(FullFileName
)
1109 SqlStatement
= """ select Modifier, ID
1111 where BelongsToFile = %d and Name = \'%s\'
1112 """ % (FileID
, PredVar
)
1113 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1115 for Result
in ResultSet
:
1116 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1117 TypedefDict
= GetTypedefDict(FullFileName
)
1118 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1121 for F
in IncludeFileList
:
1122 FileID
= GetTableID(F
)
1126 FileTable
= 'Identifier' + str(FileID
)
1127 SqlStatement
= """ select Modifier, ID
1129 where BelongsToFile = %d and Name = \'%s\'
1130 """ % (FileID
, PredVar
)
1131 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1133 for Result
in ResultSet
:
1134 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1135 TypedefDict
= GetTypedefDict(FullFileName
)
1136 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1141 # really variable, search local variable first
1142 SqlStatement
= """ select Modifier, ID
1144 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1145 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
, FuncRecord
[0], FuncRecord
[1])
1146 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1148 for Result
in ResultSet
:
1149 if len(PredVarList
) > 1:
1150 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1153 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1154 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1156 if len(TypeList
) > 1 and StarList
is not None:
1157 for Star
in StarList
:
1159 Type
= Type
.rstrip(Star
)
1160 # Get real type after de-reference pointers.
1161 if len(Type
.strip()) == 0:
1163 TypedefDict
= GetTypedefDict(FullFileName
)
1164 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1167 # search function parameters second
1168 ParamList
= GetParamList(FuncRecord
[2])
1169 for Param
in ParamList
:
1170 if Param
.Name
.strip() == PredVar
:
1171 if len(PredVarList
) > 1:
1172 Type
= GetTypeInfo(PredVarList
[1:], Param
.Modifier
, FullFileName
, TargetType
)
1175 TypeList
= GetDataTypeFromModifier(Param
.Modifier
).split()
1177 if Type
== '*' and len(TypeList
) >= 2:
1179 if len(TypeList
) > 1 and StarList
is not None:
1180 for Star
in StarList
:
1182 Type
= Type
.rstrip(Star
)
1183 # Get real type after de-reference pointers.
1184 if len(Type
.strip()) == 0:
1186 TypedefDict
= GetTypedefDict(FullFileName
)
1187 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1190 # search global variable next
1191 SqlStatement
= """ select Modifier, ID
1193 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1194 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1195 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1197 for Result
in ResultSet
:
1198 if len(PredVarList
) > 1:
1199 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1202 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1204 if len(TypeList
) > 1 and StarList
is not None:
1205 for Star
in StarList
:
1207 Type
= Type
.rstrip(Star
)
1208 # Get real type after de-reference pointers.
1209 if len(Type
.strip()) == 0:
1211 TypedefDict
= GetTypedefDict(FullFileName
)
1212 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1215 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1216 for F
in IncludeFileList
:
1217 FileID
= GetTableID(F
)
1221 FileTable
= 'Identifier' + str(FileID
)
1222 SqlStatement
= """ select Modifier, ID
1224 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1225 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1226 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1228 for Result
in ResultSet
:
1229 if len(PredVarList
) > 1:
1230 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1233 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1235 if len(TypeList
) > 1 and StarList
is not None:
1236 for Star
in StarList
:
1238 Type
= Type
.rstrip(Star
)
1239 # Get real type after de-reference pointers.
1240 if len(Type
.strip()) == 0:
1242 TypedefDict
= GetTypedefDict(FullFileName
)
1243 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1246 def GetTypeFromArray(Type
, Var
):
1247 Count
= Var
.count('[')
1251 Type
= Type
.rstrip('*')
1256 def CheckFuncLayoutReturnType(FullFileName
):
1259 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1264 FileTable
= 'Identifier' + str(FileID
)
1265 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1268 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1269 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1270 for Result
in ResultSet
:
1271 ReturnType
= GetDataTypeFromModifier(Result
[0])
1272 TypeStart
= ReturnType
.split()[0]
1273 FuncName
= Result
[5]
1274 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1277 if Result0
.upper().startswith('STATIC'):
1278 Result0
= Result0
[6:].strip()
1279 Index
= Result0
.find(TypeStart
)
1280 if Index
!= 0 or Result
[3] != 0:
1281 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1283 if Result
[2] == Result
[4]:
1284 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1286 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1288 where BelongsToFile = %d
1290 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1291 for Result
in ResultSet
:
1292 ReturnType
= GetDataTypeFromModifier(Result
[0])
1293 TypeStart
= ReturnType
.split()[0]
1294 FuncName
= Result
[5]
1295 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1298 if Result0
.upper().startswith('STATIC'):
1299 Result0
= Result0
[6:].strip()
1300 Index
= Result0
.find(TypeStart
)
1301 if Index
!= 0 or Result
[3] != 0:
1302 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1304 def CheckFuncLayoutModifier(FullFileName
):
1307 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1312 FileTable
= 'Identifier' + str(FileID
)
1313 SqlStatement
= """ select Modifier, ID
1316 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1317 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1318 for Result
in ResultSet
:
1319 ReturnType
= GetDataTypeFromModifier(Result
[0])
1320 TypeStart
= ReturnType
.split()[0]
1322 if Result0
.upper().startswith('STATIC'):
1323 Result0
= Result0
[6:].strip()
1324 Index
= Result0
.find(TypeStart
)
1326 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1328 SqlStatement
= """ select Modifier, ID
1330 where BelongsToFile = %d
1332 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1333 for Result
in ResultSet
:
1334 ReturnType
= GetDataTypeFromModifier(Result
[0])
1335 TypeStart
= ReturnType
.split()[0]
1337 if Result0
.upper().startswith('STATIC'):
1338 Result0
= Result0
[6:].strip()
1339 Index
= Result0
.find(TypeStart
)
1341 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1343 def CheckFuncLayoutName(FullFileName
):
1345 # Parameter variable format pattern.
1346 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1347 ParamIgnoreList
= ('VOID', '...')
1348 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1353 FileTable
= 'Identifier' + str(FileID
)
1354 SqlStatement
= """ select Name, ID, EndColumn, Value
1357 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1358 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1359 for Result
in ResultSet
:
1360 FuncName
= Result
[3]
1361 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1364 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1365 ParamList
= GetParamList(Result
[0])
1366 if len(ParamList
) == 0:
1369 for Param
in ParamList
:
1370 if Param
.StartLine
<= StartLine
:
1371 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1372 if Param
.StartLine
- StartLine
> 1:
1373 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1374 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
):
1375 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1376 StartLine
= Param
.StartLine
1378 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1379 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1381 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1383 where BelongsToFile = %d
1385 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1386 for Result
in ResultSet
:
1387 FuncName
= Result
[3]
1388 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1391 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1392 ParamList
= GetParamList(Result
[0])
1393 if len(ParamList
) == 0:
1396 for Param
in ParamList
:
1397 if Param
.StartLine
<= StartLine
:
1398 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1399 if Param
.StartLine
- StartLine
> 1:
1400 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1401 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
):
1402 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1403 StartLine
= Param
.StartLine
1404 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1405 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1407 def CheckFuncLayoutPrototype(FullFileName
):
1410 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1414 FileTable
= 'Identifier' + str(FileID
)
1416 SqlStatement
= """ select Modifier, Header, Name, ID
1418 where BelongsToFile = %d
1420 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1421 if len(ResultSet
) == 0:
1425 for Result
in ResultSet
:
1426 FuncDefList
.append(Result
)
1428 SqlStatement
= """ select Modifier, Name, ID
1431 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1432 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1434 for Result
in ResultSet
:
1435 FuncDeclList
.append(Result
)
1438 for FuncDef
in FuncDefList
:
1439 FuncName
= FuncDef
[2].strip()
1440 FuncModifier
= FuncDef
[0]
1441 FuncDefHeader
= FuncDef
[1]
1442 for FuncDecl
in FuncDeclList
:
1443 LBPos
= FuncDecl
[1].find('(')
1444 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1445 DeclModifier
= FuncDecl
[0]
1446 if DeclName
== FuncName
:
1447 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1448 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1449 ParamListOfDef
= GetParamList(FuncDefHeader
)
1450 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1451 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1452 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1456 while Index
< len(ParamListOfDef
):
1457 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1458 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])
1462 UndeclFuncList
.append(FuncDef
)
1464 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1466 for F
in IncludeFileList
:
1467 FileID
= GetTableID(F
, ErrorMsgList
)
1471 FileTable
= 'Identifier' + str(FileID
)
1472 SqlStatement
= """ select Modifier, Name, ID
1475 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1476 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1478 for Result
in ResultSet
:
1479 FuncDeclList
.append(Result
)
1481 for FuncDef
in UndeclFuncList
:
1482 FuncName
= FuncDef
[2].strip()
1483 FuncModifier
= FuncDef
[0]
1484 FuncDefHeader
= FuncDef
[1]
1485 for FuncDecl
in FuncDeclList
:
1486 LBPos
= FuncDecl
[1].find('(')
1487 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1488 DeclModifier
= FuncDecl
[0]
1489 if DeclName
== FuncName
:
1490 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1491 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1492 ParamListOfDef
= GetParamList(FuncDefHeader
)
1493 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1494 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1495 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1499 while Index
< len(ParamListOfDef
):
1500 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1501 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])
1505 def CheckFuncLayoutBody(FullFileName
):
1508 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1512 FileTable
= 'Identifier' + str(FileID
)
1514 SqlStatement
= """ select BodyStartColumn, EndColumn, ID, Name
1516 where BelongsToFile = %d
1518 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1519 if len(ResultSet
) == 0:
1521 for Result
in ResultSet
:
1523 if not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, Result
[3]):
1524 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
,
1525 'The open brace should be at the very beginning of a line for the function [%s].' % Result
[3],
1526 'Function', Result
[2])
1528 if not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, Result
[3]):
1529 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
,
1530 'The close brace should be at the very beginning of a line for the function [%s].' % Result
[3],
1531 'Function', Result
[2])
1533 def CheckFuncLayoutLocalVariable(FullFileName
):
1536 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1541 FileTable
= 'Identifier' + str(FileID
)
1542 SqlStatement
= """ select ID
1544 where BelongsToFile = %d
1546 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1547 if len(ResultSet
) == 0:
1550 for Result
in ResultSet
:
1554 SqlStatement
= """ select Name, Value, ID, Modifier
1556 where Model = %d and BelongsToFunction = %d
1557 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1558 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1559 if len(ResultSet
) == 0:
1562 for Result
in ResultSet
:
1563 if len(Result
[1]) > 0 and 'CONST' not in Result
[3]:
1564 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1566 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1568 # Member variable format pattern.
1569 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1571 LBPos
= Value
.find('{')
1572 RBPos
= Value
.rfind('}')
1573 if LBPos
== -1 or RBPos
== -1:
1576 Fields
= Value
[LBPos
+ 1 : RBPos
]
1577 Fields
= StripComments(Fields
).strip()
1578 NestPos
= Fields
.find ('struct')
1579 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)) and ModelId
!= DataClass
.MODEL_IDENTIFIER_UNION
:
1580 if not Fields
[NestPos
+ len('struct') + 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 struct in [%s].' % (Name
), FileTable
, TdId
)
1584 NestPos
= Fields
.find ('union')
1585 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1586 if not Fields
[NestPos
+ len('union') + 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 union in [%s].' % (Name
), FileTable
, TdId
)
1590 NestPos
= Fields
.find ('enum')
1591 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1592 if not Fields
[NestPos
+ len('enum') + 1].isalnum():
1593 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1594 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested enum in [%s].' % (Name
), FileTable
, TdId
)
1597 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1598 FieldsList
= Fields
.split(',')
1599 # deal with enum is pre-assigned a value by function call ( , , , ...)
1602 RemoveCurrentElement
= False
1603 while Index
< len(FieldsList
):
1604 Field
= FieldsList
[Index
]
1606 if Field
.find('(') != -1:
1608 RemoveCurrentElement
= True
1612 if Field
.find(')') != -1 and QuoteCount
> 0:
1615 if RemoveCurrentElement
:
1616 FieldsList
.remove(Field
)
1618 RemoveCurrentElement
= False
1622 RemoveCurrentElement
= False
1626 FieldsList
= Fields
.split(';')
1628 for Field
in FieldsList
:
1629 Field
= Field
.strip()
1632 # For the condition that the field in struct is an array with [] suffixes...
1633 if Field
[-1] == ']':
1634 LBPos
= Field
.find('[')
1635 Field
= Field
[0:LBPos
]
1636 # For the condition that bit field ": Number"
1637 if Field
.find(':') != -1:
1638 ColonPos
= Field
.find(':')
1639 Field
= Field
[0:ColonPos
]
1641 Field
= Field
.strip()
1644 if Field
.startswith("#"):
1646 # Enum could directly assign value to variable
1647 Field
= Field
.split('=')[0].strip()
1648 TokenList
= Field
.split()
1649 # Remove pointers before variable
1650 Token
= TokenList
[-1]
1651 if Token
in ['OPTIONAL']:
1652 Token
= TokenList
[-2]
1653 if not Pattern
.match(Token
.lstrip('*')):
1654 ErrMsgList
.append(Token
.lstrip('*'))
1658 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1661 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1666 FileTable
= 'Identifier' + str(FileID
)
1667 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1670 """ % (FileTable
, ModelId
)
1671 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1673 for Result
in ResultSet
:
1674 ResultList
.append(Result
)
1676 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1677 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1678 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1679 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1680 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1681 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1682 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1684 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1687 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1688 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1692 # Check member variable name format that from typedefs of ONLY this file.
1694 Name
= Td
[1].strip()
1695 Value
= Td
[2].strip()
1696 if Value
.startswith('enum'):
1697 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1698 elif Value
.startswith('struct'):
1699 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1700 elif Value
.startswith('union'):
1701 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1705 if ValueModelId
!= ModelId
:
1707 # Check member variable format.
1708 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1709 for ErrMsg
in ErrMsgList
:
1710 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+ '.' + ErrMsg
):
1712 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+ '.' + ErrMsg
), FileTable
, Td
[5])
1714 # First check in current file to see whether struct/union/enum is typedef-ed.
1715 UntypedefedList
= []
1716 for Result
in ResultList
:
1717 # Check member variable format.
1718 Name
= Result
[0].strip()
1719 Value
= Result
[4].strip()
1720 if Value
.startswith('enum'):
1721 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1722 elif Value
.startswith('struct'):
1723 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1724 elif Value
.startswith('union'):
1725 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1729 if ValueModelId
!= ModelId
:
1731 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1732 for ErrMsg
in ErrMsgList
:
1733 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0] + '.' + ErrMsg
):
1735 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0] + '.' + ErrMsg
), FileTable
, Result
[3])
1736 # Check whether it is typedefed.
1739 # skip function pointer
1742 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1744 if not Td
[1].isupper():
1745 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1746 if Result
[0] in Td
[2].split():
1748 if not Td
[1].isupper():
1749 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1754 UntypedefedList
.append(Result
)
1757 if len(UntypedefedList
) == 0:
1760 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1762 for F
in IncludeFileList
:
1763 FileID
= GetTableID(F
, ErrorMsgList
)
1767 IncludeFileTable
= 'Identifier' + str(FileID
)
1768 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1771 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1772 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1773 TdList
.extend(ResultSet
)
1775 for Result
in UntypedefedList
:
1777 # Check whether it is typedefed.
1783 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1785 if not Td
[1].isupper():
1786 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1787 if Result
[0] in Td
[2].split():
1789 if not Td
[1].isupper():
1790 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1795 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1798 def CheckDeclStructTypedef(FullFileName
):
1799 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1801 def CheckDeclEnumTypedef(FullFileName
):
1802 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1804 def CheckDeclUnionTypedef(FullFileName
):
1805 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1807 def CheckDeclArgModifier(FullFileName
):
1810 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1815 FileTable
= 'Identifier' + str(FileID
)
1816 SqlStatement
= """ select Modifier, Name, ID
1819 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1820 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1821 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1822 MAX_MODIFIER_LENGTH
= 100
1823 for Result
in ResultSet
:
1824 for Modifier
in ModifierTuple
:
1825 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1826 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1829 SqlStatement
= """ select Modifier, Name, ID
1832 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1833 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1834 for Result
in ResultSet
:
1835 for Modifier
in ModifierTuple
:
1836 if PatternInModifier(Result
[0], Modifier
):
1837 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1840 SqlStatement
= """ select Modifier, Header, ID
1842 where BelongsToFile = %d
1844 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1845 for Result
in ResultSet
:
1846 for Modifier
in ModifierTuple
:
1847 if PatternInModifier(Result
[0], Modifier
):
1848 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1851 def CheckDeclNoUseCType(FullFileName
):
1854 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1859 FileTable
= 'Identifier' + str(FileID
)
1860 SqlStatement
= """ select Modifier, Name, ID
1863 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1864 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1865 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1866 for Result
in ResultSet
:
1867 for Type
in CTypeTuple
:
1868 if PatternInModifier(Result
[0], Type
):
1869 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1870 Result
[0] + ' ' + Result
[1]):
1872 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1873 'Invalid variable type (%s) in definition [%s]' % (Type
, Result
[0] + ' ' + Result
[1]),
1878 SqlStatement
= """ select Modifier, Name, ID, Value
1881 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1882 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1883 for Result
in ResultSet
:
1884 ParamList
= GetParamList(Result
[1])
1885 FuncName
= Result
[3]
1886 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1888 for Type
in CTypeTuple
:
1889 if PatternInModifier(Result
[0], Type
):
1890 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1892 for Param
in ParamList
:
1893 if PatternInModifier(Param
.Modifier
, Type
):
1894 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1896 SqlStatement
= """ select Modifier, Header, ID, Name
1898 where BelongsToFile = %d
1900 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1901 for Result
in ResultSet
:
1902 ParamList
= GetParamList(Result
[1])
1903 FuncName
= Result
[3]
1904 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1906 for Type
in CTypeTuple
:
1907 if PatternInModifier(Result
[0], Type
):
1908 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1910 for Param
in ParamList
:
1911 if PatternInModifier(Param
.Modifier
, Type
):
1912 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1915 def CheckPointerNullComparison(FullFileName
):
1918 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1922 # cache the found function return type to accelerate later checking in this file.
1923 FuncReturnTypeDict
= {}
1926 FileTable
= 'Identifier' + str(FileID
)
1927 SqlStatement
= """ select Value, StartLine, ID
1930 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1931 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1932 if len(ResultSet
) == 0:
1935 for Result
in ResultSet
:
1936 PSL
.append([Result
[0], Result
[1], Result
[2]])
1938 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1940 where BelongsToFile = %d
1942 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1944 for Result
in ResultSet
:
1945 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1947 p
= GetFuncDeclPattern()
1949 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1950 if FuncRecord
is None:
1953 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1954 PredInfo
= SplitPredicateStr(Exp
)
1955 if PredInfo
[1] is None:
1956 PredVarStr
= PredInfo
[0][0].strip()
1958 SearchInCache
= False
1959 # PredVarStr may contain '.' or '->'
1960 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1962 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1963 SearchInCache
= True
1964 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1965 if TmpStr
.startswith(PredVarStr
):
1968 if PredVarStr
.strip() in IgnoredKeywordList
:
1971 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1972 # No variable found, maybe value first? like (0 == VarName)
1973 if len(PredVarList
) == 0:
1976 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1977 if Type
is not None:
1978 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1979 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1982 if PredVarStr
in FuncReturnTypeDict
:
1985 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1987 FuncReturnTypeDict
[PredVarStr
] = Type
1990 Type
= GetTypeFromArray(Type
, PredVarStr
)
1991 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1992 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1994 def CheckNonBooleanValueComparison(FullFileName
):
1997 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2001 # cache the found function return type to accelerate later checking in this file.
2002 FuncReturnTypeDict
= {}
2005 FileTable
= 'Identifier' + str(FileID
)
2006 SqlStatement
= """ select Value, StartLine, ID
2009 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2010 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2011 if len(ResultSet
) == 0:
2014 for Result
in ResultSet
:
2015 PSL
.append([Result
[0], Result
[1], Result
[2]])
2017 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2019 where BelongsToFile = %d
2021 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2023 for Result
in ResultSet
:
2024 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2026 p
= GetFuncDeclPattern()
2028 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2029 if FuncRecord
is None:
2032 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2033 PredInfo
= SplitPredicateStr(Exp
)
2034 if PredInfo
[1] is None:
2035 PredVarStr
= PredInfo
[0][0].strip()
2037 SearchInCache
= False
2038 # PredVarStr may contain '.' or '->'
2039 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2041 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2042 SearchInCache
= True
2043 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2044 if TmpStr
.startswith(PredVarStr
):
2047 if PredVarStr
.strip() in IgnoredKeywordList
:
2050 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2051 # No variable found, maybe value first? like (0 == VarName)
2052 if len(PredVarList
) == 0:
2056 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2057 if Type
is not None:
2058 if Type
.find('BOOLEAN') == -1:
2059 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2062 if PredVarStr
in FuncReturnTypeDict
:
2064 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2066 FuncReturnTypeDict
[PredVarStr
] = Type
2069 if Type
.find('BOOLEAN') == -1:
2070 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2073 def CheckBooleanValueComparison(FullFileName
):
2076 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2080 # cache the found function return type to accelerate later checking in this file.
2081 FuncReturnTypeDict
= {}
2084 FileTable
= 'Identifier' + str(FileID
)
2085 SqlStatement
= """ select Value, StartLine, ID
2088 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2089 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2090 if len(ResultSet
) == 0:
2093 for Result
in ResultSet
:
2094 PSL
.append([Result
[0], Result
[1], Result
[2]])
2096 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2098 where BelongsToFile = %d
2100 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2102 for Result
in ResultSet
:
2103 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2105 p
= GetFuncDeclPattern()
2107 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2108 if FuncRecord
is None:
2111 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2112 PredInfo
= SplitPredicateStr(Exp
)
2113 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2114 PredVarStr
= PredInfo
[0][0].strip()
2116 SearchInCache
= False
2117 # PredVarStr may contain '.' or '->'
2118 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2120 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2121 SearchInCache
= True
2122 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2123 if TmpStr
.startswith(PredVarStr
):
2126 if PredVarStr
.strip() in IgnoredKeywordList
:
2129 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2130 # No variable found, maybe value first? like (0 == VarName)
2131 if len(PredVarList
) == 0:
2135 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2136 if Type
is not None:
2137 if Type
.find('BOOLEAN') != -1:
2138 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2141 if PredVarStr
in FuncReturnTypeDict
:
2144 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2146 FuncReturnTypeDict
[PredVarStr
] = Type
2149 if Type
.find('BOOLEAN') != -1:
2150 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2153 def CheckHeaderFileData(FullFileName
, AllTypedefFun
=[]):
2156 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2161 FileTable
= 'Identifier' + str(FileID
)
2162 SqlStatement
= """ select ID, Modifier
2165 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2166 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2167 for Result
in ResultSet
:
2168 if not Result
[1].startswith('extern'):
2169 for Item
in AllTypedefFun
:
2170 if '(%s)' % Result
[1] in Item
:
2173 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2175 SqlStatement
= """ select ID
2177 where BelongsToFile = %d
2179 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2180 for Result
in ResultSet
:
2181 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2185 def CheckHeaderFileIfndef(FullFileName
):
2188 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2193 FileTable
= 'Identifier' + str(FileID
)
2194 SqlStatement
= """ select Value, StartLine
2196 where Model = %d order by StartLine
2197 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2198 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2199 if len(ResultSet
) == 0:
2200 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2202 for Result
in ResultSet
:
2203 SqlStatement
= """ select Value, EndLine
2206 """ % (FileTable
, Result
[1])
2207 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2208 for Result
in ResultSet
:
2209 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2210 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2
, '', 'File', FileID
)
2213 SqlStatement
= """ select Value
2215 where StartLine > (select max(EndLine) from %s where Model = %d)
2216 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2217 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2218 for Result
in ResultSet
:
2219 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2220 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2223 def CheckDoxygenCommand(FullFileName
):
2226 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2231 FileTable
= 'Identifier' + str(FileID
)
2232 SqlStatement
= """ select Value, ID
2234 where Model = %d or Model = %d
2235 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2236 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2237 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval',
2238 'return', 'sa', 'since', 'test', 'note', 'par', 'endcode', 'code']
2239 for Result
in ResultSet
:
2240 CommentStr
= Result
[0]
2241 CommentPartList
= CommentStr
.split()
2242 for Part
in CommentPartList
:
2243 if Part
.upper() == 'BUGBUG':
2244 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2245 if Part
.upper() == 'TODO':
2246 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2247 if Part
.startswith('@'):
2248 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2250 if not Part
.replace('@', '').strip():
2252 if Part
.lstrip('@') in ['{', '}']:
2254 if Part
.lstrip('@').isalpha():
2255 if Part
.lstrip('@') not in DoxygenCommandList
:
2256 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2258 Index
= Part
.find('[')
2260 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2261 RealCmd
= Part
[1:Index
]
2262 if RealCmd
not in DoxygenCommandList
:
2263 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2266 def CheckDoxygenTripleForwardSlash(FullFileName
):
2269 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2275 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2277 where BelongsToFile = %d
2279 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2280 if len(ResultSet
) == 0:
2284 for Result
in ResultSet
:
2285 FuncDefSet
.append(Result
)
2288 FileTable
= 'Identifier' + str(FileID
)
2289 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2293 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2294 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2297 for Result
in ResultSet
:
2298 CommentSet
.append(Result
)
2300 print('Unrecognized chars in comment of file %s', FullFileName
)
2303 for Result
in CommentSet
:
2304 CommentStr
= Result
[0]
2305 StartLine
= Result
[2]
2306 StartColumn
= Result
[3]
2308 EndColumn
= Result
[5]
2309 if not CommentStr
.startswith('///<'):
2313 for FuncDef
in FuncDefSet
:
2314 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2317 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2320 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2323 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2327 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2330 def CheckFileHeaderDoxygenComments(FullFileName
):
2333 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2338 FileTable
= 'Identifier' + str(FileID
)
2339 SqlStatement
= """ select Value, ID
2341 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2342 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2343 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2344 if len(ResultSet
) == 0:
2345 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No File License header appear at the very beginning of file.', 'File', FileID
)
2348 NoHeaderCommentStartFlag
= True
2349 NoHeaderCommentEndFlag
= True
2350 NoHeaderCommentPeriodFlag
= True
2351 NoCopyrightFlag
= True
2352 NoLicenseFlag
= True
2353 NoRevReferFlag
= True
2355 for Result
in ResultSet
:
2356 FileStartFlag
= False
2358 CommentStr
= Result
[0].strip()
2359 CommentStrListTemp
= CommentStr
.split('\n')
2360 if (len(CommentStrListTemp
) <= 1):
2362 CommentStrListTemp
= CommentStr
.split('\r')
2363 # Skip the content before the file header
2364 for CommentLine
in CommentStrListTemp
:
2365 if CommentLine
.strip().startswith('/** @file'):
2366 FileStartFlag
= True
2367 if FileStartFlag
== True:
2368 CommentStrList
.append(CommentLine
)
2372 if CommentStrList
and CommentStrList
[0].strip().startswith('/** @file'):
2373 NoHeaderCommentStartFlag
= False
2376 if CommentStrList
and CommentStrList
[-1].strip().endswith('**/'):
2377 NoHeaderCommentEndFlag
= False
2381 for CommentLine
in CommentStrList
:
2383 NextLineIndex
= Index
2384 if CommentLine
.startswith('/** @file'):
2386 if CommentLine
.startswith('**/'):
2388 # Check whether C File header Comment content start with two spaces.
2389 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentStartSpacesNum
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2390 if CommentLine
.startswith('/** @file') == False and CommentLine
.startswith('**/') == False and CommentLine
.strip() and CommentLine
.startswith(' ') == False:
2391 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment content should start with two spaces at each line', FileTable
, ID
)
2393 CommentLine
= CommentLine
.strip()
2394 if CommentLine
.startswith('Copyright'):
2395 NoCopyrightFlag
= False
2396 if CommentLine
.find('All rights reserved') == -1:
2397 for Copyright
in EccGlobalData
.gConfig
.Copyright
:
2398 if CommentLine
.find(Copyright
) > -1:
2399 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable
, ID
)
2401 if CommentLine
.endswith('<BR>') == -1:
2402 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'The ""<BR>"" at the end of the Copyright line is required', FileTable
, ID
)
2403 if NextLineIndex
< len(CommentStrList
) and CommentStrList
[NextLineIndex
].strip().startswith('Copyright') == False and CommentStrList
[NextLineIndex
].strip():
2404 NoLicenseFlag
= False
2405 if CommentLine
.startswith('@par Revision Reference:'):
2406 NoRevReferFlag
= False
2408 for RefLine
in CommentStrList
[NextLineIndex
:]:
2409 if RefLine
.strip() and (NextLineIndex
+ 1) < len(CommentStrList
) and CommentStrList
[NextLineIndex
+1].strip() and CommentStrList
[NextLineIndex
+1].strip().startswith('**/') == False:
2411 if RefLine
.strip() == False or RefLine
.strip().startswith('**/'):
2414 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2415 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentReferenceFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2416 if RefListFlag
== True:
2417 if RefLine
.strip() and RefLine
.strip().startswith('**/') == False and RefLine
.startswith(' -') == False:
2418 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable
, ID
)
2420 if NoHeaderCommentStartFlag
:
2421 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, ID
)
2423 if NoHeaderCommentEndFlag
:
2424 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with ""**/""', FileTable
, ID
)
2427 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment missing the ""Copyright""', FileTable
, ID
)
2428 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2429 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentLicenseFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2431 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable
, ID
)
2433 def CheckFuncHeaderDoxygenComments(FullFileName
):
2436 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2441 FileTable
= 'Identifier' + str(FileID
)
2442 SqlStatement
= """ select Value, StartLine, EndLine, ID
2445 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2447 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2450 for Result
in ResultSet
:
2451 CommentSet
.append(Result
)
2453 print('Unrecognized chars in comment of file %s', FullFileName
)
2456 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2459 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2460 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2461 for Result
in ResultSet
:
2462 FuncName
= Result
[4]
2463 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2464 if FunctionHeaderComment
:
2465 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2467 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2469 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2470 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2473 SqlStatement
= """ select Value, StartLine, EndLine, ID
2476 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2478 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2481 for Result
in ResultSet
:
2482 CommentSet
.append(Result
)
2484 print('Unrecognized chars in comment of file %s', FullFileName
)
2486 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2488 where BelongsToFile = %d
2490 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2491 for Result
in ResultSet
:
2492 FuncName
= Result
[4]
2493 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2494 if FunctionHeaderComment
:
2495 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2497 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2499 ErrorMsgList
.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2500 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), 'Function', Result
[3])
2503 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2505 for Comment
in CommentSet
:
2506 if Comment
[2] == FuncStartLine
- 1:
2510 def GetDoxygenStrFromComment(Str
):
2512 ParamTagList
= Str
.split('@param')
2513 if len(ParamTagList
) > 1:
2515 while i
< len(ParamTagList
):
2516 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2519 Str
= ParamTagList
[0]
2521 RetvalTagList
= ParamTagList
[-1].split('@retval')
2522 if len(RetvalTagList
) > 1:
2523 if len(ParamTagList
) > 1:
2524 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2526 while i
< len(RetvalTagList
):
2527 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2530 ReturnTagList
= RetvalTagList
[-1].split('@return')
2531 if len(ReturnTagList
) > 1:
2532 if len(RetvalTagList
) > 1:
2533 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2534 elif len(ParamTagList
) > 1:
2535 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2537 while i
< len(ReturnTagList
):
2538 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2541 if len(DoxygenStrList
) > 0:
2542 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2544 return DoxygenStrList
2546 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2547 #/** --*/ @retval after @param
2548 if not Str
.startswith('/**'):
2549 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2550 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2551 if not Str
.endswith('**/'):
2552 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2553 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2554 FirstRetvalIndex
= Str
.find('@retval')
2555 LastParamIndex
= Str
.rfind('@param')
2556 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2557 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2558 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2560 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2562 ParamList
= GetParamList(FuncHeader
)
2563 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2564 DescriptionStr
= CommentStr
2565 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2566 if DescriptionStr
.find('.') == -1:
2567 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2568 DoxygenTagNumber
= len(DoxygenStrList
)
2569 ParamNumber
= len(ParamList
)
2570 for Param
in ParamList
:
2571 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2574 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2575 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2576 ParamModifier
= ParamList
[Index
].Modifier
2577 ParamName
= ParamList
[Index
].Name
.strip()
2578 Tag
= DoxygenStrList
[Index
].strip(' ')
2579 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2580 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2581 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, <%s> does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2582 TagPartList
= Tag
.split()
2583 if len(TagPartList
) < 2:
2584 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2585 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2588 LBPos
= Tag
.find('[')
2589 RBPos
= Tag
.find(']')
2590 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2591 if LBPos
> 0 and len(ParamToLBContent
) == 0 and RBPos
> LBPos
:
2593 ModifierPartList
= ParamModifier
.split()
2594 for Part
in ModifierPartList
:
2595 if Part
.strip() == 'IN':
2597 if Part
.strip() == 'OUT':
2604 if Tag
.find('[' + InOutStr
+ ']') == -1:
2605 if InOutStr
!= 'in, out':
2606 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2607 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2609 if Tag
.find('[in,out]') == -1:
2610 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2611 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2614 if Tag
.find(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2615 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2616 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
)
2619 if Index
< ParamNumber
:
2620 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2621 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2622 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2623 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2625 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2626 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2627 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2628 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2630 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2631 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2632 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2634 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
2635 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2636 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need NO doxygen tags in comment ', TableName
, CommentId
)
2637 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2638 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2639 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2641 if __name__
== '__main__':
2643 # EdkLogger.Initialize()
2644 # EdkLogger.SetLevel(EdkLogger.QUIET)
2645 # CollectSourceCodeDataIntoDB(sys.argv[1])
2647 test_file
= sys
.argv
[1]
2648 except IndexError as v
:
2649 print("Usage: %s filename" % sys
.argv
[0])
2651 MsgList
= CheckFuncHeaderDoxygenComments(test_file
)