2 # This file is used to be the c coding style checking of ECC tool
4 # Copyright (c) 2009 - 2015, 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.
15 import Common
.LongFilePathOs
as os
18 import CodeFragmentCollector
20 from CommonDataClass
import DataClass
22 from Common
import EdkLogger
23 from EccToolError
import *
27 IncludeFileListDict
= {}
28 AllIncludeFileListDict
= {}
29 IncludePathListDict
= {}
32 IgnoredKeywordList
= ['EFI_ERROR']
34 def GetIgnoredDirListPattern():
35 skipList
= list(EccGlobalData
.gConfig
.SkipDirList
) + ['.svn']
36 DirString
= string
.join(skipList
, '|')
37 p
= re
.compile(r
'.*[\\/](?:%s)[\\/]?.*' % DirString
)
40 def GetFuncDeclPattern():
41 p
= re
.compile(r
'(?:EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re
.DOTALL
)
44 def GetArrayPattern():
45 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
48 def GetTypedefFuncPointerPattern():
49 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
53 return EccGlobalData
.gDb
56 return EccGlobalData
.gConfig
58 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
59 Msg
= Msg
.replace('\n', '').replace('\r', '')
60 MsgPartList
= Msg
.split()
62 for Part
in MsgPartList
:
65 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
=Msg
, BelongsToTable
=TableName
, BelongsToItem
=ItemId
)
68 Type
= DataClass
.MODEL_UNKNOWN
69 Str
= Str
.replace('#', '# ')
71 if List
[1] == 'include':
72 Type
= DataClass
.MODEL_IDENTIFIER_INCLUDE
73 elif List
[1] == 'define':
74 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_DEFINE
75 elif List
[1] == 'ifdef':
76 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFDEF
77 elif List
[1] == 'ifndef':
78 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
79 elif List
[1] == 'endif':
80 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
81 elif List
[1] == 'pragma':
82 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_PROGMA
84 Type
= DataClass
.MODEL_UNKNOWN
87 def SuOccurInTypedef (Su
, TdList
):
89 if Su
.StartPos
[0] == Td
.StartPos
[0] and Su
.EndPos
[0] == Td
.EndPos
[0]:
93 def GetIdentifierList():
95 for comment
in FileProfile
.CommentList
:
96 IdComment
= DataClass
.IdentifierClass(-1, '', '', '', comment
.Content
, DataClass
.MODEL_IDENTIFIER_COMMENT
, -1, -1, comment
.StartPos
[0], comment
.StartPos
[1], comment
.EndPos
[0], comment
.EndPos
[1])
97 IdList
.append(IdComment
)
99 for pp
in FileProfile
.PPDirectiveList
:
100 Type
= GetIdType(pp
.Content
)
101 IdPP
= DataClass
.IdentifierClass(-1, '', '', '', pp
.Content
, Type
, -1, -1, pp
.StartPos
[0], pp
.StartPos
[1], pp
.EndPos
[0], pp
.EndPos
[1])
104 for pe
in FileProfile
.PredicateExpressionList
:
105 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])
108 FuncDeclPattern
= GetFuncDeclPattern()
109 ArrayPattern
= GetArrayPattern()
110 for var
in FileProfile
.VariableDeclarationList
:
111 DeclText
= var
.Declarator
.lstrip()
112 FuncPointerPattern
= GetTypedefFuncPointerPattern()
113 if FuncPointerPattern
.match(DeclText
):
115 VarNameStartLine
= var
.NameStartPos
[0]
116 VarNameStartColumn
= var
.NameStartPos
[1]
117 FirstChar
= DeclText
[0]
118 while not FirstChar
.isalpha() and FirstChar
!= '_':
121 VarNameStartColumn
+= 1
122 DeclText
= DeclText
.lstrip('*')
123 elif FirstChar
== '\r':
124 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
125 VarNameStartLine
+= 1
126 VarNameStartColumn
= 0
127 elif FirstChar
== '\n':
128 DeclText
= DeclText
.lstrip('\n')
129 VarNameStartLine
+= 1
130 VarNameStartColumn
= 0
131 elif FirstChar
== ' ':
132 DeclText
= DeclText
.lstrip(' ')
133 VarNameStartColumn
+= 1
134 elif FirstChar
== '\t':
135 DeclText
= DeclText
.lstrip('\t')
136 VarNameStartColumn
+= 8
138 DeclText
= DeclText
[1:]
139 VarNameStartColumn
+= 1
140 FirstChar
= DeclText
[0]
142 var
.Declarator
= DeclText
143 if FuncDeclPattern
.match(var
.Declarator
):
144 DeclSplitList
= var
.Declarator
.split('(')
145 FuncName
= DeclSplitList
[0].strip()
146 FuncNamePartList
= FuncName
.split()
147 if len(FuncNamePartList
) > 1:
148 FuncName
= FuncNamePartList
[-1].strip()
149 NameStart
= DeclSplitList
[0].rfind(FuncName
)
150 var
.Declarator
= var
.Declarator
[NameStart
:]
152 var
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
155 while Index
< NameStart
:
156 FirstChar
= DeclSplitList
[0][Index
]
157 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
159 VarNameStartColumn
+= 6
162 elif FirstChar
== '\r':
164 VarNameStartLine
+= 1
165 VarNameStartColumn
= 0
166 elif FirstChar
== '\n':
169 VarNameStartLine
+= 1
170 VarNameStartColumn
= 0
171 elif FirstChar
== ' ':
173 VarNameStartColumn
+= 1
174 elif FirstChar
== '\t':
176 VarNameStartColumn
+= 8
179 VarNameStartColumn
+= 1
181 IdVar
= DataClass
.IdentifierClass(-1, var
.Modifier
, '', var
.Declarator
, FuncName
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, -1, -1, var
.StartPos
[0], var
.StartPos
[1], VarNameStartLine
, VarNameStartColumn
)
185 if var
.Declarator
.find('{') == -1:
186 for decl
in var
.Declarator
.split(','):
187 DeclList
= decl
.split('=')
188 Name
= DeclList
[0].strip()
189 if ArrayPattern
.match(Name
):
190 LSBPos
= var
.Declarator
.find('[')
191 var
.Modifier
+= ' ' + Name
[LSBPos
:]
192 Name
= Name
[0:LSBPos
]
194 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
)
197 DeclList
= var
.Declarator
.split('=')
198 Name
= DeclList
[0].strip()
199 if ArrayPattern
.match(Name
):
200 LSBPos
= var
.Declarator
.find('[')
201 var
.Modifier
+= ' ' + Name
[LSBPos
:]
202 Name
= Name
[0:LSBPos
]
203 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
)
206 for enum
in FileProfile
.EnumerationDefinitionList
:
207 LBPos
= enum
.Content
.find('{')
208 RBPos
= enum
.Content
.find('}')
209 Name
= enum
.Content
[4:LBPos
].strip()
210 Value
= enum
.Content
[LBPos
+ 1:RBPos
]
211 IdEnum
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
, -1, -1, enum
.StartPos
[0], enum
.StartPos
[1], enum
.EndPos
[0], enum
.EndPos
[1])
212 IdList
.append(IdEnum
)
214 for su
in FileProfile
.StructUnionDefinitionList
:
215 if SuOccurInTypedef(su
, FileProfile
.TypedefDefinitionList
):
217 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
219 if su
.Content
.startswith('union'):
220 Type
= DataClass
.MODEL_IDENTIFIER_UNION
222 LBPos
= su
.Content
.find('{')
223 RBPos
= su
.Content
.find('}')
224 if LBPos
== -1 or RBPos
== -1:
225 Name
= su
.Content
[SkipLen
:].strip()
228 Name
= su
.Content
[SkipLen
:LBPos
].strip()
229 Value
= su
.Content
[LBPos
:RBPos
+ 1]
230 IdPE
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, Type
, -1, -1, su
.StartPos
[0], su
.StartPos
[1], su
.EndPos
[0], su
.EndPos
[1])
233 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
234 for td
in FileProfile
.TypedefDefinitionList
:
238 if TdFuncPointerPattern
.match(td
.ToType
):
239 Modifier
= td
.FromType
240 LBPos
= td
.ToType
.find('(')
241 TmpStr
= td
.ToType
[LBPos
+ 1:].strip()
242 StarPos
= TmpStr
.find('*')
244 Modifier
+= ' ' + TmpStr
[0:StarPos
]
245 while TmpStr
[StarPos
] == '*':
246 # Modifier += ' ' + '*'
248 TmpStr
= TmpStr
[StarPos
:].strip()
249 RBPos
= TmpStr
.find(')')
250 Name
= TmpStr
[0:RBPos
]
251 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
253 while Name
.startswith('*'):
255 Name
= Name
.lstrip('*').strip()
257 if Name
.find('[') != -1:
258 LBPos
= Name
.find('[')
259 RBPos
= Name
.rfind(']')
260 Value
+= Name
[LBPos
: RBPos
+ 1]
261 Name
= Name
[0 : LBPos
]
263 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])
266 for funcCall
in FileProfile
.FunctionCallingList
:
267 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])
271 def StripNonAlnumChars(Str
):
278 def GetParamList(FuncDeclarator
, FuncNameLine
=0, FuncNameOffset
=0):
279 FuncDeclarator
= StripComments(FuncDeclarator
)
281 #DeclSplitList = FuncDeclarator.split('(')
282 LBPos
= FuncDeclarator
.find('(')
283 #if len(DeclSplitList) < 2:
286 #FuncName = DeclSplitList[0]
287 FuncName
= FuncDeclarator
[0:LBPos
]
288 #ParamStr = DeclSplitList[1].rstrip(')')
289 ParamStr
= FuncDeclarator
[LBPos
+ 1:].rstrip(')')
292 TailChar
= FuncName
[-1]
293 while not TailChar
.isalpha() and TailChar
!= '_':
296 FuncName
= FuncName
.rstrip('\r\n').rstrip('\n')
299 elif TailChar
== '\r':
300 FuncName
= FuncName
.rstrip('\r')
303 elif TailChar
== ' ':
304 FuncName
= FuncName
.rstrip(' ')
306 elif TailChar
== '\t':
307 FuncName
= FuncName
.rstrip('\t')
310 FuncName
= FuncName
[:-1]
311 TailChar
= FuncName
[-1]
313 OffsetSkipped
+= 1 #skip '('
315 for p
in ParamStr
.split(','):
319 ParamName
= ListP
[-1]
320 DeclText
= ParamName
.strip()
321 RightSpacePos
= p
.rfind(ParamName
)
322 ParamModifier
= p
[0:RightSpacePos
]
323 if ParamName
== 'OPTIONAL':
324 if ParamModifier
== '':
325 ParamModifier
+= ' ' + 'OPTIONAL'
328 ParamName
= ListP
[-2]
329 DeclText
= ParamName
.strip()
330 RightSpacePos
= p
.rfind(ParamName
)
331 ParamModifier
= p
[0:RightSpacePos
]
332 ParamModifier
+= 'OPTIONAL'
333 while DeclText
.startswith('*'):
334 ParamModifier
+= ' ' + '*'
335 DeclText
= DeclText
.lstrip('*').strip()
337 # ignore array length if exists.
338 LBIndex
= ParamName
.find('[')
340 ParamName
= ParamName
[0:LBIndex
]
342 Start
= RightSpacePos
348 if FirstChar
== '\r':
352 elif FirstChar
== '\n':
357 elif FirstChar
== ' ':
360 elif FirstChar
== '\t':
368 ParamBeginLine
= FuncNameLine
+ LineSkipped
369 ParamBeginOffset
= FuncNameOffset
+ OffsetSkipped
371 Index
= Start
+ len(ParamName
)
373 while Index
< len(p
):
376 if FirstChar
== '\r':
380 elif FirstChar
== '\n':
385 elif FirstChar
== ' ':
388 elif FirstChar
== '\t':
396 ParamEndLine
= FuncNameLine
+ LineSkipped
397 ParamEndOffset
= FuncNameOffset
+ OffsetSkipped
398 if ParamName
!= '...':
399 ParamName
= StripNonAlnumChars(ParamName
)
400 IdParam
= DataClass
.IdentifierClass(-1, ParamModifier
, '', ParamName
, '', DataClass
.MODEL_IDENTIFIER_PARAMETER
, -1, -1, ParamBeginLine
, ParamBeginOffset
, ParamEndLine
, ParamEndOffset
)
401 ParamIdList
.append(IdParam
)
403 OffsetSkipped
+= 1 #skip ','
407 def GetFunctionList():
409 for FuncDef
in FileProfile
.FunctionDefinitionList
:
411 DeclText
= FuncDef
.Declarator
.lstrip()
412 FuncNameStartLine
= FuncDef
.NamePos
[0]
413 FuncNameStartColumn
= FuncDef
.NamePos
[1]
414 FirstChar
= DeclText
[0]
415 while not FirstChar
.isalpha() and FirstChar
!= '_':
417 FuncDef
.Modifier
+= '*'
418 FuncNameStartColumn
+= 1
419 DeclText
= DeclText
.lstrip('*')
420 elif FirstChar
== '\r':
421 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
422 FuncNameStartLine
+= 1
423 FuncNameStartColumn
= 0
424 elif FirstChar
== '\n':
425 DeclText
= DeclText
.lstrip('\n')
426 FuncNameStartLine
+= 1
427 FuncNameStartColumn
= 0
428 elif FirstChar
== ' ':
429 DeclText
= DeclText
.lstrip(' ')
430 FuncNameStartColumn
+= 1
431 elif FirstChar
== '\t':
432 DeclText
= DeclText
.lstrip('\t')
433 FuncNameStartColumn
+= 8
435 DeclText
= DeclText
[1:]
436 FuncNameStartColumn
+= 1
437 FirstChar
= DeclText
[0]
439 FuncDef
.Declarator
= DeclText
440 DeclSplitList
= FuncDef
.Declarator
.split('(')
441 if len(DeclSplitList
) < 2:
444 FuncName
= DeclSplitList
[0]
445 FuncNamePartList
= FuncName
.split()
446 if len(FuncNamePartList
) > 1:
447 FuncName
= FuncNamePartList
[-1]
448 NameStart
= DeclSplitList
[0].rfind(FuncName
)
450 FuncDef
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
453 while Index
< NameStart
:
454 FirstChar
= DeclSplitList
[0][Index
]
455 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
457 FuncNameStartColumn
+= 6
460 elif FirstChar
== '\r':
462 FuncNameStartLine
+= 1
463 FuncNameStartColumn
= 0
464 elif FirstChar
== '\n':
467 FuncNameStartLine
+= 1
468 FuncNameStartColumn
= 0
469 elif FirstChar
== ' ':
471 FuncNameStartColumn
+= 1
472 elif FirstChar
== '\t':
474 FuncNameStartColumn
+= 8
477 FuncNameStartColumn
+= 1
480 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
)
481 FuncObjList
.append(FuncObj
)
485 def GetFileModificationTimeFromDB(FullFileName
):
488 SqlStatement
= """ select TimeStamp
490 where FullPath = \'%s\'
492 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
493 for Result
in ResultSet
:
494 TimeValue
= Result
[0]
497 def CollectSourceCodeDataIntoDB(RootDir
):
499 tuple = os
.walk(RootDir
)
500 IgnoredPattern
= GetIgnoredDirListPattern()
501 ParseErrorFileList
= []
503 for dirpath
, dirnames
, filenames
in tuple:
504 if IgnoredPattern
.match(dirpath
.upper()):
508 Dirname
= os
.path
.join(dirpath
, Dir
)
509 if os
.path
.islink(Dirname
):
510 Dirname
= os
.path
.realpath(Dirname
)
511 if os
.path
.isdir(Dirname
):
512 # symlinks to directories are treated as directories
514 dirnames
.append(Dirname
)
517 if f
.lower() in EccGlobalData
.gConfig
.SkipFileList
:
520 FullName
= os
.path
.normpath(os
.path
.join(dirpath
, f
))
521 model
= DataClass
.MODEL_FILE_OTHERS
522 if os
.path
.splitext(f
)[1] in ('.h', '.c'):
523 EdkLogger
.info("Parsing " + FullName
)
524 model
= f
.endswith('c') and DataClass
.MODEL_FILE_C
or DataClass
.MODEL_FILE_H
525 collector
= CodeFragmentCollector
.CodeFragmentCollector(FullName
)
527 collector
.ParseFile()
529 ParseErrorFileList
.append(FullName
)
530 collector
.CleanFileProfileBuffer()
531 collector
.ParseFileWithClearedPPDirective()
532 # collector.PrintFragments()
533 BaseName
= os
.path
.basename(f
)
534 DirName
= os
.path
.dirname(FullName
)
535 Ext
= os
.path
.splitext(f
)[1].lstrip('.')
536 ModifiedTime
= os
.path
.getmtime(FullName
)
537 FileObj
= DataClass
.FileClass(-1, BaseName
, Ext
, DirName
, FullName
, model
, ModifiedTime
, GetFunctionList(), GetIdentifierList(), [])
538 FileObjList
.append(FileObj
)
540 collector
.CleanFileProfileBuffer()
542 if len(ParseErrorFileList
) > 0:
543 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
546 for file in FileObjList
:
547 if file.ExtName
.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
548 Db
.InsertOneFile(file)
550 Db
.UpdateIdentifierBelongsToFunction()
552 def GetTableID(FullFileName
, ErrorMsgList
=None):
553 if ErrorMsgList
== None:
557 SqlStatement
= """ select ID
559 where FullPath like '%s'
561 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
564 for Result
in ResultSet
:
566 ErrorMsgList
.append('Duplicate file ID found in DB for file %s' % FullFileName
)
570 ErrorMsgList
.append('NO file ID found in DB for file %s' % FullFileName
)
574 def GetIncludeFileList(FullFileName
):
575 if os
.path
.splitext(FullFileName
)[1].upper() not in ('.H'):
577 IFList
= IncludeFileListDict
.get(FullFileName
)
581 FileID
= GetTableID(FullFileName
)
586 FileTable
= 'Identifier' + str(FileID
)
587 SqlStatement
= """ select Value
590 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_INCLUDE
)
591 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
592 IncludeFileListDict
[FullFileName
] = ResultSet
595 def GetFullPathOfIncludeFile(Str
, IncludePathList
):
596 for IncludePath
in IncludePathList
:
597 FullPath
= os
.path
.join(IncludePath
, Str
)
598 FullPath
= os
.path
.normpath(FullPath
)
599 if os
.path
.exists(FullPath
):
603 def GetAllIncludeFiles(FullFileName
):
604 if AllIncludeFileListDict
.get(FullFileName
) != None:
605 return AllIncludeFileListDict
.get(FullFileName
)
607 FileDirName
= os
.path
.dirname(FullFileName
)
608 IncludePathList
= IncludePathListDict
.get(FileDirName
)
609 if IncludePathList
== None:
610 IncludePathList
= MetaDataParser
.GetIncludeListOfFile(EccGlobalData
.gWorkspace
, FullFileName
, GetDB())
611 if FileDirName
not in IncludePathList
:
612 IncludePathList
.insert(0, FileDirName
)
613 IncludePathListDict
[FileDirName
] = IncludePathList
614 IncludeFileQueue
= []
615 for IncludeFile
in GetIncludeFileList(FullFileName
):
616 FileName
= IncludeFile
[0].lstrip('#').strip()
617 FileName
= FileName
.lstrip('include').strip()
618 FileName
= FileName
.strip('\"')
619 FileName
= FileName
.lstrip('<').rstrip('>').strip()
620 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
622 IncludeFileQueue
.append(FullPath
)
625 while i
< len(IncludeFileQueue
):
626 for IncludeFile
in GetIncludeFileList(IncludeFileQueue
[i
]):
627 FileName
= IncludeFile
[0].lstrip('#').strip()
628 FileName
= FileName
.lstrip('include').strip()
629 FileName
= FileName
.strip('\"')
630 FileName
= FileName
.lstrip('<').rstrip('>').strip()
631 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
632 if FullPath
!= None and FullPath
not in IncludeFileQueue
:
633 IncludeFileQueue
.insert(i
+ 1, FullPath
)
636 AllIncludeFileListDict
[FullFileName
] = IncludeFileQueue
637 return IncludeFileQueue
639 def GetPredicateListFromPredicateExpStr(PES
):
646 p
= GetFuncDeclPattern()
647 while i
< len(PES
) - 1:
648 if (PES
[i
].isalnum() or PES
[i
] == '_' or PES
[i
] == '*') and LogicOpPos
> PredicateBegin
:
650 if (PES
[i
] == '&' and PES
[i
+ 1] == '&') or (PES
[i
] == '|' and PES
[i
+ 1] == '|'):
652 Exp
= PES
[PredicateBegin
:i
].strip()
653 # Exp may contain '.' or '->'
654 TmpExp
= Exp
.replace('.', '').replace('->', '')
656 PredicateList
.append(Exp
)
658 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
661 if PredicateBegin
> LogicOpPos
:
662 while PredicateBegin
< len(PES
):
663 if PES
[PredicateBegin
].isalnum() or PES
[PredicateBegin
] == '_' or PES
[PredicateBegin
] == '*':
666 Exp
= PES
[PredicateBegin
:len(PES
)].strip()
667 # Exp may contain '.' or '->'
668 TmpExp
= Exp
.replace('.', '').replace('->', '')
670 PredicateList
.append(Exp
)
672 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
675 def GetCNameList(Lvalue
, StarList
=[]):
683 while SearchBegin
< len(Lvalue
):
684 while i
< len(Lvalue
):
685 if Lvalue
[i
].isalnum() or Lvalue
[i
] == '_':
691 VarList
.append(Lvalue
[VarStart
:VarEnd
+ 1])
695 if VarStart
== -1 and Lvalue
[i
] == '*':
702 DotIndex
= Lvalue
[VarEnd
:].find('.')
703 ArrowIndex
= Lvalue
[VarEnd
:].find('->')
704 if DotIndex
== -1 and ArrowIndex
== -1:
706 elif DotIndex
== -1 and ArrowIndex
!= -1:
707 SearchBegin
= VarEnd
+ ArrowIndex
708 elif ArrowIndex
== -1 and DotIndex
!= -1:
709 SearchBegin
= VarEnd
+ DotIndex
711 SearchBegin
= VarEnd
+ ((DotIndex
< ArrowIndex
) and DotIndex
or ArrowIndex
)
719 def SplitPredicateByOp(Str
, Op
, IsFuncCalling
=False):
728 while Index
< len(Str
):
729 while not LBFound
and Str
[Index
] != '_' and not Str
[Index
].isalnum():
732 while not LBFound
and (Str
[Index
].isalnum() or Str
[Index
] == '_'):
734 # maybe type-cast at the begining, skip it.
735 RemainingStr
= Str
[Index
:].lstrip()
736 if RemainingStr
.startswith(')') and not LBFound
:
740 if RemainingStr
.startswith('(') and not LBFound
:
743 if Str
[Index
] == '(':
744 UnmatchedLBCount
+= 1
748 if Str
[Index
] == ')':
749 UnmatchedLBCount
-= 1
751 if UnmatchedLBCount
== 0:
757 if UnmatchedLBCount
> 0:
760 IndexInRemainingStr
= Str
[Index
:].find(Op
)
761 if IndexInRemainingStr
== -1:
764 Name
= Str
[0:Index
+ IndexInRemainingStr
].strip()
765 Value
= Str
[Index
+ IndexInRemainingStr
+ len(Op
):].strip().strip(')')
768 TmpStr
= Str
.rstrip(';').rstrip(')')
770 Index
= TmpStr
.rfind(Op
)
774 if Str
[Index
- 1].isalnum() or Str
[Index
- 1].isspace() or Str
[Index
- 1] == ')' or Str
[Index
- 1] == ']':
775 Name
= Str
[0:Index
].strip()
776 Value
= Str
[Index
+ len(Op
):].strip()
779 TmpStr
= Str
[0:Index
- 1]
781 def SplitPredicateStr(Str
):
783 Str
= Str
.lstrip('(')
784 IsFuncCalling
= False
785 p
= GetFuncDeclPattern()
786 TmpStr
= Str
.replace('.', '').replace('->', '')
790 PredPartList
= SplitPredicateByOp(Str
, '==', IsFuncCalling
)
791 if len(PredPartList
) > 1:
792 return [PredPartList
, '==']
794 PredPartList
= SplitPredicateByOp(Str
, '!=', IsFuncCalling
)
795 if len(PredPartList
) > 1:
796 return [PredPartList
, '!=']
798 PredPartList
= SplitPredicateByOp(Str
, '>=', IsFuncCalling
)
799 if len(PredPartList
) > 1:
800 return [PredPartList
, '>=']
802 PredPartList
= SplitPredicateByOp(Str
, '<=', IsFuncCalling
)
803 if len(PredPartList
) > 1:
804 return [PredPartList
, '<=']
806 PredPartList
= SplitPredicateByOp(Str
, '>', IsFuncCalling
)
807 if len(PredPartList
) > 1:
808 return [PredPartList
, '>']
810 PredPartList
= SplitPredicateByOp(Str
, '<', IsFuncCalling
)
811 if len(PredPartList
) > 1:
812 return [PredPartList
, '<']
814 return [[Str
, None], None]
816 def GetFuncContainsPE(ExpLine
, ResultSet
):
817 for Result
in ResultSet
:
818 if Result
[0] < ExpLine
and Result
[1] > ExpLine
:
822 def PatternInModifier(Modifier
, SubStr
):
823 PartList
= Modifier
.split()
824 for Part
in PartList
:
829 def GetDataTypeFromModifier(ModifierStr
):
830 MList
= ModifierStr
.split()
833 if M
in EccGlobalData
.gConfig
.ModifierList
:
836 if M
.startswith('[') or M
.endswith(']'):
838 ReturnType
+= M
+ ' '
840 ReturnType
= ReturnType
.strip()
841 if len(ReturnType
) == 0:
845 def DiffModifier(Str1
, Str2
):
846 PartList1
= Str1
.split()
847 PartList2
= Str2
.split()
848 if PartList1
== PartList2
:
853 def GetTypedefDict(FullFileName
):
855 Dict
= ComplexTypeDict
.get(FullFileName
)
859 FileID
= GetTableID(FullFileName
)
860 FileTable
= 'Identifier' + str(FileID
)
862 SqlStatement
= """ select Modifier, Name, Value, ID
865 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
866 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
869 for Result
in ResultSet
:
870 if len(Result
[0]) == 0:
871 Dict
[Result
[1]] = Result
[2]
873 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
874 for F
in IncludeFileList
:
875 FileID
= GetTableID(F
)
879 FileTable
= 'Identifier' + str(FileID
)
880 SqlStatement
= """ select Modifier, Name, Value, ID
883 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
884 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
886 for Result
in ResultSet
:
887 if not Result
[2].startswith('FP ('):
888 Dict
[Result
[1]] = Result
[2]
890 if len(Result
[0]) == 0:
891 Dict
[Result
[1]] = 'VOID'
893 Dict
[Result
[1]] = GetDataTypeFromModifier(Result
[0])
895 ComplexTypeDict
[FullFileName
] = Dict
898 def GetSUDict(FullFileName
):
900 Dict
= SUDict
.get(FullFileName
)
904 FileID
= GetTableID(FullFileName
)
905 FileTable
= 'Identifier' + str(FileID
)
907 SqlStatement
= """ select Name, Value, ID
909 where Model = %d or Model = %d
910 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
911 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
914 for Result
in ResultSet
:
915 if len(Result
[1]) > 0:
916 Dict
[Result
[0]] = Result
[1]
918 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
919 for F
in IncludeFileList
:
920 FileID
= GetTableID(F
)
924 FileTable
= 'Identifier' + str(FileID
)
925 SqlStatement
= """ select Name, Value, ID
927 where Model = %d or Model = %d
928 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
929 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
931 for Result
in ResultSet
:
932 if len(Result
[1]) > 0:
933 Dict
[Result
[0]] = Result
[1]
935 SUDict
[FullFileName
] = Dict
938 def StripComments(Str
):
940 ListFromStr
= list(Str
)
943 DoubleSlashComment
= False
945 while Index
< len(ListFromStr
):
946 # meet new line, then no longer in a comment for //
947 if ListFromStr
[Index
] == '\n':
948 if InComment
and DoubleSlashComment
:
950 DoubleSlashComment
= False
952 # check for */ comment end
953 elif InComment
and not DoubleSlashComment
and ListFromStr
[Index
] == '*' and ListFromStr
[Index
+ 1] == '/':
954 ListFromStr
[Index
] = ' '
956 ListFromStr
[Index
] = ' '
959 # set comments to spaces
961 ListFromStr
[Index
] = ' '
963 # check for // comment
964 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '/' and ListFromStr
[Index
+ 2] != '\n':
966 DoubleSlashComment
= True
968 # check for /* comment start
969 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '*':
970 ListFromStr
[Index
] = ' '
972 ListFromStr
[Index
] = ' '
978 # restore from List to String
979 Str
= "".join(ListFromStr
)
980 Str
= Str
.rstrip(' ')
984 def GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
):
985 Value
= TypedefDict
.get(Type
)
987 Value
= SUDict
.get(Type
)
991 LBPos
= Value
.find('{')
993 FTList
= Value
.split()
995 if FT
not in ('struct', 'union'):
996 Value
= TypedefDict
.get(FT
)
998 Value
= SUDict
.get(FT
)
1004 LBPos
= Value
.find('{')
1006 # RBPos = Value.find('}')
1007 Fields
= Value
[LBPos
+ 1:]
1008 Fields
= StripComments(Fields
)
1009 FieldsList
= Fields
.split(';')
1010 for Field
in FieldsList
:
1011 Field
= Field
.strip()
1012 Index
= Field
.rfind(FieldName
)
1015 if not Field
[Index
- 1].isalnum():
1016 if Index
+ len(FieldName
) == len(Field
):
1017 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1020 # For the condition that the field in struct is an array with [] sufixes...
1021 if not Field
[Index
+ len(FieldName
)].isalnum():
1022 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1027 def GetRealType(Type
, TypedefDict
, TargetType
=None):
1028 if TargetType
!= None and Type
== TargetType
:
1030 while TypedefDict
.get(Type
):
1031 Type
= TypedefDict
.get(Type
)
1032 if TargetType
!= None and Type
== TargetType
:
1036 def GetTypeInfo(RefList
, Modifier
, FullFileName
, TargetType
=None):
1037 TypedefDict
= GetTypedefDict(FullFileName
)
1038 SUDict
= GetSUDict(FullFileName
)
1039 Type
= GetDataTypeFromModifier(Modifier
).replace('*', '').strip()
1041 Type
= Type
.split()[-1]
1043 while Index
< len(RefList
):
1044 FieldName
= RefList
[Index
]
1045 FromType
= GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
)
1046 if FromType
== None:
1048 # we want to determine the exact type.
1049 if TargetType
!= None:
1050 Type
= FromType
.split()[0]
1051 # we only want to check if it is a pointer
1054 if Type
.find('*') != -1 and Index
== len(RefList
) - 1:
1056 Type
= FromType
.split()[0]
1060 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1064 def GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
=False, TargetType
=None, StarList
=None):
1066 PredVar
= PredVarList
[0]
1067 FileID
= GetTableID(FullFileName
)
1070 FileTable
= 'Identifier' + str(FileID
)
1071 # search variable in include files
1073 # it is a function call, search function declarations and definitions
1075 SqlStatement
= """ select Modifier, ID
1077 where Model = %d and Value = \'%s\'
1078 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1079 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1081 for Result
in ResultSet
:
1082 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1083 TypedefDict
= GetTypedefDict(FullFileName
)
1084 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1087 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1088 for F
in IncludeFileList
:
1089 FileID
= GetTableID(F
)
1093 FileTable
= 'Identifier' + str(FileID
)
1094 SqlStatement
= """ select Modifier, ID
1096 where Model = %d and Value = \'%s\'
1097 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1098 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1100 for Result
in ResultSet
:
1101 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1102 TypedefDict
= GetTypedefDict(FullFileName
)
1103 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1106 FileID
= GetTableID(FullFileName
)
1107 SqlStatement
= """ select Modifier, ID
1109 where BelongsToFile = %d and Name = \'%s\'
1110 """ % (FileID
, PredVar
)
1111 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1113 for Result
in ResultSet
:
1114 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1115 TypedefDict
= GetTypedefDict(FullFileName
)
1116 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1119 for F
in IncludeFileList
:
1120 FileID
= GetTableID(F
)
1124 FileTable
= 'Identifier' + str(FileID
)
1125 SqlStatement
= """ select Modifier, ID
1127 where BelongsToFile = %d and Name = \'%s\'
1128 """ % (FileID
, PredVar
)
1129 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1131 for Result
in ResultSet
:
1132 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1133 TypedefDict
= GetTypedefDict(FullFileName
)
1134 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1139 # really variable, search local variable first
1140 SqlStatement
= """ select Modifier, ID
1142 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1143 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
, FuncRecord
[0], FuncRecord
[1])
1144 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1146 for Result
in ResultSet
:
1147 if len(PredVarList
) > 1:
1148 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1151 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1152 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1154 if len(TypeList
) > 1 and StarList
!= None:
1155 for Star
in StarList
:
1157 Type
= Type
.rstrip(Star
)
1158 # Get real type after de-reference pointers.
1159 if len(Type
.strip()) == 0:
1161 TypedefDict
= GetTypedefDict(FullFileName
)
1162 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1165 # search function parameters second
1166 ParamList
= GetParamList(FuncRecord
[2])
1167 for Param
in ParamList
:
1168 if Param
.Name
.strip() == PredVar
:
1169 if len(PredVarList
) > 1:
1170 Type
= GetTypeInfo(PredVarList
[1:], Param
.Modifier
, FullFileName
, TargetType
)
1173 TypeList
= GetDataTypeFromModifier(Param
.Modifier
).split()
1175 if Type
== '*' and len(TypeList
) >= 2:
1177 if len(TypeList
) > 1 and StarList
!= None:
1178 for Star
in StarList
:
1180 Type
= Type
.rstrip(Star
)
1181 # Get real type after de-reference pointers.
1182 if len(Type
.strip()) == 0:
1184 TypedefDict
= GetTypedefDict(FullFileName
)
1185 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1188 # search global variable next
1189 SqlStatement
= """ select Modifier, ID
1191 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1192 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1193 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1195 for Result
in ResultSet
:
1196 if len(PredVarList
) > 1:
1197 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1200 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1202 if len(TypeList
) > 1 and StarList
!= None:
1203 for Star
in StarList
:
1205 Type
= Type
.rstrip(Star
)
1206 # Get real type after de-reference pointers.
1207 if len(Type
.strip()) == 0:
1209 TypedefDict
= GetTypedefDict(FullFileName
)
1210 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1213 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1214 for F
in IncludeFileList
:
1215 FileID
= GetTableID(F
)
1219 FileTable
= 'Identifier' + str(FileID
)
1220 SqlStatement
= """ select Modifier, ID
1222 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1223 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1224 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1226 for Result
in ResultSet
:
1227 if len(PredVarList
) > 1:
1228 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1231 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1233 if len(TypeList
) > 1 and StarList
!= None:
1234 for Star
in StarList
:
1236 Type
= Type
.rstrip(Star
)
1237 # Get real type after de-reference pointers.
1238 if len(Type
.strip()) == 0:
1240 TypedefDict
= GetTypedefDict(FullFileName
)
1241 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1244 def GetTypeFromArray(Type
, Var
):
1245 Count
= Var
.count('[')
1249 Type
= Type
.rstrip('*')
1254 def CheckFuncLayoutReturnType(FullFileName
):
1257 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1262 FileTable
= 'Identifier' + str(FileID
)
1263 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1266 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1267 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1268 for Result
in ResultSet
:
1269 ReturnType
= GetDataTypeFromModifier(Result
[0])
1270 TypeStart
= ReturnType
.split()[0]
1271 FuncName
= Result
[5]
1272 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1274 Index
= Result
[0].find(TypeStart
)
1275 if Index
!= 0 or Result
[3] != 0:
1276 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1278 if Result
[2] == Result
[4]:
1279 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1281 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1283 where BelongsToFile = %d
1285 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1286 for Result
in ResultSet
:
1287 ReturnType
= GetDataTypeFromModifier(Result
[0])
1288 TypeStart
= ReturnType
.split()[0]
1289 FuncName
= Result
[5]
1290 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1292 Index
= Result
[0].find(ReturnType
)
1293 if Index
!= 0 or Result
[3] != 0:
1294 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1296 if Result
[2] == Result
[4]:
1297 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, 'Function', Result
[1])
1299 def CheckFuncLayoutModifier(FullFileName
):
1302 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1307 FileTable
= 'Identifier' + str(FileID
)
1308 SqlStatement
= """ select Modifier, ID
1311 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1312 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1313 for Result
in ResultSet
:
1314 ReturnType
= GetDataTypeFromModifier(Result
[0])
1315 TypeStart
= ReturnType
.split()[0]
1316 # if len(ReturnType) == 0:
1318 Index
= Result
[0].find(TypeStart
)
1320 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1322 SqlStatement
= """ select Modifier, ID
1324 where BelongsToFile = %d
1326 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1327 for Result
in ResultSet
:
1328 ReturnType
= GetDataTypeFromModifier(Result
[0])
1329 TypeStart
= ReturnType
.split()[0]
1330 # if len(ReturnType) == 0:
1332 Index
= Result
[0].find(TypeStart
)
1334 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1336 def CheckFuncLayoutName(FullFileName
):
1338 # Parameter variable format pattern.
1339 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1340 ParamIgnoreList
= ('VOID', '...')
1341 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1346 FileTable
= 'Identifier' + str(FileID
)
1347 SqlStatement
= """ select Name, ID, EndColumn, Value
1350 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1351 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1352 for Result
in ResultSet
:
1353 FuncName
= Result
[3]
1354 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1357 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1358 ParamList
= GetParamList(Result
[0])
1359 if len(ParamList
) == 0:
1362 for Param
in ParamList
:
1363 if Param
.StartLine
<= StartLine
:
1364 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1365 if Param
.StartLine
- StartLine
> 1:
1366 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1367 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
):
1368 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1369 StartLine
= Param
.StartLine
1371 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1372 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1374 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1376 where BelongsToFile = %d
1378 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1379 for Result
in ResultSet
:
1380 FuncName
= Result
[3]
1381 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1384 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1385 ParamList
= GetParamList(Result
[0])
1386 if len(ParamList
) == 0:
1389 for Param
in ParamList
:
1390 if Param
.StartLine
<= StartLine
:
1391 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1392 if Param
.StartLine
- StartLine
> 1:
1393 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1394 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
):
1395 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1396 StartLine
= Param
.StartLine
1397 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1398 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1400 def CheckFuncLayoutPrototype(FullFileName
):
1403 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1407 FileTable
= 'Identifier' + str(FileID
)
1409 SqlStatement
= """ select Modifier, Header, Name, ID
1411 where BelongsToFile = %d
1413 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1414 if len(ResultSet
) == 0:
1418 for Result
in ResultSet
:
1419 FuncDefList
.append(Result
)
1421 SqlStatement
= """ select Modifier, Name, ID
1424 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1425 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1427 for Result
in ResultSet
:
1428 FuncDeclList
.append(Result
)
1431 for FuncDef
in FuncDefList
:
1432 FuncName
= FuncDef
[2].strip()
1433 FuncModifier
= FuncDef
[0]
1434 FuncDefHeader
= FuncDef
[1]
1435 for FuncDecl
in FuncDeclList
:
1436 LBPos
= FuncDecl
[1].find('(')
1437 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1438 DeclModifier
= FuncDecl
[0]
1439 if DeclName
== FuncName
:
1440 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1441 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1442 ParamListOfDef
= GetParamList(FuncDefHeader
)
1443 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1444 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1445 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1449 while Index
< len(ParamListOfDef
):
1450 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1451 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])
1455 UndeclFuncList
.append(FuncDef
)
1457 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1459 for F
in IncludeFileList
:
1460 FileID
= GetTableID(F
, ErrorMsgList
)
1464 FileTable
= 'Identifier' + str(FileID
)
1465 SqlStatement
= """ select Modifier, Name, ID
1468 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1469 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1471 for Result
in ResultSet
:
1472 FuncDeclList
.append(Result
)
1474 for FuncDef
in UndeclFuncList
:
1475 FuncName
= FuncDef
[2].strip()
1476 FuncModifier
= FuncDef
[0]
1477 FuncDefHeader
= FuncDef
[1]
1478 for FuncDecl
in FuncDeclList
:
1479 LBPos
= FuncDecl
[1].find('(')
1480 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1481 DeclModifier
= FuncDecl
[0]
1482 if DeclName
== FuncName
:
1483 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1484 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1485 ParamListOfDef
= GetParamList(FuncDefHeader
)
1486 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1487 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1488 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1492 while Index
< len(ParamListOfDef
):
1493 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1494 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])
1498 def CheckFuncLayoutBody(FullFileName
):
1501 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1505 FileTable
= 'Identifier' + str(FileID
)
1507 SqlStatement
= """ select BodyStartColumn, EndColumn, ID
1509 where BelongsToFile = %d
1511 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1512 if len(ResultSet
) == 0:
1514 for Result
in ResultSet
:
1516 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'open brace should be at the very beginning of a line.', 'Function', Result
[2])
1518 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'close brace should be at the very beginning of a line.', 'Function', Result
[2])
1520 def CheckFuncLayoutLocalVariable(FullFileName
):
1523 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1528 FileTable
= 'Identifier' + str(FileID
)
1529 SqlStatement
= """ select ID
1531 where BelongsToFile = %d
1533 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1534 if len(ResultSet
) == 0:
1537 for Result
in ResultSet
:
1541 SqlStatement
= """ select Name, Value, ID, Modifier
1543 where Model = %d and BelongsToFunction = %d
1544 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1545 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1546 if len(ResultSet
) == 0:
1549 for Result
in ResultSet
:
1550 if len(Result
[1]) > 0 and 'CONST' not in Result
[3]:
1551 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1553 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1555 # Member variable format pattern.
1556 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1558 LBPos
= Value
.find('{')
1559 RBPos
= Value
.rfind('}')
1560 if LBPos
== -1 or RBPos
== -1:
1563 Fields
= Value
[LBPos
+ 1 : RBPos
]
1564 Fields
= StripComments(Fields
).strip()
1565 NestPos
= Fields
.find ('struct')
1566 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)):
1567 if not Fields
[NestPos
+ len('struct') + 1].isalnum():
1568 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1569 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested struct in [%s].' % (Name
), FileTable
, TdId
)
1571 NestPos
= Fields
.find ('union')
1572 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1573 if not Fields
[NestPos
+ len('union') + 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 union in [%s].' % (Name
), FileTable
, TdId
)
1577 NestPos
= Fields
.find ('enum')
1578 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1579 if not Fields
[NestPos
+ len('enum') + 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 enum in [%s].' % (Name
), FileTable
, TdId
)
1584 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1585 FieldsList
= Fields
.split(',')
1586 # deal with enum is pre-assigned a value by function call ( , , , ...)
1589 RemoveCurrentElement
= False
1590 while Index
< len(FieldsList
):
1591 Field
= FieldsList
[Index
]
1593 if Field
.find('(') != -1:
1595 RemoveCurrentElement
= True
1599 if Field
.find(')') != -1 and QuoteCount
> 0:
1602 if RemoveCurrentElement
:
1603 FieldsList
.remove(Field
)
1605 RemoveCurrentElement
= False
1609 RemoveCurrentElement
= False
1613 FieldsList
= Fields
.split(';')
1615 for Field
in FieldsList
:
1616 Field
= Field
.strip()
1619 # For the condition that the field in struct is an array with [] sufixes...
1620 if Field
[-1] == ']':
1621 LBPos
= Field
.find('[')
1622 Field
= Field
[0:LBPos
]
1623 # For the condition that bit field ": Number"
1624 if Field
.find(':') != -1:
1625 ColonPos
= Field
.find(':')
1626 Field
= Field
[0:ColonPos
]
1628 Field
= Field
.strip()
1631 # Enum could directly assign value to variable
1632 Field
= Field
.split('=')[0].strip()
1633 TokenList
= Field
.split()
1634 # Remove pointers before variable
1635 Token
= TokenList
[-1]
1636 if Token
in ['OPTIONAL']:
1637 Token
= TokenList
[-2]
1638 if not Pattern
.match(Token
.lstrip('*')):
1639 ErrMsgList
.append(Token
.lstrip('*'))
1643 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1646 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1651 FileTable
= 'Identifier' + str(FileID
)
1652 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1655 """ % (FileTable
, ModelId
)
1656 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1658 for Result
in ResultSet
:
1659 ResultList
.append(Result
)
1661 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1662 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1663 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1664 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1665 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1666 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1667 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1669 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1672 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1673 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1677 # Check member variable name format that from typedefs of ONLY this file.
1679 Name
= Td
[1].strip()
1680 Value
= Td
[2].strip()
1681 if Value
.startswith('enum'):
1682 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1683 elif Value
.startswith('struct'):
1684 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1685 elif Value
.startswith('union'):
1686 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1690 if ValueModelId
!= ModelId
:
1692 # Check member variable format.
1693 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1694 for ErrMsg
in ErrMsgList
:
1695 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+ '.' + ErrMsg
):
1697 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+ '.' + ErrMsg
), FileTable
, Td
[5])
1699 # First check in current file to see whether struct/union/enum is typedef-ed.
1700 UntypedefedList
= []
1701 for Result
in ResultList
:
1702 # Check member variable format.
1703 Name
= Result
[0].strip()
1704 Value
= Result
[4].strip()
1705 if Value
.startswith('enum'):
1706 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1707 elif Value
.startswith('struct'):
1708 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1709 elif Value
.startswith('union'):
1710 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1714 if ValueModelId
!= ModelId
:
1716 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1717 for ErrMsg
in ErrMsgList
:
1718 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0] + '.' + ErrMsg
):
1720 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0] + '.' + ErrMsg
), FileTable
, Result
[3])
1721 # Check whether it is typedefed.
1724 # skip function pointer
1727 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1729 if not Td
[1].isupper():
1730 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1731 if Result
[0] in Td
[2].split():
1733 if not Td
[1].isupper():
1734 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1739 UntypedefedList
.append(Result
)
1742 if len(UntypedefedList
) == 0:
1745 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1747 for F
in IncludeFileList
:
1748 FileID
= GetTableID(F
, ErrorMsgList
)
1752 IncludeFileTable
= 'Identifier' + str(FileID
)
1753 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1756 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1757 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1758 TdList
.extend(ResultSet
)
1760 for Result
in UntypedefedList
:
1762 # Check whether it is typedefed.
1768 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1770 if not Td
[1].isupper():
1771 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1772 if Result
[0] in Td
[2].split():
1774 if not Td
[1].isupper():
1775 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1780 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1783 def CheckDeclStructTypedef(FullFileName
):
1784 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1786 def CheckDeclEnumTypedef(FullFileName
):
1787 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1789 def CheckDeclUnionTypedef(FullFileName
):
1790 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1792 def CheckDeclArgModifier(FullFileName
):
1795 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1800 FileTable
= 'Identifier' + str(FileID
)
1801 SqlStatement
= """ select Modifier, Name, ID
1804 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1805 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1806 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1807 MAX_MODIFIER_LENGTH
= 100
1808 for Result
in ResultSet
:
1809 for Modifier
in ModifierTuple
:
1810 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1811 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1814 SqlStatement
= """ select Modifier, Name, ID
1817 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1818 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1819 for Result
in ResultSet
:
1820 for Modifier
in ModifierTuple
:
1821 if PatternInModifier(Result
[0], Modifier
):
1822 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1825 SqlStatement
= """ select Modifier, Header, ID
1827 where BelongsToFile = %d
1829 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1830 for Result
in ResultSet
:
1831 for Modifier
in ModifierTuple
:
1832 if PatternInModifier(Result
[0], Modifier
):
1833 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1836 def CheckDeclNoUseCType(FullFileName
):
1839 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1844 FileTable
= 'Identifier' + str(FileID
)
1845 SqlStatement
= """ select Modifier, Name, ID
1848 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1849 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1850 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1851 for Result
in ResultSet
:
1852 for Type
in CTypeTuple
:
1853 if PatternInModifier(Result
[0], Type
):
1854 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Variable type %s' % Type
, FileTable
, Result
[2])
1857 SqlStatement
= """ select Modifier, Name, ID, Value
1860 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1861 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1862 for Result
in ResultSet
:
1863 ParamList
= GetParamList(Result
[1])
1864 FuncName
= Result
[3]
1865 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1867 for Type
in CTypeTuple
:
1868 if PatternInModifier(Result
[0], Type
):
1869 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1871 for Param
in ParamList
:
1872 if PatternInModifier(Param
.Modifier
, Type
):
1873 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1875 SqlStatement
= """ select Modifier, Header, ID, Name
1877 where BelongsToFile = %d
1879 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1880 for Result
in ResultSet
:
1881 ParamList
= GetParamList(Result
[1])
1882 FuncName
= Result
[3]
1883 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1885 for Type
in CTypeTuple
:
1886 if PatternInModifier(Result
[0], Type
):
1887 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1889 for Param
in ParamList
:
1890 if PatternInModifier(Param
.Modifier
, Type
):
1891 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1894 def CheckPointerNullComparison(FullFileName
):
1897 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1901 # cache the found function return type to accelerate later checking in this file.
1902 FuncReturnTypeDict
= {}
1905 FileTable
= 'Identifier' + str(FileID
)
1906 SqlStatement
= """ select Value, StartLine, ID
1909 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1910 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1911 if len(ResultSet
) == 0:
1914 for Result
in ResultSet
:
1915 PSL
.append([Result
[0], Result
[1], Result
[2]])
1917 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1919 where BelongsToFile = %d
1921 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1923 for Result
in ResultSet
:
1924 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1926 p
= GetFuncDeclPattern()
1928 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1929 if FuncRecord
== None:
1932 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1933 PredInfo
= SplitPredicateStr(Exp
)
1934 if PredInfo
[1] == None:
1935 PredVarStr
= PredInfo
[0][0].strip()
1937 SearchInCache
= False
1938 # PredVarStr may contain '.' or '->'
1939 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1941 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1942 SearchInCache
= True
1943 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1944 if TmpStr
.startswith(PredVarStr
):
1947 if PredVarStr
.strip() in IgnoredKeywordList
:
1950 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1951 # No variable found, maybe value first? like (0 == VarName)
1952 if len(PredVarList
) == 0:
1955 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1957 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1958 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1961 if PredVarStr
in FuncReturnTypeDict
:
1964 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1966 FuncReturnTypeDict
[PredVarStr
] = Type
1969 Type
= GetTypeFromArray(Type
, PredVarStr
)
1970 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1971 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1973 def CheckNonBooleanValueComparison(FullFileName
):
1976 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1980 # cache the found function return type to accelerate later checking in this file.
1981 FuncReturnTypeDict
= {}
1984 FileTable
= 'Identifier' + str(FileID
)
1985 SqlStatement
= """ select Value, StartLine, ID
1988 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1989 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1990 if len(ResultSet
) == 0:
1993 for Result
in ResultSet
:
1994 PSL
.append([Result
[0], Result
[1], Result
[2]])
1996 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1998 where BelongsToFile = %d
2000 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2002 for Result
in ResultSet
:
2003 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2005 p
= GetFuncDeclPattern()
2007 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2008 if FuncRecord
== None:
2011 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2012 PredInfo
= SplitPredicateStr(Exp
)
2013 if PredInfo
[1] == None:
2014 PredVarStr
= PredInfo
[0][0].strip()
2016 SearchInCache
= False
2017 # PredVarStr may contain '.' or '->'
2018 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2020 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2021 SearchInCache
= True
2022 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2023 if TmpStr
.startswith(PredVarStr
):
2026 if PredVarStr
.strip() in IgnoredKeywordList
:
2029 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2030 # No variable found, maybe value first? like (0 == VarName)
2031 if len(PredVarList
) == 0:
2035 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2037 if Type
.find('BOOLEAN') == -1:
2038 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2041 if PredVarStr
in FuncReturnTypeDict
:
2043 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2045 FuncReturnTypeDict
[PredVarStr
] = Type
2048 if Type
.find('BOOLEAN') == -1:
2049 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2052 def CheckBooleanValueComparison(FullFileName
):
2055 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2059 # cache the found function return type to accelerate later checking in this file.
2060 FuncReturnTypeDict
= {}
2063 FileTable
= 'Identifier' + str(FileID
)
2064 SqlStatement
= """ select Value, StartLine, ID
2067 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2068 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2069 if len(ResultSet
) == 0:
2072 for Result
in ResultSet
:
2073 PSL
.append([Result
[0], Result
[1], Result
[2]])
2075 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2077 where BelongsToFile = %d
2079 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2081 for Result
in ResultSet
:
2082 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2084 p
= GetFuncDeclPattern()
2086 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2087 if FuncRecord
== None:
2090 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2091 PredInfo
= SplitPredicateStr(Exp
)
2092 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2093 PredVarStr
= PredInfo
[0][0].strip()
2095 SearchInCache
= False
2096 # PredVarStr may contain '.' or '->'
2097 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2099 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2100 SearchInCache
= True
2101 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2102 if TmpStr
.startswith(PredVarStr
):
2105 if PredVarStr
.strip() in IgnoredKeywordList
:
2108 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2109 # No variable found, maybe value first? like (0 == VarName)
2110 if len(PredVarList
) == 0:
2114 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2116 if Type
.find('BOOLEAN') != -1:
2117 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2120 if PredVarStr
in FuncReturnTypeDict
:
2123 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2125 FuncReturnTypeDict
[PredVarStr
] = Type
2128 if Type
.find('BOOLEAN') != -1:
2129 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2132 def CheckHeaderFileData(FullFileName
):
2135 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2140 FileTable
= 'Identifier' + str(FileID
)
2141 SqlStatement
= """ select ID, Modifier
2144 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2145 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2146 for Result
in ResultSet
:
2147 if not Result
[1].startswith('extern'):
2148 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2150 SqlStatement
= """ select ID
2152 where BelongsToFile = %d
2154 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2155 for Result
in ResultSet
:
2156 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2160 def CheckHeaderFileIfndef(FullFileName
):
2163 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2168 FileTable
= 'Identifier' + str(FileID
)
2169 SqlStatement
= """ select Value, StartLine
2171 where Model = %d order by StartLine
2172 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2173 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2174 if len(ResultSet
) == 0:
2175 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2177 for Result
in ResultSet
:
2178 SqlStatement
= """ select Value, EndLine
2181 """ % (FileTable
, Result
[1])
2182 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2183 for Result
in ResultSet
:
2184 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2185 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2
, '', 'File', FileID
)
2188 SqlStatement
= """ select Value
2190 where StartLine > (select max(EndLine) from %s where Model = %d)
2191 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2192 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2193 for Result
in ResultSet
:
2194 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2195 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2198 def CheckDoxygenCommand(FullFileName
):
2201 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2206 FileTable
= 'Identifier' + str(FileID
)
2207 SqlStatement
= """ select Value, ID
2209 where Model = %d or Model = %d
2210 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2211 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2212 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval', 'return', 'sa', 'since', 'test', 'note', 'par']
2213 for Result
in ResultSet
:
2214 CommentStr
= Result
[0]
2215 CommentPartList
= CommentStr
.split()
2216 for Part
in CommentPartList
:
2217 if Part
.upper() == 'BUGBUG':
2218 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2219 if Part
.upper() == 'TODO':
2220 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2221 if Part
.startswith('@'):
2222 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2224 if Part
.lstrip('@').isalpha():
2225 if Part
.lstrip('@') not in DoxygenCommandList
:
2226 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2228 Index
= Part
.find('[')
2230 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2231 RealCmd
= Part
[1:Index
]
2232 if RealCmd
not in DoxygenCommandList
:
2233 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2236 def CheckDoxygenTripleForwardSlash(FullFileName
):
2239 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2245 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2247 where BelongsToFile = %d
2249 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2250 if len(ResultSet
) == 0:
2254 for Result
in ResultSet
:
2255 FuncDefSet
.append(Result
)
2258 FileTable
= 'Identifier' + str(FileID
)
2259 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2263 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2264 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2267 for Result
in ResultSet
:
2268 CommentSet
.append(Result
)
2270 print 'Unrecognized chars in comment of file %s', FullFileName
2273 for Result
in CommentSet
:
2274 CommentStr
= Result
[0]
2275 StartLine
= Result
[2]
2276 StartColumn
= Result
[3]
2278 EndColumn
= Result
[5]
2279 if not CommentStr
.startswith('///<'):
2283 for FuncDef
in FuncDefSet
:
2284 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2287 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2290 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2293 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2297 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2300 def CheckFileHeaderDoxygenComments(FullFileName
):
2303 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2308 FileTable
= 'Identifier' + str(FileID
)
2309 SqlStatement
= """ select Value, ID
2311 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2312 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2313 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2314 if len(ResultSet
) == 0:
2315 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No File License header appear at the very beginning of file.', 'File', FileID
)
2318 NoHeaderCommentStartFlag
= True
2319 NoHeaderCommentEndFlag
= True
2320 NoHeaderCommentPeriodFlag
= True
2321 NoCopyrightFlag
= True
2322 NoLicenseFlag
= True
2323 NoRevReferFlag
= True
2325 for Result
in ResultSet
:
2326 FileStartFlag
= False
2328 CommentStr
= Result
[0].strip()
2329 CommentStrListTemp
= CommentStr
.split('\n')
2330 if (len(CommentStrListTemp
) <= 1):
2332 CommentStrListTemp
= CommentStr
.split('\r')
2333 # Skip the content before the file header
2334 for CommentLine
in CommentStrListTemp
:
2335 if CommentLine
.strip().startswith('/** @file'):
2336 FileStartFlag
= True
2337 if FileStartFlag
== True:
2338 CommentStrList
.append(CommentLine
)
2342 if CommentStrList
and CommentStrList
[0].strip().startswith('/** @file'):
2343 NoHeaderCommentStartFlag
= False
2346 if CommentStrList
and CommentStrList
[-1].strip().endswith('**/'):
2347 NoHeaderCommentEndFlag
= False
2351 for CommentLine
in CommentStrList
:
2353 NextLineIndex
= Index
2354 if CommentLine
.startswith('/** @file'):
2356 if CommentLine
.startswith('**/'):
2358 # Check whether C File header Comment content start with two spaces.
2359 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentStartSpacesNum
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2360 if CommentLine
.startswith('/** @file') == False and CommentLine
.startswith('**/') == False and CommentLine
.strip() and CommentLine
.startswith(' ') == False:
2361 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment content should start with two spaces at each line', FileTable
, ID
)
2363 CommentLine
= CommentLine
.strip()
2364 if CommentLine
.startswith('Copyright'):
2365 NoCopyrightFlag
= False
2366 if CommentLine
.find('All rights reserved') == -1:
2367 for Copyright
in EccGlobalData
.gConfig
.Copyright
:
2368 if CommentLine
.find(Copyright
) > -1:
2369 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable
, ID
)
2371 if CommentLine
.endswith('<BR>') == -1:
2372 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'The ""<BR>"" at the end of the Copyright line is required', FileTable
, ID
)
2373 if NextLineIndex
< len(CommentStrList
) and CommentStrList
[NextLineIndex
].strip().startswith('Copyright') == False and CommentStrList
[NextLineIndex
].strip():
2374 NoLicenseFlag
= False
2375 if CommentLine
.startswith('@par Revision Reference:'):
2376 NoRevReferFlag
= False
2378 for RefLine
in CommentStrList
[NextLineIndex
:]:
2379 if RefLine
.strip() and (NextLineIndex
+ 1) < len(CommentStrList
) and CommentStrList
[NextLineIndex
+1].strip() and CommentStrList
[NextLineIndex
+1].strip().startswith('**/') == False:
2381 if RefLine
.strip() == False or RefLine
.strip().startswith('**/'):
2384 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2385 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentReferenceFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2386 if RefListFlag
== True:
2387 if RefLine
.strip() and RefLine
.strip().startswith('**/') == False and RefLine
.startswith(' -') == False:
2388 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable
, ID
)
2390 if NoHeaderCommentStartFlag
:
2391 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, ID
)
2393 if NoHeaderCommentEndFlag
:
2394 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with ""**/""', FileTable
, ID
)
2397 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment missing the ""Copyright""', FileTable
, ID
)
2398 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2399 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentLicenseFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2401 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable
, ID
)
2403 def CheckFuncHeaderDoxygenComments(FullFileName
):
2406 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2411 FileTable
= 'Identifier' + str(FileID
)
2412 SqlStatement
= """ select Value, StartLine, EndLine, ID
2415 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2417 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2420 for Result
in ResultSet
:
2421 CommentSet
.append(Result
)
2423 print 'Unrecognized chars in comment of file %s', FullFileName
2426 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2429 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2430 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2431 for Result
in ResultSet
:
2432 FuncName
= Result
[4]
2433 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2434 if FunctionHeaderComment
:
2435 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2437 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2439 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2440 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2443 SqlStatement
= """ select Value, StartLine, EndLine, ID
2446 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2448 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2451 for Result
in ResultSet
:
2452 CommentSet
.append(Result
)
2454 print 'Unrecognized chars in comment of file %s', FullFileName
2456 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2458 where BelongsToFile = %d
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
), 'Function', Result
[3])
2473 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2475 for Comment
in CommentSet
:
2476 if Comment
[2] == FuncStartLine
- 1:
2480 def GetDoxygenStrFromComment(Str
):
2482 ParamTagList
= Str
.split('@param')
2483 if len(ParamTagList
) > 1:
2485 while i
< len(ParamTagList
):
2486 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2489 Str
= ParamTagList
[0]
2491 RetvalTagList
= ParamTagList
[-1].split('@retval')
2492 if len(RetvalTagList
) > 1:
2493 if len(ParamTagList
) > 1:
2494 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2496 while i
< len(RetvalTagList
):
2497 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2500 ReturnTagList
= RetvalTagList
[-1].split('@return')
2501 if len(ReturnTagList
) > 1:
2502 if len(RetvalTagList
) > 1:
2503 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2504 elif len(ParamTagList
) > 1:
2505 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2507 while i
< len(ReturnTagList
):
2508 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2511 if len(DoxygenStrList
) > 0:
2512 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2514 return DoxygenStrList
2516 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2517 #/** --*/ @retval after @param
2518 if not Str
.startswith('/**'):
2519 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2520 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2521 if not Str
.endswith('**/'):
2522 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2523 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2524 FirstRetvalIndex
= Str
.find('@retval')
2525 LastParamIndex
= Str
.rfind('@param')
2526 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2527 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2528 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2530 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2532 ParamList
= GetParamList(FuncHeader
)
2533 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2534 DescriptionStr
= CommentStr
2535 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2536 if DescriptionStr
.find('.') == -1:
2537 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2538 DoxygenTagNumber
= len(DoxygenStrList
)
2539 ParamNumber
= len(ParamList
)
2540 for Param
in ParamList
:
2541 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2544 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2545 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2546 ParamModifier
= ParamList
[Index
].Modifier
2547 ParamName
= ParamList
[Index
].Name
.strip()
2548 Tag
= DoxygenStrList
[Index
].strip(' ')
2549 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2550 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2551 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, <%s> does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2552 TagPartList
= Tag
.split()
2553 if len(TagPartList
) < 2:
2554 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2555 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2558 LBPos
= Tag
.find('[')
2559 RBPos
= Tag
.find(']')
2560 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2561 if LBPos
> 0 and len(ParamToLBContent
) == 0 and RBPos
> LBPos
:
2563 ModifierPartList
= ParamModifier
.split()
2564 for Part
in ModifierPartList
:
2565 if Part
.strip() == 'IN':
2567 if Part
.strip() == 'OUT':
2574 if Tag
.find('[' + InOutStr
+ ']') == -1:
2575 if InOutStr
!= 'in, out':
2576 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2577 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2579 if Tag
.find('[in,out]') == -1:
2580 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2581 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2584 if Tag
.find(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2585 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2586 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
)
2589 if Index
< ParamNumber
:
2590 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2591 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2592 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2593 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2595 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2596 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2597 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2598 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2600 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2601 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2602 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2604 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
2605 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2606 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need NO doxygen tags in comment ', TableName
, CommentId
)
2607 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2608 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2609 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2611 if __name__
== '__main__':
2613 # EdkLogger.Initialize()
2614 # EdkLogger.SetLevel(EdkLogger.QUIET)
2615 # CollectSourceCodeDataIntoDB(sys.argv[1])
2617 test_file
= sys
.argv
[1]
2618 except IndexError, v
:
2619 print "Usage: %s filename" % sys
.argv
[0]
2621 MsgList
= CheckFuncHeaderDoxygenComments(test_file
)