2 # This file is used to be the c coding style checking of ECC tool
4 # Copyright (c) 2009 - 2018, 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
16 import Common
.LongFilePathOs
as os
19 import CodeFragmentCollector
21 from CommonDataClass
import DataClass
23 from Common
import EdkLogger
24 from EccToolError
import *
28 IncludeFileListDict
= {}
29 AllIncludeFileListDict
= {}
30 IncludePathListDict
= {}
33 IgnoredKeywordList
= ['EFI_ERROR']
35 def GetIgnoredDirListPattern():
36 skipList
= list(EccGlobalData
.gConfig
.SkipDirList
) + ['.svn']
37 DirString
= string
.join(skipList
, '|')
38 p
= re
.compile(r
'.*[\\/](?:%s)[\\/]?.*' % DirString
)
41 def GetFuncDeclPattern():
42 p
= re
.compile(r
'(?:EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re
.DOTALL
)
45 def GetArrayPattern():
46 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
49 def GetTypedefFuncPointerPattern():
50 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
54 return EccGlobalData
.gDb
57 return EccGlobalData
.gConfig
59 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
60 Msg
= Msg
.replace('\n', '').replace('\r', '')
61 MsgPartList
= Msg
.split()
63 for Part
in MsgPartList
:
66 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
=Msg
, BelongsToTable
=TableName
, BelongsToItem
=ItemId
)
69 Type
= DataClass
.MODEL_UNKNOWN
70 Str
= Str
.replace('#', '# ')
72 if List
[1] == 'include':
73 Type
= DataClass
.MODEL_IDENTIFIER_INCLUDE
74 elif List
[1] == 'define':
75 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_DEFINE
76 elif List
[1] == 'ifdef':
77 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFDEF
78 elif List
[1] == 'ifndef':
79 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
80 elif List
[1] == 'endif':
81 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
82 elif List
[1] == 'pragma':
83 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_PROGMA
85 Type
= DataClass
.MODEL_UNKNOWN
88 def SuOccurInTypedef (Su
, TdList
):
90 if Su
.StartPos
[0] == Td
.StartPos
[0] and Su
.EndPos
[0] == Td
.EndPos
[0]:
94 def GetIdentifierList():
96 for comment
in FileProfile
.CommentList
:
97 IdComment
= DataClass
.IdentifierClass(-1, '', '', '', comment
.Content
, DataClass
.MODEL_IDENTIFIER_COMMENT
, -1, -1, comment
.StartPos
[0], comment
.StartPos
[1], comment
.EndPos
[0], comment
.EndPos
[1])
98 IdList
.append(IdComment
)
100 for pp
in FileProfile
.PPDirectiveList
:
101 Type
= GetIdType(pp
.Content
)
102 IdPP
= DataClass
.IdentifierClass(-1, '', '', '', pp
.Content
, Type
, -1, -1, pp
.StartPos
[0], pp
.StartPos
[1], pp
.EndPos
[0], pp
.EndPos
[1])
105 for pe
in FileProfile
.PredicateExpressionList
:
106 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])
109 FuncDeclPattern
= GetFuncDeclPattern()
110 ArrayPattern
= GetArrayPattern()
111 for var
in FileProfile
.VariableDeclarationList
:
112 DeclText
= var
.Declarator
.lstrip()
113 FuncPointerPattern
= GetTypedefFuncPointerPattern()
114 if FuncPointerPattern
.match(DeclText
):
116 VarNameStartLine
= var
.NameStartPos
[0]
117 VarNameStartColumn
= var
.NameStartPos
[1]
118 FirstChar
= DeclText
[0]
119 while not FirstChar
.isalpha() and FirstChar
!= '_':
122 VarNameStartColumn
+= 1
123 DeclText
= DeclText
.lstrip('*')
124 elif FirstChar
== '\r':
125 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
126 VarNameStartLine
+= 1
127 VarNameStartColumn
= 0
128 elif FirstChar
== '\n':
129 DeclText
= DeclText
.lstrip('\n')
130 VarNameStartLine
+= 1
131 VarNameStartColumn
= 0
132 elif FirstChar
== ' ':
133 DeclText
= DeclText
.lstrip(' ')
134 VarNameStartColumn
+= 1
135 elif FirstChar
== '\t':
136 DeclText
= DeclText
.lstrip('\t')
137 VarNameStartColumn
+= 8
139 DeclText
= DeclText
[1:]
140 VarNameStartColumn
+= 1
141 FirstChar
= DeclText
[0]
143 var
.Declarator
= DeclText
144 if FuncDeclPattern
.match(var
.Declarator
):
145 DeclSplitList
= var
.Declarator
.split('(')
146 FuncName
= DeclSplitList
[0].strip()
147 FuncNamePartList
= FuncName
.split()
148 if len(FuncNamePartList
) > 1:
149 FuncName
= FuncNamePartList
[-1].strip()
150 NameStart
= DeclSplitList
[0].rfind(FuncName
)
151 var
.Declarator
= var
.Declarator
[NameStart
:]
153 var
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
156 while Index
< NameStart
:
157 FirstChar
= DeclSplitList
[0][Index
]
158 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
160 VarNameStartColumn
+= 6
163 elif FirstChar
== '\r':
165 VarNameStartLine
+= 1
166 VarNameStartColumn
= 0
167 elif FirstChar
== '\n':
170 VarNameStartLine
+= 1
171 VarNameStartColumn
= 0
172 elif FirstChar
== ' ':
174 VarNameStartColumn
+= 1
175 elif FirstChar
== '\t':
177 VarNameStartColumn
+= 8
180 VarNameStartColumn
+= 1
182 IdVar
= DataClass
.IdentifierClass(-1, var
.Modifier
, '', var
.Declarator
, FuncName
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, -1, -1, var
.StartPos
[0], var
.StartPos
[1], VarNameStartLine
, VarNameStartColumn
)
186 if var
.Declarator
.find('{') == -1:
187 for decl
in var
.Declarator
.split(','):
188 DeclList
= decl
.split('=')
189 Name
= DeclList
[0].strip()
190 if ArrayPattern
.match(Name
):
191 LSBPos
= var
.Declarator
.find('[')
192 var
.Modifier
+= ' ' + Name
[LSBPos
:]
193 Name
= Name
[0:LSBPos
]
195 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
)
198 DeclList
= var
.Declarator
.split('=')
199 Name
= DeclList
[0].strip()
200 if ArrayPattern
.match(Name
):
201 LSBPos
= var
.Declarator
.find('[')
202 var
.Modifier
+= ' ' + Name
[LSBPos
:]
203 Name
= Name
[0:LSBPos
]
204 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
)
207 for enum
in FileProfile
.EnumerationDefinitionList
:
208 LBPos
= enum
.Content
.find('{')
209 RBPos
= enum
.Content
.find('}')
210 Name
= enum
.Content
[4:LBPos
].strip()
211 Value
= enum
.Content
[LBPos
+ 1:RBPos
]
212 IdEnum
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
, -1, -1, enum
.StartPos
[0], enum
.StartPos
[1], enum
.EndPos
[0], enum
.EndPos
[1])
213 IdList
.append(IdEnum
)
215 for su
in FileProfile
.StructUnionDefinitionList
:
216 if SuOccurInTypedef(su
, FileProfile
.TypedefDefinitionList
):
218 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
220 if su
.Content
.startswith('union'):
221 Type
= DataClass
.MODEL_IDENTIFIER_UNION
223 LBPos
= su
.Content
.find('{')
224 RBPos
= su
.Content
.find('}')
225 if LBPos
== -1 or RBPos
== -1:
226 Name
= su
.Content
[SkipLen
:].strip()
229 Name
= su
.Content
[SkipLen
:LBPos
].strip()
230 Value
= su
.Content
[LBPos
:RBPos
+ 1]
231 IdPE
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, Type
, -1, -1, su
.StartPos
[0], su
.StartPos
[1], su
.EndPos
[0], su
.EndPos
[1])
234 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
235 for td
in FileProfile
.TypedefDefinitionList
:
239 if TdFuncPointerPattern
.match(td
.ToType
):
240 Modifier
= td
.FromType
241 LBPos
= td
.ToType
.find('(')
242 TmpStr
= td
.ToType
[LBPos
+ 1:].strip()
243 StarPos
= TmpStr
.find('*')
245 Modifier
+= ' ' + TmpStr
[0:StarPos
]
246 while TmpStr
[StarPos
] == '*':
247 # Modifier += ' ' + '*'
249 TmpStr
= TmpStr
[StarPos
:].strip()
250 RBPos
= TmpStr
.find(')')
251 Name
= TmpStr
[0:RBPos
]
252 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
254 while Name
.startswith('*'):
256 Name
= Name
.lstrip('*').strip()
258 if Name
.find('[') != -1:
259 LBPos
= Name
.find('[')
260 RBPos
= Name
.rfind(']')
261 Value
+= Name
[LBPos
: RBPos
+ 1]
262 Name
= Name
[0 : LBPos
]
264 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])
267 for funcCall
in FileProfile
.FunctionCallingList
:
268 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])
272 def StripNonAlnumChars(Str
):
275 if Char
.isalnum() or Char
== '_':
279 def GetParamList(FuncDeclarator
, FuncNameLine
=0, FuncNameOffset
=0):
280 FuncDeclarator
= StripComments(FuncDeclarator
)
282 #DeclSplitList = FuncDeclarator.split('(')
283 LBPos
= FuncDeclarator
.find('(')
284 #if len(DeclSplitList) < 2:
287 #FuncName = DeclSplitList[0]
288 FuncName
= FuncDeclarator
[0:LBPos
]
289 #ParamStr = DeclSplitList[1].rstrip(')')
290 ParamStr
= FuncDeclarator
[LBPos
+ 1:].rstrip(')')
293 TailChar
= FuncName
[-1]
294 while not TailChar
.isalpha() and TailChar
!= '_':
297 FuncName
= FuncName
.rstrip('\r\n').rstrip('\n')
300 elif TailChar
== '\r':
301 FuncName
= FuncName
.rstrip('\r')
304 elif TailChar
== ' ':
305 FuncName
= FuncName
.rstrip(' ')
307 elif TailChar
== '\t':
308 FuncName
= FuncName
.rstrip('\t')
311 FuncName
= FuncName
[:-1]
312 TailChar
= FuncName
[-1]
314 OffsetSkipped
+= 1 #skip '('
316 for p
in ParamStr
.split(','):
320 ParamName
= ListP
[-1]
321 DeclText
= ParamName
.strip()
322 RightSpacePos
= p
.rfind(ParamName
)
323 ParamModifier
= p
[0:RightSpacePos
]
324 if ParamName
== 'OPTIONAL':
325 if ParamModifier
== '':
326 ParamModifier
+= ' ' + 'OPTIONAL'
329 ParamName
= ListP
[-2]
330 DeclText
= ParamName
.strip()
331 RightSpacePos
= p
.rfind(ParamName
)
332 ParamModifier
= p
[0:RightSpacePos
]
333 ParamModifier
+= 'OPTIONAL'
334 while DeclText
.startswith('*'):
335 ParamModifier
+= ' ' + '*'
336 DeclText
= DeclText
.lstrip('*').strip()
338 # ignore array length if exists.
339 LBIndex
= ParamName
.find('[')
341 ParamName
= ParamName
[0:LBIndex
]
343 Start
= RightSpacePos
349 if FirstChar
== '\r':
353 elif FirstChar
== '\n':
358 elif FirstChar
== ' ':
361 elif FirstChar
== '\t':
369 ParamBeginLine
= FuncNameLine
+ LineSkipped
370 ParamBeginOffset
= FuncNameOffset
+ OffsetSkipped
372 Index
= Start
+ len(ParamName
)
374 while Index
< len(p
):
377 if FirstChar
== '\r':
381 elif FirstChar
== '\n':
386 elif FirstChar
== ' ':
389 elif FirstChar
== '\t':
397 ParamEndLine
= FuncNameLine
+ LineSkipped
398 ParamEndOffset
= FuncNameOffset
+ OffsetSkipped
399 if ParamName
!= '...':
400 ParamName
= StripNonAlnumChars(ParamName
)
401 IdParam
= DataClass
.IdentifierClass(-1, ParamModifier
, '', ParamName
, '', DataClass
.MODEL_IDENTIFIER_PARAMETER
, -1, -1, ParamBeginLine
, ParamBeginOffset
, ParamEndLine
, ParamEndOffset
)
402 ParamIdList
.append(IdParam
)
404 OffsetSkipped
+= 1 #skip ','
408 def GetFunctionList():
410 for FuncDef
in FileProfile
.FunctionDefinitionList
:
412 DeclText
= FuncDef
.Declarator
.lstrip()
413 FuncNameStartLine
= FuncDef
.NamePos
[0]
414 FuncNameStartColumn
= FuncDef
.NamePos
[1]
415 FirstChar
= DeclText
[0]
416 while not FirstChar
.isalpha() and FirstChar
!= '_':
418 FuncDef
.Modifier
+= '*'
419 FuncNameStartColumn
+= 1
420 DeclText
= DeclText
.lstrip('*')
421 elif FirstChar
== '\r':
422 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
423 FuncNameStartLine
+= 1
424 FuncNameStartColumn
= 0
425 elif FirstChar
== '\n':
426 DeclText
= DeclText
.lstrip('\n')
427 FuncNameStartLine
+= 1
428 FuncNameStartColumn
= 0
429 elif FirstChar
== ' ':
430 DeclText
= DeclText
.lstrip(' ')
431 FuncNameStartColumn
+= 1
432 elif FirstChar
== '\t':
433 DeclText
= DeclText
.lstrip('\t')
434 FuncNameStartColumn
+= 8
436 DeclText
= DeclText
[1:]
437 FuncNameStartColumn
+= 1
438 FirstChar
= DeclText
[0]
440 FuncDef
.Declarator
= DeclText
441 DeclSplitList
= FuncDef
.Declarator
.split('(')
442 if len(DeclSplitList
) < 2:
445 FuncName
= DeclSplitList
[0]
446 FuncNamePartList
= FuncName
.split()
447 if len(FuncNamePartList
) > 1:
448 FuncName
= FuncNamePartList
[-1]
449 NameStart
= DeclSplitList
[0].rfind(FuncName
)
451 FuncDef
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
454 while Index
< NameStart
:
455 FirstChar
= DeclSplitList
[0][Index
]
456 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
458 FuncNameStartColumn
+= 6
461 elif FirstChar
== '\r':
463 FuncNameStartLine
+= 1
464 FuncNameStartColumn
= 0
465 elif FirstChar
== '\n':
468 FuncNameStartLine
+= 1
469 FuncNameStartColumn
= 0
470 elif FirstChar
== ' ':
472 FuncNameStartColumn
+= 1
473 elif FirstChar
== '\t':
475 FuncNameStartColumn
+= 8
478 FuncNameStartColumn
+= 1
481 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
)
482 FuncObjList
.append(FuncObj
)
486 def GetFileModificationTimeFromDB(FullFileName
):
489 SqlStatement
= """ select TimeStamp
491 where FullPath = \'%s\'
493 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
494 for Result
in ResultSet
:
495 TimeValue
= Result
[0]
498 def CollectSourceCodeDataIntoDB(RootDir
):
500 tuple = os
.walk(RootDir
)
501 IgnoredPattern
= GetIgnoredDirListPattern()
502 ParseErrorFileList
= []
504 for dirpath
, dirnames
, filenames
in tuple:
505 if IgnoredPattern
.match(dirpath
.upper()):
509 Dirname
= os
.path
.join(dirpath
, Dir
)
510 if os
.path
.islink(Dirname
):
511 Dirname
= os
.path
.realpath(Dirname
)
512 if os
.path
.isdir(Dirname
):
513 # symlinks to directories are treated as directories
515 dirnames
.append(Dirname
)
518 if f
.lower() in EccGlobalData
.gConfig
.SkipFileList
:
521 FullName
= os
.path
.normpath(os
.path
.join(dirpath
, f
))
522 model
= DataClass
.MODEL_FILE_OTHERS
523 if os
.path
.splitext(f
)[1] in ('.h', '.c'):
524 EdkLogger
.info("Parsing " + FullName
)
525 model
= f
.endswith('c') and DataClass
.MODEL_FILE_C
or DataClass
.MODEL_FILE_H
526 collector
= CodeFragmentCollector
.CodeFragmentCollector(FullName
)
528 collector
.ParseFile()
530 ParseErrorFileList
.append(FullName
)
531 collector
.CleanFileProfileBuffer()
532 collector
.ParseFileWithClearedPPDirective()
533 # collector.PrintFragments()
534 BaseName
= os
.path
.basename(f
)
535 DirName
= os
.path
.dirname(FullName
)
536 Ext
= os
.path
.splitext(f
)[1].lstrip('.')
537 ModifiedTime
= os
.path
.getmtime(FullName
)
538 FileObj
= DataClass
.FileClass(-1, BaseName
, Ext
, DirName
, FullName
, model
, ModifiedTime
, GetFunctionList(), GetIdentifierList(), [])
539 FileObjList
.append(FileObj
)
541 collector
.CleanFileProfileBuffer()
543 if len(ParseErrorFileList
) > 0:
544 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
547 for file in FileObjList
:
548 if file.ExtName
.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
549 Db
.InsertOneFile(file)
551 Db
.UpdateIdentifierBelongsToFunction()
553 def GetTableID(FullFileName
, ErrorMsgList
=None):
554 if ErrorMsgList
is None:
558 SqlStatement
= """ select ID
560 where FullPath like '%s'
562 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
565 for Result
in ResultSet
:
567 ErrorMsgList
.append('Duplicate file ID found in DB for file %s' % FullFileName
)
571 ErrorMsgList
.append('NO file ID found in DB for file %s' % FullFileName
)
575 def GetIncludeFileList(FullFileName
):
576 if os
.path
.splitext(FullFileName
)[1].upper() not in ('.H'):
578 IFList
= IncludeFileListDict
.get(FullFileName
)
579 if IFList
is not None:
582 FileID
= GetTableID(FullFileName
)
587 FileTable
= 'Identifier' + str(FileID
)
588 SqlStatement
= """ select Value
591 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_INCLUDE
)
592 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
593 IncludeFileListDict
[FullFileName
] = ResultSet
596 def GetFullPathOfIncludeFile(Str
, IncludePathList
):
597 for IncludePath
in IncludePathList
:
598 FullPath
= os
.path
.join(IncludePath
, Str
)
599 FullPath
= os
.path
.normpath(FullPath
)
600 if os
.path
.exists(FullPath
):
604 def GetAllIncludeFiles(FullFileName
):
605 if AllIncludeFileListDict
.get(FullFileName
) is not None:
606 return AllIncludeFileListDict
.get(FullFileName
)
608 FileDirName
= os
.path
.dirname(FullFileName
)
609 IncludePathList
= IncludePathListDict
.get(FileDirName
)
610 if IncludePathList
is None:
611 IncludePathList
= MetaDataParser
.GetIncludeListOfFile(EccGlobalData
.gWorkspace
, FullFileName
, GetDB())
612 if FileDirName
not in IncludePathList
:
613 IncludePathList
.insert(0, FileDirName
)
614 IncludePathListDict
[FileDirName
] = IncludePathList
615 IncludeFileQueue
= []
616 for IncludeFile
in GetIncludeFileList(FullFileName
):
617 FileName
= IncludeFile
[0].lstrip('#').strip()
618 FileName
= FileName
.lstrip('include').strip()
619 FileName
= FileName
.strip('\"')
620 FileName
= FileName
.lstrip('<').rstrip('>').strip()
621 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
622 if FullPath
is not None:
623 IncludeFileQueue
.append(FullPath
)
626 while i
< len(IncludeFileQueue
):
627 for IncludeFile
in GetIncludeFileList(IncludeFileQueue
[i
]):
628 FileName
= IncludeFile
[0].lstrip('#').strip()
629 FileName
= FileName
.lstrip('include').strip()
630 FileName
= FileName
.strip('\"')
631 FileName
= FileName
.lstrip('<').rstrip('>').strip()
632 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
633 if FullPath
is not None and FullPath
not in IncludeFileQueue
:
634 IncludeFileQueue
.insert(i
+ 1, FullPath
)
637 AllIncludeFileListDict
[FullFileName
] = IncludeFileQueue
638 return IncludeFileQueue
640 def GetPredicateListFromPredicateExpStr(PES
):
647 p
= GetFuncDeclPattern()
648 while i
< len(PES
) - 1:
649 if (PES
[i
].isalnum() or PES
[i
] == '_' or PES
[i
] == '*') and LogicOpPos
> PredicateBegin
:
651 if (PES
[i
] == '&' and PES
[i
+ 1] == '&') or (PES
[i
] == '|' and PES
[i
+ 1] == '|'):
653 Exp
= PES
[PredicateBegin
:i
].strip()
654 # Exp may contain '.' or '->'
655 TmpExp
= Exp
.replace('.', '').replace('->', '')
657 PredicateList
.append(Exp
)
659 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
662 if PredicateBegin
> LogicOpPos
:
663 while PredicateBegin
< len(PES
):
664 if PES
[PredicateBegin
].isalnum() or PES
[PredicateBegin
] == '_' or PES
[PredicateBegin
] == '*':
667 Exp
= PES
[PredicateBegin
:len(PES
)].strip()
668 # Exp may contain '.' or '->'
669 TmpExp
= Exp
.replace('.', '').replace('->', '')
671 PredicateList
.append(Exp
)
673 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
676 def GetCNameList(Lvalue
, StarList
=[]):
684 while SearchBegin
< len(Lvalue
):
685 while i
< len(Lvalue
):
686 if Lvalue
[i
].isalnum() or Lvalue
[i
] == '_':
692 VarList
.append(Lvalue
[VarStart
:VarEnd
+ 1])
696 if VarStart
== -1 and Lvalue
[i
] == '*':
703 DotIndex
= Lvalue
[VarEnd
:].find('.')
704 ArrowIndex
= Lvalue
[VarEnd
:].find('->')
705 if DotIndex
== -1 and ArrowIndex
== -1:
707 elif DotIndex
== -1 and ArrowIndex
!= -1:
708 SearchBegin
= VarEnd
+ ArrowIndex
709 elif ArrowIndex
== -1 and DotIndex
!= -1:
710 SearchBegin
= VarEnd
+ DotIndex
712 SearchBegin
= VarEnd
+ ((DotIndex
< ArrowIndex
) and DotIndex
or ArrowIndex
)
720 def SplitPredicateByOp(Str
, Op
, IsFuncCalling
=False):
729 while Index
< len(Str
):
730 while not LBFound
and Str
[Index
] != '_' and not Str
[Index
].isalnum():
733 while not LBFound
and (Str
[Index
].isalnum() or Str
[Index
] == '_'):
735 # maybe type-cast at the begining, skip it.
736 RemainingStr
= Str
[Index
:].lstrip()
737 if RemainingStr
.startswith(')') and not LBFound
:
741 if RemainingStr
.startswith('(') and not LBFound
:
744 if Str
[Index
] == '(':
745 UnmatchedLBCount
+= 1
749 if Str
[Index
] == ')':
750 UnmatchedLBCount
-= 1
752 if UnmatchedLBCount
== 0:
758 if UnmatchedLBCount
> 0:
761 IndexInRemainingStr
= Str
[Index
:].find(Op
)
762 if IndexInRemainingStr
== -1:
765 Name
= Str
[0:Index
+ IndexInRemainingStr
].strip()
766 Value
= Str
[Index
+ IndexInRemainingStr
+ len(Op
):].strip().strip(')')
769 TmpStr
= Str
.rstrip(';').rstrip(')')
771 Index
= TmpStr
.rfind(Op
)
775 if Str
[Index
- 1].isalnum() or Str
[Index
- 1].isspace() or Str
[Index
- 1] == ')' or Str
[Index
- 1] == ']':
776 Name
= Str
[0:Index
].strip()
777 Value
= Str
[Index
+ len(Op
):].strip()
780 TmpStr
= Str
[0:Index
- 1]
782 def SplitPredicateStr(Str
):
784 Str
= Str
.lstrip('(')
785 IsFuncCalling
= False
786 p
= GetFuncDeclPattern()
787 TmpStr
= Str
.replace('.', '').replace('->', '')
791 PredPartList
= SplitPredicateByOp(Str
, '==', IsFuncCalling
)
792 if len(PredPartList
) > 1:
793 return [PredPartList
, '==']
795 PredPartList
= SplitPredicateByOp(Str
, '!=', IsFuncCalling
)
796 if len(PredPartList
) > 1:
797 return [PredPartList
, '!=']
799 PredPartList
= SplitPredicateByOp(Str
, '>=', IsFuncCalling
)
800 if len(PredPartList
) > 1:
801 return [PredPartList
, '>=']
803 PredPartList
= SplitPredicateByOp(Str
, '<=', IsFuncCalling
)
804 if len(PredPartList
) > 1:
805 return [PredPartList
, '<=']
807 PredPartList
= SplitPredicateByOp(Str
, '>', IsFuncCalling
)
808 if len(PredPartList
) > 1:
809 return [PredPartList
, '>']
811 PredPartList
= SplitPredicateByOp(Str
, '<', IsFuncCalling
)
812 if len(PredPartList
) > 1:
813 return [PredPartList
, '<']
815 return [[Str
, None], None]
817 def GetFuncContainsPE(ExpLine
, ResultSet
):
818 for Result
in ResultSet
:
819 if Result
[0] < ExpLine
and Result
[1] > ExpLine
:
823 def PatternInModifier(Modifier
, SubStr
):
824 PartList
= Modifier
.split()
825 for Part
in PartList
:
830 def GetDataTypeFromModifier(ModifierStr
):
831 MList
= ModifierStr
.split()
834 if M
in EccGlobalData
.gConfig
.ModifierSet
:
837 if M
.startswith('[') or M
.endswith(']'):
839 ReturnType
+= M
+ ' '
841 ReturnType
= ReturnType
.strip()
842 if len(ReturnType
) == 0:
846 def DiffModifier(Str1
, Str2
):
847 PartList1
= Str1
.split()
848 PartList2
= Str2
.split()
849 if PartList1
== PartList2
:
854 def GetTypedefDict(FullFileName
):
856 Dict
= ComplexTypeDict
.get(FullFileName
)
860 FileID
= GetTableID(FullFileName
)
861 FileTable
= 'Identifier' + str(FileID
)
863 SqlStatement
= """ select Modifier, Name, Value, ID
866 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
867 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
870 for Result
in ResultSet
:
871 if len(Result
[0]) == 0:
872 Dict
[Result
[1]] = Result
[2]
874 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
875 for F
in IncludeFileList
:
876 FileID
= GetTableID(F
)
880 FileTable
= 'Identifier' + str(FileID
)
881 SqlStatement
= """ select Modifier, Name, Value, ID
884 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
885 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
887 for Result
in ResultSet
:
888 if not Result
[2].startswith('FP ('):
889 Dict
[Result
[1]] = Result
[2]
891 if len(Result
[0]) == 0:
892 Dict
[Result
[1]] = 'VOID'
894 Dict
[Result
[1]] = GetDataTypeFromModifier(Result
[0])
896 ComplexTypeDict
[FullFileName
] = Dict
899 def GetSUDict(FullFileName
):
901 Dict
= SUDict
.get(FullFileName
)
905 FileID
= GetTableID(FullFileName
)
906 FileTable
= 'Identifier' + str(FileID
)
908 SqlStatement
= """ select Name, Value, ID
910 where Model = %d or Model = %d
911 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
912 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
915 for Result
in ResultSet
:
916 if len(Result
[1]) > 0:
917 Dict
[Result
[0]] = Result
[1]
919 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
920 for F
in IncludeFileList
:
921 FileID
= GetTableID(F
)
925 FileTable
= 'Identifier' + str(FileID
)
926 SqlStatement
= """ select Name, Value, ID
928 where Model = %d or Model = %d
929 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
930 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
932 for Result
in ResultSet
:
933 if len(Result
[1]) > 0:
934 Dict
[Result
[0]] = Result
[1]
936 SUDict
[FullFileName
] = Dict
939 def StripComments(Str
):
941 ListFromStr
= list(Str
)
944 DoubleSlashComment
= False
946 while Index
< len(ListFromStr
):
947 # meet new line, then no longer in a comment for //
948 if ListFromStr
[Index
] == '\n':
949 if InComment
and DoubleSlashComment
:
951 DoubleSlashComment
= False
953 # check for */ comment end
954 elif InComment
and not DoubleSlashComment
and ListFromStr
[Index
] == '*' and ListFromStr
[Index
+ 1] == '/':
955 ListFromStr
[Index
] = ' '
957 ListFromStr
[Index
] = ' '
960 # set comments to spaces
962 ListFromStr
[Index
] = ' '
964 # check for // comment
965 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '/' and ListFromStr
[Index
+ 2] != '\n':
967 DoubleSlashComment
= True
969 # check for /* comment start
970 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '*':
971 ListFromStr
[Index
] = ' '
973 ListFromStr
[Index
] = ' '
979 # restore from List to String
980 Str
= "".join(ListFromStr
)
981 Str
= Str
.rstrip(' ')
985 def GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
):
986 Value
= TypedefDict
.get(Type
)
988 Value
= SUDict
.get(Type
)
992 LBPos
= Value
.find('{')
994 FTList
= Value
.split()
996 if FT
not in ('struct', 'union'):
997 Value
= TypedefDict
.get(FT
)
999 Value
= SUDict
.get(FT
)
1005 LBPos
= Value
.find('{')
1007 # RBPos = Value.find('}')
1008 Fields
= Value
[LBPos
+ 1:]
1009 Fields
= StripComments(Fields
)
1010 FieldsList
= Fields
.split(';')
1011 for Field
in FieldsList
:
1012 Field
= Field
.strip()
1013 Index
= Field
.rfind(FieldName
)
1016 if not Field
[Index
- 1].isalnum():
1017 if Index
+ len(FieldName
) == len(Field
):
1018 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1021 # For the condition that the field in struct is an array with [] sufixes...
1022 if not Field
[Index
+ len(FieldName
)].isalnum():
1023 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1028 def GetRealType(Type
, TypedefDict
, TargetType
=None):
1029 if TargetType
is not None and Type
== TargetType
:
1031 while TypedefDict
.get(Type
):
1032 Type
= TypedefDict
.get(Type
)
1033 if TargetType
is not None and Type
== TargetType
:
1037 def GetTypeInfo(RefList
, Modifier
, FullFileName
, TargetType
=None):
1038 TypedefDict
= GetTypedefDict(FullFileName
)
1039 SUDict
= GetSUDict(FullFileName
)
1040 Type
= GetDataTypeFromModifier(Modifier
).replace('*', '').strip()
1042 Type
= Type
.split()[-1]
1044 while Index
< len(RefList
):
1045 FieldName
= RefList
[Index
]
1046 FromType
= GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
)
1047 if FromType
is None:
1049 # we want to determine the exact type.
1050 if TargetType
is not None:
1051 Type
= FromType
.split()[0]
1052 # we only want to check if it is a pointer
1055 if Type
.find('*') != -1 and Index
== len(RefList
) - 1:
1057 Type
= FromType
.split()[0]
1061 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1065 def GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
=False, TargetType
=None, StarList
=None):
1067 PredVar
= PredVarList
[0]
1068 FileID
= GetTableID(FullFileName
)
1071 FileTable
= 'Identifier' + str(FileID
)
1072 # search variable in include files
1074 # it is a function call, search function declarations and definitions
1076 SqlStatement
= """ select Modifier, ID
1078 where Model = %d and Value = \'%s\'
1079 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1080 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1082 for Result
in ResultSet
:
1083 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1084 TypedefDict
= GetTypedefDict(FullFileName
)
1085 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1088 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1089 for F
in IncludeFileList
:
1090 FileID
= GetTableID(F
)
1094 FileTable
= 'Identifier' + str(FileID
)
1095 SqlStatement
= """ select Modifier, ID
1097 where Model = %d and Value = \'%s\'
1098 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1099 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1101 for Result
in ResultSet
:
1102 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1103 TypedefDict
= GetTypedefDict(FullFileName
)
1104 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1107 FileID
= GetTableID(FullFileName
)
1108 SqlStatement
= """ select Modifier, ID
1110 where BelongsToFile = %d and Name = \'%s\'
1111 """ % (FileID
, PredVar
)
1112 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1114 for Result
in ResultSet
:
1115 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1116 TypedefDict
= GetTypedefDict(FullFileName
)
1117 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1120 for F
in IncludeFileList
:
1121 FileID
= GetTableID(F
)
1125 FileTable
= 'Identifier' + str(FileID
)
1126 SqlStatement
= """ select Modifier, ID
1128 where BelongsToFile = %d and Name = \'%s\'
1129 """ % (FileID
, PredVar
)
1130 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1132 for Result
in ResultSet
:
1133 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1134 TypedefDict
= GetTypedefDict(FullFileName
)
1135 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1140 # really variable, search local variable first
1141 SqlStatement
= """ select Modifier, ID
1143 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1144 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
, FuncRecord
[0], FuncRecord
[1])
1145 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1147 for Result
in ResultSet
:
1148 if len(PredVarList
) > 1:
1149 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1152 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1153 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1155 if len(TypeList
) > 1 and StarList
is not None:
1156 for Star
in StarList
:
1158 Type
= Type
.rstrip(Star
)
1159 # Get real type after de-reference pointers.
1160 if len(Type
.strip()) == 0:
1162 TypedefDict
= GetTypedefDict(FullFileName
)
1163 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1166 # search function parameters second
1167 ParamList
= GetParamList(FuncRecord
[2])
1168 for Param
in ParamList
:
1169 if Param
.Name
.strip() == PredVar
:
1170 if len(PredVarList
) > 1:
1171 Type
= GetTypeInfo(PredVarList
[1:], Param
.Modifier
, FullFileName
, TargetType
)
1174 TypeList
= GetDataTypeFromModifier(Param
.Modifier
).split()
1176 if Type
== '*' and len(TypeList
) >= 2:
1178 if len(TypeList
) > 1 and StarList
is not None:
1179 for Star
in StarList
:
1181 Type
= Type
.rstrip(Star
)
1182 # Get real type after de-reference pointers.
1183 if len(Type
.strip()) == 0:
1185 TypedefDict
= GetTypedefDict(FullFileName
)
1186 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1189 # search global variable next
1190 SqlStatement
= """ select Modifier, ID
1192 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1193 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1194 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1196 for Result
in ResultSet
:
1197 if len(PredVarList
) > 1:
1198 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1201 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1203 if len(TypeList
) > 1 and StarList
is not None:
1204 for Star
in StarList
:
1206 Type
= Type
.rstrip(Star
)
1207 # Get real type after de-reference pointers.
1208 if len(Type
.strip()) == 0:
1210 TypedefDict
= GetTypedefDict(FullFileName
)
1211 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1214 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1215 for F
in IncludeFileList
:
1216 FileID
= GetTableID(F
)
1220 FileTable
= 'Identifier' + str(FileID
)
1221 SqlStatement
= """ select Modifier, ID
1223 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1224 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1225 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1227 for Result
in ResultSet
:
1228 if len(PredVarList
) > 1:
1229 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1232 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1234 if len(TypeList
) > 1 and StarList
is not None:
1235 for Star
in StarList
:
1237 Type
= Type
.rstrip(Star
)
1238 # Get real type after de-reference pointers.
1239 if len(Type
.strip()) == 0:
1241 TypedefDict
= GetTypedefDict(FullFileName
)
1242 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1245 def GetTypeFromArray(Type
, Var
):
1246 Count
= Var
.count('[')
1250 Type
= Type
.rstrip('*')
1255 def CheckFuncLayoutReturnType(FullFileName
):
1258 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1263 FileTable
= 'Identifier' + str(FileID
)
1264 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1267 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1268 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1269 for Result
in ResultSet
:
1270 ReturnType
= GetDataTypeFromModifier(Result
[0])
1271 TypeStart
= ReturnType
.split()[0]
1272 FuncName
= Result
[5]
1273 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1276 if Result0
.upper().startswith('STATIC'):
1277 Result0
= Result0
[6:].strip()
1278 Index
= Result0
.find(TypeStart
)
1279 if Index
!= 0 or Result
[3] != 0:
1280 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1282 if Result
[2] == Result
[4]:
1283 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1285 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1287 where BelongsToFile = %d
1289 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1290 for Result
in ResultSet
:
1291 ReturnType
= GetDataTypeFromModifier(Result
[0])
1292 TypeStart
= ReturnType
.split()[0]
1293 FuncName
= Result
[5]
1294 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1297 if Result0
.upper().startswith('STATIC'):
1298 Result0
= Result0
[6:].strip()
1299 Index
= Result0
.find(ReturnType
)
1300 if Index
!= 0 or Result
[3] != 0:
1301 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1303 def CheckFuncLayoutModifier(FullFileName
):
1306 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1311 FileTable
= 'Identifier' + str(FileID
)
1312 SqlStatement
= """ select Modifier, ID
1315 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1316 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1317 for Result
in ResultSet
:
1318 ReturnType
= GetDataTypeFromModifier(Result
[0])
1319 TypeStart
= ReturnType
.split()[0]
1321 if Result0
.upper().startswith('STATIC'):
1322 Result0
= Result0
[6:].strip()
1323 Index
= Result0
.find(TypeStart
)
1325 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1327 SqlStatement
= """ select Modifier, ID
1329 where BelongsToFile = %d
1331 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1332 for Result
in ResultSet
:
1333 ReturnType
= GetDataTypeFromModifier(Result
[0])
1334 TypeStart
= ReturnType
.split()[0]
1336 if Result0
.upper().startswith('STATIC'):
1337 Result0
= Result0
[6:].strip()
1338 Index
= Result0
.find(TypeStart
)
1340 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1342 def CheckFuncLayoutName(FullFileName
):
1344 # Parameter variable format pattern.
1345 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1346 ParamIgnoreList
= ('VOID', '...')
1347 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1352 FileTable
= 'Identifier' + str(FileID
)
1353 SqlStatement
= """ select Name, ID, EndColumn, Value
1356 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1357 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1358 for Result
in ResultSet
:
1359 FuncName
= Result
[3]
1360 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1363 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1364 ParamList
= GetParamList(Result
[0])
1365 if len(ParamList
) == 0:
1368 for Param
in ParamList
:
1369 if Param
.StartLine
<= StartLine
:
1370 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1371 if Param
.StartLine
- StartLine
> 1:
1372 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1373 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
):
1374 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1375 StartLine
= Param
.StartLine
1377 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1378 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1380 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1382 where BelongsToFile = %d
1384 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1385 for Result
in ResultSet
:
1386 FuncName
= Result
[3]
1387 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1390 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1391 ParamList
= GetParamList(Result
[0])
1392 if len(ParamList
) == 0:
1395 for Param
in ParamList
:
1396 if Param
.StartLine
<= StartLine
:
1397 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1398 if Param
.StartLine
- StartLine
> 1:
1399 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1400 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
):
1401 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1402 StartLine
= Param
.StartLine
1403 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1404 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1406 def CheckFuncLayoutPrototype(FullFileName
):
1409 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1413 FileTable
= 'Identifier' + str(FileID
)
1415 SqlStatement
= """ select Modifier, Header, Name, ID
1417 where BelongsToFile = %d
1419 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1420 if len(ResultSet
) == 0:
1424 for Result
in ResultSet
:
1425 FuncDefList
.append(Result
)
1427 SqlStatement
= """ select Modifier, Name, ID
1430 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1431 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1433 for Result
in ResultSet
:
1434 FuncDeclList
.append(Result
)
1437 for FuncDef
in FuncDefList
:
1438 FuncName
= FuncDef
[2].strip()
1439 FuncModifier
= FuncDef
[0]
1440 FuncDefHeader
= FuncDef
[1]
1441 for FuncDecl
in FuncDeclList
:
1442 LBPos
= FuncDecl
[1].find('(')
1443 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1444 DeclModifier
= FuncDecl
[0]
1445 if DeclName
== FuncName
:
1446 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1447 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1448 ParamListOfDef
= GetParamList(FuncDefHeader
)
1449 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1450 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1451 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1455 while Index
< len(ParamListOfDef
):
1456 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1457 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])
1461 UndeclFuncList
.append(FuncDef
)
1463 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1465 for F
in IncludeFileList
:
1466 FileID
= GetTableID(F
, ErrorMsgList
)
1470 FileTable
= 'Identifier' + str(FileID
)
1471 SqlStatement
= """ select Modifier, Name, ID
1474 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1475 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1477 for Result
in ResultSet
:
1478 FuncDeclList
.append(Result
)
1480 for FuncDef
in UndeclFuncList
:
1481 FuncName
= FuncDef
[2].strip()
1482 FuncModifier
= FuncDef
[0]
1483 FuncDefHeader
= FuncDef
[1]
1484 for FuncDecl
in FuncDeclList
:
1485 LBPos
= FuncDecl
[1].find('(')
1486 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1487 DeclModifier
= FuncDecl
[0]
1488 if DeclName
== FuncName
:
1489 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1490 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1491 ParamListOfDef
= GetParamList(FuncDefHeader
)
1492 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1493 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1494 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1498 while Index
< len(ParamListOfDef
):
1499 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1500 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])
1504 def CheckFuncLayoutBody(FullFileName
):
1507 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1511 FileTable
= 'Identifier' + str(FileID
)
1513 SqlStatement
= """ select BodyStartColumn, EndColumn, ID
1515 where BelongsToFile = %d
1517 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1518 if len(ResultSet
) == 0:
1520 for Result
in ResultSet
:
1522 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'open brace should be at the very beginning of a line.', 'Function', Result
[2])
1524 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'close brace should be at the very beginning of a line.', 'Function', Result
[2])
1526 def CheckFuncLayoutLocalVariable(FullFileName
):
1529 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1534 FileTable
= 'Identifier' + str(FileID
)
1535 SqlStatement
= """ select ID
1537 where BelongsToFile = %d
1539 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1540 if len(ResultSet
) == 0:
1543 for Result
in ResultSet
:
1547 SqlStatement
= """ select Name, Value, ID, Modifier
1549 where Model = %d and BelongsToFunction = %d
1550 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1551 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1552 if len(ResultSet
) == 0:
1555 for Result
in ResultSet
:
1556 if len(Result
[1]) > 0 and 'CONST' not in Result
[3]:
1557 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1559 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1561 # Member variable format pattern.
1562 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1564 LBPos
= Value
.find('{')
1565 RBPos
= Value
.rfind('}')
1566 if LBPos
== -1 or RBPos
== -1:
1569 Fields
= Value
[LBPos
+ 1 : RBPos
]
1570 Fields
= StripComments(Fields
).strip()
1571 NestPos
= Fields
.find ('struct')
1572 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)) and ModelId
!= DataClass
.MODEL_IDENTIFIER_UNION
:
1573 if not Fields
[NestPos
+ len('struct') + 1].isalnum():
1574 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1575 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested struct in [%s].' % (Name
), FileTable
, TdId
)
1577 NestPos
= Fields
.find ('union')
1578 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1579 if not Fields
[NestPos
+ len('union') + 1].isalnum():
1580 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1581 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested union in [%s].' % (Name
), FileTable
, TdId
)
1583 NestPos
= Fields
.find ('enum')
1584 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1585 if not Fields
[NestPos
+ len('enum') + 1].isalnum():
1586 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1587 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested enum in [%s].' % (Name
), FileTable
, TdId
)
1590 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1591 FieldsList
= Fields
.split(',')
1592 # deal with enum is pre-assigned a value by function call ( , , , ...)
1595 RemoveCurrentElement
= False
1596 while Index
< len(FieldsList
):
1597 Field
= FieldsList
[Index
]
1599 if Field
.find('(') != -1:
1601 RemoveCurrentElement
= True
1605 if Field
.find(')') != -1 and QuoteCount
> 0:
1608 if RemoveCurrentElement
:
1609 FieldsList
.remove(Field
)
1611 RemoveCurrentElement
= False
1615 RemoveCurrentElement
= False
1619 FieldsList
= Fields
.split(';')
1621 for Field
in FieldsList
:
1622 Field
= Field
.strip()
1625 # For the condition that the field in struct is an array with [] sufixes...
1626 if Field
[-1] == ']':
1627 LBPos
= Field
.find('[')
1628 Field
= Field
[0:LBPos
]
1629 # For the condition that bit field ": Number"
1630 if Field
.find(':') != -1:
1631 ColonPos
= Field
.find(':')
1632 Field
= Field
[0:ColonPos
]
1634 Field
= Field
.strip()
1637 if Field
.startswith("#"):
1639 # Enum could directly assign value to variable
1640 Field
= Field
.split('=')[0].strip()
1641 TokenList
= Field
.split()
1642 # Remove pointers before variable
1643 Token
= TokenList
[-1]
1644 if Token
in ['OPTIONAL']:
1645 Token
= TokenList
[-2]
1646 if not Pattern
.match(Token
.lstrip('*')):
1647 ErrMsgList
.append(Token
.lstrip('*'))
1651 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1654 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1659 FileTable
= 'Identifier' + str(FileID
)
1660 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1663 """ % (FileTable
, ModelId
)
1664 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1666 for Result
in ResultSet
:
1667 ResultList
.append(Result
)
1669 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1670 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1671 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1672 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1673 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1674 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1675 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1677 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1680 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1681 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1685 # Check member variable name format that from typedefs of ONLY this file.
1687 Name
= Td
[1].strip()
1688 Value
= Td
[2].strip()
1689 if Value
.startswith('enum'):
1690 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1691 elif Value
.startswith('struct'):
1692 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1693 elif Value
.startswith('union'):
1694 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1698 if ValueModelId
!= ModelId
:
1700 # Check member variable format.
1701 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1702 for ErrMsg
in ErrMsgList
:
1703 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+ '.' + ErrMsg
):
1705 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+ '.' + ErrMsg
), FileTable
, Td
[5])
1707 # First check in current file to see whether struct/union/enum is typedef-ed.
1708 UntypedefedList
= []
1709 for Result
in ResultList
:
1710 # Check member variable format.
1711 Name
= Result
[0].strip()
1712 Value
= Result
[4].strip()
1713 if Value
.startswith('enum'):
1714 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1715 elif Value
.startswith('struct'):
1716 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1717 elif Value
.startswith('union'):
1718 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1722 if ValueModelId
!= ModelId
:
1724 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1725 for ErrMsg
in ErrMsgList
:
1726 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0] + '.' + ErrMsg
):
1728 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0] + '.' + ErrMsg
), FileTable
, Result
[3])
1729 # Check whether it is typedefed.
1732 # skip function pointer
1735 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1737 if not Td
[1].isupper():
1738 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1739 if Result
[0] in Td
[2].split():
1741 if not Td
[1].isupper():
1742 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1747 UntypedefedList
.append(Result
)
1750 if len(UntypedefedList
) == 0:
1753 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1755 for F
in IncludeFileList
:
1756 FileID
= GetTableID(F
, ErrorMsgList
)
1760 IncludeFileTable
= 'Identifier' + str(FileID
)
1761 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1764 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1765 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1766 TdList
.extend(ResultSet
)
1768 for Result
in UntypedefedList
:
1770 # Check whether it is typedefed.
1776 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1778 if not Td
[1].isupper():
1779 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1780 if Result
[0] in Td
[2].split():
1782 if not Td
[1].isupper():
1783 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1788 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1791 def CheckDeclStructTypedef(FullFileName
):
1792 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1794 def CheckDeclEnumTypedef(FullFileName
):
1795 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1797 def CheckDeclUnionTypedef(FullFileName
):
1798 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1800 def CheckDeclArgModifier(FullFileName
):
1803 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1808 FileTable
= 'Identifier' + str(FileID
)
1809 SqlStatement
= """ select Modifier, Name, ID
1812 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1813 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1814 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1815 MAX_MODIFIER_LENGTH
= 100
1816 for Result
in ResultSet
:
1817 for Modifier
in ModifierTuple
:
1818 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1819 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1822 SqlStatement
= """ select Modifier, Name, ID
1825 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1826 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1827 for Result
in ResultSet
:
1828 for Modifier
in ModifierTuple
:
1829 if PatternInModifier(Result
[0], Modifier
):
1830 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1833 SqlStatement
= """ select Modifier, Header, ID
1835 where BelongsToFile = %d
1837 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1838 for Result
in ResultSet
:
1839 for Modifier
in ModifierTuple
:
1840 if PatternInModifier(Result
[0], Modifier
):
1841 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1844 def CheckDeclNoUseCType(FullFileName
):
1847 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1852 FileTable
= 'Identifier' + str(FileID
)
1853 SqlStatement
= """ select Modifier, Name, ID
1856 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1857 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1858 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1859 for Result
in ResultSet
:
1860 for Type
in CTypeTuple
:
1861 if PatternInModifier(Result
[0], Type
):
1862 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1863 Result
[0] + ' ' + Result
[1]):
1865 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1866 'Invalid variable type (%s) in definition [%s]' % (Type
, Result
[0] + ' ' + Result
[1]),
1871 SqlStatement
= """ select Modifier, Name, ID, Value
1874 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1875 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1876 for Result
in ResultSet
:
1877 ParamList
= GetParamList(Result
[1])
1878 FuncName
= Result
[3]
1879 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1881 for Type
in CTypeTuple
:
1882 if PatternInModifier(Result
[0], Type
):
1883 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1885 for Param
in ParamList
:
1886 if PatternInModifier(Param
.Modifier
, Type
):
1887 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1889 SqlStatement
= """ select Modifier, Header, ID, Name
1891 where BelongsToFile = %d
1893 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1894 for Result
in ResultSet
:
1895 ParamList
= GetParamList(Result
[1])
1896 FuncName
= Result
[3]
1897 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1899 for Type
in CTypeTuple
:
1900 if PatternInModifier(Result
[0], Type
):
1901 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1903 for Param
in ParamList
:
1904 if PatternInModifier(Param
.Modifier
, Type
):
1905 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1908 def CheckPointerNullComparison(FullFileName
):
1911 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1915 # cache the found function return type to accelerate later checking in this file.
1916 FuncReturnTypeDict
= {}
1919 FileTable
= 'Identifier' + str(FileID
)
1920 SqlStatement
= """ select Value, StartLine, ID
1923 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1924 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1925 if len(ResultSet
) == 0:
1928 for Result
in ResultSet
:
1929 PSL
.append([Result
[0], Result
[1], Result
[2]])
1931 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1933 where BelongsToFile = %d
1935 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1937 for Result
in ResultSet
:
1938 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1940 p
= GetFuncDeclPattern()
1942 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1943 if FuncRecord
is None:
1946 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1947 PredInfo
= SplitPredicateStr(Exp
)
1948 if PredInfo
[1] is None:
1949 PredVarStr
= PredInfo
[0][0].strip()
1951 SearchInCache
= False
1952 # PredVarStr may contain '.' or '->'
1953 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1955 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1956 SearchInCache
= True
1957 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1958 if TmpStr
.startswith(PredVarStr
):
1961 if PredVarStr
.strip() in IgnoredKeywordList
:
1964 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1965 # No variable found, maybe value first? like (0 == VarName)
1966 if len(PredVarList
) == 0:
1969 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1970 if Type
is not None:
1971 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1972 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1975 if PredVarStr
in FuncReturnTypeDict
:
1978 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1980 FuncReturnTypeDict
[PredVarStr
] = Type
1983 Type
= GetTypeFromArray(Type
, PredVarStr
)
1984 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1985 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1987 def CheckNonBooleanValueComparison(FullFileName
):
1990 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1994 # cache the found function return type to accelerate later checking in this file.
1995 FuncReturnTypeDict
= {}
1998 FileTable
= 'Identifier' + str(FileID
)
1999 SqlStatement
= """ select Value, StartLine, ID
2002 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2003 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2004 if len(ResultSet
) == 0:
2007 for Result
in ResultSet
:
2008 PSL
.append([Result
[0], Result
[1], Result
[2]])
2010 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2012 where BelongsToFile = %d
2014 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2016 for Result
in ResultSet
:
2017 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2019 p
= GetFuncDeclPattern()
2021 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2022 if FuncRecord
is None:
2025 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2026 PredInfo
= SplitPredicateStr(Exp
)
2027 if PredInfo
[1] is None:
2028 PredVarStr
= PredInfo
[0][0].strip()
2030 SearchInCache
= False
2031 # PredVarStr may contain '.' or '->'
2032 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2034 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2035 SearchInCache
= True
2036 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2037 if TmpStr
.startswith(PredVarStr
):
2040 if PredVarStr
.strip() in IgnoredKeywordList
:
2043 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2044 # No variable found, maybe value first? like (0 == VarName)
2045 if len(PredVarList
) == 0:
2049 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2050 if Type
is not None:
2051 if Type
.find('BOOLEAN') == -1:
2052 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2055 if PredVarStr
in FuncReturnTypeDict
:
2057 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2059 FuncReturnTypeDict
[PredVarStr
] = Type
2062 if Type
.find('BOOLEAN') == -1:
2063 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2066 def CheckBooleanValueComparison(FullFileName
):
2069 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2073 # cache the found function return type to accelerate later checking in this file.
2074 FuncReturnTypeDict
= {}
2077 FileTable
= 'Identifier' + str(FileID
)
2078 SqlStatement
= """ select Value, StartLine, ID
2081 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2082 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2083 if len(ResultSet
) == 0:
2086 for Result
in ResultSet
:
2087 PSL
.append([Result
[0], Result
[1], Result
[2]])
2089 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2091 where BelongsToFile = %d
2093 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2095 for Result
in ResultSet
:
2096 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2098 p
= GetFuncDeclPattern()
2100 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2101 if FuncRecord
is None:
2104 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2105 PredInfo
= SplitPredicateStr(Exp
)
2106 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2107 PredVarStr
= PredInfo
[0][0].strip()
2109 SearchInCache
= False
2110 # PredVarStr may contain '.' or '->'
2111 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2113 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2114 SearchInCache
= True
2115 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2116 if TmpStr
.startswith(PredVarStr
):
2119 if PredVarStr
.strip() in IgnoredKeywordList
:
2122 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2123 # No variable found, maybe value first? like (0 == VarName)
2124 if len(PredVarList
) == 0:
2128 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2129 if Type
is not None:
2130 if Type
.find('BOOLEAN') != -1:
2131 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2134 if PredVarStr
in FuncReturnTypeDict
:
2137 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2139 FuncReturnTypeDict
[PredVarStr
] = Type
2142 if Type
.find('BOOLEAN') != -1:
2143 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2146 def CheckHeaderFileData(FullFileName
):
2149 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2154 FileTable
= 'Identifier' + str(FileID
)
2155 SqlStatement
= """ select ID, Modifier
2158 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2159 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2160 for Result
in ResultSet
:
2161 if not Result
[1].startswith('extern'):
2162 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2164 SqlStatement
= """ select ID
2166 where BelongsToFile = %d
2168 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2169 for Result
in ResultSet
:
2170 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2174 def CheckHeaderFileIfndef(FullFileName
):
2177 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2182 FileTable
= 'Identifier' + str(FileID
)
2183 SqlStatement
= """ select Value, StartLine
2185 where Model = %d order by StartLine
2186 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2187 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2188 if len(ResultSet
) == 0:
2189 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2191 for Result
in ResultSet
:
2192 SqlStatement
= """ select Value, EndLine
2195 """ % (FileTable
, Result
[1])
2196 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2197 for Result
in ResultSet
:
2198 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2199 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2
, '', 'File', FileID
)
2202 SqlStatement
= """ select Value
2204 where StartLine > (select max(EndLine) from %s where Model = %d)
2205 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2206 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2207 for Result
in ResultSet
:
2208 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2209 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2212 def CheckDoxygenCommand(FullFileName
):
2215 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2220 FileTable
= 'Identifier' + str(FileID
)
2221 SqlStatement
= """ select Value, ID
2223 where Model = %d or Model = %d
2224 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2225 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2226 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval',
2227 'return', 'sa', 'since', 'test', 'note', 'par', 'endcode', 'code']
2228 for Result
in ResultSet
:
2229 CommentStr
= Result
[0]
2230 CommentPartList
= CommentStr
.split()
2231 for Part
in CommentPartList
:
2232 if Part
.upper() == 'BUGBUG':
2233 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2234 if Part
.upper() == 'TODO':
2235 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2236 if Part
.startswith('@'):
2237 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2239 if not Part
.replace('@', '').strip():
2241 if Part
.lstrip('@') in ['{', '}']:
2243 if Part
.lstrip('@').isalpha():
2244 if Part
.lstrip('@') not in DoxygenCommandList
:
2245 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2247 Index
= Part
.find('[')
2249 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2250 RealCmd
= Part
[1:Index
]
2251 if RealCmd
not in DoxygenCommandList
:
2252 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2255 def CheckDoxygenTripleForwardSlash(FullFileName
):
2258 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2264 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2266 where BelongsToFile = %d
2268 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2269 if len(ResultSet
) == 0:
2273 for Result
in ResultSet
:
2274 FuncDefSet
.append(Result
)
2277 FileTable
= 'Identifier' + str(FileID
)
2278 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2282 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2283 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2286 for Result
in ResultSet
:
2287 CommentSet
.append(Result
)
2289 print('Unrecognized chars in comment of file %s', FullFileName
)
2292 for Result
in CommentSet
:
2293 CommentStr
= Result
[0]
2294 StartLine
= Result
[2]
2295 StartColumn
= Result
[3]
2297 EndColumn
= Result
[5]
2298 if not CommentStr
.startswith('///<'):
2302 for FuncDef
in FuncDefSet
:
2303 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2306 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2309 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2312 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2316 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2319 def CheckFileHeaderDoxygenComments(FullFileName
):
2322 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2327 FileTable
= 'Identifier' + str(FileID
)
2328 SqlStatement
= """ select Value, ID
2330 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2331 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2332 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2333 if len(ResultSet
) == 0:
2334 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No File License header appear at the very beginning of file.', 'File', FileID
)
2337 NoHeaderCommentStartFlag
= True
2338 NoHeaderCommentEndFlag
= True
2339 NoHeaderCommentPeriodFlag
= True
2340 NoCopyrightFlag
= True
2341 NoLicenseFlag
= True
2342 NoRevReferFlag
= True
2344 for Result
in ResultSet
:
2345 FileStartFlag
= False
2347 CommentStr
= Result
[0].strip()
2348 CommentStrListTemp
= CommentStr
.split('\n')
2349 if (len(CommentStrListTemp
) <= 1):
2351 CommentStrListTemp
= CommentStr
.split('\r')
2352 # Skip the content before the file header
2353 for CommentLine
in CommentStrListTemp
:
2354 if CommentLine
.strip().startswith('/** @file'):
2355 FileStartFlag
= True
2356 if FileStartFlag
== True:
2357 CommentStrList
.append(CommentLine
)
2361 if CommentStrList
and CommentStrList
[0].strip().startswith('/** @file'):
2362 NoHeaderCommentStartFlag
= False
2365 if CommentStrList
and CommentStrList
[-1].strip().endswith('**/'):
2366 NoHeaderCommentEndFlag
= False
2370 for CommentLine
in CommentStrList
:
2372 NextLineIndex
= Index
2373 if CommentLine
.startswith('/** @file'):
2375 if CommentLine
.startswith('**/'):
2377 # Check whether C File header Comment content start with two spaces.
2378 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentStartSpacesNum
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2379 if CommentLine
.startswith('/** @file') == False and CommentLine
.startswith('**/') == False and CommentLine
.strip() and CommentLine
.startswith(' ') == False:
2380 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment content should start with two spaces at each line', FileTable
, ID
)
2382 CommentLine
= CommentLine
.strip()
2383 if CommentLine
.startswith('Copyright'):
2384 NoCopyrightFlag
= False
2385 if CommentLine
.find('All rights reserved') == -1:
2386 for Copyright
in EccGlobalData
.gConfig
.Copyright
:
2387 if CommentLine
.find(Copyright
) > -1:
2388 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable
, ID
)
2390 if CommentLine
.endswith('<BR>') == -1:
2391 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'The ""<BR>"" at the end of the Copyright line is required', FileTable
, ID
)
2392 if NextLineIndex
< len(CommentStrList
) and CommentStrList
[NextLineIndex
].strip().startswith('Copyright') == False and CommentStrList
[NextLineIndex
].strip():
2393 NoLicenseFlag
= False
2394 if CommentLine
.startswith('@par Revision Reference:'):
2395 NoRevReferFlag
= False
2397 for RefLine
in CommentStrList
[NextLineIndex
:]:
2398 if RefLine
.strip() and (NextLineIndex
+ 1) < len(CommentStrList
) and CommentStrList
[NextLineIndex
+1].strip() and CommentStrList
[NextLineIndex
+1].strip().startswith('**/') == False:
2400 if RefLine
.strip() == False or RefLine
.strip().startswith('**/'):
2403 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2404 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentReferenceFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2405 if RefListFlag
== True:
2406 if RefLine
.strip() and RefLine
.strip().startswith('**/') == False and RefLine
.startswith(' -') == False:
2407 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable
, ID
)
2409 if NoHeaderCommentStartFlag
:
2410 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, ID
)
2412 if NoHeaderCommentEndFlag
:
2413 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with ""**/""', FileTable
, ID
)
2416 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment missing the ""Copyright""', FileTable
, ID
)
2417 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2418 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentLicenseFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2420 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable
, ID
)
2422 def CheckFuncHeaderDoxygenComments(FullFileName
):
2425 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2430 FileTable
= 'Identifier' + str(FileID
)
2431 SqlStatement
= """ select Value, StartLine, EndLine, ID
2434 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2436 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2439 for Result
in ResultSet
:
2440 CommentSet
.append(Result
)
2442 print('Unrecognized chars in comment of file %s', FullFileName
)
2445 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2448 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2449 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2450 for Result
in ResultSet
:
2451 FuncName
= Result
[4]
2452 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2453 if FunctionHeaderComment
:
2454 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2456 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2458 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2459 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2462 SqlStatement
= """ select Value, StartLine, EndLine, ID
2465 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2467 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2470 for Result
in ResultSet
:
2471 CommentSet
.append(Result
)
2473 print('Unrecognized chars in comment of file %s', FullFileName
)
2475 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2477 where BelongsToFile = %d
2479 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2480 for Result
in ResultSet
:
2481 FuncName
= Result
[4]
2482 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2483 if FunctionHeaderComment
:
2484 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2486 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2488 ErrorMsgList
.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2489 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), 'Function', Result
[3])
2492 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2494 for Comment
in CommentSet
:
2495 if Comment
[2] == FuncStartLine
- 1:
2499 def GetDoxygenStrFromComment(Str
):
2501 ParamTagList
= Str
.split('@param')
2502 if len(ParamTagList
) > 1:
2504 while i
< len(ParamTagList
):
2505 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2508 Str
= ParamTagList
[0]
2510 RetvalTagList
= ParamTagList
[-1].split('@retval')
2511 if len(RetvalTagList
) > 1:
2512 if len(ParamTagList
) > 1:
2513 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2515 while i
< len(RetvalTagList
):
2516 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2519 ReturnTagList
= RetvalTagList
[-1].split('@return')
2520 if len(ReturnTagList
) > 1:
2521 if len(RetvalTagList
) > 1:
2522 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2523 elif len(ParamTagList
) > 1:
2524 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2526 while i
< len(ReturnTagList
):
2527 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2530 if len(DoxygenStrList
) > 0:
2531 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2533 return DoxygenStrList
2535 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2536 #/** --*/ @retval after @param
2537 if not Str
.startswith('/**'):
2538 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2539 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2540 if not Str
.endswith('**/'):
2541 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2542 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2543 FirstRetvalIndex
= Str
.find('@retval')
2544 LastParamIndex
= Str
.rfind('@param')
2545 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2546 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2547 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2549 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2551 ParamList
= GetParamList(FuncHeader
)
2552 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2553 DescriptionStr
= CommentStr
2554 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2555 if DescriptionStr
.find('.') == -1:
2556 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2557 DoxygenTagNumber
= len(DoxygenStrList
)
2558 ParamNumber
= len(ParamList
)
2559 for Param
in ParamList
:
2560 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2563 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2564 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2565 ParamModifier
= ParamList
[Index
].Modifier
2566 ParamName
= ParamList
[Index
].Name
.strip()
2567 Tag
= DoxygenStrList
[Index
].strip(' ')
2568 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2569 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2570 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, <%s> does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2571 TagPartList
= Tag
.split()
2572 if len(TagPartList
) < 2:
2573 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2574 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2577 LBPos
= Tag
.find('[')
2578 RBPos
= Tag
.find(']')
2579 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2580 if LBPos
> 0 and len(ParamToLBContent
) == 0 and RBPos
> LBPos
:
2582 ModifierPartList
= ParamModifier
.split()
2583 for Part
in ModifierPartList
:
2584 if Part
.strip() == 'IN':
2586 if Part
.strip() == 'OUT':
2593 if Tag
.find('[' + InOutStr
+ ']') == -1:
2594 if InOutStr
!= 'in, out':
2595 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2596 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2598 if Tag
.find('[in,out]') == -1:
2599 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2600 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(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2604 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2605 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
)
2608 if Index
< ParamNumber
:
2609 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2610 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2611 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2612 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2614 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2615 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2616 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2617 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2619 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2620 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2621 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2623 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
2624 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2625 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need NO doxygen tags in comment ', TableName
, CommentId
)
2626 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2627 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2628 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2630 if __name__
== '__main__':
2632 # EdkLogger.Initialize()
2633 # EdkLogger.SetLevel(EdkLogger.QUIET)
2634 # CollectSourceCodeDataIntoDB(sys.argv[1])
2636 test_file
= sys
.argv
[1]
2637 except IndexError as v
:
2638 print("Usage: %s filename" % sys
.argv
[0])
2640 MsgList
= CheckFuncHeaderDoxygenComments(test_file
)