2 # This file is used to be the c coding style checking of ECC tool
4 # Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 import Common
.LongFilePathOs
as os
18 import CodeFragmentCollector
20 from CommonDataClass
import DataClass
22 from Common
import EdkLogger
23 from EccToolError
import *
27 IncludeFileListDict
= {}
28 AllIncludeFileListDict
= {}
29 IncludePathListDict
= {}
32 IgnoredKeywordList
= ['EFI_ERROR']
34 def GetIgnoredDirListPattern():
35 skipList
= list(EccGlobalData
.gConfig
.SkipDirList
) + ['.svn']
36 DirString
= string
.join(skipList
, '|')
37 p
= re
.compile(r
'.*[\\/](?:%s)[\\/]?.*' % DirString
)
40 def GetFuncDeclPattern():
41 p
= re
.compile(r
'(?:EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re
.DOTALL
)
44 def GetArrayPattern():
45 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
48 def GetTypedefFuncPointerPattern():
49 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
53 return EccGlobalData
.gDb
56 return EccGlobalData
.gConfig
58 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
59 Msg
= Msg
.replace('\n', '').replace('\r', '')
60 MsgPartList
= Msg
.split()
62 for Part
in MsgPartList
:
65 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
=Msg
, BelongsToTable
=TableName
, BelongsToItem
=ItemId
)
68 Type
= DataClass
.MODEL_UNKNOWN
69 Str
= Str
.replace('#', '# ')
71 if List
[1] == 'include':
72 Type
= DataClass
.MODEL_IDENTIFIER_INCLUDE
73 elif List
[1] == 'define':
74 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_DEFINE
75 elif List
[1] == 'ifdef':
76 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFDEF
77 elif List
[1] == 'ifndef':
78 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
79 elif List
[1] == 'endif':
80 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
81 elif List
[1] == 'pragma':
82 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_PROGMA
84 Type
= DataClass
.MODEL_UNKNOWN
87 def SuOccurInTypedef (Su
, TdList
):
89 if Su
.StartPos
[0] == Td
.StartPos
[0] and Su
.EndPos
[0] == Td
.EndPos
[0]:
93 def GetIdentifierList():
95 for comment
in FileProfile
.CommentList
:
96 IdComment
= DataClass
.IdentifierClass(-1, '', '', '', comment
.Content
, DataClass
.MODEL_IDENTIFIER_COMMENT
, -1, -1, comment
.StartPos
[0], comment
.StartPos
[1], comment
.EndPos
[0], comment
.EndPos
[1])
97 IdList
.append(IdComment
)
99 for pp
in FileProfile
.PPDirectiveList
:
100 Type
= GetIdType(pp
.Content
)
101 IdPP
= DataClass
.IdentifierClass(-1, '', '', '', pp
.Content
, Type
, -1, -1, pp
.StartPos
[0], pp
.StartPos
[1], pp
.EndPos
[0], pp
.EndPos
[1])
104 for pe
in FileProfile
.PredicateExpressionList
:
105 IdPE
= DataClass
.IdentifierClass(-1, '', '', '', pe
.Content
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
, -1, -1, pe
.StartPos
[0], pe
.StartPos
[1], pe
.EndPos
[0], pe
.EndPos
[1])
108 FuncDeclPattern
= GetFuncDeclPattern()
109 ArrayPattern
= GetArrayPattern()
110 for var
in FileProfile
.VariableDeclarationList
:
111 DeclText
= var
.Declarator
.lstrip()
112 FuncPointerPattern
= GetTypedefFuncPointerPattern()
113 if FuncPointerPattern
.match(DeclText
):
115 VarNameStartLine
= var
.NameStartPos
[0]
116 VarNameStartColumn
= var
.NameStartPos
[1]
117 FirstChar
= DeclText
[0]
118 while not FirstChar
.isalpha() and FirstChar
!= '_':
121 VarNameStartColumn
+= 1
122 DeclText
= DeclText
.lstrip('*')
123 elif FirstChar
== '\r':
124 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
125 VarNameStartLine
+= 1
126 VarNameStartColumn
= 0
127 elif FirstChar
== '\n':
128 DeclText
= DeclText
.lstrip('\n')
129 VarNameStartLine
+= 1
130 VarNameStartColumn
= 0
131 elif FirstChar
== ' ':
132 DeclText
= DeclText
.lstrip(' ')
133 VarNameStartColumn
+= 1
134 elif FirstChar
== '\t':
135 DeclText
= DeclText
.lstrip('\t')
136 VarNameStartColumn
+= 8
138 DeclText
= DeclText
[1:]
139 VarNameStartColumn
+= 1
140 FirstChar
= DeclText
[0]
142 var
.Declarator
= DeclText
143 if FuncDeclPattern
.match(var
.Declarator
):
144 DeclSplitList
= var
.Declarator
.split('(')
145 FuncName
= DeclSplitList
[0].strip()
146 FuncNamePartList
= FuncName
.split()
147 if len(FuncNamePartList
) > 1:
148 FuncName
= FuncNamePartList
[-1].strip()
149 NameStart
= DeclSplitList
[0].rfind(FuncName
)
150 var
.Declarator
= var
.Declarator
[NameStart
:]
152 var
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
155 while Index
< NameStart
:
156 FirstChar
= DeclSplitList
[0][Index
]
157 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
159 VarNameStartColumn
+= 6
162 elif FirstChar
== '\r':
164 VarNameStartLine
+= 1
165 VarNameStartColumn
= 0
166 elif FirstChar
== '\n':
169 VarNameStartLine
+= 1
170 VarNameStartColumn
= 0
171 elif FirstChar
== ' ':
173 VarNameStartColumn
+= 1
174 elif FirstChar
== '\t':
176 VarNameStartColumn
+= 8
179 VarNameStartColumn
+= 1
181 IdVar
= DataClass
.IdentifierClass(-1, var
.Modifier
, '', var
.Declarator
, FuncName
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, -1, -1, var
.StartPos
[0], var
.StartPos
[1], VarNameStartLine
, VarNameStartColumn
)
185 if var
.Declarator
.find('{') == -1:
186 for decl
in var
.Declarator
.split(','):
187 DeclList
= decl
.split('=')
188 Name
= DeclList
[0].strip()
189 if ArrayPattern
.match(Name
):
190 LSBPos
= var
.Declarator
.find('[')
191 var
.Modifier
+= ' ' + Name
[LSBPos
:]
192 Name
= Name
[0:LSBPos
]
194 IdVar
= DataClass
.IdentifierClass(-1, var
.Modifier
, '', Name
, (len(DeclList
) > 1 and [DeclList
[1]]or [''])[0], DataClass
.MODEL_IDENTIFIER_VARIABLE
, -1, -1, var
.StartPos
[0], var
.StartPos
[1], VarNameStartLine
, VarNameStartColumn
)
197 DeclList
= var
.Declarator
.split('=')
198 Name
= DeclList
[0].strip()
199 if ArrayPattern
.match(Name
):
200 LSBPos
= var
.Declarator
.find('[')
201 var
.Modifier
+= ' ' + Name
[LSBPos
:]
202 Name
= Name
[0:LSBPos
]
203 IdVar
= DataClass
.IdentifierClass(-1, var
.Modifier
, '', Name
, (len(DeclList
) > 1 and [DeclList
[1]]or [''])[0], DataClass
.MODEL_IDENTIFIER_VARIABLE
, -1, -1, var
.StartPos
[0], var
.StartPos
[1], VarNameStartLine
, VarNameStartColumn
)
206 for enum
in FileProfile
.EnumerationDefinitionList
:
207 LBPos
= enum
.Content
.find('{')
208 RBPos
= enum
.Content
.find('}')
209 Name
= enum
.Content
[4:LBPos
].strip()
210 Value
= enum
.Content
[LBPos
+ 1:RBPos
]
211 IdEnum
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
, -1, -1, enum
.StartPos
[0], enum
.StartPos
[1], enum
.EndPos
[0], enum
.EndPos
[1])
212 IdList
.append(IdEnum
)
214 for su
in FileProfile
.StructUnionDefinitionList
:
215 if SuOccurInTypedef(su
, FileProfile
.TypedefDefinitionList
):
217 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
219 if su
.Content
.startswith('union'):
220 Type
= DataClass
.MODEL_IDENTIFIER_UNION
222 LBPos
= su
.Content
.find('{')
223 RBPos
= su
.Content
.find('}')
224 if LBPos
== -1 or RBPos
== -1:
225 Name
= su
.Content
[SkipLen
:].strip()
228 Name
= su
.Content
[SkipLen
:LBPos
].strip()
229 Value
= su
.Content
[LBPos
:RBPos
+ 1]
230 IdPE
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, Type
, -1, -1, su
.StartPos
[0], su
.StartPos
[1], su
.EndPos
[0], su
.EndPos
[1])
233 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
234 for td
in FileProfile
.TypedefDefinitionList
:
238 if TdFuncPointerPattern
.match(td
.ToType
):
239 Modifier
= td
.FromType
240 LBPos
= td
.ToType
.find('(')
241 TmpStr
= td
.ToType
[LBPos
+ 1:].strip()
242 StarPos
= TmpStr
.find('*')
244 Modifier
+= ' ' + TmpStr
[0:StarPos
]
245 while TmpStr
[StarPos
] == '*':
246 # Modifier += ' ' + '*'
248 TmpStr
= TmpStr
[StarPos
:].strip()
249 RBPos
= TmpStr
.find(')')
250 Name
= TmpStr
[0:RBPos
]
251 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
253 while Name
.startswith('*'):
255 Name
= Name
.lstrip('*').strip()
257 if Name
.find('[') != -1:
258 LBPos
= Name
.find('[')
259 RBPos
= Name
.rfind(']')
260 Value
+= Name
[LBPos
: RBPos
+ 1]
261 Name
= Name
[0 : LBPos
]
263 IdTd
= DataClass
.IdentifierClass(-1, Modifier
, '', Name
, Value
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
, -1, -1, td
.StartPos
[0], td
.StartPos
[1], td
.EndPos
[0], td
.EndPos
[1])
266 for funcCall
in FileProfile
.FunctionCallingList
:
267 IdFC
= DataClass
.IdentifierClass(-1, '', '', funcCall
.FuncName
, funcCall
.ParamList
, DataClass
.MODEL_IDENTIFIER_FUNCTION_CALLING
, -1, -1, funcCall
.StartPos
[0], funcCall
.StartPos
[1], funcCall
.EndPos
[0], funcCall
.EndPos
[1])
271 def StripNonAlnumChars(Str
):
278 def GetParamList(FuncDeclarator
, FuncNameLine
=0, FuncNameOffset
=0):
279 FuncDeclarator
= StripComments(FuncDeclarator
)
281 #DeclSplitList = FuncDeclarator.split('(')
282 LBPos
= FuncDeclarator
.find('(')
283 #if len(DeclSplitList) < 2:
286 #FuncName = DeclSplitList[0]
287 FuncName
= FuncDeclarator
[0:LBPos
]
288 #ParamStr = DeclSplitList[1].rstrip(')')
289 ParamStr
= FuncDeclarator
[LBPos
+ 1:].rstrip(')')
292 TailChar
= FuncName
[-1]
293 while not TailChar
.isalpha() and TailChar
!= '_':
296 FuncName
= FuncName
.rstrip('\r\n').rstrip('\n')
299 elif TailChar
== '\r':
300 FuncName
= FuncName
.rstrip('\r')
303 elif TailChar
== ' ':
304 FuncName
= FuncName
.rstrip(' ')
306 elif TailChar
== '\t':
307 FuncName
= FuncName
.rstrip('\t')
310 FuncName
= FuncName
[:-1]
311 TailChar
= FuncName
[-1]
313 OffsetSkipped
+= 1 #skip '('
315 for p
in ParamStr
.split(','):
319 ParamName
= ListP
[-1]
320 DeclText
= ParamName
.strip()
321 RightSpacePos
= p
.rfind(ParamName
)
322 ParamModifier
= p
[0:RightSpacePos
]
323 if ParamName
== 'OPTIONAL':
324 if ParamModifier
== '':
325 ParamModifier
+= ' ' + 'OPTIONAL'
328 ParamName
= ListP
[-2]
329 DeclText
= ParamName
.strip()
330 RightSpacePos
= p
.rfind(ParamName
)
331 ParamModifier
= p
[0:RightSpacePos
]
332 ParamModifier
+= 'OPTIONAL'
333 while DeclText
.startswith('*'):
334 ParamModifier
+= ' ' + '*'
335 DeclText
= DeclText
.lstrip('*').strip()
337 # ignore array length if exists.
338 LBIndex
= ParamName
.find('[')
340 ParamName
= ParamName
[0:LBIndex
]
342 Start
= RightSpacePos
348 if FirstChar
== '\r':
352 elif FirstChar
== '\n':
357 elif FirstChar
== ' ':
360 elif FirstChar
== '\t':
368 ParamBeginLine
= FuncNameLine
+ LineSkipped
369 ParamBeginOffset
= FuncNameOffset
+ OffsetSkipped
371 Index
= Start
+ len(ParamName
)
373 while Index
< len(p
):
376 if FirstChar
== '\r':
380 elif FirstChar
== '\n':
385 elif FirstChar
== ' ':
388 elif FirstChar
== '\t':
396 ParamEndLine
= FuncNameLine
+ LineSkipped
397 ParamEndOffset
= FuncNameOffset
+ OffsetSkipped
398 if ParamName
!= '...':
399 ParamName
= StripNonAlnumChars(ParamName
)
400 IdParam
= DataClass
.IdentifierClass(-1, ParamModifier
, '', ParamName
, '', DataClass
.MODEL_IDENTIFIER_PARAMETER
, -1, -1, ParamBeginLine
, ParamBeginOffset
, ParamEndLine
, ParamEndOffset
)
401 ParamIdList
.append(IdParam
)
403 OffsetSkipped
+= 1 #skip ','
407 def GetFunctionList():
409 for FuncDef
in FileProfile
.FunctionDefinitionList
:
411 DeclText
= FuncDef
.Declarator
.lstrip()
412 FuncNameStartLine
= FuncDef
.NamePos
[0]
413 FuncNameStartColumn
= FuncDef
.NamePos
[1]
414 FirstChar
= DeclText
[0]
415 while not FirstChar
.isalpha() and FirstChar
!= '_':
417 FuncDef
.Modifier
+= '*'
418 FuncNameStartColumn
+= 1
419 DeclText
= DeclText
.lstrip('*')
420 elif FirstChar
== '\r':
421 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
422 FuncNameStartLine
+= 1
423 FuncNameStartColumn
= 0
424 elif FirstChar
== '\n':
425 DeclText
= DeclText
.lstrip('\n')
426 FuncNameStartLine
+= 1
427 FuncNameStartColumn
= 0
428 elif FirstChar
== ' ':
429 DeclText
= DeclText
.lstrip(' ')
430 FuncNameStartColumn
+= 1
431 elif FirstChar
== '\t':
432 DeclText
= DeclText
.lstrip('\t')
433 FuncNameStartColumn
+= 8
435 DeclText
= DeclText
[1:]
436 FuncNameStartColumn
+= 1
437 FirstChar
= DeclText
[0]
439 FuncDef
.Declarator
= DeclText
440 DeclSplitList
= FuncDef
.Declarator
.split('(')
441 if len(DeclSplitList
) < 2:
444 FuncName
= DeclSplitList
[0]
445 FuncNamePartList
= FuncName
.split()
446 if len(FuncNamePartList
) > 1:
447 FuncName
= FuncNamePartList
[-1]
448 NameStart
= DeclSplitList
[0].rfind(FuncName
)
450 FuncDef
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
453 while Index
< NameStart
:
454 FirstChar
= DeclSplitList
[0][Index
]
455 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
457 FuncNameStartColumn
+= 6
460 elif FirstChar
== '\r':
462 FuncNameStartLine
+= 1
463 FuncNameStartColumn
= 0
464 elif FirstChar
== '\n':
467 FuncNameStartLine
+= 1
468 FuncNameStartColumn
= 0
469 elif FirstChar
== ' ':
471 FuncNameStartColumn
+= 1
472 elif FirstChar
== '\t':
474 FuncNameStartColumn
+= 8
477 FuncNameStartColumn
+= 1
480 FuncObj
= DataClass
.FunctionClass(-1, FuncDef
.Declarator
, FuncDef
.Modifier
, FuncName
.strip(), '', FuncDef
.StartPos
[0], FuncDef
.StartPos
[1], FuncDef
.EndPos
[0], FuncDef
.EndPos
[1], FuncDef
.LeftBracePos
[0], FuncDef
.LeftBracePos
[1], -1, ParamIdList
, [], FuncNameStartLine
, FuncNameStartColumn
)
481 FuncObjList
.append(FuncObj
)
485 def GetFileModificationTimeFromDB(FullFileName
):
488 SqlStatement
= """ select TimeStamp
490 where FullPath = \'%s\'
492 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
493 for Result
in ResultSet
:
494 TimeValue
= Result
[0]
497 def CollectSourceCodeDataIntoDB(RootDir
):
499 tuple = os
.walk(RootDir
)
500 IgnoredPattern
= GetIgnoredDirListPattern()
501 ParseErrorFileList
= []
503 for dirpath
, dirnames
, filenames
in tuple:
504 if IgnoredPattern
.match(dirpath
.upper()):
508 Dirname
= os
.path
.join(dirpath
, Dir
)
509 if os
.path
.islink(Dirname
):
510 Dirname
= os
.path
.realpath(Dirname
)
511 if os
.path
.isdir(Dirname
):
512 # symlinks to directories are treated as directories
514 dirnames
.append(Dirname
)
517 if f
.lower() in EccGlobalData
.gConfig
.SkipFileList
:
520 FullName
= os
.path
.normpath(os
.path
.join(dirpath
, f
))
521 model
= DataClass
.MODEL_FILE_OTHERS
522 if os
.path
.splitext(f
)[1] in ('.h', '.c'):
523 EdkLogger
.info("Parsing " + FullName
)
524 model
= f
.endswith('c') and DataClass
.MODEL_FILE_C
or DataClass
.MODEL_FILE_H
525 collector
= CodeFragmentCollector
.CodeFragmentCollector(FullName
)
527 collector
.ParseFile()
529 ParseErrorFileList
.append(FullName
)
530 collector
.CleanFileProfileBuffer()
531 collector
.ParseFileWithClearedPPDirective()
532 # collector.PrintFragments()
533 BaseName
= os
.path
.basename(f
)
534 DirName
= os
.path
.dirname(FullName
)
535 Ext
= os
.path
.splitext(f
)[1].lstrip('.')
536 ModifiedTime
= os
.path
.getmtime(FullName
)
537 FileObj
= DataClass
.FileClass(-1, BaseName
, Ext
, DirName
, FullName
, model
, ModifiedTime
, GetFunctionList(), GetIdentifierList(), [])
538 FileObjList
.append(FileObj
)
540 collector
.CleanFileProfileBuffer()
542 if len(ParseErrorFileList
) > 0:
543 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
546 for file in FileObjList
:
547 if file.ExtName
.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
548 Db
.InsertOneFile(file)
550 Db
.UpdateIdentifierBelongsToFunction()
552 def GetTableID(FullFileName
, ErrorMsgList
=None):
553 if ErrorMsgList
== None:
557 SqlStatement
= """ select ID
559 where FullPath like '%s'
561 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
564 for Result
in ResultSet
:
566 ErrorMsgList
.append('Duplicate file ID found in DB for file %s' % FullFileName
)
570 ErrorMsgList
.append('NO file ID found in DB for file %s' % FullFileName
)
574 def GetIncludeFileList(FullFileName
):
575 if os
.path
.splitext(FullFileName
)[1].upper() not in ('.H'):
577 IFList
= IncludeFileListDict
.get(FullFileName
)
581 FileID
= GetTableID(FullFileName
)
586 FileTable
= 'Identifier' + str(FileID
)
587 SqlStatement
= """ select Value
590 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_INCLUDE
)
591 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
592 IncludeFileListDict
[FullFileName
] = ResultSet
595 def GetFullPathOfIncludeFile(Str
, IncludePathList
):
596 for IncludePath
in IncludePathList
:
597 FullPath
= os
.path
.join(IncludePath
, Str
)
598 FullPath
= os
.path
.normpath(FullPath
)
599 if os
.path
.exists(FullPath
):
603 def GetAllIncludeFiles(FullFileName
):
604 if AllIncludeFileListDict
.get(FullFileName
) != None:
605 return AllIncludeFileListDict
.get(FullFileName
)
607 FileDirName
= os
.path
.dirname(FullFileName
)
608 IncludePathList
= IncludePathListDict
.get(FileDirName
)
609 if IncludePathList
== None:
610 IncludePathList
= MetaDataParser
.GetIncludeListOfFile(EccGlobalData
.gWorkspace
, FullFileName
, GetDB())
611 if FileDirName
not in IncludePathList
:
612 IncludePathList
.insert(0, FileDirName
)
613 IncludePathListDict
[FileDirName
] = IncludePathList
614 IncludeFileQueue
= []
615 for IncludeFile
in GetIncludeFileList(FullFileName
):
616 FileName
= IncludeFile
[0].lstrip('#').strip()
617 FileName
= FileName
.lstrip('include').strip()
618 FileName
= FileName
.strip('\"')
619 FileName
= FileName
.lstrip('<').rstrip('>').strip()
620 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
622 IncludeFileQueue
.append(FullPath
)
625 while i
< len(IncludeFileQueue
):
626 for IncludeFile
in GetIncludeFileList(IncludeFileQueue
[i
]):
627 FileName
= IncludeFile
[0].lstrip('#').strip()
628 FileName
= FileName
.lstrip('include').strip()
629 FileName
= FileName
.strip('\"')
630 FileName
= FileName
.lstrip('<').rstrip('>').strip()
631 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
632 if FullPath
!= None and FullPath
not in IncludeFileQueue
:
633 IncludeFileQueue
.insert(i
+ 1, FullPath
)
636 AllIncludeFileListDict
[FullFileName
] = IncludeFileQueue
637 return IncludeFileQueue
639 def GetPredicateListFromPredicateExpStr(PES
):
646 p
= GetFuncDeclPattern()
647 while i
< len(PES
) - 1:
648 if (PES
[i
].isalnum() or PES
[i
] == '_' or PES
[i
] == '*') and LogicOpPos
> PredicateBegin
:
650 if (PES
[i
] == '&' and PES
[i
+ 1] == '&') or (PES
[i
] == '|' and PES
[i
+ 1] == '|'):
652 Exp
= PES
[PredicateBegin
:i
].strip()
653 # Exp may contain '.' or '->'
654 TmpExp
= Exp
.replace('.', '').replace('->', '')
656 PredicateList
.append(Exp
)
658 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
661 if PredicateBegin
> LogicOpPos
:
662 while PredicateBegin
< len(PES
):
663 if PES
[PredicateBegin
].isalnum() or PES
[PredicateBegin
] == '_' or PES
[PredicateBegin
] == '*':
666 Exp
= PES
[PredicateBegin
:len(PES
)].strip()
667 # Exp may contain '.' or '->'
668 TmpExp
= Exp
.replace('.', '').replace('->', '')
670 PredicateList
.append(Exp
)
672 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
675 def GetCNameList(Lvalue
, StarList
=[]):
683 while SearchBegin
< len(Lvalue
):
684 while i
< len(Lvalue
):
685 if Lvalue
[i
].isalnum() or Lvalue
[i
] == '_':
691 VarList
.append(Lvalue
[VarStart
:VarEnd
+ 1])
695 if VarStart
== -1 and Lvalue
[i
] == '*':
702 DotIndex
= Lvalue
[VarEnd
:].find('.')
703 ArrowIndex
= Lvalue
[VarEnd
:].find('->')
704 if DotIndex
== -1 and ArrowIndex
== -1:
706 elif DotIndex
== -1 and ArrowIndex
!= -1:
707 SearchBegin
= VarEnd
+ ArrowIndex
708 elif ArrowIndex
== -1 and DotIndex
!= -1:
709 SearchBegin
= VarEnd
+ DotIndex
711 SearchBegin
= VarEnd
+ ((DotIndex
< ArrowIndex
) and DotIndex
or ArrowIndex
)
719 def SplitPredicateByOp(Str
, Op
, IsFuncCalling
=False):
728 while Index
< len(Str
):
729 while not LBFound
and Str
[Index
] != '_' and not Str
[Index
].isalnum():
732 while not LBFound
and (Str
[Index
].isalnum() or Str
[Index
] == '_'):
734 # maybe type-cast at the begining, skip it.
735 RemainingStr
= Str
[Index
:].lstrip()
736 if RemainingStr
.startswith(')') and not LBFound
:
740 if RemainingStr
.startswith('(') and not LBFound
:
743 if Str
[Index
] == '(':
744 UnmatchedLBCount
+= 1
748 if Str
[Index
] == ')':
749 UnmatchedLBCount
-= 1
751 if UnmatchedLBCount
== 0:
757 if UnmatchedLBCount
> 0:
760 IndexInRemainingStr
= Str
[Index
:].find(Op
)
761 if IndexInRemainingStr
== -1:
764 Name
= Str
[0:Index
+ IndexInRemainingStr
].strip()
765 Value
= Str
[Index
+ IndexInRemainingStr
+ len(Op
):].strip().strip(')')
768 TmpStr
= Str
.rstrip(';').rstrip(')')
770 Index
= TmpStr
.rfind(Op
)
774 if Str
[Index
- 1].isalnum() or Str
[Index
- 1].isspace() or Str
[Index
- 1] == ')' or Str
[Index
- 1] == ']':
775 Name
= Str
[0:Index
].strip()
776 Value
= Str
[Index
+ len(Op
):].strip()
779 TmpStr
= Str
[0:Index
- 1]
781 def SplitPredicateStr(Str
):
783 Str
= Str
.lstrip('(')
784 IsFuncCalling
= False
785 p
= GetFuncDeclPattern()
786 TmpStr
= Str
.replace('.', '').replace('->', '')
790 PredPartList
= SplitPredicateByOp(Str
, '==', IsFuncCalling
)
791 if len(PredPartList
) > 1:
792 return [PredPartList
, '==']
794 PredPartList
= SplitPredicateByOp(Str
, '!=', IsFuncCalling
)
795 if len(PredPartList
) > 1:
796 return [PredPartList
, '!=']
798 PredPartList
= SplitPredicateByOp(Str
, '>=', IsFuncCalling
)
799 if len(PredPartList
) > 1:
800 return [PredPartList
, '>=']
802 PredPartList
= SplitPredicateByOp(Str
, '<=', IsFuncCalling
)
803 if len(PredPartList
) > 1:
804 return [PredPartList
, '<=']
806 PredPartList
= SplitPredicateByOp(Str
, '>', IsFuncCalling
)
807 if len(PredPartList
) > 1:
808 return [PredPartList
, '>']
810 PredPartList
= SplitPredicateByOp(Str
, '<', IsFuncCalling
)
811 if len(PredPartList
) > 1:
812 return [PredPartList
, '<']
814 return [[Str
, None], None]
816 def GetFuncContainsPE(ExpLine
, ResultSet
):
817 for Result
in ResultSet
:
818 if Result
[0] < ExpLine
and Result
[1] > ExpLine
:
822 def PatternInModifier(Modifier
, SubStr
):
823 PartList
= Modifier
.split()
824 for Part
in PartList
:
829 def GetDataTypeFromModifier(ModifierStr
):
830 MList
= ModifierStr
.split()
833 if M
in EccGlobalData
.gConfig
.ModifierList
:
836 if M
.startswith('[') or M
.endswith(']'):
838 ReturnType
+= M
+ ' '
840 ReturnType
= ReturnType
.strip()
841 if len(ReturnType
) == 0:
845 def DiffModifier(Str1
, Str2
):
846 PartList1
= Str1
.split()
847 PartList2
= Str2
.split()
848 if PartList1
== PartList2
:
853 def GetTypedefDict(FullFileName
):
855 Dict
= ComplexTypeDict
.get(FullFileName
)
859 FileID
= GetTableID(FullFileName
)
860 FileTable
= 'Identifier' + str(FileID
)
862 SqlStatement
= """ select Modifier, Name, Value, ID
865 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
866 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
869 for Result
in ResultSet
:
870 if len(Result
[0]) == 0:
871 Dict
[Result
[1]] = Result
[2]
873 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
874 for F
in IncludeFileList
:
875 FileID
= GetTableID(F
)
879 FileTable
= 'Identifier' + str(FileID
)
880 SqlStatement
= """ select Modifier, Name, Value, ID
883 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
884 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
886 for Result
in ResultSet
:
887 if not Result
[2].startswith('FP ('):
888 Dict
[Result
[1]] = Result
[2]
890 if len(Result
[0]) == 0:
891 Dict
[Result
[1]] = 'VOID'
893 Dict
[Result
[1]] = GetDataTypeFromModifier(Result
[0])
895 ComplexTypeDict
[FullFileName
] = Dict
898 def GetSUDict(FullFileName
):
900 Dict
= SUDict
.get(FullFileName
)
904 FileID
= GetTableID(FullFileName
)
905 FileTable
= 'Identifier' + str(FileID
)
907 SqlStatement
= """ select Name, Value, ID
909 where Model = %d or Model = %d
910 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
911 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
914 for Result
in ResultSet
:
915 if len(Result
[1]) > 0:
916 Dict
[Result
[0]] = Result
[1]
918 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
919 for F
in IncludeFileList
:
920 FileID
= GetTableID(F
)
924 FileTable
= 'Identifier' + str(FileID
)
925 SqlStatement
= """ select Name, Value, ID
927 where Model = %d or Model = %d
928 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
929 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
931 for Result
in ResultSet
:
932 if len(Result
[1]) > 0:
933 Dict
[Result
[0]] = Result
[1]
935 SUDict
[FullFileName
] = Dict
938 def StripComments(Str
):
940 ListFromStr
= list(Str
)
943 DoubleSlashComment
= False
945 while Index
< len(ListFromStr
):
946 # meet new line, then no longer in a comment for //
947 if ListFromStr
[Index
] == '\n':
948 if InComment
and DoubleSlashComment
:
950 DoubleSlashComment
= False
952 # check for */ comment end
953 elif InComment
and not DoubleSlashComment
and ListFromStr
[Index
] == '*' and ListFromStr
[Index
+ 1] == '/':
954 ListFromStr
[Index
] = ' '
956 ListFromStr
[Index
] = ' '
959 # set comments to spaces
961 ListFromStr
[Index
] = ' '
963 # check for // comment
964 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '/' and ListFromStr
[Index
+ 2] != '\n':
966 DoubleSlashComment
= True
968 # check for /* comment start
969 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '*':
970 ListFromStr
[Index
] = ' '
972 ListFromStr
[Index
] = ' '
978 # restore from List to String
979 Str
= "".join(ListFromStr
)
980 Str
= Str
.rstrip(' ')
984 def GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
):
985 Value
= TypedefDict
.get(Type
)
987 Value
= SUDict
.get(Type
)
991 LBPos
= Value
.find('{')
993 FTList
= Value
.split()
995 if FT
not in ('struct', 'union'):
996 Value
= TypedefDict
.get(FT
)
998 Value
= SUDict
.get(FT
)
1004 LBPos
= Value
.find('{')
1006 # RBPos = Value.find('}')
1007 Fields
= Value
[LBPos
+ 1:]
1008 Fields
= StripComments(Fields
)
1009 FieldsList
= Fields
.split(';')
1010 for Field
in FieldsList
:
1011 Field
= Field
.strip()
1012 Index
= Field
.rfind(FieldName
)
1015 if not Field
[Index
- 1].isalnum():
1016 if Index
+ len(FieldName
) == len(Field
):
1017 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1020 # For the condition that the field in struct is an array with [] sufixes...
1021 if not Field
[Index
+ len(FieldName
)].isalnum():
1022 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1027 def GetRealType(Type
, TypedefDict
, TargetType
=None):
1028 if TargetType
!= None and Type
== TargetType
:
1030 while TypedefDict
.get(Type
):
1031 Type
= TypedefDict
.get(Type
)
1032 if TargetType
!= None and Type
== TargetType
:
1036 def GetTypeInfo(RefList
, Modifier
, FullFileName
, TargetType
=None):
1037 TypedefDict
= GetTypedefDict(FullFileName
)
1038 SUDict
= GetSUDict(FullFileName
)
1039 Type
= GetDataTypeFromModifier(Modifier
).replace('*', '').strip()
1041 Type
= Type
.split()[-1]
1043 while Index
< len(RefList
):
1044 FieldName
= RefList
[Index
]
1045 FromType
= GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
)
1046 if FromType
== None:
1048 # we want to determine the exact type.
1049 if TargetType
!= None:
1050 Type
= FromType
.split()[0]
1051 # we only want to check if it is a pointer
1054 if Type
.find('*') != -1 and Index
== len(RefList
) - 1:
1056 Type
= FromType
.split()[0]
1060 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1064 def GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
=False, TargetType
=None, StarList
=None):
1066 PredVar
= PredVarList
[0]
1067 FileID
= GetTableID(FullFileName
)
1070 FileTable
= 'Identifier' + str(FileID
)
1071 # search variable in include files
1073 # it is a function call, search function declarations and definitions
1075 SqlStatement
= """ select Modifier, ID
1077 where Model = %d and Value = \'%s\'
1078 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1079 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1081 for Result
in ResultSet
:
1082 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1083 TypedefDict
= GetTypedefDict(FullFileName
)
1084 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1087 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1088 for F
in IncludeFileList
:
1089 FileID
= GetTableID(F
)
1093 FileTable
= 'Identifier' + str(FileID
)
1094 SqlStatement
= """ select Modifier, ID
1096 where Model = %d and Value = \'%s\'
1097 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1098 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1100 for Result
in ResultSet
:
1101 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1102 TypedefDict
= GetTypedefDict(FullFileName
)
1103 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1106 FileID
= GetTableID(FullFileName
)
1107 SqlStatement
= """ select Modifier, ID
1109 where BelongsToFile = %d and Name = \'%s\'
1110 """ % (FileID
, PredVar
)
1111 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1113 for Result
in ResultSet
:
1114 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1115 TypedefDict
= GetTypedefDict(FullFileName
)
1116 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1119 for F
in IncludeFileList
:
1120 FileID
= GetTableID(F
)
1124 FileTable
= 'Identifier' + str(FileID
)
1125 SqlStatement
= """ select Modifier, ID
1127 where BelongsToFile = %d and Name = \'%s\'
1128 """ % (FileID
, PredVar
)
1129 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1131 for Result
in ResultSet
:
1132 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1133 TypedefDict
= GetTypedefDict(FullFileName
)
1134 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1139 # really variable, search local variable first
1140 SqlStatement
= """ select Modifier, ID
1142 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1143 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
, FuncRecord
[0], FuncRecord
[1])
1144 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1146 for Result
in ResultSet
:
1147 if len(PredVarList
) > 1:
1148 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1151 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1152 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1154 if len(TypeList
) > 1 and StarList
!= None:
1155 for Star
in StarList
:
1157 Type
= Type
.rstrip(Star
)
1158 # Get real type after de-reference pointers.
1159 if len(Type
.strip()) == 0:
1161 TypedefDict
= GetTypedefDict(FullFileName
)
1162 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1165 # search function parameters second
1166 ParamList
= GetParamList(FuncRecord
[2])
1167 for Param
in ParamList
:
1168 if Param
.Name
.strip() == PredVar
:
1169 if len(PredVarList
) > 1:
1170 Type
= GetTypeInfo(PredVarList
[1:], Param
.Modifier
, FullFileName
, TargetType
)
1173 TypeList
= GetDataTypeFromModifier(Param
.Modifier
).split()
1175 if Type
== '*' and len(TypeList
) >= 2:
1177 if len(TypeList
) > 1 and StarList
!= None:
1178 for Star
in StarList
:
1180 Type
= Type
.rstrip(Star
)
1181 # Get real type after de-reference pointers.
1182 if len(Type
.strip()) == 0:
1184 TypedefDict
= GetTypedefDict(FullFileName
)
1185 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1188 # search global variable next
1189 SqlStatement
= """ select Modifier, ID
1191 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1192 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1193 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1195 for Result
in ResultSet
:
1196 if len(PredVarList
) > 1:
1197 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1200 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1202 if len(TypeList
) > 1 and StarList
!= None:
1203 for Star
in StarList
:
1205 Type
= Type
.rstrip(Star
)
1206 # Get real type after de-reference pointers.
1207 if len(Type
.strip()) == 0:
1209 TypedefDict
= GetTypedefDict(FullFileName
)
1210 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1213 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1214 for F
in IncludeFileList
:
1215 FileID
= GetTableID(F
)
1219 FileTable
= 'Identifier' + str(FileID
)
1220 SqlStatement
= """ select Modifier, ID
1222 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1223 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1224 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1226 for Result
in ResultSet
:
1227 if len(PredVarList
) > 1:
1228 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1231 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1233 if len(TypeList
) > 1 and StarList
!= None:
1234 for Star
in StarList
:
1236 Type
= Type
.rstrip(Star
)
1237 # Get real type after de-reference pointers.
1238 if len(Type
.strip()) == 0:
1240 TypedefDict
= GetTypedefDict(FullFileName
)
1241 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1244 def GetTypeFromArray(Type
, Var
):
1245 Count
= Var
.count('[')
1249 Type
= Type
.rstrip('*')
1254 def CheckFuncLayoutReturnType(FullFileName
):
1257 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1262 FileTable
= 'Identifier' + str(FileID
)
1263 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1266 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1267 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1268 for Result
in ResultSet
:
1269 ReturnType
= GetDataTypeFromModifier(Result
[0])
1270 TypeStart
= ReturnType
.split()[0]
1271 FuncName
= Result
[5]
1272 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1274 Index
= Result
[0].find(TypeStart
)
1275 if Index
!= 0 or Result
[3] != 0:
1276 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1278 if Result
[2] == Result
[4]:
1279 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1281 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1283 where BelongsToFile = %d
1285 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1286 for Result
in ResultSet
:
1287 ReturnType
= GetDataTypeFromModifier(Result
[0])
1288 TypeStart
= ReturnType
.split()[0]
1289 FuncName
= Result
[5]
1290 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1293 if Result0
.upper().startswith('STATIC'):
1294 Result0
= Result0
[6:].strip()
1295 Index
= Result0
.find(ReturnType
)
1296 if Index
!= 0 or Result
[3] != 0:
1297 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1299 def CheckFuncLayoutModifier(FullFileName
):
1302 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1307 FileTable
= 'Identifier' + str(FileID
)
1308 SqlStatement
= """ select Modifier, ID
1311 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1312 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1313 for Result
in ResultSet
:
1314 ReturnType
= GetDataTypeFromModifier(Result
[0])
1315 TypeStart
= ReturnType
.split()[0]
1316 # if len(ReturnType) == 0:
1318 Index
= Result
[0].find(TypeStart
)
1320 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1322 SqlStatement
= """ select Modifier, ID
1324 where BelongsToFile = %d
1326 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1327 for Result
in ResultSet
:
1328 ReturnType
= GetDataTypeFromModifier(Result
[0])
1329 TypeStart
= ReturnType
.split()[0]
1330 # if len(ReturnType) == 0:
1333 if Result0
.upper().startswith('STATIC'):
1334 Result0
= Result0
[6:].strip()
1335 Index
= Result0
.find(TypeStart
)
1337 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1339 def CheckFuncLayoutName(FullFileName
):
1341 # Parameter variable format pattern.
1342 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1343 ParamIgnoreList
= ('VOID', '...')
1344 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1349 FileTable
= 'Identifier' + str(FileID
)
1350 SqlStatement
= """ select Name, ID, EndColumn, Value
1353 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1354 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1355 for Result
in ResultSet
:
1356 FuncName
= Result
[3]
1357 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1360 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1361 ParamList
= GetParamList(Result
[0])
1362 if len(ParamList
) == 0:
1365 for Param
in ParamList
:
1366 if Param
.StartLine
<= StartLine
:
1367 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1368 if Param
.StartLine
- StartLine
> 1:
1369 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1370 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
):
1371 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1372 StartLine
= Param
.StartLine
1374 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1375 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1377 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1379 where BelongsToFile = %d
1381 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1382 for Result
in ResultSet
:
1383 FuncName
= Result
[3]
1384 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1387 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1388 ParamList
= GetParamList(Result
[0])
1389 if len(ParamList
) == 0:
1392 for Param
in ParamList
:
1393 if Param
.StartLine
<= StartLine
:
1394 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1395 if Param
.StartLine
- StartLine
> 1:
1396 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1397 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
):
1398 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1399 StartLine
= Param
.StartLine
1400 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1401 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1403 def CheckFuncLayoutPrototype(FullFileName
):
1406 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1410 FileTable
= 'Identifier' + str(FileID
)
1412 SqlStatement
= """ select Modifier, Header, Name, ID
1414 where BelongsToFile = %d
1416 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1417 if len(ResultSet
) == 0:
1421 for Result
in ResultSet
:
1422 FuncDefList
.append(Result
)
1424 SqlStatement
= """ select Modifier, Name, ID
1427 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1428 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1430 for Result
in ResultSet
:
1431 FuncDeclList
.append(Result
)
1434 for FuncDef
in FuncDefList
:
1435 FuncName
= FuncDef
[2].strip()
1436 FuncModifier
= FuncDef
[0]
1437 FuncDefHeader
= FuncDef
[1]
1438 for FuncDecl
in FuncDeclList
:
1439 LBPos
= FuncDecl
[1].find('(')
1440 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1441 DeclModifier
= FuncDecl
[0]
1442 if DeclName
== FuncName
:
1443 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1444 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1445 ParamListOfDef
= GetParamList(FuncDefHeader
)
1446 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1447 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1448 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1452 while Index
< len(ParamListOfDef
):
1453 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1454 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])
1458 UndeclFuncList
.append(FuncDef
)
1460 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1462 for F
in IncludeFileList
:
1463 FileID
= GetTableID(F
, ErrorMsgList
)
1467 FileTable
= 'Identifier' + str(FileID
)
1468 SqlStatement
= """ select Modifier, Name, ID
1471 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1472 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1474 for Result
in ResultSet
:
1475 FuncDeclList
.append(Result
)
1477 for FuncDef
in UndeclFuncList
:
1478 FuncName
= FuncDef
[2].strip()
1479 FuncModifier
= FuncDef
[0]
1480 FuncDefHeader
= FuncDef
[1]
1481 for FuncDecl
in FuncDeclList
:
1482 LBPos
= FuncDecl
[1].find('(')
1483 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1484 DeclModifier
= FuncDecl
[0]
1485 if DeclName
== FuncName
:
1486 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1487 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1488 ParamListOfDef
= GetParamList(FuncDefHeader
)
1489 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1490 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1491 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1495 while Index
< len(ParamListOfDef
):
1496 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1497 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])
1501 def CheckFuncLayoutBody(FullFileName
):
1504 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1508 FileTable
= 'Identifier' + str(FileID
)
1510 SqlStatement
= """ select BodyStartColumn, EndColumn, ID
1512 where BelongsToFile = %d
1514 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1515 if len(ResultSet
) == 0:
1517 for Result
in ResultSet
:
1519 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'open brace should be at the very beginning of a line.', 'Function', Result
[2])
1521 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'close brace should be at the very beginning of a line.', 'Function', Result
[2])
1523 def CheckFuncLayoutLocalVariable(FullFileName
):
1526 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1531 FileTable
= 'Identifier' + str(FileID
)
1532 SqlStatement
= """ select ID
1534 where BelongsToFile = %d
1536 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1537 if len(ResultSet
) == 0:
1540 for Result
in ResultSet
:
1544 SqlStatement
= """ select Name, Value, ID, Modifier
1546 where Model = %d and BelongsToFunction = %d
1547 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1548 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1549 if len(ResultSet
) == 0:
1552 for Result
in ResultSet
:
1553 if len(Result
[1]) > 0 and 'CONST' not in Result
[3]:
1554 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1556 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1558 # Member variable format pattern.
1559 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1561 LBPos
= Value
.find('{')
1562 RBPos
= Value
.rfind('}')
1563 if LBPos
== -1 or RBPos
== -1:
1566 Fields
= Value
[LBPos
+ 1 : RBPos
]
1567 Fields
= StripComments(Fields
).strip()
1568 NestPos
= Fields
.find ('struct')
1569 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)):
1570 if not Fields
[NestPos
+ len('struct') + 1].isalnum():
1571 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1572 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested struct in [%s].' % (Name
), FileTable
, TdId
)
1574 NestPos
= Fields
.find ('union')
1575 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1576 if not Fields
[NestPos
+ len('union') + 1].isalnum():
1577 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1578 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested union in [%s].' % (Name
), FileTable
, TdId
)
1580 NestPos
= Fields
.find ('enum')
1581 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1582 if not Fields
[NestPos
+ len('enum') + 1].isalnum():
1583 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1584 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested enum in [%s].' % (Name
), FileTable
, TdId
)
1587 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1588 FieldsList
= Fields
.split(',')
1589 # deal with enum is pre-assigned a value by function call ( , , , ...)
1592 RemoveCurrentElement
= False
1593 while Index
< len(FieldsList
):
1594 Field
= FieldsList
[Index
]
1596 if Field
.find('(') != -1:
1598 RemoveCurrentElement
= True
1602 if Field
.find(')') != -1 and QuoteCount
> 0:
1605 if RemoveCurrentElement
:
1606 FieldsList
.remove(Field
)
1608 RemoveCurrentElement
= False
1612 RemoveCurrentElement
= False
1616 FieldsList
= Fields
.split(';')
1618 for Field
in FieldsList
:
1619 Field
= Field
.strip()
1622 # For the condition that the field in struct is an array with [] sufixes...
1623 if Field
[-1] == ']':
1624 LBPos
= Field
.find('[')
1625 Field
= Field
[0:LBPos
]
1626 # For the condition that bit field ": Number"
1627 if Field
.find(':') != -1:
1628 ColonPos
= Field
.find(':')
1629 Field
= Field
[0:ColonPos
]
1631 Field
= Field
.strip()
1634 # Enum could directly assign value to variable
1635 Field
= Field
.split('=')[0].strip()
1636 TokenList
= Field
.split()
1637 # Remove pointers before variable
1638 Token
= TokenList
[-1]
1639 if Token
in ['OPTIONAL']:
1640 Token
= TokenList
[-2]
1641 if not Pattern
.match(Token
.lstrip('*')):
1642 ErrMsgList
.append(Token
.lstrip('*'))
1646 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1649 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1654 FileTable
= 'Identifier' + str(FileID
)
1655 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1658 """ % (FileTable
, ModelId
)
1659 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1661 for Result
in ResultSet
:
1662 ResultList
.append(Result
)
1664 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1665 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1666 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1667 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1668 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1669 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1670 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1672 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1675 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1676 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1680 # Check member variable name format that from typedefs of ONLY this file.
1682 Name
= Td
[1].strip()
1683 Value
= Td
[2].strip()
1684 if Value
.startswith('enum'):
1685 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1686 elif Value
.startswith('struct'):
1687 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1688 elif Value
.startswith('union'):
1689 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1693 if ValueModelId
!= ModelId
:
1695 # Check member variable format.
1696 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1697 for ErrMsg
in ErrMsgList
:
1698 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+ '.' + ErrMsg
):
1700 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+ '.' + ErrMsg
), FileTable
, Td
[5])
1702 # First check in current file to see whether struct/union/enum is typedef-ed.
1703 UntypedefedList
= []
1704 for Result
in ResultList
:
1705 # Check member variable format.
1706 Name
= Result
[0].strip()
1707 Value
= Result
[4].strip()
1708 if Value
.startswith('enum'):
1709 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1710 elif Value
.startswith('struct'):
1711 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1712 elif Value
.startswith('union'):
1713 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1717 if ValueModelId
!= ModelId
:
1719 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1720 for ErrMsg
in ErrMsgList
:
1721 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0] + '.' + ErrMsg
):
1723 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0] + '.' + ErrMsg
), FileTable
, Result
[3])
1724 # Check whether it is typedefed.
1727 # skip function pointer
1730 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1732 if not Td
[1].isupper():
1733 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1734 if Result
[0] in Td
[2].split():
1736 if not Td
[1].isupper():
1737 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1742 UntypedefedList
.append(Result
)
1745 if len(UntypedefedList
) == 0:
1748 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1750 for F
in IncludeFileList
:
1751 FileID
= GetTableID(F
, ErrorMsgList
)
1755 IncludeFileTable
= 'Identifier' + str(FileID
)
1756 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1759 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1760 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1761 TdList
.extend(ResultSet
)
1763 for Result
in UntypedefedList
:
1765 # Check whether it is typedefed.
1771 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1773 if not Td
[1].isupper():
1774 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1775 if Result
[0] in Td
[2].split():
1777 if not Td
[1].isupper():
1778 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1783 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1786 def CheckDeclStructTypedef(FullFileName
):
1787 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1789 def CheckDeclEnumTypedef(FullFileName
):
1790 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1792 def CheckDeclUnionTypedef(FullFileName
):
1793 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1795 def CheckDeclArgModifier(FullFileName
):
1798 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1803 FileTable
= 'Identifier' + str(FileID
)
1804 SqlStatement
= """ select Modifier, Name, ID
1807 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1808 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1809 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1810 MAX_MODIFIER_LENGTH
= 100
1811 for Result
in ResultSet
:
1812 for Modifier
in ModifierTuple
:
1813 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1814 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1817 SqlStatement
= """ select Modifier, Name, ID
1820 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1821 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1822 for Result
in ResultSet
:
1823 for Modifier
in ModifierTuple
:
1824 if PatternInModifier(Result
[0], Modifier
):
1825 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1828 SqlStatement
= """ select Modifier, Header, ID
1830 where BelongsToFile = %d
1832 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1833 for Result
in ResultSet
:
1834 for Modifier
in ModifierTuple
:
1835 if PatternInModifier(Result
[0], Modifier
):
1836 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1839 def CheckDeclNoUseCType(FullFileName
):
1842 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1847 FileTable
= 'Identifier' + str(FileID
)
1848 SqlStatement
= """ select Modifier, Name, ID
1851 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1852 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1853 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1854 for Result
in ResultSet
:
1855 for Type
in CTypeTuple
:
1856 if PatternInModifier(Result
[0], Type
):
1857 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Variable type %s' % Type
, FileTable
, Result
[2])
1860 SqlStatement
= """ select Modifier, Name, ID, Value
1863 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1864 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1865 for Result
in ResultSet
:
1866 ParamList
= GetParamList(Result
[1])
1867 FuncName
= Result
[3]
1868 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1870 for Type
in CTypeTuple
:
1871 if PatternInModifier(Result
[0], Type
):
1872 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1874 for Param
in ParamList
:
1875 if PatternInModifier(Param
.Modifier
, Type
):
1876 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1878 SqlStatement
= """ select Modifier, Header, ID, Name
1880 where BelongsToFile = %d
1882 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1883 for Result
in ResultSet
:
1884 ParamList
= GetParamList(Result
[1])
1885 FuncName
= Result
[3]
1886 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1888 for Type
in CTypeTuple
:
1889 if PatternInModifier(Result
[0], Type
):
1890 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1892 for Param
in ParamList
:
1893 if PatternInModifier(Param
.Modifier
, Type
):
1894 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1897 def CheckPointerNullComparison(FullFileName
):
1900 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1904 # cache the found function return type to accelerate later checking in this file.
1905 FuncReturnTypeDict
= {}
1908 FileTable
= 'Identifier' + str(FileID
)
1909 SqlStatement
= """ select Value, StartLine, ID
1912 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1913 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1914 if len(ResultSet
) == 0:
1917 for Result
in ResultSet
:
1918 PSL
.append([Result
[0], Result
[1], Result
[2]])
1920 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1922 where BelongsToFile = %d
1924 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1926 for Result
in ResultSet
:
1927 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1929 p
= GetFuncDeclPattern()
1931 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1932 if FuncRecord
== None:
1935 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1936 PredInfo
= SplitPredicateStr(Exp
)
1937 if PredInfo
[1] == None:
1938 PredVarStr
= PredInfo
[0][0].strip()
1940 SearchInCache
= False
1941 # PredVarStr may contain '.' or '->'
1942 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1944 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1945 SearchInCache
= True
1946 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1947 if TmpStr
.startswith(PredVarStr
):
1950 if PredVarStr
.strip() in IgnoredKeywordList
:
1953 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1954 # No variable found, maybe value first? like (0 == VarName)
1955 if len(PredVarList
) == 0:
1958 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1960 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1961 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1964 if PredVarStr
in FuncReturnTypeDict
:
1967 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1969 FuncReturnTypeDict
[PredVarStr
] = Type
1972 Type
= GetTypeFromArray(Type
, PredVarStr
)
1973 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1974 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1976 def CheckNonBooleanValueComparison(FullFileName
):
1979 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1983 # cache the found function return type to accelerate later checking in this file.
1984 FuncReturnTypeDict
= {}
1987 FileTable
= 'Identifier' + str(FileID
)
1988 SqlStatement
= """ select Value, StartLine, ID
1991 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1992 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1993 if len(ResultSet
) == 0:
1996 for Result
in ResultSet
:
1997 PSL
.append([Result
[0], Result
[1], Result
[2]])
1999 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2001 where BelongsToFile = %d
2003 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2005 for Result
in ResultSet
:
2006 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2008 p
= GetFuncDeclPattern()
2010 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2011 if FuncRecord
== None:
2014 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2015 PredInfo
= SplitPredicateStr(Exp
)
2016 if PredInfo
[1] == None:
2017 PredVarStr
= PredInfo
[0][0].strip()
2019 SearchInCache
= False
2020 # PredVarStr may contain '.' or '->'
2021 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2023 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2024 SearchInCache
= True
2025 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2026 if TmpStr
.startswith(PredVarStr
):
2029 if PredVarStr
.strip() in IgnoredKeywordList
:
2032 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2033 # No variable found, maybe value first? like (0 == VarName)
2034 if len(PredVarList
) == 0:
2038 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2040 if Type
.find('BOOLEAN') == -1:
2041 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2044 if PredVarStr
in FuncReturnTypeDict
:
2046 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2048 FuncReturnTypeDict
[PredVarStr
] = Type
2051 if Type
.find('BOOLEAN') == -1:
2052 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2055 def CheckBooleanValueComparison(FullFileName
):
2058 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2062 # cache the found function return type to accelerate later checking in this file.
2063 FuncReturnTypeDict
= {}
2066 FileTable
= 'Identifier' + str(FileID
)
2067 SqlStatement
= """ select Value, StartLine, ID
2070 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2071 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2072 if len(ResultSet
) == 0:
2075 for Result
in ResultSet
:
2076 PSL
.append([Result
[0], Result
[1], Result
[2]])
2078 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2080 where BelongsToFile = %d
2082 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2084 for Result
in ResultSet
:
2085 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2087 p
= GetFuncDeclPattern()
2089 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2090 if FuncRecord
== None:
2093 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2094 PredInfo
= SplitPredicateStr(Exp
)
2095 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2096 PredVarStr
= PredInfo
[0][0].strip()
2098 SearchInCache
= False
2099 # PredVarStr may contain '.' or '->'
2100 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2102 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2103 SearchInCache
= True
2104 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2105 if TmpStr
.startswith(PredVarStr
):
2108 if PredVarStr
.strip() in IgnoredKeywordList
:
2111 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2112 # No variable found, maybe value first? like (0 == VarName)
2113 if len(PredVarList
) == 0:
2117 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2119 if Type
.find('BOOLEAN') != -1:
2120 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2123 if PredVarStr
in FuncReturnTypeDict
:
2126 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2128 FuncReturnTypeDict
[PredVarStr
] = Type
2131 if Type
.find('BOOLEAN') != -1:
2132 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2135 def CheckHeaderFileData(FullFileName
):
2138 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2143 FileTable
= 'Identifier' + str(FileID
)
2144 SqlStatement
= """ select ID, Modifier
2147 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2148 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2149 for Result
in ResultSet
:
2150 if not Result
[1].startswith('extern'):
2151 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2153 SqlStatement
= """ select ID
2155 where BelongsToFile = %d
2157 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2158 for Result
in ResultSet
:
2159 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2163 def CheckHeaderFileIfndef(FullFileName
):
2166 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2171 FileTable
= 'Identifier' + str(FileID
)
2172 SqlStatement
= """ select Value, StartLine
2174 where Model = %d order by StartLine
2175 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2176 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2177 if len(ResultSet
) == 0:
2178 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2180 for Result
in ResultSet
:
2181 SqlStatement
= """ select Value, EndLine
2184 """ % (FileTable
, Result
[1])
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_2
, '', 'File', FileID
)
2191 SqlStatement
= """ select Value
2193 where StartLine > (select max(EndLine) from %s where Model = %d)
2194 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2195 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2196 for Result
in ResultSet
:
2197 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2198 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2201 def CheckDoxygenCommand(FullFileName
):
2204 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2209 FileTable
= 'Identifier' + str(FileID
)
2210 SqlStatement
= """ select Value, ID
2212 where Model = %d or Model = %d
2213 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2214 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2215 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval', 'return', 'sa', 'since', 'test', 'note', 'par']
2216 for Result
in ResultSet
:
2217 CommentStr
= Result
[0]
2218 CommentPartList
= CommentStr
.split()
2219 for Part
in CommentPartList
:
2220 if Part
.upper() == 'BUGBUG':
2221 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2222 if Part
.upper() == 'TODO':
2223 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2224 if Part
.startswith('@'):
2225 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2227 if Part
.lstrip('@').isalpha():
2228 if Part
.lstrip('@') not in DoxygenCommandList
:
2229 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2231 Index
= Part
.find('[')
2233 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2234 RealCmd
= Part
[1:Index
]
2235 if RealCmd
not in DoxygenCommandList
:
2236 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2239 def CheckDoxygenTripleForwardSlash(FullFileName
):
2242 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2248 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2250 where BelongsToFile = %d
2252 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2253 if len(ResultSet
) == 0:
2257 for Result
in ResultSet
:
2258 FuncDefSet
.append(Result
)
2261 FileTable
= 'Identifier' + str(FileID
)
2262 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2266 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2267 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2270 for Result
in ResultSet
:
2271 CommentSet
.append(Result
)
2273 print 'Unrecognized chars in comment of file %s', FullFileName
2276 for Result
in CommentSet
:
2277 CommentStr
= Result
[0]
2278 StartLine
= Result
[2]
2279 StartColumn
= Result
[3]
2281 EndColumn
= Result
[5]
2282 if not CommentStr
.startswith('///<'):
2286 for FuncDef
in FuncDefSet
:
2287 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2290 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2293 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2296 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2300 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2303 def CheckFileHeaderDoxygenComments(FullFileName
):
2306 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2311 FileTable
= 'Identifier' + str(FileID
)
2312 SqlStatement
= """ select Value, ID
2314 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2315 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2316 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2317 if len(ResultSet
) == 0:
2318 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No File License header appear at the very beginning of file.', 'File', FileID
)
2321 NoHeaderCommentStartFlag
= True
2322 NoHeaderCommentEndFlag
= True
2323 NoHeaderCommentPeriodFlag
= True
2324 NoCopyrightFlag
= True
2325 NoLicenseFlag
= True
2326 NoRevReferFlag
= True
2328 for Result
in ResultSet
:
2329 FileStartFlag
= False
2331 CommentStr
= Result
[0].strip()
2332 CommentStrListTemp
= CommentStr
.split('\n')
2333 if (len(CommentStrListTemp
) <= 1):
2335 CommentStrListTemp
= CommentStr
.split('\r')
2336 # Skip the content before the file header
2337 for CommentLine
in CommentStrListTemp
:
2338 if CommentLine
.strip().startswith('/** @file'):
2339 FileStartFlag
= True
2340 if FileStartFlag
== True:
2341 CommentStrList
.append(CommentLine
)
2345 if CommentStrList
and CommentStrList
[0].strip().startswith('/** @file'):
2346 NoHeaderCommentStartFlag
= False
2349 if CommentStrList
and CommentStrList
[-1].strip().endswith('**/'):
2350 NoHeaderCommentEndFlag
= False
2354 for CommentLine
in CommentStrList
:
2356 NextLineIndex
= Index
2357 if CommentLine
.startswith('/** @file'):
2359 if CommentLine
.startswith('**/'):
2361 # Check whether C File header Comment content start with two spaces.
2362 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentStartSpacesNum
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2363 if CommentLine
.startswith('/** @file') == False and CommentLine
.startswith('**/') == False and CommentLine
.strip() and CommentLine
.startswith(' ') == False:
2364 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment content should start with two spaces at each line', FileTable
, ID
)
2366 CommentLine
= CommentLine
.strip()
2367 if CommentLine
.startswith('Copyright'):
2368 NoCopyrightFlag
= False
2369 if CommentLine
.find('All rights reserved') == -1:
2370 for Copyright
in EccGlobalData
.gConfig
.Copyright
:
2371 if CommentLine
.find(Copyright
) > -1:
2372 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable
, ID
)
2374 if CommentLine
.endswith('<BR>') == -1:
2375 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'The ""<BR>"" at the end of the Copyright line is required', FileTable
, ID
)
2376 if NextLineIndex
< len(CommentStrList
) and CommentStrList
[NextLineIndex
].strip().startswith('Copyright') == False and CommentStrList
[NextLineIndex
].strip():
2377 NoLicenseFlag
= False
2378 if CommentLine
.startswith('@par Revision Reference:'):
2379 NoRevReferFlag
= False
2381 for RefLine
in CommentStrList
[NextLineIndex
:]:
2382 if RefLine
.strip() and (NextLineIndex
+ 1) < len(CommentStrList
) and CommentStrList
[NextLineIndex
+1].strip() and CommentStrList
[NextLineIndex
+1].strip().startswith('**/') == False:
2384 if RefLine
.strip() == False or RefLine
.strip().startswith('**/'):
2387 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2388 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentReferenceFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2389 if RefListFlag
== True:
2390 if RefLine
.strip() and RefLine
.strip().startswith('**/') == False and RefLine
.startswith(' -') == False:
2391 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable
, ID
)
2393 if NoHeaderCommentStartFlag
:
2394 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, ID
)
2396 if NoHeaderCommentEndFlag
:
2397 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with ""**/""', FileTable
, ID
)
2400 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment missing the ""Copyright""', FileTable
, ID
)
2401 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2402 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentLicenseFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2404 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable
, ID
)
2406 def CheckFuncHeaderDoxygenComments(FullFileName
):
2409 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2414 FileTable
= 'Identifier' + str(FileID
)
2415 SqlStatement
= """ select Value, StartLine, EndLine, ID
2418 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2420 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2423 for Result
in ResultSet
:
2424 CommentSet
.append(Result
)
2426 print 'Unrecognized chars in comment of file %s', FullFileName
2429 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2432 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2433 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2434 for Result
in ResultSet
:
2435 FuncName
= Result
[4]
2436 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2437 if FunctionHeaderComment
:
2438 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2440 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2442 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2443 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2446 SqlStatement
= """ select Value, StartLine, EndLine, ID
2449 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2451 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2454 for Result
in ResultSet
:
2455 CommentSet
.append(Result
)
2457 print 'Unrecognized chars in comment of file %s', FullFileName
2459 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2461 where BelongsToFile = %d
2463 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2464 for Result
in ResultSet
:
2465 FuncName
= Result
[4]
2466 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2467 if FunctionHeaderComment
:
2468 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2470 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2472 ErrorMsgList
.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2473 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), 'Function', Result
[3])
2476 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2478 for Comment
in CommentSet
:
2479 if Comment
[2] == FuncStartLine
- 1:
2483 def GetDoxygenStrFromComment(Str
):
2485 ParamTagList
= Str
.split('@param')
2486 if len(ParamTagList
) > 1:
2488 while i
< len(ParamTagList
):
2489 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2492 Str
= ParamTagList
[0]
2494 RetvalTagList
= ParamTagList
[-1].split('@retval')
2495 if len(RetvalTagList
) > 1:
2496 if len(ParamTagList
) > 1:
2497 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2499 while i
< len(RetvalTagList
):
2500 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2503 ReturnTagList
= RetvalTagList
[-1].split('@return')
2504 if len(ReturnTagList
) > 1:
2505 if len(RetvalTagList
) > 1:
2506 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2507 elif len(ParamTagList
) > 1:
2508 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2510 while i
< len(ReturnTagList
):
2511 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2514 if len(DoxygenStrList
) > 0:
2515 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2517 return DoxygenStrList
2519 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2520 #/** --*/ @retval after @param
2521 if not Str
.startswith('/**'):
2522 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2523 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2524 if not Str
.endswith('**/'):
2525 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2526 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2527 FirstRetvalIndex
= Str
.find('@retval')
2528 LastParamIndex
= Str
.rfind('@param')
2529 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2530 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2531 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2533 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2535 ParamList
= GetParamList(FuncHeader
)
2536 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2537 DescriptionStr
= CommentStr
2538 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2539 if DescriptionStr
.find('.') == -1:
2540 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2541 DoxygenTagNumber
= len(DoxygenStrList
)
2542 ParamNumber
= len(ParamList
)
2543 for Param
in ParamList
:
2544 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2547 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2548 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2549 ParamModifier
= ParamList
[Index
].Modifier
2550 ParamName
= ParamList
[Index
].Name
.strip()
2551 Tag
= DoxygenStrList
[Index
].strip(' ')
2552 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2553 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2554 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, <%s> does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2555 TagPartList
= Tag
.split()
2556 if len(TagPartList
) < 2:
2557 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2558 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2561 LBPos
= Tag
.find('[')
2562 RBPos
= Tag
.find(']')
2563 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2564 if LBPos
> 0 and len(ParamToLBContent
) == 0 and RBPos
> LBPos
:
2566 ModifierPartList
= ParamModifier
.split()
2567 for Part
in ModifierPartList
:
2568 if Part
.strip() == 'IN':
2570 if Part
.strip() == 'OUT':
2577 if Tag
.find('[' + InOutStr
+ ']') == -1:
2578 if InOutStr
!= 'in, out':
2579 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2580 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2582 if Tag
.find('[in,out]') == -1:
2583 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2584 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2587 if Tag
.find(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2588 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2589 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
)
2592 if Index
< ParamNumber
:
2593 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2594 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2595 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2596 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2598 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2599 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2600 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2601 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2603 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2604 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2605 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2607 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
2608 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2609 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need NO doxygen tags in comment ', TableName
, CommentId
)
2610 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2611 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2612 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2614 if __name__
== '__main__':
2616 # EdkLogger.Initialize()
2617 # EdkLogger.SetLevel(EdkLogger.QUIET)
2618 # CollectSourceCodeDataIntoDB(sys.argv[1])
2620 test_file
= sys
.argv
[1]
2621 except IndexError, v
:
2622 print "Usage: %s filename" % sys
.argv
[0]
2624 MsgList
= CheckFuncHeaderDoxygenComments(test_file
)