2 # This file is used to be the c coding style checking of ECC tool
4 # Copyright (c) 2009 - 2014, 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
)
518 FullName
= os
.path
.normpath(os
.path
.join(dirpath
, f
))
519 model
= DataClass
.MODEL_FILE_OTHERS
520 if os
.path
.splitext(f
)[1] in ('.h', '.c'):
521 EdkLogger
.info("Parsing " + FullName
)
522 model
= f
.endswith('c') and DataClass
.MODEL_FILE_C
or DataClass
.MODEL_FILE_H
523 collector
= CodeFragmentCollector
.CodeFragmentCollector(FullName
)
525 collector
.ParseFile()
527 ParseErrorFileList
.append(FullName
)
528 collector
.CleanFileProfileBuffer()
529 collector
.ParseFileWithClearedPPDirective()
530 # collector.PrintFragments()
531 BaseName
= os
.path
.basename(f
)
532 DirName
= os
.path
.dirname(FullName
)
533 Ext
= os
.path
.splitext(f
)[1].lstrip('.')
534 ModifiedTime
= os
.path
.getmtime(FullName
)
535 FileObj
= DataClass
.FileClass(-1, BaseName
, Ext
, DirName
, FullName
, model
, ModifiedTime
, GetFunctionList(), GetIdentifierList(), [])
536 FileObjList
.append(FileObj
)
538 collector
.CleanFileProfileBuffer()
540 if len(ParseErrorFileList
) > 0:
541 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
544 for file in FileObjList
:
545 if file.ExtName
.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
546 Db
.InsertOneFile(file)
548 Db
.UpdateIdentifierBelongsToFunction()
550 def GetTableID(FullFileName
, ErrorMsgList
=None):
551 if ErrorMsgList
== None:
555 SqlStatement
= """ select ID
557 where FullPath like '%s'
559 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
562 for Result
in ResultSet
:
564 ErrorMsgList
.append('Duplicate file ID found in DB for file %s' % FullFileName
)
568 ErrorMsgList
.append('NO file ID found in DB for file %s' % FullFileName
)
572 def GetIncludeFileList(FullFileName
):
573 if os
.path
.splitext(FullFileName
)[1].upper() not in ('.H'):
575 IFList
= IncludeFileListDict
.get(FullFileName
)
579 FileID
= GetTableID(FullFileName
)
584 FileTable
= 'Identifier' + str(FileID
)
585 SqlStatement
= """ select Value
588 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_INCLUDE
)
589 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
590 IncludeFileListDict
[FullFileName
] = ResultSet
593 def GetFullPathOfIncludeFile(Str
, IncludePathList
):
594 for IncludePath
in IncludePathList
:
595 FullPath
= os
.path
.join(IncludePath
, Str
)
596 FullPath
= os
.path
.normpath(FullPath
)
597 if os
.path
.exists(FullPath
):
601 def GetAllIncludeFiles(FullFileName
):
602 if AllIncludeFileListDict
.get(FullFileName
) != None:
603 return AllIncludeFileListDict
.get(FullFileName
)
605 FileDirName
= os
.path
.dirname(FullFileName
)
606 IncludePathList
= IncludePathListDict
.get(FileDirName
)
607 if IncludePathList
== None:
608 IncludePathList
= MetaDataParser
.GetIncludeListOfFile(EccGlobalData
.gWorkspace
, FullFileName
, GetDB())
609 if FileDirName
not in IncludePathList
:
610 IncludePathList
.insert(0, FileDirName
)
611 IncludePathListDict
[FileDirName
] = IncludePathList
612 IncludeFileQueue
= []
613 for IncludeFile
in GetIncludeFileList(FullFileName
):
614 FileName
= IncludeFile
[0].lstrip('#').strip()
615 FileName
= FileName
.lstrip('include').strip()
616 FileName
= FileName
.strip('\"')
617 FileName
= FileName
.lstrip('<').rstrip('>').strip()
618 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
620 IncludeFileQueue
.append(FullPath
)
623 while i
< len(IncludeFileQueue
):
624 for IncludeFile
in GetIncludeFileList(IncludeFileQueue
[i
]):
625 FileName
= IncludeFile
[0].lstrip('#').strip()
626 FileName
= FileName
.lstrip('include').strip()
627 FileName
= FileName
.strip('\"')
628 FileName
= FileName
.lstrip('<').rstrip('>').strip()
629 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
630 if FullPath
!= None and FullPath
not in IncludeFileQueue
:
631 IncludeFileQueue
.insert(i
+ 1, FullPath
)
634 AllIncludeFileListDict
[FullFileName
] = IncludeFileQueue
635 return IncludeFileQueue
637 def GetPredicateListFromPredicateExpStr(PES
):
644 p
= GetFuncDeclPattern()
645 while i
< len(PES
) - 1:
646 if (PES
[i
].isalnum() or PES
[i
] == '_' or PES
[i
] == '*') and LogicOpPos
> PredicateBegin
:
648 if (PES
[i
] == '&' and PES
[i
+ 1] == '&') or (PES
[i
] == '|' and PES
[i
+ 1] == '|'):
650 Exp
= PES
[PredicateBegin
:i
].strip()
651 # Exp may contain '.' or '->'
652 TmpExp
= Exp
.replace('.', '').replace('->', '')
654 PredicateList
.append(Exp
)
656 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
659 if PredicateBegin
> LogicOpPos
:
660 while PredicateBegin
< len(PES
):
661 if PES
[PredicateBegin
].isalnum() or PES
[PredicateBegin
] == '_' or PES
[PredicateBegin
] == '*':
664 Exp
= PES
[PredicateBegin
:len(PES
)].strip()
665 # Exp may contain '.' or '->'
666 TmpExp
= Exp
.replace('.', '').replace('->', '')
668 PredicateList
.append(Exp
)
670 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
673 def GetCNameList(Lvalue
, StarList
=[]):
681 while SearchBegin
< len(Lvalue
):
682 while i
< len(Lvalue
):
683 if Lvalue
[i
].isalnum() or Lvalue
[i
] == '_':
689 VarList
.append(Lvalue
[VarStart
:VarEnd
+ 1])
693 if VarStart
== -1 and Lvalue
[i
] == '*':
700 DotIndex
= Lvalue
[VarEnd
:].find('.')
701 ArrowIndex
= Lvalue
[VarEnd
:].find('->')
702 if DotIndex
== -1 and ArrowIndex
== -1:
704 elif DotIndex
== -1 and ArrowIndex
!= -1:
705 SearchBegin
= VarEnd
+ ArrowIndex
706 elif ArrowIndex
== -1 and DotIndex
!= -1:
707 SearchBegin
= VarEnd
+ DotIndex
709 SearchBegin
= VarEnd
+ ((DotIndex
< ArrowIndex
) and DotIndex
or ArrowIndex
)
717 def SplitPredicateByOp(Str
, Op
, IsFuncCalling
=False):
726 while Index
< len(Str
):
727 while not LBFound
and Str
[Index
] != '_' and not Str
[Index
].isalnum():
730 while not LBFound
and (Str
[Index
].isalnum() or Str
[Index
] == '_'):
732 # maybe type-cast at the begining, skip it.
733 RemainingStr
= Str
[Index
:].lstrip()
734 if RemainingStr
.startswith(')') and not LBFound
:
738 if RemainingStr
.startswith('(') and not LBFound
:
741 if Str
[Index
] == '(':
742 UnmatchedLBCount
+= 1
746 if Str
[Index
] == ')':
747 UnmatchedLBCount
-= 1
749 if UnmatchedLBCount
== 0:
755 if UnmatchedLBCount
> 0:
758 IndexInRemainingStr
= Str
[Index
:].find(Op
)
759 if IndexInRemainingStr
== -1:
762 Name
= Str
[0:Index
+ IndexInRemainingStr
].strip()
763 Value
= Str
[Index
+ IndexInRemainingStr
+ len(Op
):].strip().strip(')')
766 TmpStr
= Str
.rstrip(';').rstrip(')')
768 Index
= TmpStr
.rfind(Op
)
772 if Str
[Index
- 1].isalnum() or Str
[Index
- 1].isspace() or Str
[Index
- 1] == ')' or Str
[Index
- 1] == ']':
773 Name
= Str
[0:Index
].strip()
774 Value
= Str
[Index
+ len(Op
):].strip()
777 TmpStr
= Str
[0:Index
- 1]
779 def SplitPredicateStr(Str
):
781 Str
= Str
.lstrip('(')
782 IsFuncCalling
= False
783 p
= GetFuncDeclPattern()
784 TmpStr
= Str
.replace('.', '').replace('->', '')
788 PredPartList
= SplitPredicateByOp(Str
, '==', IsFuncCalling
)
789 if len(PredPartList
) > 1:
790 return [PredPartList
, '==']
792 PredPartList
= SplitPredicateByOp(Str
, '!=', IsFuncCalling
)
793 if len(PredPartList
) > 1:
794 return [PredPartList
, '!=']
796 PredPartList
= SplitPredicateByOp(Str
, '>=', IsFuncCalling
)
797 if len(PredPartList
) > 1:
798 return [PredPartList
, '>=']
800 PredPartList
= SplitPredicateByOp(Str
, '<=', IsFuncCalling
)
801 if len(PredPartList
) > 1:
802 return [PredPartList
, '<=']
804 PredPartList
= SplitPredicateByOp(Str
, '>', IsFuncCalling
)
805 if len(PredPartList
) > 1:
806 return [PredPartList
, '>']
808 PredPartList
= SplitPredicateByOp(Str
, '<', IsFuncCalling
)
809 if len(PredPartList
) > 1:
810 return [PredPartList
, '<']
812 return [[Str
, None], None]
814 def GetFuncContainsPE(ExpLine
, ResultSet
):
815 for Result
in ResultSet
:
816 if Result
[0] < ExpLine
and Result
[1] > ExpLine
:
820 def PatternInModifier(Modifier
, SubStr
):
821 PartList
= Modifier
.split()
822 for Part
in PartList
:
827 def GetDataTypeFromModifier(ModifierStr
):
828 MList
= ModifierStr
.split()
831 if M
in EccGlobalData
.gConfig
.ModifierList
:
834 if M
.startswith('[') or M
.endswith(']'):
836 ReturnType
+= M
+ ' '
838 ReturnType
= ReturnType
.strip()
839 if len(ReturnType
) == 0:
843 def DiffModifier(Str1
, Str2
):
844 PartList1
= Str1
.split()
845 PartList2
= Str2
.split()
846 if PartList1
== PartList2
:
851 def GetTypedefDict(FullFileName
):
853 Dict
= ComplexTypeDict
.get(FullFileName
)
857 FileID
= GetTableID(FullFileName
)
858 FileTable
= 'Identifier' + str(FileID
)
860 SqlStatement
= """ select Modifier, Name, Value, ID
863 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
864 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
867 for Result
in ResultSet
:
868 if len(Result
[0]) == 0:
869 Dict
[Result
[1]] = Result
[2]
871 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
872 for F
in IncludeFileList
:
873 FileID
= GetTableID(F
)
877 FileTable
= 'Identifier' + str(FileID
)
878 SqlStatement
= """ select Modifier, Name, Value, ID
881 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
882 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
884 for Result
in ResultSet
:
885 if not Result
[2].startswith('FP ('):
886 Dict
[Result
[1]] = Result
[2]
888 if len(Result
[0]) == 0:
889 Dict
[Result
[1]] = 'VOID'
891 Dict
[Result
[1]] = GetDataTypeFromModifier(Result
[0])
893 ComplexTypeDict
[FullFileName
] = Dict
896 def GetSUDict(FullFileName
):
898 Dict
= SUDict
.get(FullFileName
)
902 FileID
= GetTableID(FullFileName
)
903 FileTable
= 'Identifier' + str(FileID
)
905 SqlStatement
= """ select Name, Value, ID
907 where Model = %d or Model = %d
908 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
909 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
912 for Result
in ResultSet
:
913 if len(Result
[1]) > 0:
914 Dict
[Result
[0]] = Result
[1]
916 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
917 for F
in IncludeFileList
:
918 FileID
= GetTableID(F
)
922 FileTable
= 'Identifier' + str(FileID
)
923 SqlStatement
= """ select Name, Value, ID
925 where Model = %d or Model = %d
926 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
927 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
929 for Result
in ResultSet
:
930 if len(Result
[1]) > 0:
931 Dict
[Result
[0]] = Result
[1]
933 SUDict
[FullFileName
] = Dict
936 def StripComments(Str
):
938 ListFromStr
= list(Str
)
941 DoubleSlashComment
= False
943 while Index
< len(ListFromStr
):
944 # meet new line, then no longer in a comment for //
945 if ListFromStr
[Index
] == '\n':
946 if InComment
and DoubleSlashComment
:
948 DoubleSlashComment
= False
950 # check for */ comment end
951 elif InComment
and not DoubleSlashComment
and ListFromStr
[Index
] == '*' and ListFromStr
[Index
+ 1] == '/':
952 ListFromStr
[Index
] = ' '
954 ListFromStr
[Index
] = ' '
957 # set comments to spaces
959 ListFromStr
[Index
] = ' '
961 # check for // comment
962 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '/' and ListFromStr
[Index
+ 2] != '\n':
964 DoubleSlashComment
= True
966 # check for /* comment start
967 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '*':
968 ListFromStr
[Index
] = ' '
970 ListFromStr
[Index
] = ' '
976 # restore from List to String
977 Str
= "".join(ListFromStr
)
978 Str
= Str
.rstrip(' ')
982 def GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
):
983 Value
= TypedefDict
.get(Type
)
985 Value
= SUDict
.get(Type
)
989 LBPos
= Value
.find('{')
991 FTList
= Value
.split()
993 if FT
not in ('struct', 'union'):
994 Value
= TypedefDict
.get(FT
)
996 Value
= SUDict
.get(FT
)
1002 LBPos
= Value
.find('{')
1004 # RBPos = Value.find('}')
1005 Fields
= Value
[LBPos
+ 1:]
1006 Fields
= StripComments(Fields
)
1007 FieldsList
= Fields
.split(';')
1008 for Field
in FieldsList
:
1009 Field
= Field
.strip()
1010 Index
= Field
.rfind(FieldName
)
1013 if not Field
[Index
- 1].isalnum():
1014 if Index
+ len(FieldName
) == len(Field
):
1015 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1018 # For the condition that the field in struct is an array with [] sufixes...
1019 if not Field
[Index
+ len(FieldName
)].isalnum():
1020 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1025 def GetRealType(Type
, TypedefDict
, TargetType
=None):
1026 if TargetType
!= None and Type
== TargetType
:
1028 while TypedefDict
.get(Type
):
1029 Type
= TypedefDict
.get(Type
)
1030 if TargetType
!= None and Type
== TargetType
:
1034 def GetTypeInfo(RefList
, Modifier
, FullFileName
, TargetType
=None):
1035 TypedefDict
= GetTypedefDict(FullFileName
)
1036 SUDict
= GetSUDict(FullFileName
)
1037 Type
= GetDataTypeFromModifier(Modifier
).replace('*', '').strip()
1039 Type
= Type
.split()[-1]
1041 while Index
< len(RefList
):
1042 FieldName
= RefList
[Index
]
1043 FromType
= GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
)
1044 if FromType
== None:
1046 # we want to determine the exact type.
1047 if TargetType
!= None:
1048 Type
= FromType
.split()[0]
1049 # we only want to check if it is a pointer
1052 if Type
.find('*') != -1 and Index
== len(RefList
) - 1:
1054 Type
= FromType
.split()[0]
1058 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1062 def GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
=False, TargetType
=None, StarList
=None):
1064 PredVar
= PredVarList
[0]
1065 FileID
= GetTableID(FullFileName
)
1068 FileTable
= 'Identifier' + str(FileID
)
1069 # search variable in include files
1071 # it is a function call, search function declarations and definitions
1073 SqlStatement
= """ select Modifier, ID
1075 where Model = %d and Value = \'%s\'
1076 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1077 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1079 for Result
in ResultSet
:
1080 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1081 TypedefDict
= GetTypedefDict(FullFileName
)
1082 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1085 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1086 for F
in IncludeFileList
:
1087 FileID
= GetTableID(F
)
1091 FileTable
= 'Identifier' + str(FileID
)
1092 SqlStatement
= """ select Modifier, ID
1094 where Model = %d and Value = \'%s\'
1095 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1096 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1098 for Result
in ResultSet
:
1099 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1100 TypedefDict
= GetTypedefDict(FullFileName
)
1101 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1104 FileID
= GetTableID(FullFileName
)
1105 SqlStatement
= """ select Modifier, ID
1107 where BelongsToFile = %d and Name = \'%s\'
1108 """ % (FileID
, PredVar
)
1109 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1111 for Result
in ResultSet
:
1112 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1113 TypedefDict
= GetTypedefDict(FullFileName
)
1114 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1117 for F
in IncludeFileList
:
1118 FileID
= GetTableID(F
)
1122 FileTable
= 'Identifier' + str(FileID
)
1123 SqlStatement
= """ select Modifier, ID
1125 where BelongsToFile = %d and Name = \'%s\'
1126 """ % (FileID
, PredVar
)
1127 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1129 for Result
in ResultSet
:
1130 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1131 TypedefDict
= GetTypedefDict(FullFileName
)
1132 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1137 # really variable, search local variable first
1138 SqlStatement
= """ select Modifier, ID
1140 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1141 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
, FuncRecord
[0], FuncRecord
[1])
1142 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1144 for Result
in ResultSet
:
1145 if len(PredVarList
) > 1:
1146 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1149 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1150 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1152 if len(TypeList
) > 1 and StarList
!= None:
1153 for Star
in StarList
:
1155 Type
= Type
.rstrip(Star
)
1156 # Get real type after de-reference pointers.
1157 if len(Type
.strip()) == 0:
1159 TypedefDict
= GetTypedefDict(FullFileName
)
1160 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1163 # search function parameters second
1164 ParamList
= GetParamList(FuncRecord
[2])
1165 for Param
in ParamList
:
1166 if Param
.Name
.strip() == PredVar
:
1167 if len(PredVarList
) > 1:
1168 Type
= GetTypeInfo(PredVarList
[1:], Param
.Modifier
, FullFileName
, TargetType
)
1171 TypeList
= GetDataTypeFromModifier(Param
.Modifier
).split()
1173 if len(TypeList
) > 1 and StarList
!= None:
1174 for Star
in StarList
:
1176 Type
= Type
.rstrip(Star
)
1177 # Get real type after de-reference pointers.
1178 if len(Type
.strip()) == 0:
1180 TypedefDict
= GetTypedefDict(FullFileName
)
1181 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1184 # search global variable next
1185 SqlStatement
= """ select Modifier, ID
1187 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1188 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1189 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1191 for Result
in ResultSet
:
1192 if len(PredVarList
) > 1:
1193 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1196 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1198 if len(TypeList
) > 1 and StarList
!= None:
1199 for Star
in StarList
:
1201 Type
= Type
.rstrip(Star
)
1202 # Get real type after de-reference pointers.
1203 if len(Type
.strip()) == 0:
1205 TypedefDict
= GetTypedefDict(FullFileName
)
1206 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1209 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1210 for F
in IncludeFileList
:
1211 FileID
= GetTableID(F
)
1215 FileTable
= 'Identifier' + str(FileID
)
1216 SqlStatement
= """ select Modifier, ID
1218 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1219 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1220 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1222 for Result
in ResultSet
:
1223 if len(PredVarList
) > 1:
1224 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1227 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1229 if len(TypeList
) > 1 and StarList
!= None:
1230 for Star
in StarList
:
1232 Type
= Type
.rstrip(Star
)
1233 # Get real type after de-reference pointers.
1234 if len(Type
.strip()) == 0:
1236 TypedefDict
= GetTypedefDict(FullFileName
)
1237 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1240 def GetTypeFromArray(Type
, Var
):
1241 Count
= Var
.count('[')
1245 Type
= Type
.rstrip('*')
1250 def CheckFuncLayoutReturnType(FullFileName
):
1253 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1258 FileTable
= 'Identifier' + str(FileID
)
1259 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1262 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1263 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1264 for Result
in ResultSet
:
1265 ReturnType
= GetDataTypeFromModifier(Result
[0])
1266 TypeStart
= ReturnType
.split()[0]
1267 FuncName
= Result
[5]
1268 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1270 Index
= Result
[0].find(TypeStart
)
1271 if Index
!= 0 or Result
[3] != 0:
1272 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1274 if Result
[2] == Result
[4]:
1275 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1277 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1279 where BelongsToFile = %d
1281 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1282 for Result
in ResultSet
:
1283 ReturnType
= GetDataTypeFromModifier(Result
[0])
1284 TypeStart
= ReturnType
.split()[0]
1285 FuncName
= Result
[5]
1286 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1288 Index
= Result
[0].find(ReturnType
)
1289 if Index
!= 0 or Result
[3] != 0:
1290 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1292 if Result
[2] == Result
[4]:
1293 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, 'Function', Result
[1])
1295 def CheckFuncLayoutModifier(FullFileName
):
1298 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1303 FileTable
= 'Identifier' + str(FileID
)
1304 SqlStatement
= """ select Modifier, ID
1307 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1308 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1309 for Result
in ResultSet
:
1310 ReturnType
= GetDataTypeFromModifier(Result
[0])
1311 TypeStart
= ReturnType
.split()[0]
1312 # if len(ReturnType) == 0:
1314 Index
= Result
[0].find(TypeStart
)
1316 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1318 SqlStatement
= """ select Modifier, ID
1320 where BelongsToFile = %d
1322 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1323 for Result
in ResultSet
:
1324 ReturnType
= GetDataTypeFromModifier(Result
[0])
1325 TypeStart
= ReturnType
.split()[0]
1326 # if len(ReturnType) == 0:
1328 Index
= Result
[0].find(TypeStart
)
1330 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1332 def CheckFuncLayoutName(FullFileName
):
1334 # Parameter variable format pattern.
1335 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1336 ParamIgnoreList
= ('VOID', '...')
1337 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1342 FileTable
= 'Identifier' + str(FileID
)
1343 SqlStatement
= """ select Name, ID, EndColumn, Value
1346 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1347 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1348 for Result
in ResultSet
:
1349 FuncName
= Result
[3]
1350 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1353 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1354 ParamList
= GetParamList(Result
[0])
1355 if len(ParamList
) == 0:
1358 for Param
in ParamList
:
1359 if Param
.StartLine
<= StartLine
:
1360 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1361 if Param
.StartLine
- StartLine
> 1:
1362 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1363 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
):
1364 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1365 StartLine
= Param
.StartLine
1367 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1368 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1370 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1372 where BelongsToFile = %d
1374 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1375 for Result
in ResultSet
:
1376 FuncName
= Result
[3]
1377 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1380 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1381 ParamList
= GetParamList(Result
[0])
1382 if len(ParamList
) == 0:
1385 for Param
in ParamList
:
1386 if Param
.StartLine
<= StartLine
:
1387 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1388 if Param
.StartLine
- StartLine
> 1:
1389 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1390 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
):
1391 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1392 StartLine
= Param
.StartLine
1393 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1394 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1396 def CheckFuncLayoutPrototype(FullFileName
):
1399 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1403 FileTable
= 'Identifier' + str(FileID
)
1405 SqlStatement
= """ select Modifier, Header, Name, ID
1407 where BelongsToFile = %d
1409 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1410 if len(ResultSet
) == 0:
1414 for Result
in ResultSet
:
1415 FuncDefList
.append(Result
)
1417 SqlStatement
= """ select Modifier, Name, ID
1420 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1421 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1423 for Result
in ResultSet
:
1424 FuncDeclList
.append(Result
)
1427 for FuncDef
in FuncDefList
:
1428 FuncName
= FuncDef
[2].strip()
1429 FuncModifier
= FuncDef
[0]
1430 FuncDefHeader
= FuncDef
[1]
1431 for FuncDecl
in FuncDeclList
:
1432 LBPos
= FuncDecl
[1].find('(')
1433 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1434 DeclModifier
= FuncDecl
[0]
1435 if DeclName
== FuncName
:
1436 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1437 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1438 ParamListOfDef
= GetParamList(FuncDefHeader
)
1439 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1440 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1441 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1445 while Index
< len(ParamListOfDef
):
1446 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1447 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])
1451 UndeclFuncList
.append(FuncDef
)
1453 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1455 for F
in IncludeFileList
:
1456 FileID
= GetTableID(F
, ErrorMsgList
)
1460 FileTable
= 'Identifier' + str(FileID
)
1461 SqlStatement
= """ select Modifier, Name, ID
1464 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1465 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1467 for Result
in ResultSet
:
1468 FuncDeclList
.append(Result
)
1470 for FuncDef
in UndeclFuncList
:
1471 FuncName
= FuncDef
[2].strip()
1472 FuncModifier
= FuncDef
[0]
1473 FuncDefHeader
= FuncDef
[1]
1474 for FuncDecl
in FuncDeclList
:
1475 LBPos
= FuncDecl
[1].find('(')
1476 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1477 DeclModifier
= FuncDecl
[0]
1478 if DeclName
== FuncName
:
1479 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1480 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1481 ParamListOfDef
= GetParamList(FuncDefHeader
)
1482 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1483 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1484 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1488 while Index
< len(ParamListOfDef
):
1489 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1490 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])
1494 def CheckFuncLayoutBody(FullFileName
):
1497 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1501 FileTable
= 'Identifier' + str(FileID
)
1503 SqlStatement
= """ select BodyStartColumn, EndColumn, ID
1505 where BelongsToFile = %d
1507 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1508 if len(ResultSet
) == 0:
1510 for Result
in ResultSet
:
1512 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'open brace should be at the very beginning of a line.', 'Function', Result
[2])
1514 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'close brace should be at the very beginning of a line.', 'Function', Result
[2])
1516 def CheckFuncLayoutLocalVariable(FullFileName
):
1519 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1524 FileTable
= 'Identifier' + str(FileID
)
1525 SqlStatement
= """ select ID
1527 where BelongsToFile = %d
1529 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1530 if len(ResultSet
) == 0:
1533 for Result
in ResultSet
:
1537 SqlStatement
= """ select Name, Value, ID, Modifier
1539 where Model = %d and BelongsToFunction = %d
1540 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1541 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1542 if len(ResultSet
) == 0:
1545 for Result
in ResultSet
:
1546 if len(Result
[1]) > 0 and 'CONST' not in Result
[3]:
1547 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1549 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1551 # Member variable format pattern.
1552 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1554 LBPos
= Value
.find('{')
1555 RBPos
= Value
.rfind('}')
1556 if LBPos
== -1 or RBPos
== -1:
1559 Fields
= Value
[LBPos
+ 1 : RBPos
]
1560 Fields
= StripComments(Fields
).strip()
1561 NestPos
= Fields
.find ('struct')
1562 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)):
1563 if not Fields
[NestPos
+ len('struct') + 1].isalnum():
1564 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1565 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested struct in [%s].' % (Name
), FileTable
, TdId
)
1567 NestPos
= Fields
.find ('union')
1568 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1569 if not Fields
[NestPos
+ len('union') + 1].isalnum():
1570 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1571 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested union in [%s].' % (Name
), FileTable
, TdId
)
1573 NestPos
= Fields
.find ('enum')
1574 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1575 if not Fields
[NestPos
+ len('enum') + 1].isalnum():
1576 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1577 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested enum in [%s].' % (Name
), FileTable
, TdId
)
1580 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1581 FieldsList
= Fields
.split(',')
1582 # deal with enum is pre-assigned a value by function call ( , , , ...)
1585 RemoveCurrentElement
= False
1586 while Index
< len(FieldsList
):
1587 Field
= FieldsList
[Index
]
1589 if Field
.find('(') != -1:
1591 RemoveCurrentElement
= True
1595 if Field
.find(')') != -1 and QuoteCount
> 0:
1598 if RemoveCurrentElement
:
1599 FieldsList
.remove(Field
)
1601 RemoveCurrentElement
= False
1605 RemoveCurrentElement
= False
1609 FieldsList
= Fields
.split(';')
1611 for Field
in FieldsList
:
1612 Field
= Field
.strip()
1615 # For the condition that the field in struct is an array with [] sufixes...
1616 if Field
[-1] == ']':
1617 LBPos
= Field
.find('[')
1618 Field
= Field
[0:LBPos
]
1619 # For the condition that bit field ": Number"
1620 if Field
.find(':') != -1:
1621 ColonPos
= Field
.find(':')
1622 Field
= Field
[0:ColonPos
]
1624 Field
= Field
.strip()
1627 # Enum could directly assign value to variable
1628 Field
= Field
.split('=')[0].strip()
1629 TokenList
= Field
.split()
1630 # Remove pointers before variable
1631 if not Pattern
.match(TokenList
[-1].lstrip('*')):
1632 ErrMsgList
.append(TokenList
[-1].lstrip('*'))
1636 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1639 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1644 FileTable
= 'Identifier' + str(FileID
)
1645 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1648 """ % (FileTable
, ModelId
)
1649 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1651 for Result
in ResultSet
:
1652 ResultList
.append(Result
)
1654 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1655 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1656 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1657 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1658 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1659 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1660 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1662 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1665 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1666 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1670 # Check member variable name format that from typedefs of ONLY this file.
1672 Name
= Td
[1].strip()
1673 Value
= Td
[2].strip()
1674 if Value
.startswith('enum'):
1675 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1676 elif Value
.startswith('struct'):
1677 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1678 elif Value
.startswith('union'):
1679 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1683 if ValueModelId
!= ModelId
:
1685 # Check member variable format.
1686 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1687 for ErrMsg
in ErrMsgList
:
1688 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+ '.' + ErrMsg
):
1690 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+ '.' + ErrMsg
), FileTable
, Td
[5])
1692 # First check in current file to see whether struct/union/enum is typedef-ed.
1693 UntypedefedList
= []
1694 for Result
in ResultList
:
1695 # Check member variable format.
1696 Name
= Result
[0].strip()
1697 Value
= Result
[4].strip()
1698 if Value
.startswith('enum'):
1699 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1700 elif Value
.startswith('struct'):
1701 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1702 elif Value
.startswith('union'):
1703 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1707 if ValueModelId
!= ModelId
:
1709 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1710 for ErrMsg
in ErrMsgList
:
1711 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0] + '.' + ErrMsg
):
1713 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0] + '.' + ErrMsg
), FileTable
, Result
[3])
1714 # Check whether it is typedefed.
1717 # skip function pointer
1720 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1722 if not Td
[1].isupper():
1723 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1724 if Result
[0] in Td
[2].split():
1726 if not Td
[1].isupper():
1727 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1732 UntypedefedList
.append(Result
)
1735 if len(UntypedefedList
) == 0:
1738 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1740 for F
in IncludeFileList
:
1741 FileID
= GetTableID(F
, ErrorMsgList
)
1745 IncludeFileTable
= 'Identifier' + str(FileID
)
1746 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1749 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1750 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1751 TdList
.extend(ResultSet
)
1753 for Result
in UntypedefedList
:
1755 # Check whether it is typedefed.
1761 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1763 if not Td
[1].isupper():
1764 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1765 if Result
[0] in Td
[2].split():
1767 if not Td
[1].isupper():
1768 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1773 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1776 def CheckDeclStructTypedef(FullFileName
):
1777 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1779 def CheckDeclEnumTypedef(FullFileName
):
1780 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1782 def CheckDeclUnionTypedef(FullFileName
):
1783 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1785 def CheckDeclArgModifier(FullFileName
):
1788 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1793 FileTable
= 'Identifier' + str(FileID
)
1794 SqlStatement
= """ select Modifier, Name, ID
1797 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1798 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1799 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1800 MAX_MODIFIER_LENGTH
= 100
1801 for Result
in ResultSet
:
1802 for Modifier
in ModifierTuple
:
1803 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1804 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1807 SqlStatement
= """ select Modifier, Name, ID
1810 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1811 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1812 for Result
in ResultSet
:
1813 for Modifier
in ModifierTuple
:
1814 if PatternInModifier(Result
[0], Modifier
):
1815 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1818 SqlStatement
= """ select Modifier, Header, ID
1820 where BelongsToFile = %d
1822 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1823 for Result
in ResultSet
:
1824 for Modifier
in ModifierTuple
:
1825 if PatternInModifier(Result
[0], Modifier
):
1826 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1829 def CheckDeclNoUseCType(FullFileName
):
1832 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1837 FileTable
= 'Identifier' + str(FileID
)
1838 SqlStatement
= """ select Modifier, Name, ID
1841 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1842 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1843 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1844 for Result
in ResultSet
:
1845 for Type
in CTypeTuple
:
1846 if PatternInModifier(Result
[0], Type
):
1847 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Variable type %s' % Type
, FileTable
, Result
[2])
1850 SqlStatement
= """ select Modifier, Name, ID, Value
1853 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1854 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1855 for Result
in ResultSet
:
1856 ParamList
= GetParamList(Result
[1])
1857 FuncName
= Result
[3]
1858 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1860 for Type
in CTypeTuple
:
1861 if PatternInModifier(Result
[0], Type
):
1862 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1864 for Param
in ParamList
:
1865 if PatternInModifier(Param
.Modifier
, Type
):
1866 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1868 SqlStatement
= """ select Modifier, Header, ID, Name
1870 where BelongsToFile = %d
1872 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1873 for Result
in ResultSet
:
1874 ParamList
= GetParamList(Result
[1])
1875 FuncName
= Result
[3]
1876 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1878 for Type
in CTypeTuple
:
1879 if PatternInModifier(Result
[0], Type
):
1880 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1882 for Param
in ParamList
:
1883 if PatternInModifier(Param
.Modifier
, Type
):
1884 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1887 def CheckPointerNullComparison(FullFileName
):
1890 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1894 # cache the found function return type to accelerate later checking in this file.
1895 FuncReturnTypeDict
= {}
1898 FileTable
= 'Identifier' + str(FileID
)
1899 SqlStatement
= """ select Value, StartLine, ID
1902 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1903 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1904 if len(ResultSet
) == 0:
1907 for Result
in ResultSet
:
1908 PSL
.append([Result
[0], Result
[1], Result
[2]])
1910 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1912 where BelongsToFile = %d
1914 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1916 for Result
in ResultSet
:
1917 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1919 p
= GetFuncDeclPattern()
1921 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1922 if FuncRecord
== None:
1925 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1926 PredInfo
= SplitPredicateStr(Exp
)
1927 if PredInfo
[1] == None:
1928 PredVarStr
= PredInfo
[0][0].strip()
1930 SearchInCache
= False
1931 # PredVarStr may contain '.' or '->'
1932 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1934 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1935 SearchInCache
= True
1936 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1937 if TmpStr
.startswith(PredVarStr
):
1940 if PredVarStr
.strip() in IgnoredKeywordList
:
1943 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1944 # No variable found, maybe value first? like (0 == VarName)
1945 if len(PredVarList
) == 0:
1948 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1950 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1951 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1954 if PredVarStr
in FuncReturnTypeDict
:
1957 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1959 FuncReturnTypeDict
[PredVarStr
] = Type
1962 Type
= GetTypeFromArray(Type
, PredVarStr
)
1963 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1964 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1966 def CheckNonBooleanValueComparison(FullFileName
):
1969 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1973 # cache the found function return type to accelerate later checking in this file.
1974 FuncReturnTypeDict
= {}
1977 FileTable
= 'Identifier' + str(FileID
)
1978 SqlStatement
= """ select Value, StartLine, ID
1981 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1982 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1983 if len(ResultSet
) == 0:
1986 for Result
in ResultSet
:
1987 PSL
.append([Result
[0], Result
[1], Result
[2]])
1989 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1991 where BelongsToFile = %d
1993 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1995 for Result
in ResultSet
:
1996 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1998 p
= GetFuncDeclPattern()
2000 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2001 if FuncRecord
== None:
2004 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2005 PredInfo
= SplitPredicateStr(Exp
)
2006 if PredInfo
[1] == None:
2007 PredVarStr
= PredInfo
[0][0].strip()
2009 SearchInCache
= False
2010 # PredVarStr may contain '.' or '->'
2011 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2013 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2014 SearchInCache
= True
2015 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2016 if TmpStr
.startswith(PredVarStr
):
2019 if PredVarStr
.strip() in IgnoredKeywordList
:
2022 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2023 # No variable found, maybe value first? like (0 == VarName)
2024 if len(PredVarList
) == 0:
2028 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2030 if Type
.find('BOOLEAN') == -1:
2031 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2034 if PredVarStr
in FuncReturnTypeDict
:
2036 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2038 FuncReturnTypeDict
[PredVarStr
] = Type
2041 if Type
.find('BOOLEAN') == -1:
2042 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2045 def CheckBooleanValueComparison(FullFileName
):
2048 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2052 # cache the found function return type to accelerate later checking in this file.
2053 FuncReturnTypeDict
= {}
2056 FileTable
= 'Identifier' + str(FileID
)
2057 SqlStatement
= """ select Value, StartLine, ID
2060 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2061 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2062 if len(ResultSet
) == 0:
2065 for Result
in ResultSet
:
2066 PSL
.append([Result
[0], Result
[1], Result
[2]])
2068 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2070 where BelongsToFile = %d
2072 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2074 for Result
in ResultSet
:
2075 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2077 p
= GetFuncDeclPattern()
2079 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2080 if FuncRecord
== None:
2083 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2084 PredInfo
= SplitPredicateStr(Exp
)
2085 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2086 PredVarStr
= PredInfo
[0][0].strip()
2088 SearchInCache
= False
2089 # PredVarStr may contain '.' or '->'
2090 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2092 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2093 SearchInCache
= True
2094 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2095 if TmpStr
.startswith(PredVarStr
):
2098 if PredVarStr
.strip() in IgnoredKeywordList
:
2101 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2102 # No variable found, maybe value first? like (0 == VarName)
2103 if len(PredVarList
) == 0:
2107 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2109 if Type
.find('BOOLEAN') != -1:
2110 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2113 if PredVarStr
in FuncReturnTypeDict
:
2116 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2118 FuncReturnTypeDict
[PredVarStr
] = Type
2121 if Type
.find('BOOLEAN') != -1:
2122 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2125 def CheckHeaderFileData(FullFileName
):
2128 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2133 FileTable
= 'Identifier' + str(FileID
)
2134 SqlStatement
= """ select ID, Modifier
2137 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2138 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2139 for Result
in ResultSet
:
2140 if not Result
[1].startswith('extern'):
2141 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2143 SqlStatement
= """ select ID
2145 where BelongsToFile = %d
2147 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2148 for Result
in ResultSet
:
2149 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2153 def CheckHeaderFileIfndef(FullFileName
):
2156 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2161 FileTable
= 'Identifier' + str(FileID
)
2162 SqlStatement
= """ select Value, StartLine
2164 where Model = %d order by StartLine
2165 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2166 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2167 if len(ResultSet
) == 0:
2168 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2170 for Result
in ResultSet
:
2171 SqlStatement
= """ select Value, EndLine
2174 """ % (FileTable
, Result
[1])
2175 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2176 for Result
in ResultSet
:
2177 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2178 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2
, '', 'File', FileID
)
2181 SqlStatement
= """ select Value
2183 where StartLine > (select max(EndLine) from %s where Model = %d)
2184 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2185 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2186 for Result
in ResultSet
:
2187 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2188 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2191 def CheckDoxygenCommand(FullFileName
):
2194 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2199 FileTable
= 'Identifier' + str(FileID
)
2200 SqlStatement
= """ select Value, ID
2202 where Model = %d or Model = %d
2203 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2204 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2205 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval', 'return', 'sa', 'since', 'test', 'note', 'par']
2206 for Result
in ResultSet
:
2207 CommentStr
= Result
[0]
2208 CommentPartList
= CommentStr
.split()
2209 for Part
in CommentPartList
:
2210 if Part
.upper() == 'BUGBUG':
2211 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2212 if Part
.upper() == 'TODO':
2213 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2214 if Part
.startswith('@'):
2215 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2217 if Part
.lstrip('@').isalpha():
2218 if Part
.lstrip('@') not in DoxygenCommandList
:
2219 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2221 Index
= Part
.find('[')
2223 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2224 RealCmd
= Part
[1:Index
]
2225 if RealCmd
not in DoxygenCommandList
:
2226 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2229 def CheckDoxygenTripleForwardSlash(FullFileName
):
2232 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2238 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2240 where BelongsToFile = %d
2242 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2243 if len(ResultSet
) == 0:
2247 for Result
in ResultSet
:
2248 FuncDefSet
.append(Result
)
2251 FileTable
= 'Identifier' + str(FileID
)
2252 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2256 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2257 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2260 for Result
in ResultSet
:
2261 CommentSet
.append(Result
)
2263 print 'Unrecognized chars in comment of file %s', FullFileName
2266 for Result
in CommentSet
:
2267 CommentStr
= Result
[0]
2268 StartLine
= Result
[2]
2269 StartColumn
= Result
[3]
2271 EndColumn
= Result
[5]
2272 if not CommentStr
.startswith('///<'):
2276 for FuncDef
in FuncDefSet
:
2277 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2280 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2283 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2286 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2290 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2293 def CheckFileHeaderDoxygenComments(FullFileName
):
2296 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2301 FileTable
= 'Identifier' + str(FileID
)
2302 SqlStatement
= """ select Value, ID
2304 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2305 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2306 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2307 if len(ResultSet
) == 0:
2308 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No File License header appear at the very beginning of file.', 'File', FileID
)
2311 NoHeaderCommentStartFlag
= True
2312 NoHeaderCommentEndFlag
= True
2313 NoHeaderCommentPeriodFlag
= True
2314 NoCopyrightFlag
= True
2315 NoLicenseFlag
= True
2316 NoRevReferFlag
= True
2318 for Result
in ResultSet
:
2319 FileStartFlag
= False
2321 CommentStr
= Result
[0].strip()
2322 CommentStrListTemp
= CommentStr
.split('\n')
2323 if (len(CommentStrListTemp
) <= 1):
2325 CommentStrListTemp
= CommentStr
.split('\r')
2326 # Skip the content before the file header
2327 for CommentLine
in CommentStrListTemp
:
2328 if CommentLine
.strip().startswith('/** @file'):
2329 FileStartFlag
= True
2330 if FileStartFlag
== True:
2331 CommentStrList
.append(CommentLine
)
2335 if CommentStrList
and CommentStrList
[0].strip().startswith('/** @file'):
2336 NoHeaderCommentStartFlag
= False
2339 if CommentStrList
and CommentStrList
[-1].strip().endswith('**/'):
2340 NoHeaderCommentEndFlag
= False
2344 for CommentLine
in CommentStrList
:
2346 NextLineIndex
= Index
2347 if CommentLine
.startswith('/** @file'):
2349 if CommentLine
.startswith('**/'):
2351 # Check whether C File header Comment content start with two spaces.
2352 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentStartSpacesNum
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2353 if CommentLine
.startswith('/** @file') == False and CommentLine
.startswith('**/') == False and CommentLine
.strip() and CommentLine
.startswith(' ') == False:
2354 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment content should start with two spaces at each line', FileTable
, ID
)
2356 CommentLine
= CommentLine
.strip()
2357 if CommentLine
.startswith('Copyright'):
2358 NoCopyrightFlag
= False
2359 if CommentLine
.find('All rights reserved') == -1:
2360 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable
, ID
)
2361 if CommentLine
.endswith('<BR>') == -1:
2362 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'The ""<BR>"" at the end of the Copyright line is required', FileTable
, ID
)
2363 if NextLineIndex
< len(CommentStrList
) and CommentStrList
[NextLineIndex
].strip().startswith('Copyright') == False and CommentStrList
[NextLineIndex
].strip():
2364 NoLicenseFlag
= False
2365 if CommentLine
.startswith('@par Revision Reference:'):
2366 NoRevReferFlag
= False
2368 for RefLine
in CommentStrList
[NextLineIndex
:]:
2369 if RefLine
.strip() and (NextLineIndex
+ 1) < len(CommentStrList
) and CommentStrList
[NextLineIndex
+1].strip() and CommentStrList
[NextLineIndex
+1].strip().startswith('**/') == False:
2371 if RefLine
.strip() == False or RefLine
.strip().startswith('**/'):
2374 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2375 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentReferenceFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2376 if RefListFlag
== True:
2377 if RefLine
.strip() and RefLine
.strip().startswith('**/') == False and RefLine
.startswith(' -') == False:
2378 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable
, ID
)
2380 if NoHeaderCommentStartFlag
:
2381 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, ID
)
2383 if NoHeaderCommentEndFlag
:
2384 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with ""**/""', FileTable
, ID
)
2387 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment missing the ""Copyright""', FileTable
, ID
)
2388 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2389 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentLicenseFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2391 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable
, ID
)
2393 def CheckFuncHeaderDoxygenComments(FullFileName
):
2396 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2401 FileTable
= 'Identifier' + str(FileID
)
2402 SqlStatement
= """ select Value, StartLine, EndLine, ID
2405 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2407 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2410 for Result
in ResultSet
:
2411 CommentSet
.append(Result
)
2413 print 'Unrecognized chars in comment of file %s', FullFileName
2416 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2419 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2420 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2421 for Result
in ResultSet
:
2422 FuncName
= Result
[4]
2423 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2424 if FunctionHeaderComment
:
2425 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2427 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2429 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2430 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2433 SqlStatement
= """ select Value, StartLine, EndLine, ID
2436 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2438 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2441 for Result
in ResultSet
:
2442 CommentSet
.append(Result
)
2444 print 'Unrecognized chars in comment of file %s', FullFileName
2446 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2448 where BelongsToFile = %d
2450 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2451 for Result
in ResultSet
:
2452 FuncName
= Result
[4]
2453 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2454 if FunctionHeaderComment
:
2455 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2457 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2459 ErrorMsgList
.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2460 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), 'Function', Result
[3])
2463 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2465 for Comment
in CommentSet
:
2466 if Comment
[2] == FuncStartLine
- 1:
2470 def GetDoxygenStrFromComment(Str
):
2472 ParamTagList
= Str
.split('@param')
2473 if len(ParamTagList
) > 1:
2475 while i
< len(ParamTagList
):
2476 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2479 Str
= ParamTagList
[0]
2481 RetvalTagList
= ParamTagList
[-1].split('@retval')
2482 if len(RetvalTagList
) > 1:
2483 if len(ParamTagList
) > 1:
2484 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2486 while i
< len(RetvalTagList
):
2487 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2490 ReturnTagList
= RetvalTagList
[-1].split('@return')
2491 if len(ReturnTagList
) > 1:
2492 if len(RetvalTagList
) > 1:
2493 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2494 elif len(ParamTagList
) > 1:
2495 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2497 while i
< len(ReturnTagList
):
2498 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2501 if len(DoxygenStrList
) > 0:
2502 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2504 return DoxygenStrList
2506 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2507 #/** --*/ @retval after @param
2508 if not Str
.startswith('/**'):
2509 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2510 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2511 if not Str
.endswith('**/'):
2512 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2513 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2514 FirstRetvalIndex
= Str
.find('@retval')
2515 LastParamIndex
= Str
.rfind('@param')
2516 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2517 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2518 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2520 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2522 ParamList
= GetParamList(FuncHeader
)
2523 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2524 DescriptionStr
= CommentStr
2525 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2526 if DescriptionStr
.find('.') == -1:
2527 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2528 DoxygenTagNumber
= len(DoxygenStrList
)
2529 ParamNumber
= len(ParamList
)
2530 for Param
in ParamList
:
2531 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2534 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2535 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2536 ParamModifier
= ParamList
[Index
].Modifier
2537 ParamName
= ParamList
[Index
].Name
.strip()
2538 Tag
= DoxygenStrList
[Index
].strip(' ')
2539 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2540 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2541 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, <%s> does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2542 TagPartList
= Tag
.split()
2543 if len(TagPartList
) < 2:
2544 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2545 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2548 LBPos
= Tag
.find('[')
2549 RBPos
= Tag
.find(']')
2550 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2551 if LBPos
> 0 and len(ParamToLBContent
) == 0 and RBPos
> LBPos
:
2553 ModifierPartList
= ParamModifier
.split()
2554 for Part
in ModifierPartList
:
2555 if Part
.strip() == 'IN':
2557 if Part
.strip() == 'OUT':
2564 if Tag
.find('[' + InOutStr
+ ']') == -1:
2565 if InOutStr
!= 'in, out':
2566 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2567 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2569 if Tag
.find('[in,out]') == -1:
2570 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2571 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2574 if Tag
.find(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2575 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2576 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
)
2579 if Index
< ParamNumber
:
2580 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2581 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2582 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2583 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2585 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2586 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2587 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2588 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2590 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2591 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2592 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2594 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
2595 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2596 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need NO doxygen tags in comment ', TableName
, CommentId
)
2597 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2598 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2599 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2601 if __name__
== '__main__':
2603 # EdkLogger.Initialize()
2604 # EdkLogger.SetLevel(EdkLogger.QUIET)
2605 # CollectSourceCodeDataIntoDB(sys.argv[1])
2607 test_file
= sys
.argv
[1]
2608 except IndexError, v
:
2609 print "Usage: %s filename" % sys
.argv
[0]
2611 MsgList
= CheckFuncHeaderDoxygenComments(test_file
)