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 len(TypeList
) > 1 and StarList
!= None:
1176 for Star
in StarList
:
1178 Type
= Type
.rstrip(Star
)
1179 # Get real type after de-reference pointers.
1180 if len(Type
.strip()) == 0:
1182 TypedefDict
= GetTypedefDict(FullFileName
)
1183 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1186 # search global variable next
1187 SqlStatement
= """ select Modifier, ID
1189 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1190 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1191 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1193 for Result
in ResultSet
:
1194 if len(PredVarList
) > 1:
1195 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1198 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1200 if len(TypeList
) > 1 and StarList
!= None:
1201 for Star
in StarList
:
1203 Type
= Type
.rstrip(Star
)
1204 # Get real type after de-reference pointers.
1205 if len(Type
.strip()) == 0:
1207 TypedefDict
= GetTypedefDict(FullFileName
)
1208 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1211 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1212 for F
in IncludeFileList
:
1213 FileID
= GetTableID(F
)
1217 FileTable
= 'Identifier' + str(FileID
)
1218 SqlStatement
= """ select Modifier, ID
1220 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1221 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1222 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1224 for Result
in ResultSet
:
1225 if len(PredVarList
) > 1:
1226 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1229 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1231 if len(TypeList
) > 1 and StarList
!= None:
1232 for Star
in StarList
:
1234 Type
= Type
.rstrip(Star
)
1235 # Get real type after de-reference pointers.
1236 if len(Type
.strip()) == 0:
1238 TypedefDict
= GetTypedefDict(FullFileName
)
1239 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1242 def GetTypeFromArray(Type
, Var
):
1243 Count
= Var
.count('[')
1247 Type
= Type
.rstrip('*')
1252 def CheckFuncLayoutReturnType(FullFileName
):
1255 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1260 FileTable
= 'Identifier' + str(FileID
)
1261 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1264 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1265 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1266 for Result
in ResultSet
:
1267 ReturnType
= GetDataTypeFromModifier(Result
[0])
1268 TypeStart
= ReturnType
.split()[0]
1269 FuncName
= Result
[5]
1270 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1272 Index
= Result
[0].find(TypeStart
)
1273 if Index
!= 0 or Result
[3] != 0:
1274 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1276 if Result
[2] == Result
[4]:
1277 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1279 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1281 where BelongsToFile = %d
1283 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1284 for Result
in ResultSet
:
1285 ReturnType
= GetDataTypeFromModifier(Result
[0])
1286 TypeStart
= ReturnType
.split()[0]
1287 FuncName
= Result
[5]
1288 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1290 Index
= Result
[0].find(ReturnType
)
1291 if Index
!= 0 or Result
[3] != 0:
1292 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1294 if Result
[2] == Result
[4]:
1295 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, 'Function', Result
[1])
1297 def CheckFuncLayoutModifier(FullFileName
):
1300 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1305 FileTable
= 'Identifier' + str(FileID
)
1306 SqlStatement
= """ select Modifier, ID
1309 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1310 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1311 for Result
in ResultSet
:
1312 ReturnType
= GetDataTypeFromModifier(Result
[0])
1313 TypeStart
= ReturnType
.split()[0]
1314 # if len(ReturnType) == 0:
1316 Index
= Result
[0].find(TypeStart
)
1318 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1320 SqlStatement
= """ select Modifier, ID
1322 where BelongsToFile = %d
1324 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1325 for Result
in ResultSet
:
1326 ReturnType
= GetDataTypeFromModifier(Result
[0])
1327 TypeStart
= ReturnType
.split()[0]
1328 # if len(ReturnType) == 0:
1330 Index
= Result
[0].find(TypeStart
)
1332 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1334 def CheckFuncLayoutName(FullFileName
):
1336 # Parameter variable format pattern.
1337 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1338 ParamIgnoreList
= ('VOID', '...')
1339 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1344 FileTable
= 'Identifier' + str(FileID
)
1345 SqlStatement
= """ select Name, ID, EndColumn, Value
1348 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1349 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1350 for Result
in ResultSet
:
1351 FuncName
= Result
[3]
1352 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1355 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1356 ParamList
= GetParamList(Result
[0])
1357 if len(ParamList
) == 0:
1360 for Param
in ParamList
:
1361 if Param
.StartLine
<= StartLine
:
1362 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1363 if Param
.StartLine
- StartLine
> 1:
1364 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1365 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
):
1366 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1367 StartLine
= Param
.StartLine
1369 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1370 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1372 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1374 where BelongsToFile = %d
1376 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1377 for Result
in ResultSet
:
1378 FuncName
= Result
[3]
1379 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1382 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1383 ParamList
= GetParamList(Result
[0])
1384 if len(ParamList
) == 0:
1387 for Param
in ParamList
:
1388 if Param
.StartLine
<= StartLine
:
1389 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1390 if Param
.StartLine
- StartLine
> 1:
1391 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1392 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
):
1393 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1394 StartLine
= Param
.StartLine
1395 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1396 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1398 def CheckFuncLayoutPrototype(FullFileName
):
1401 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1405 FileTable
= 'Identifier' + str(FileID
)
1407 SqlStatement
= """ select Modifier, Header, Name, ID
1409 where BelongsToFile = %d
1411 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1412 if len(ResultSet
) == 0:
1416 for Result
in ResultSet
:
1417 FuncDefList
.append(Result
)
1419 SqlStatement
= """ select Modifier, Name, ID
1422 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1423 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1425 for Result
in ResultSet
:
1426 FuncDeclList
.append(Result
)
1429 for FuncDef
in FuncDefList
:
1430 FuncName
= FuncDef
[2].strip()
1431 FuncModifier
= FuncDef
[0]
1432 FuncDefHeader
= FuncDef
[1]
1433 for FuncDecl
in FuncDeclList
:
1434 LBPos
= FuncDecl
[1].find('(')
1435 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1436 DeclModifier
= FuncDecl
[0]
1437 if DeclName
== FuncName
:
1438 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1439 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1440 ParamListOfDef
= GetParamList(FuncDefHeader
)
1441 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1442 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1443 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1447 while Index
< len(ParamListOfDef
):
1448 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1449 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])
1453 UndeclFuncList
.append(FuncDef
)
1455 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1457 for F
in IncludeFileList
:
1458 FileID
= GetTableID(F
, ErrorMsgList
)
1462 FileTable
= 'Identifier' + str(FileID
)
1463 SqlStatement
= """ select Modifier, Name, ID
1466 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1467 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1469 for Result
in ResultSet
:
1470 FuncDeclList
.append(Result
)
1472 for FuncDef
in UndeclFuncList
:
1473 FuncName
= FuncDef
[2].strip()
1474 FuncModifier
= FuncDef
[0]
1475 FuncDefHeader
= FuncDef
[1]
1476 for FuncDecl
in FuncDeclList
:
1477 LBPos
= FuncDecl
[1].find('(')
1478 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1479 DeclModifier
= FuncDecl
[0]
1480 if DeclName
== FuncName
:
1481 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1482 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1483 ParamListOfDef
= GetParamList(FuncDefHeader
)
1484 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1485 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1486 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1490 while Index
< len(ParamListOfDef
):
1491 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1492 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])
1496 def CheckFuncLayoutBody(FullFileName
):
1499 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1503 FileTable
= 'Identifier' + str(FileID
)
1505 SqlStatement
= """ select BodyStartColumn, EndColumn, ID
1507 where BelongsToFile = %d
1509 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1510 if len(ResultSet
) == 0:
1512 for Result
in ResultSet
:
1514 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'open brace should be at the very beginning of a line.', 'Function', Result
[2])
1516 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'close brace should be at the very beginning of a line.', 'Function', Result
[2])
1518 def CheckFuncLayoutLocalVariable(FullFileName
):
1521 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1526 FileTable
= 'Identifier' + str(FileID
)
1527 SqlStatement
= """ select ID
1529 where BelongsToFile = %d
1531 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1532 if len(ResultSet
) == 0:
1535 for Result
in ResultSet
:
1539 SqlStatement
= """ select Name, Value, ID, Modifier
1541 where Model = %d and BelongsToFunction = %d
1542 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1543 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1544 if len(ResultSet
) == 0:
1547 for Result
in ResultSet
:
1548 if len(Result
[1]) > 0 and 'CONST' not in Result
[3]:
1549 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1551 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1553 # Member variable format pattern.
1554 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1556 LBPos
= Value
.find('{')
1557 RBPos
= Value
.rfind('}')
1558 if LBPos
== -1 or RBPos
== -1:
1561 Fields
= Value
[LBPos
+ 1 : RBPos
]
1562 Fields
= StripComments(Fields
).strip()
1563 NestPos
= Fields
.find ('struct')
1564 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)):
1565 if not Fields
[NestPos
+ len('struct') + 1].isalnum():
1566 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1567 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested struct in [%s].' % (Name
), FileTable
, TdId
)
1569 NestPos
= Fields
.find ('union')
1570 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1571 if not Fields
[NestPos
+ len('union') + 1].isalnum():
1572 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1573 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested union in [%s].' % (Name
), FileTable
, TdId
)
1575 NestPos
= Fields
.find ('enum')
1576 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1577 if not Fields
[NestPos
+ len('enum') + 1].isalnum():
1578 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1579 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested enum in [%s].' % (Name
), FileTable
, TdId
)
1582 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1583 FieldsList
= Fields
.split(',')
1584 # deal with enum is pre-assigned a value by function call ( , , , ...)
1587 RemoveCurrentElement
= False
1588 while Index
< len(FieldsList
):
1589 Field
= FieldsList
[Index
]
1591 if Field
.find('(') != -1:
1593 RemoveCurrentElement
= True
1597 if Field
.find(')') != -1 and QuoteCount
> 0:
1600 if RemoveCurrentElement
:
1601 FieldsList
.remove(Field
)
1603 RemoveCurrentElement
= False
1607 RemoveCurrentElement
= False
1611 FieldsList
= Fields
.split(';')
1613 for Field
in FieldsList
:
1614 Field
= Field
.strip()
1617 # For the condition that the field in struct is an array with [] sufixes...
1618 if Field
[-1] == ']':
1619 LBPos
= Field
.find('[')
1620 Field
= Field
[0:LBPos
]
1621 # For the condition that bit field ": Number"
1622 if Field
.find(':') != -1:
1623 ColonPos
= Field
.find(':')
1624 Field
= Field
[0:ColonPos
]
1626 Field
= Field
.strip()
1629 # Enum could directly assign value to variable
1630 Field
= Field
.split('=')[0].strip()
1631 TokenList
= Field
.split()
1632 # Remove pointers before variable
1633 if not Pattern
.match(TokenList
[-1].lstrip('*')):
1634 ErrMsgList
.append(TokenList
[-1].lstrip('*'))
1638 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1641 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1646 FileTable
= 'Identifier' + str(FileID
)
1647 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1650 """ % (FileTable
, ModelId
)
1651 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1653 for Result
in ResultSet
:
1654 ResultList
.append(Result
)
1656 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1657 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1658 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1659 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1660 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1661 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1662 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1664 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1667 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1668 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1672 # Check member variable name format that from typedefs of ONLY this file.
1674 Name
= Td
[1].strip()
1675 Value
= Td
[2].strip()
1676 if Value
.startswith('enum'):
1677 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1678 elif Value
.startswith('struct'):
1679 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1680 elif Value
.startswith('union'):
1681 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1685 if ValueModelId
!= ModelId
:
1687 # Check member variable format.
1688 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1689 for ErrMsg
in ErrMsgList
:
1690 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+ '.' + ErrMsg
):
1692 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+ '.' + ErrMsg
), FileTable
, Td
[5])
1694 # First check in current file to see whether struct/union/enum is typedef-ed.
1695 UntypedefedList
= []
1696 for Result
in ResultList
:
1697 # Check member variable format.
1698 Name
= Result
[0].strip()
1699 Value
= Result
[4].strip()
1700 if Value
.startswith('enum'):
1701 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1702 elif Value
.startswith('struct'):
1703 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1704 elif Value
.startswith('union'):
1705 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1709 if ValueModelId
!= ModelId
:
1711 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1712 for ErrMsg
in ErrMsgList
:
1713 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0] + '.' + ErrMsg
):
1715 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0] + '.' + ErrMsg
), FileTable
, Result
[3])
1716 # Check whether it is typedefed.
1719 # skip function pointer
1722 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1724 if not Td
[1].isupper():
1725 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1726 if Result
[0] in Td
[2].split():
1728 if not Td
[1].isupper():
1729 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1734 UntypedefedList
.append(Result
)
1737 if len(UntypedefedList
) == 0:
1740 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1742 for F
in IncludeFileList
:
1743 FileID
= GetTableID(F
, ErrorMsgList
)
1747 IncludeFileTable
= 'Identifier' + str(FileID
)
1748 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1751 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1752 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1753 TdList
.extend(ResultSet
)
1755 for Result
in UntypedefedList
:
1757 # Check whether it is typedefed.
1763 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1765 if not Td
[1].isupper():
1766 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1767 if Result
[0] in Td
[2].split():
1769 if not Td
[1].isupper():
1770 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1775 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1778 def CheckDeclStructTypedef(FullFileName
):
1779 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1781 def CheckDeclEnumTypedef(FullFileName
):
1782 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1784 def CheckDeclUnionTypedef(FullFileName
):
1785 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1787 def CheckDeclArgModifier(FullFileName
):
1790 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1795 FileTable
= 'Identifier' + str(FileID
)
1796 SqlStatement
= """ select Modifier, Name, ID
1799 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1800 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1801 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1802 MAX_MODIFIER_LENGTH
= 100
1803 for Result
in ResultSet
:
1804 for Modifier
in ModifierTuple
:
1805 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1806 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1809 SqlStatement
= """ select Modifier, Name, ID
1812 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1813 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1814 for Result
in ResultSet
:
1815 for Modifier
in ModifierTuple
:
1816 if PatternInModifier(Result
[0], Modifier
):
1817 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1820 SqlStatement
= """ select Modifier, Header, ID
1822 where BelongsToFile = %d
1824 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1825 for Result
in ResultSet
:
1826 for Modifier
in ModifierTuple
:
1827 if PatternInModifier(Result
[0], Modifier
):
1828 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1831 def CheckDeclNoUseCType(FullFileName
):
1834 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1839 FileTable
= 'Identifier' + str(FileID
)
1840 SqlStatement
= """ select Modifier, Name, ID
1843 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1844 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1845 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1846 for Result
in ResultSet
:
1847 for Type
in CTypeTuple
:
1848 if PatternInModifier(Result
[0], Type
):
1849 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Variable type %s' % Type
, FileTable
, Result
[2])
1852 SqlStatement
= """ select Modifier, Name, ID, Value
1855 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1856 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1857 for Result
in ResultSet
:
1858 ParamList
= GetParamList(Result
[1])
1859 FuncName
= Result
[3]
1860 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1862 for Type
in CTypeTuple
:
1863 if PatternInModifier(Result
[0], Type
):
1864 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1866 for Param
in ParamList
:
1867 if PatternInModifier(Param
.Modifier
, Type
):
1868 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1870 SqlStatement
= """ select Modifier, Header, ID, Name
1872 where BelongsToFile = %d
1874 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1875 for Result
in ResultSet
:
1876 ParamList
= GetParamList(Result
[1])
1877 FuncName
= Result
[3]
1878 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1880 for Type
in CTypeTuple
:
1881 if PatternInModifier(Result
[0], Type
):
1882 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1884 for Param
in ParamList
:
1885 if PatternInModifier(Param
.Modifier
, Type
):
1886 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1889 def CheckPointerNullComparison(FullFileName
):
1892 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1896 # cache the found function return type to accelerate later checking in this file.
1897 FuncReturnTypeDict
= {}
1900 FileTable
= 'Identifier' + str(FileID
)
1901 SqlStatement
= """ select Value, StartLine, ID
1904 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1905 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1906 if len(ResultSet
) == 0:
1909 for Result
in ResultSet
:
1910 PSL
.append([Result
[0], Result
[1], Result
[2]])
1912 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1914 where BelongsToFile = %d
1916 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1918 for Result
in ResultSet
:
1919 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1921 p
= GetFuncDeclPattern()
1923 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1924 if FuncRecord
== None:
1927 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1928 PredInfo
= SplitPredicateStr(Exp
)
1929 if PredInfo
[1] == None:
1930 PredVarStr
= PredInfo
[0][0].strip()
1932 SearchInCache
= False
1933 # PredVarStr may contain '.' or '->'
1934 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1936 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1937 SearchInCache
= True
1938 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1939 if TmpStr
.startswith(PredVarStr
):
1942 if PredVarStr
.strip() in IgnoredKeywordList
:
1945 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1946 # No variable found, maybe value first? like (0 == VarName)
1947 if len(PredVarList
) == 0:
1950 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1952 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1953 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1956 if PredVarStr
in FuncReturnTypeDict
:
1959 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1961 FuncReturnTypeDict
[PredVarStr
] = Type
1964 Type
= GetTypeFromArray(Type
, PredVarStr
)
1965 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1966 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1968 def CheckNonBooleanValueComparison(FullFileName
):
1971 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1975 # cache the found function return type to accelerate later checking in this file.
1976 FuncReturnTypeDict
= {}
1979 FileTable
= 'Identifier' + str(FileID
)
1980 SqlStatement
= """ select Value, StartLine, ID
1983 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1984 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1985 if len(ResultSet
) == 0:
1988 for Result
in ResultSet
:
1989 PSL
.append([Result
[0], Result
[1], Result
[2]])
1991 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1993 where BelongsToFile = %d
1995 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1997 for Result
in ResultSet
:
1998 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2000 p
= GetFuncDeclPattern()
2002 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2003 if FuncRecord
== None:
2006 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2007 PredInfo
= SplitPredicateStr(Exp
)
2008 if PredInfo
[1] == None:
2009 PredVarStr
= PredInfo
[0][0].strip()
2011 SearchInCache
= False
2012 # PredVarStr may contain '.' or '->'
2013 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2015 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2016 SearchInCache
= True
2017 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2018 if TmpStr
.startswith(PredVarStr
):
2021 if PredVarStr
.strip() in IgnoredKeywordList
:
2024 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2025 # No variable found, maybe value first? like (0 == VarName)
2026 if len(PredVarList
) == 0:
2030 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2032 if Type
.find('BOOLEAN') == -1:
2033 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2036 if PredVarStr
in FuncReturnTypeDict
:
2038 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2040 FuncReturnTypeDict
[PredVarStr
] = Type
2043 if Type
.find('BOOLEAN') == -1:
2044 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2047 def CheckBooleanValueComparison(FullFileName
):
2050 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2054 # cache the found function return type to accelerate later checking in this file.
2055 FuncReturnTypeDict
= {}
2058 FileTable
= 'Identifier' + str(FileID
)
2059 SqlStatement
= """ select Value, StartLine, ID
2062 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2063 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2064 if len(ResultSet
) == 0:
2067 for Result
in ResultSet
:
2068 PSL
.append([Result
[0], Result
[1], Result
[2]])
2070 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2072 where BelongsToFile = %d
2074 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2076 for Result
in ResultSet
:
2077 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2079 p
= GetFuncDeclPattern()
2081 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2082 if FuncRecord
== None:
2085 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2086 PredInfo
= SplitPredicateStr(Exp
)
2087 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2088 PredVarStr
= PredInfo
[0][0].strip()
2090 SearchInCache
= False
2091 # PredVarStr may contain '.' or '->'
2092 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2094 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2095 SearchInCache
= True
2096 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2097 if TmpStr
.startswith(PredVarStr
):
2100 if PredVarStr
.strip() in IgnoredKeywordList
:
2103 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2104 # No variable found, maybe value first? like (0 == VarName)
2105 if len(PredVarList
) == 0:
2109 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2111 if Type
.find('BOOLEAN') != -1:
2112 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2115 if PredVarStr
in FuncReturnTypeDict
:
2118 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2120 FuncReturnTypeDict
[PredVarStr
] = Type
2123 if Type
.find('BOOLEAN') != -1:
2124 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2127 def CheckHeaderFileData(FullFileName
):
2130 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2135 FileTable
= 'Identifier' + str(FileID
)
2136 SqlStatement
= """ select ID, Modifier
2139 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2140 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2141 for Result
in ResultSet
:
2142 if not Result
[1].startswith('extern'):
2143 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2145 SqlStatement
= """ select ID
2147 where BelongsToFile = %d
2149 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2150 for Result
in ResultSet
:
2151 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2155 def CheckHeaderFileIfndef(FullFileName
):
2158 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2163 FileTable
= 'Identifier' + str(FileID
)
2164 SqlStatement
= """ select Value, StartLine
2166 where Model = %d order by StartLine
2167 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2168 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2169 if len(ResultSet
) == 0:
2170 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2172 for Result
in ResultSet
:
2173 SqlStatement
= """ select Value, EndLine
2176 """ % (FileTable
, Result
[1])
2177 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2178 for Result
in ResultSet
:
2179 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2180 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2
, '', 'File', FileID
)
2183 SqlStatement
= """ select Value
2185 where StartLine > (select max(EndLine) from %s where Model = %d)
2186 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2187 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2188 for Result
in ResultSet
:
2189 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2190 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2193 def CheckDoxygenCommand(FullFileName
):
2196 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2201 FileTable
= 'Identifier' + str(FileID
)
2202 SqlStatement
= """ select Value, ID
2204 where Model = %d or Model = %d
2205 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2206 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2207 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval', 'return', 'sa', 'since', 'test', 'note', 'par']
2208 for Result
in ResultSet
:
2209 CommentStr
= Result
[0]
2210 CommentPartList
= CommentStr
.split()
2211 for Part
in CommentPartList
:
2212 if Part
.upper() == 'BUGBUG':
2213 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2214 if Part
.upper() == 'TODO':
2215 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2216 if Part
.startswith('@'):
2217 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2219 if Part
.lstrip('@').isalpha():
2220 if Part
.lstrip('@') not in DoxygenCommandList
:
2221 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2223 Index
= Part
.find('[')
2225 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2226 RealCmd
= Part
[1:Index
]
2227 if RealCmd
not in DoxygenCommandList
:
2228 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2231 def CheckDoxygenTripleForwardSlash(FullFileName
):
2234 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2240 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2242 where BelongsToFile = %d
2244 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2245 if len(ResultSet
) == 0:
2249 for Result
in ResultSet
:
2250 FuncDefSet
.append(Result
)
2253 FileTable
= 'Identifier' + str(FileID
)
2254 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2258 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2259 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2262 for Result
in ResultSet
:
2263 CommentSet
.append(Result
)
2265 print 'Unrecognized chars in comment of file %s', FullFileName
2268 for Result
in CommentSet
:
2269 CommentStr
= Result
[0]
2270 StartLine
= Result
[2]
2271 StartColumn
= Result
[3]
2273 EndColumn
= Result
[5]
2274 if not CommentStr
.startswith('///<'):
2278 for FuncDef
in FuncDefSet
:
2279 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2282 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2285 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2288 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2292 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2295 def CheckFileHeaderDoxygenComments(FullFileName
):
2298 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2303 FileTable
= 'Identifier' + str(FileID
)
2304 SqlStatement
= """ select Value, ID
2306 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2307 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2308 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2309 if len(ResultSet
) == 0:
2310 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No File License header appear at the very beginning of file.', 'File', FileID
)
2313 NoHeaderCommentStartFlag
= True
2314 NoHeaderCommentEndFlag
= True
2315 NoHeaderCommentPeriodFlag
= True
2316 NoCopyrightFlag
= True
2317 NoLicenseFlag
= True
2318 NoRevReferFlag
= True
2320 for Result
in ResultSet
:
2321 FileStartFlag
= False
2323 CommentStr
= Result
[0].strip()
2324 CommentStrListTemp
= CommentStr
.split('\n')
2325 if (len(CommentStrListTemp
) <= 1):
2327 CommentStrListTemp
= CommentStr
.split('\r')
2328 # Skip the content before the file header
2329 for CommentLine
in CommentStrListTemp
:
2330 if CommentLine
.strip().startswith('/** @file'):
2331 FileStartFlag
= True
2332 if FileStartFlag
== True:
2333 CommentStrList
.append(CommentLine
)
2337 if CommentStrList
and CommentStrList
[0].strip().startswith('/** @file'):
2338 NoHeaderCommentStartFlag
= False
2341 if CommentStrList
and CommentStrList
[-1].strip().endswith('**/'):
2342 NoHeaderCommentEndFlag
= False
2346 for CommentLine
in CommentStrList
:
2348 NextLineIndex
= Index
2349 if CommentLine
.startswith('/** @file'):
2351 if CommentLine
.startswith('**/'):
2353 # Check whether C File header Comment content start with two spaces.
2354 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentStartSpacesNum
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2355 if CommentLine
.startswith('/** @file') == False and CommentLine
.startswith('**/') == False and CommentLine
.strip() and CommentLine
.startswith(' ') == False:
2356 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment content should start with two spaces at each line', FileTable
, ID
)
2358 CommentLine
= CommentLine
.strip()
2359 if CommentLine
.startswith('Copyright'):
2360 NoCopyrightFlag
= False
2361 if CommentLine
.find('All rights reserved') == -1:
2362 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable
, ID
)
2363 if CommentLine
.endswith('<BR>') == -1:
2364 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'The ""<BR>"" at the end of the Copyright line is required', FileTable
, ID
)
2365 if NextLineIndex
< len(CommentStrList
) and CommentStrList
[NextLineIndex
].strip().startswith('Copyright') == False and CommentStrList
[NextLineIndex
].strip():
2366 NoLicenseFlag
= False
2367 if CommentLine
.startswith('@par Revision Reference:'):
2368 NoRevReferFlag
= False
2370 for RefLine
in CommentStrList
[NextLineIndex
:]:
2371 if RefLine
.strip() and (NextLineIndex
+ 1) < len(CommentStrList
) and CommentStrList
[NextLineIndex
+1].strip() and CommentStrList
[NextLineIndex
+1].strip().startswith('**/') == False:
2373 if RefLine
.strip() == False or RefLine
.strip().startswith('**/'):
2376 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2377 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentReferenceFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2378 if RefListFlag
== True:
2379 if RefLine
.strip() and RefLine
.strip().startswith('**/') == False and RefLine
.startswith(' -') == False:
2380 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable
, ID
)
2382 if NoHeaderCommentStartFlag
:
2383 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, ID
)
2385 if NoHeaderCommentEndFlag
:
2386 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with ""**/""', FileTable
, ID
)
2389 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment missing the ""Copyright""', FileTable
, ID
)
2390 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2391 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentLicenseFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2393 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable
, ID
)
2395 def CheckFuncHeaderDoxygenComments(FullFileName
):
2398 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2403 FileTable
= 'Identifier' + str(FileID
)
2404 SqlStatement
= """ select Value, StartLine, EndLine, ID
2407 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2409 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2412 for Result
in ResultSet
:
2413 CommentSet
.append(Result
)
2415 print 'Unrecognized chars in comment of file %s', FullFileName
2418 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2421 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2422 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2423 for Result
in ResultSet
:
2424 FuncName
= Result
[4]
2425 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2426 if FunctionHeaderComment
:
2427 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2429 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2431 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2432 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2435 SqlStatement
= """ select Value, StartLine, EndLine, ID
2438 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2440 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2443 for Result
in ResultSet
:
2444 CommentSet
.append(Result
)
2446 print 'Unrecognized chars in comment of file %s', FullFileName
2448 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2450 where BelongsToFile = %d
2452 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2453 for Result
in ResultSet
:
2454 FuncName
= Result
[4]
2455 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2456 if FunctionHeaderComment
:
2457 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2459 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2461 ErrorMsgList
.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2462 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), 'Function', Result
[3])
2465 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2467 for Comment
in CommentSet
:
2468 if Comment
[2] == FuncStartLine
- 1:
2472 def GetDoxygenStrFromComment(Str
):
2474 ParamTagList
= Str
.split('@param')
2475 if len(ParamTagList
) > 1:
2477 while i
< len(ParamTagList
):
2478 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2481 Str
= ParamTagList
[0]
2483 RetvalTagList
= ParamTagList
[-1].split('@retval')
2484 if len(RetvalTagList
) > 1:
2485 if len(ParamTagList
) > 1:
2486 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2488 while i
< len(RetvalTagList
):
2489 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2492 ReturnTagList
= RetvalTagList
[-1].split('@return')
2493 if len(ReturnTagList
) > 1:
2494 if len(RetvalTagList
) > 1:
2495 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2496 elif len(ParamTagList
) > 1:
2497 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2499 while i
< len(ReturnTagList
):
2500 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2503 if len(DoxygenStrList
) > 0:
2504 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2506 return DoxygenStrList
2508 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2509 #/** --*/ @retval after @param
2510 if not Str
.startswith('/**'):
2511 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2512 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2513 if not Str
.endswith('**/'):
2514 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2515 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2516 FirstRetvalIndex
= Str
.find('@retval')
2517 LastParamIndex
= Str
.rfind('@param')
2518 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2519 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2520 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2522 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2524 ParamList
= GetParamList(FuncHeader
)
2525 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2526 DescriptionStr
= CommentStr
2527 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2528 if DescriptionStr
.find('.') == -1:
2529 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2530 DoxygenTagNumber
= len(DoxygenStrList
)
2531 ParamNumber
= len(ParamList
)
2532 for Param
in ParamList
:
2533 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2536 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2537 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2538 ParamModifier
= ParamList
[Index
].Modifier
2539 ParamName
= ParamList
[Index
].Name
.strip()
2540 Tag
= DoxygenStrList
[Index
].strip(' ')
2541 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2542 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2543 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, <%s> does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2544 TagPartList
= Tag
.split()
2545 if len(TagPartList
) < 2:
2546 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2547 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2550 LBPos
= Tag
.find('[')
2551 RBPos
= Tag
.find(']')
2552 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2553 if LBPos
> 0 and len(ParamToLBContent
) == 0 and RBPos
> LBPos
:
2555 ModifierPartList
= ParamModifier
.split()
2556 for Part
in ModifierPartList
:
2557 if Part
.strip() == 'IN':
2559 if Part
.strip() == 'OUT':
2566 if Tag
.find('[' + InOutStr
+ ']') == -1:
2567 if InOutStr
!= 'in, out':
2568 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2569 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2571 if Tag
.find('[in,out]') == -1:
2572 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2573 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2576 if Tag
.find(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2577 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2578 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
)
2581 if Index
< ParamNumber
:
2582 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2583 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2584 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2585 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2587 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2588 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2589 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2590 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2592 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2593 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2594 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2596 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
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
)
2599 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2600 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2601 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2603 if __name__
== '__main__':
2605 # EdkLogger.Initialize()
2606 # EdkLogger.SetLevel(EdkLogger.QUIET)
2607 # CollectSourceCodeDataIntoDB(sys.argv[1])
2609 test_file
= sys
.argv
[1]
2610 except IndexError, v
:
2611 print "Usage: %s filename" % sys
.argv
[0]
2613 MsgList
= CheckFuncHeaderDoxygenComments(test_file
)