2 # This file is used to be the c coding style checking of ECC tool
4 # Copyright (c) 2009 - 2018, 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
):
274 if Char
.isalnum() or Char
== '_':
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
is 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
)
578 if IFList
is not None:
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
) is not None:
605 return AllIncludeFileListDict
.get(FullFileName
)
607 FileDirName
= os
.path
.dirname(FullFileName
)
608 IncludePathList
= IncludePathListDict
.get(FileDirName
)
609 if IncludePathList
is 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
)
621 if FullPath
is not None:
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
is not 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
.ModifierSet
:
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
is not None and Type
== TargetType
:
1030 while TypedefDict
.get(Type
):
1031 Type
= TypedefDict
.get(Type
)
1032 if TargetType
is not 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
is None:
1048 # we want to determine the exact type.
1049 if TargetType
is not 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
is not 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
is not 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
is not 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
is not 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
):
1275 if Result0
.upper().startswith('STATIC'):
1276 Result0
= Result0
[6:].strip()
1277 Index
= Result0
.find(TypeStart
)
1278 if Index
!= 0 or Result
[3] != 0:
1279 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1281 if Result
[2] == Result
[4]:
1282 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1284 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1286 where BelongsToFile = %d
1288 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1289 for Result
in ResultSet
:
1290 ReturnType
= GetDataTypeFromModifier(Result
[0])
1291 TypeStart
= ReturnType
.split()[0]
1292 FuncName
= Result
[5]
1293 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1296 if Result0
.upper().startswith('STATIC'):
1297 Result0
= Result0
[6:].strip()
1298 Index
= Result0
.find(ReturnType
)
1299 if Index
!= 0 or Result
[3] != 0:
1300 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1302 def CheckFuncLayoutModifier(FullFileName
):
1305 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1310 FileTable
= 'Identifier' + str(FileID
)
1311 SqlStatement
= """ select Modifier, ID
1314 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1315 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1316 for Result
in ResultSet
:
1317 ReturnType
= GetDataTypeFromModifier(Result
[0])
1318 TypeStart
= ReturnType
.split()[0]
1320 if Result0
.upper().startswith('STATIC'):
1321 Result0
= Result0
[6:].strip()
1322 Index
= Result0
.find(TypeStart
)
1324 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1326 SqlStatement
= """ select Modifier, ID
1328 where BelongsToFile = %d
1330 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1331 for Result
in ResultSet
:
1332 ReturnType
= GetDataTypeFromModifier(Result
[0])
1333 TypeStart
= ReturnType
.split()[0]
1335 if Result0
.upper().startswith('STATIC'):
1336 Result0
= Result0
[6:].strip()
1337 Index
= Result0
.find(TypeStart
)
1339 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1341 def CheckFuncLayoutName(FullFileName
):
1343 # Parameter variable format pattern.
1344 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1345 ParamIgnoreList
= ('VOID', '...')
1346 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1351 FileTable
= 'Identifier' + str(FileID
)
1352 SqlStatement
= """ select Name, ID, EndColumn, Value
1355 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1356 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1357 for Result
in ResultSet
:
1358 FuncName
= Result
[3]
1359 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1362 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1363 ParamList
= GetParamList(Result
[0])
1364 if len(ParamList
) == 0:
1367 for Param
in ParamList
:
1368 if Param
.StartLine
<= StartLine
:
1369 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1370 if Param
.StartLine
- StartLine
> 1:
1371 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1372 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
):
1373 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1374 StartLine
= Param
.StartLine
1376 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1377 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1379 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1381 where BelongsToFile = %d
1383 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1384 for Result
in ResultSet
:
1385 FuncName
= Result
[3]
1386 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1389 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1390 ParamList
= GetParamList(Result
[0])
1391 if len(ParamList
) == 0:
1394 for Param
in ParamList
:
1395 if Param
.StartLine
<= StartLine
:
1396 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1397 if Param
.StartLine
- StartLine
> 1:
1398 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1399 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
):
1400 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1401 StartLine
= Param
.StartLine
1402 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1403 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1405 def CheckFuncLayoutPrototype(FullFileName
):
1408 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1412 FileTable
= 'Identifier' + str(FileID
)
1414 SqlStatement
= """ select Modifier, Header, Name, ID
1416 where BelongsToFile = %d
1418 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1419 if len(ResultSet
) == 0:
1423 for Result
in ResultSet
:
1424 FuncDefList
.append(Result
)
1426 SqlStatement
= """ select Modifier, Name, ID
1429 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1430 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1432 for Result
in ResultSet
:
1433 FuncDeclList
.append(Result
)
1436 for FuncDef
in FuncDefList
:
1437 FuncName
= FuncDef
[2].strip()
1438 FuncModifier
= FuncDef
[0]
1439 FuncDefHeader
= FuncDef
[1]
1440 for FuncDecl
in FuncDeclList
:
1441 LBPos
= FuncDecl
[1].find('(')
1442 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1443 DeclModifier
= FuncDecl
[0]
1444 if DeclName
== FuncName
:
1445 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1446 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1447 ParamListOfDef
= GetParamList(FuncDefHeader
)
1448 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1449 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1450 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1454 while Index
< len(ParamListOfDef
):
1455 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1456 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])
1460 UndeclFuncList
.append(FuncDef
)
1462 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1464 for F
in IncludeFileList
:
1465 FileID
= GetTableID(F
, ErrorMsgList
)
1469 FileTable
= 'Identifier' + str(FileID
)
1470 SqlStatement
= """ select Modifier, Name, ID
1473 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1474 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1476 for Result
in ResultSet
:
1477 FuncDeclList
.append(Result
)
1479 for FuncDef
in UndeclFuncList
:
1480 FuncName
= FuncDef
[2].strip()
1481 FuncModifier
= FuncDef
[0]
1482 FuncDefHeader
= FuncDef
[1]
1483 for FuncDecl
in FuncDeclList
:
1484 LBPos
= FuncDecl
[1].find('(')
1485 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1486 DeclModifier
= FuncDecl
[0]
1487 if DeclName
== FuncName
:
1488 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1489 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1490 ParamListOfDef
= GetParamList(FuncDefHeader
)
1491 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1492 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1493 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1497 while Index
< len(ParamListOfDef
):
1498 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1499 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])
1503 def CheckFuncLayoutBody(FullFileName
):
1506 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1510 FileTable
= 'Identifier' + str(FileID
)
1512 SqlStatement
= """ select BodyStartColumn, EndColumn, ID
1514 where BelongsToFile = %d
1516 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1517 if len(ResultSet
) == 0:
1519 for Result
in ResultSet
:
1521 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'open brace should be at the very beginning of a line.', 'Function', Result
[2])
1523 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'close brace should be at the very beginning of a line.', 'Function', Result
[2])
1525 def CheckFuncLayoutLocalVariable(FullFileName
):
1528 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1533 FileTable
= 'Identifier' + str(FileID
)
1534 SqlStatement
= """ select ID
1536 where BelongsToFile = %d
1538 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1539 if len(ResultSet
) == 0:
1542 for Result
in ResultSet
:
1546 SqlStatement
= """ select Name, Value, ID, Modifier
1548 where Model = %d and BelongsToFunction = %d
1549 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1550 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1551 if len(ResultSet
) == 0:
1554 for Result
in ResultSet
:
1555 if len(Result
[1]) > 0 and 'CONST' not in Result
[3]:
1556 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1558 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1560 # Member variable format pattern.
1561 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1563 LBPos
= Value
.find('{')
1564 RBPos
= Value
.rfind('}')
1565 if LBPos
== -1 or RBPos
== -1:
1568 Fields
= Value
[LBPos
+ 1 : RBPos
]
1569 Fields
= StripComments(Fields
).strip()
1570 NestPos
= Fields
.find ('struct')
1571 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)) and ModelId
!= DataClass
.MODEL_IDENTIFIER_UNION
:
1572 if not Fields
[NestPos
+ len('struct') + 1].isalnum():
1573 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1574 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested struct in [%s].' % (Name
), FileTable
, TdId
)
1576 NestPos
= Fields
.find ('union')
1577 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1578 if not Fields
[NestPos
+ len('union') + 1].isalnum():
1579 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1580 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested union in [%s].' % (Name
), FileTable
, TdId
)
1582 NestPos
= Fields
.find ('enum')
1583 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1584 if not Fields
[NestPos
+ len('enum') + 1].isalnum():
1585 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1586 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested enum in [%s].' % (Name
), FileTable
, TdId
)
1589 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1590 FieldsList
= Fields
.split(',')
1591 # deal with enum is pre-assigned a value by function call ( , , , ...)
1594 RemoveCurrentElement
= False
1595 while Index
< len(FieldsList
):
1596 Field
= FieldsList
[Index
]
1598 if Field
.find('(') != -1:
1600 RemoveCurrentElement
= True
1604 if Field
.find(')') != -1 and QuoteCount
> 0:
1607 if RemoveCurrentElement
:
1608 FieldsList
.remove(Field
)
1610 RemoveCurrentElement
= False
1614 RemoveCurrentElement
= False
1618 FieldsList
= Fields
.split(';')
1620 for Field
in FieldsList
:
1621 Field
= Field
.strip()
1624 # For the condition that the field in struct is an array with [] sufixes...
1625 if Field
[-1] == ']':
1626 LBPos
= Field
.find('[')
1627 Field
= Field
[0:LBPos
]
1628 # For the condition that bit field ": Number"
1629 if Field
.find(':') != -1:
1630 ColonPos
= Field
.find(':')
1631 Field
= Field
[0:ColonPos
]
1633 Field
= Field
.strip()
1636 if Field
.startswith("#"):
1638 # Enum could directly assign value to variable
1639 Field
= Field
.split('=')[0].strip()
1640 TokenList
= Field
.split()
1641 # Remove pointers before variable
1642 Token
= TokenList
[-1]
1643 if Token
in ['OPTIONAL']:
1644 Token
= TokenList
[-2]
1645 if not Pattern
.match(Token
.lstrip('*')):
1646 ErrMsgList
.append(Token
.lstrip('*'))
1650 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1653 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1658 FileTable
= 'Identifier' + str(FileID
)
1659 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1662 """ % (FileTable
, ModelId
)
1663 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1665 for Result
in ResultSet
:
1666 ResultList
.append(Result
)
1668 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1669 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1670 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1671 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1672 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1673 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1674 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1676 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1679 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1680 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1684 # Check member variable name format that from typedefs of ONLY this file.
1686 Name
= Td
[1].strip()
1687 Value
= Td
[2].strip()
1688 if Value
.startswith('enum'):
1689 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1690 elif Value
.startswith('struct'):
1691 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1692 elif Value
.startswith('union'):
1693 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1697 if ValueModelId
!= ModelId
:
1699 # Check member variable format.
1700 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1701 for ErrMsg
in ErrMsgList
:
1702 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+ '.' + ErrMsg
):
1704 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+ '.' + ErrMsg
), FileTable
, Td
[5])
1706 # First check in current file to see whether struct/union/enum is typedef-ed.
1707 UntypedefedList
= []
1708 for Result
in ResultList
:
1709 # Check member variable format.
1710 Name
= Result
[0].strip()
1711 Value
= Result
[4].strip()
1712 if Value
.startswith('enum'):
1713 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1714 elif Value
.startswith('struct'):
1715 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1716 elif Value
.startswith('union'):
1717 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1721 if ValueModelId
!= ModelId
:
1723 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1724 for ErrMsg
in ErrMsgList
:
1725 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0] + '.' + ErrMsg
):
1727 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0] + '.' + ErrMsg
), FileTable
, Result
[3])
1728 # Check whether it is typedefed.
1731 # skip function pointer
1734 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1736 if not Td
[1].isupper():
1737 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1738 if Result
[0] in Td
[2].split():
1740 if not Td
[1].isupper():
1741 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1746 UntypedefedList
.append(Result
)
1749 if len(UntypedefedList
) == 0:
1752 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1754 for F
in IncludeFileList
:
1755 FileID
= GetTableID(F
, ErrorMsgList
)
1759 IncludeFileTable
= 'Identifier' + str(FileID
)
1760 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1763 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1764 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1765 TdList
.extend(ResultSet
)
1767 for Result
in UntypedefedList
:
1769 # Check whether it is typedefed.
1775 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1777 if not Td
[1].isupper():
1778 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1779 if Result
[0] in Td
[2].split():
1781 if not Td
[1].isupper():
1782 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1787 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1790 def CheckDeclStructTypedef(FullFileName
):
1791 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1793 def CheckDeclEnumTypedef(FullFileName
):
1794 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1796 def CheckDeclUnionTypedef(FullFileName
):
1797 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1799 def CheckDeclArgModifier(FullFileName
):
1802 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1807 FileTable
= 'Identifier' + str(FileID
)
1808 SqlStatement
= """ select Modifier, Name, ID
1811 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1812 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1813 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1814 MAX_MODIFIER_LENGTH
= 100
1815 for Result
in ResultSet
:
1816 for Modifier
in ModifierTuple
:
1817 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1818 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1821 SqlStatement
= """ select Modifier, Name, ID
1824 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1825 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1826 for Result
in ResultSet
:
1827 for Modifier
in ModifierTuple
:
1828 if PatternInModifier(Result
[0], Modifier
):
1829 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1832 SqlStatement
= """ select Modifier, Header, ID
1834 where BelongsToFile = %d
1836 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1837 for Result
in ResultSet
:
1838 for Modifier
in ModifierTuple
:
1839 if PatternInModifier(Result
[0], Modifier
):
1840 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1843 def CheckDeclNoUseCType(FullFileName
):
1846 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1851 FileTable
= 'Identifier' + str(FileID
)
1852 SqlStatement
= """ select Modifier, Name, ID
1855 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1856 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1857 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1858 for Result
in ResultSet
:
1859 for Type
in CTypeTuple
:
1860 if PatternInModifier(Result
[0], Type
):
1861 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1862 Result
[0] + ' ' + Result
[1]):
1864 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1865 'Invalid variable type (%s) in definition [%s]' % (Type
, Result
[0] + ' ' + Result
[1]),
1870 SqlStatement
= """ select Modifier, Name, ID, Value
1873 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1874 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1875 for Result
in ResultSet
:
1876 ParamList
= GetParamList(Result
[1])
1877 FuncName
= Result
[3]
1878 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1880 for Type
in CTypeTuple
:
1881 if PatternInModifier(Result
[0], Type
):
1882 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1884 for Param
in ParamList
:
1885 if PatternInModifier(Param
.Modifier
, Type
):
1886 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1888 SqlStatement
= """ select Modifier, Header, ID, Name
1890 where BelongsToFile = %d
1892 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1893 for Result
in ResultSet
:
1894 ParamList
= GetParamList(Result
[1])
1895 FuncName
= Result
[3]
1896 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1898 for Type
in CTypeTuple
:
1899 if PatternInModifier(Result
[0], Type
):
1900 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1902 for Param
in ParamList
:
1903 if PatternInModifier(Param
.Modifier
, Type
):
1904 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1907 def CheckPointerNullComparison(FullFileName
):
1910 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1914 # cache the found function return type to accelerate later checking in this file.
1915 FuncReturnTypeDict
= {}
1918 FileTable
= 'Identifier' + str(FileID
)
1919 SqlStatement
= """ select Value, StartLine, ID
1922 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1923 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1924 if len(ResultSet
) == 0:
1927 for Result
in ResultSet
:
1928 PSL
.append([Result
[0], Result
[1], Result
[2]])
1930 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1932 where BelongsToFile = %d
1934 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1936 for Result
in ResultSet
:
1937 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1939 p
= GetFuncDeclPattern()
1941 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1942 if FuncRecord
is None:
1945 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1946 PredInfo
= SplitPredicateStr(Exp
)
1947 if PredInfo
[1] is None:
1948 PredVarStr
= PredInfo
[0][0].strip()
1950 SearchInCache
= False
1951 # PredVarStr may contain '.' or '->'
1952 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1954 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1955 SearchInCache
= True
1956 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1957 if TmpStr
.startswith(PredVarStr
):
1960 if PredVarStr
.strip() in IgnoredKeywordList
:
1963 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1964 # No variable found, maybe value first? like (0 == VarName)
1965 if len(PredVarList
) == 0:
1968 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1969 if Type
is not None:
1970 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1971 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1974 if PredVarStr
in FuncReturnTypeDict
:
1977 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1979 FuncReturnTypeDict
[PredVarStr
] = Type
1982 Type
= GetTypeFromArray(Type
, PredVarStr
)
1983 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1984 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1986 def CheckNonBooleanValueComparison(FullFileName
):
1989 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1993 # cache the found function return type to accelerate later checking in this file.
1994 FuncReturnTypeDict
= {}
1997 FileTable
= 'Identifier' + str(FileID
)
1998 SqlStatement
= """ select Value, StartLine, ID
2001 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2002 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2003 if len(ResultSet
) == 0:
2006 for Result
in ResultSet
:
2007 PSL
.append([Result
[0], Result
[1], Result
[2]])
2009 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2011 where BelongsToFile = %d
2013 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2015 for Result
in ResultSet
:
2016 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2018 p
= GetFuncDeclPattern()
2020 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2021 if FuncRecord
is None:
2024 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2025 PredInfo
= SplitPredicateStr(Exp
)
2026 if PredInfo
[1] is None:
2027 PredVarStr
= PredInfo
[0][0].strip()
2029 SearchInCache
= False
2030 # PredVarStr may contain '.' or '->'
2031 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2033 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2034 SearchInCache
= True
2035 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2036 if TmpStr
.startswith(PredVarStr
):
2039 if PredVarStr
.strip() in IgnoredKeywordList
:
2042 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2043 # No variable found, maybe value first? like (0 == VarName)
2044 if len(PredVarList
) == 0:
2048 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2049 if Type
is not None:
2050 if Type
.find('BOOLEAN') == -1:
2051 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2054 if PredVarStr
in FuncReturnTypeDict
:
2056 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2058 FuncReturnTypeDict
[PredVarStr
] = Type
2061 if Type
.find('BOOLEAN') == -1:
2062 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2065 def CheckBooleanValueComparison(FullFileName
):
2068 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2072 # cache the found function return type to accelerate later checking in this file.
2073 FuncReturnTypeDict
= {}
2076 FileTable
= 'Identifier' + str(FileID
)
2077 SqlStatement
= """ select Value, StartLine, ID
2080 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2081 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2082 if len(ResultSet
) == 0:
2085 for Result
in ResultSet
:
2086 PSL
.append([Result
[0], Result
[1], Result
[2]])
2088 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2090 where BelongsToFile = %d
2092 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2094 for Result
in ResultSet
:
2095 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2097 p
= GetFuncDeclPattern()
2099 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2100 if FuncRecord
is None:
2103 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2104 PredInfo
= SplitPredicateStr(Exp
)
2105 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2106 PredVarStr
= PredInfo
[0][0].strip()
2108 SearchInCache
= False
2109 # PredVarStr may contain '.' or '->'
2110 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2112 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2113 SearchInCache
= True
2114 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2115 if TmpStr
.startswith(PredVarStr
):
2118 if PredVarStr
.strip() in IgnoredKeywordList
:
2121 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2122 # No variable found, maybe value first? like (0 == VarName)
2123 if len(PredVarList
) == 0:
2127 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2128 if Type
is not None:
2129 if Type
.find('BOOLEAN') != -1:
2130 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2133 if PredVarStr
in FuncReturnTypeDict
:
2136 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2138 FuncReturnTypeDict
[PredVarStr
] = Type
2141 if Type
.find('BOOLEAN') != -1:
2142 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2145 def CheckHeaderFileData(FullFileName
):
2148 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2153 FileTable
= 'Identifier' + str(FileID
)
2154 SqlStatement
= """ select ID, Modifier
2157 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2158 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2159 for Result
in ResultSet
:
2160 if not Result
[1].startswith('extern'):
2161 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2163 SqlStatement
= """ select ID
2165 where BelongsToFile = %d
2167 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2168 for Result
in ResultSet
:
2169 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2173 def CheckHeaderFileIfndef(FullFileName
):
2176 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2181 FileTable
= 'Identifier' + str(FileID
)
2182 SqlStatement
= """ select Value, StartLine
2184 where Model = %d order by StartLine
2185 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2186 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2187 if len(ResultSet
) == 0:
2188 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2190 for Result
in ResultSet
:
2191 SqlStatement
= """ select Value, EndLine
2194 """ % (FileTable
, Result
[1])
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_2
, '', 'File', FileID
)
2201 SqlStatement
= """ select Value
2203 where StartLine > (select max(EndLine) from %s where Model = %d)
2204 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2205 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2206 for Result
in ResultSet
:
2207 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2208 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2211 def CheckDoxygenCommand(FullFileName
):
2214 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2219 FileTable
= 'Identifier' + str(FileID
)
2220 SqlStatement
= """ select Value, ID
2222 where Model = %d or Model = %d
2223 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2224 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2225 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval',
2226 'return', 'sa', 'since', 'test', 'note', 'par', 'endcode', 'code']
2227 for Result
in ResultSet
:
2228 CommentStr
= Result
[0]
2229 CommentPartList
= CommentStr
.split()
2230 for Part
in CommentPartList
:
2231 if Part
.upper() == 'BUGBUG':
2232 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2233 if Part
.upper() == 'TODO':
2234 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2235 if Part
.startswith('@'):
2236 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2238 if not Part
.replace('@', '').strip():
2240 if Part
.lstrip('@') in ['{', '}']:
2242 if Part
.lstrip('@').isalpha():
2243 if Part
.lstrip('@') not in DoxygenCommandList
:
2244 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2246 Index
= Part
.find('[')
2248 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2249 RealCmd
= Part
[1:Index
]
2250 if RealCmd
not in DoxygenCommandList
:
2251 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2254 def CheckDoxygenTripleForwardSlash(FullFileName
):
2257 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2263 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2265 where BelongsToFile = %d
2267 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2268 if len(ResultSet
) == 0:
2272 for Result
in ResultSet
:
2273 FuncDefSet
.append(Result
)
2276 FileTable
= 'Identifier' + str(FileID
)
2277 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2281 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2282 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2285 for Result
in ResultSet
:
2286 CommentSet
.append(Result
)
2288 print 'Unrecognized chars in comment of file %s', FullFileName
2291 for Result
in CommentSet
:
2292 CommentStr
= Result
[0]
2293 StartLine
= Result
[2]
2294 StartColumn
= Result
[3]
2296 EndColumn
= Result
[5]
2297 if not CommentStr
.startswith('///<'):
2301 for FuncDef
in FuncDefSet
:
2302 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2305 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2308 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2311 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2315 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2318 def CheckFileHeaderDoxygenComments(FullFileName
):
2321 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2326 FileTable
= 'Identifier' + str(FileID
)
2327 SqlStatement
= """ select Value, ID
2329 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2330 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2331 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2332 if len(ResultSet
) == 0:
2333 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No File License header appear at the very beginning of file.', 'File', FileID
)
2336 NoHeaderCommentStartFlag
= True
2337 NoHeaderCommentEndFlag
= True
2338 NoHeaderCommentPeriodFlag
= True
2339 NoCopyrightFlag
= True
2340 NoLicenseFlag
= True
2341 NoRevReferFlag
= True
2343 for Result
in ResultSet
:
2344 FileStartFlag
= False
2346 CommentStr
= Result
[0].strip()
2347 CommentStrListTemp
= CommentStr
.split('\n')
2348 if (len(CommentStrListTemp
) <= 1):
2350 CommentStrListTemp
= CommentStr
.split('\r')
2351 # Skip the content before the file header
2352 for CommentLine
in CommentStrListTemp
:
2353 if CommentLine
.strip().startswith('/** @file'):
2354 FileStartFlag
= True
2355 if FileStartFlag
== True:
2356 CommentStrList
.append(CommentLine
)
2360 if CommentStrList
and CommentStrList
[0].strip().startswith('/** @file'):
2361 NoHeaderCommentStartFlag
= False
2364 if CommentStrList
and CommentStrList
[-1].strip().endswith('**/'):
2365 NoHeaderCommentEndFlag
= False
2369 for CommentLine
in CommentStrList
:
2371 NextLineIndex
= Index
2372 if CommentLine
.startswith('/** @file'):
2374 if CommentLine
.startswith('**/'):
2376 # Check whether C File header Comment content start with two spaces.
2377 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentStartSpacesNum
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2378 if CommentLine
.startswith('/** @file') == False and CommentLine
.startswith('**/') == False and CommentLine
.strip() and CommentLine
.startswith(' ') == False:
2379 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment content should start with two spaces at each line', FileTable
, ID
)
2381 CommentLine
= CommentLine
.strip()
2382 if CommentLine
.startswith('Copyright'):
2383 NoCopyrightFlag
= False
2384 if CommentLine
.find('All rights reserved') == -1:
2385 for Copyright
in EccGlobalData
.gConfig
.Copyright
:
2386 if CommentLine
.find(Copyright
) > -1:
2387 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable
, ID
)
2389 if CommentLine
.endswith('<BR>') == -1:
2390 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'The ""<BR>"" at the end of the Copyright line is required', FileTable
, ID
)
2391 if NextLineIndex
< len(CommentStrList
) and CommentStrList
[NextLineIndex
].strip().startswith('Copyright') == False and CommentStrList
[NextLineIndex
].strip():
2392 NoLicenseFlag
= False
2393 if CommentLine
.startswith('@par Revision Reference:'):
2394 NoRevReferFlag
= False
2396 for RefLine
in CommentStrList
[NextLineIndex
:]:
2397 if RefLine
.strip() and (NextLineIndex
+ 1) < len(CommentStrList
) and CommentStrList
[NextLineIndex
+1].strip() and CommentStrList
[NextLineIndex
+1].strip().startswith('**/') == False:
2399 if RefLine
.strip() == False or RefLine
.strip().startswith('**/'):
2402 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2403 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentReferenceFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2404 if RefListFlag
== True:
2405 if RefLine
.strip() and RefLine
.strip().startswith('**/') == False and RefLine
.startswith(' -') == False:
2406 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable
, ID
)
2408 if NoHeaderCommentStartFlag
:
2409 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, ID
)
2411 if NoHeaderCommentEndFlag
:
2412 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with ""**/""', FileTable
, ID
)
2415 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment missing the ""Copyright""', FileTable
, ID
)
2416 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2417 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentLicenseFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2419 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable
, ID
)
2421 def CheckFuncHeaderDoxygenComments(FullFileName
):
2424 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2429 FileTable
= 'Identifier' + str(FileID
)
2430 SqlStatement
= """ select Value, StartLine, EndLine, ID
2433 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2435 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2438 for Result
in ResultSet
:
2439 CommentSet
.append(Result
)
2441 print 'Unrecognized chars in comment of file %s', FullFileName
2444 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2447 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2448 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2449 for Result
in ResultSet
:
2450 FuncName
= Result
[4]
2451 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2452 if FunctionHeaderComment
:
2453 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2455 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2457 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2458 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2461 SqlStatement
= """ select Value, StartLine, EndLine, ID
2464 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2466 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2469 for Result
in ResultSet
:
2470 CommentSet
.append(Result
)
2472 print 'Unrecognized chars in comment of file %s', FullFileName
2474 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2476 where BelongsToFile = %d
2478 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2479 for Result
in ResultSet
:
2480 FuncName
= Result
[4]
2481 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2482 if FunctionHeaderComment
:
2483 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2485 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2487 ErrorMsgList
.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2488 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), 'Function', Result
[3])
2491 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2493 for Comment
in CommentSet
:
2494 if Comment
[2] == FuncStartLine
- 1:
2498 def GetDoxygenStrFromComment(Str
):
2500 ParamTagList
= Str
.split('@param')
2501 if len(ParamTagList
) > 1:
2503 while i
< len(ParamTagList
):
2504 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2507 Str
= ParamTagList
[0]
2509 RetvalTagList
= ParamTagList
[-1].split('@retval')
2510 if len(RetvalTagList
) > 1:
2511 if len(ParamTagList
) > 1:
2512 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2514 while i
< len(RetvalTagList
):
2515 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2518 ReturnTagList
= RetvalTagList
[-1].split('@return')
2519 if len(ReturnTagList
) > 1:
2520 if len(RetvalTagList
) > 1:
2521 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2522 elif len(ParamTagList
) > 1:
2523 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2525 while i
< len(ReturnTagList
):
2526 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2529 if len(DoxygenStrList
) > 0:
2530 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2532 return DoxygenStrList
2534 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2535 #/** --*/ @retval after @param
2536 if not Str
.startswith('/**'):
2537 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2538 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2539 if not Str
.endswith('**/'):
2540 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2541 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2542 FirstRetvalIndex
= Str
.find('@retval')
2543 LastParamIndex
= Str
.rfind('@param')
2544 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2545 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2546 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2548 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2550 ParamList
= GetParamList(FuncHeader
)
2551 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2552 DescriptionStr
= CommentStr
2553 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2554 if DescriptionStr
.find('.') == -1:
2555 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2556 DoxygenTagNumber
= len(DoxygenStrList
)
2557 ParamNumber
= len(ParamList
)
2558 for Param
in ParamList
:
2559 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2562 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2563 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2564 ParamModifier
= ParamList
[Index
].Modifier
2565 ParamName
= ParamList
[Index
].Name
.strip()
2566 Tag
= DoxygenStrList
[Index
].strip(' ')
2567 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2568 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2569 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, <%s> does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2570 TagPartList
= Tag
.split()
2571 if len(TagPartList
) < 2:
2572 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2573 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2576 LBPos
= Tag
.find('[')
2577 RBPos
= Tag
.find(']')
2578 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2579 if LBPos
> 0 and len(ParamToLBContent
) == 0 and RBPos
> LBPos
:
2581 ModifierPartList
= ParamModifier
.split()
2582 for Part
in ModifierPartList
:
2583 if Part
.strip() == 'IN':
2585 if Part
.strip() == 'OUT':
2592 if Tag
.find('[' + InOutStr
+ ']') == -1:
2593 if InOutStr
!= 'in, out':
2594 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2595 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2597 if Tag
.find('[in,out]') == -1:
2598 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2599 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2602 if Tag
.find(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2603 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2604 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
)
2607 if Index
< ParamNumber
:
2608 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2609 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2610 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2611 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2613 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2614 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2615 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2616 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2618 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2619 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2620 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2622 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
2623 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2624 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need NO doxygen tags in comment ', TableName
, CommentId
)
2625 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2626 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2627 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2629 if __name__
== '__main__':
2631 # EdkLogger.Initialize()
2632 # EdkLogger.SetLevel(EdkLogger.QUIET)
2633 # CollectSourceCodeDataIntoDB(sys.argv[1])
2635 test_file
= sys
.argv
[1]
2636 except IndexError, v
:
2637 print "Usage: %s filename" % sys
.argv
[0]
2639 MsgList
= CheckFuncHeaderDoxygenComments(test_file
)