2 # This file is used to be the c coding style checking of ECC tool
4 # Copyright (c) 2009 - 2010, 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.
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
)