2 # This file is used to be the c coding style checking of ECC tool
4 # Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 import CodeFragmentCollector
20 from CommonDataClass
import DataClass
22 from Common
import EdkLogger
23 from EccToolError
import *
27 IncludeFileListDict
= {}
28 AllIncludeFileListDict
= {}
29 IncludePathListDict
= {}
32 IgnoredKeywordList
= ['EFI_ERROR']
34 def GetIgnoredDirListPattern():
35 skipList
= list(EccGlobalData
.gConfig
.SkipDirList
) + ['.svn']
36 DirString
= string
.join(skipList
, '|')
37 p
= re
.compile(r
'.*[\\/](?:%s)[\\/]?.*' % DirString
)
40 def GetFuncDeclPattern():
41 p
= re
.compile(r
'(?:EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re
.DOTALL
)
44 def GetArrayPattern():
45 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
48 def GetTypedefFuncPointerPattern():
49 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
53 return EccGlobalData
.gDb
56 return EccGlobalData
.gConfig
58 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
59 Msg
= Msg
.replace('\n', '').replace('\r', '')
60 MsgPartList
= Msg
.split()
62 for Part
in MsgPartList
:
65 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
= Msg
, BelongsToTable
= TableName
, BelongsToItem
= ItemId
)
68 Type
= DataClass
.MODEL_UNKNOWN
69 Str
= Str
.replace('#', '# ')
71 if List
[1] == 'include':
72 Type
= DataClass
.MODEL_IDENTIFIER_INCLUDE
73 elif List
[1] == 'define':
74 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_DEFINE
75 elif List
[1] == 'ifdef':
76 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFDEF
77 elif List
[1] == 'ifndef':
78 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
79 elif List
[1] == 'endif':
80 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
81 elif List
[1] == 'pragma':
82 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_PROGMA
84 Type
= DataClass
.MODEL_UNKNOWN
87 def SuOccurInTypedef (Su
, TdList
):
89 if Su
.StartPos
[0] == Td
.StartPos
[0] and Su
.EndPos
[0] == Td
.EndPos
[0]:
93 def GetIdentifierList():
95 for comment
in FileProfile
.CommentList
:
96 IdComment
= DataClass
.IdentifierClass(-1, '', '', '', comment
.Content
, DataClass
.MODEL_IDENTIFIER_COMMENT
, -1, -1, comment
.StartPos
[0],comment
.StartPos
[1],comment
.EndPos
[0],comment
.EndPos
[1])
97 IdList
.append(IdComment
)
99 for pp
in FileProfile
.PPDirectiveList
:
100 Type
= GetIdType(pp
.Content
)
101 IdPP
= DataClass
.IdentifierClass(-1, '', '', '', pp
.Content
, Type
, -1, -1, pp
.StartPos
[0],pp
.StartPos
[1],pp
.EndPos
[0],pp
.EndPos
[1])
104 for pe
in FileProfile
.PredicateExpressionList
:
105 IdPE
= DataClass
.IdentifierClass(-1, '', '', '', pe
.Content
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
, -1, -1, pe
.StartPos
[0],pe
.StartPos
[1],pe
.EndPos
[0],pe
.EndPos
[1])
108 FuncDeclPattern
= GetFuncDeclPattern()
109 ArrayPattern
= GetArrayPattern()
110 for var
in FileProfile
.VariableDeclarationList
:
111 DeclText
= var
.Declarator
.lstrip()
112 FuncPointerPattern
= GetTypedefFuncPointerPattern()
113 if FuncPointerPattern
.match(DeclText
):
115 VarNameStartLine
= var
.NameStartPos
[0]
116 VarNameStartColumn
= var
.NameStartPos
[1]
117 FirstChar
= DeclText
[0]
118 while not FirstChar
.isalpha() and FirstChar
!= '_':
121 VarNameStartColumn
+= 1
122 DeclText
= DeclText
.lstrip('*')
123 elif FirstChar
== '\r':
124 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
125 VarNameStartLine
+= 1
126 VarNameStartColumn
= 0
127 elif FirstChar
== '\n':
128 DeclText
= DeclText
.lstrip('\n')
129 VarNameStartLine
+= 1
130 VarNameStartColumn
= 0
131 elif FirstChar
== ' ':
132 DeclText
= DeclText
.lstrip(' ')
133 VarNameStartColumn
+= 1
134 elif FirstChar
== '\t':
135 DeclText
= DeclText
.lstrip('\t')
136 VarNameStartColumn
+= 8
138 DeclText
= DeclText
[1:]
139 VarNameStartColumn
+= 1
140 FirstChar
= DeclText
[0]
142 var
.Declarator
= DeclText
143 if FuncDeclPattern
.match(var
.Declarator
):
144 DeclSplitList
= var
.Declarator
.split('(')
145 FuncName
= DeclSplitList
[0].strip()
146 FuncNamePartList
= FuncName
.split()
147 if len(FuncNamePartList
) > 1:
148 FuncName
= FuncNamePartList
[-1].strip()
149 NameStart
= DeclSplitList
[0].rfind(FuncName
)
150 var
.Declarator
= var
.Declarator
[NameStart
:]
152 var
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
155 while Index
< NameStart
:
156 FirstChar
= DeclSplitList
[0][Index
]
157 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
159 VarNameStartColumn
+= 6
162 elif FirstChar
== '\r':
164 VarNameStartLine
+= 1
165 VarNameStartColumn
= 0
166 elif FirstChar
== '\n':
169 VarNameStartLine
+= 1
170 VarNameStartColumn
= 0
171 elif FirstChar
== ' ':
173 VarNameStartColumn
+= 1
174 elif FirstChar
== '\t':
176 VarNameStartColumn
+= 8
179 VarNameStartColumn
+= 1
181 IdVar
= DataClass
.IdentifierClass(-1, var
.Modifier
, '', var
.Declarator
, FuncName
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, -1, -1, var
.StartPos
[0], var
.StartPos
[1], VarNameStartLine
, VarNameStartColumn
)
185 if var
.Declarator
.find('{') == -1:
186 for decl
in var
.Declarator
.split(','):
187 DeclList
= decl
.split('=')
188 Name
= DeclList
[0].strip()
189 if ArrayPattern
.match(Name
):
190 LSBPos
= var
.Declarator
.find('[')
191 var
.Modifier
+= ' ' + Name
[LSBPos
:]
192 Name
= Name
[0:LSBPos
]
194 IdVar
= DataClass
.IdentifierClass(-1, var
.Modifier
, '', Name
, (len(DeclList
) > 1 and [DeclList
[1]]or [''])[0], DataClass
.MODEL_IDENTIFIER_VARIABLE
, -1, -1, var
.StartPos
[0],var
.StartPos
[1], VarNameStartLine
, VarNameStartColumn
)
197 DeclList
= var
.Declarator
.split('=')
198 Name
= DeclList
[0].strip()
199 if ArrayPattern
.match(Name
):
200 LSBPos
= var
.Declarator
.find('[')
201 var
.Modifier
+= ' ' + Name
[LSBPos
:]
202 Name
= Name
[0:LSBPos
]
203 IdVar
= DataClass
.IdentifierClass(-1, var
.Modifier
, '', Name
, (len(DeclList
) > 1 and [DeclList
[1]]or [''])[0], DataClass
.MODEL_IDENTIFIER_VARIABLE
, -1, -1, var
.StartPos
[0],var
.StartPos
[1], VarNameStartLine
, VarNameStartColumn
)
206 for enum
in FileProfile
.EnumerationDefinitionList
:
207 LBPos
= enum
.Content
.find('{')
208 RBPos
= enum
.Content
.find('}')
209 Name
= enum
.Content
[4:LBPos
].strip()
210 Value
= enum
.Content
[LBPos
+1:RBPos
]
211 IdEnum
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
, -1, -1, enum
.StartPos
[0],enum
.StartPos
[1],enum
.EndPos
[0],enum
.EndPos
[1])
212 IdList
.append(IdEnum
)
214 for su
in FileProfile
.StructUnionDefinitionList
:
215 if SuOccurInTypedef(su
, FileProfile
.TypedefDefinitionList
):
217 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
219 if su
.Content
.startswith('union'):
220 Type
= DataClass
.MODEL_IDENTIFIER_UNION
222 LBPos
= su
.Content
.find('{')
223 RBPos
= su
.Content
.find('}')
224 if LBPos
== -1 or RBPos
== -1:
225 Name
= su
.Content
[SkipLen
:].strip()
228 Name
= su
.Content
[SkipLen
:LBPos
].strip()
229 Value
= su
.Content
[LBPos
:RBPos
+1]
230 IdPE
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, Type
, -1, -1, su
.StartPos
[0],su
.StartPos
[1],su
.EndPos
[0],su
.EndPos
[1])
233 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
234 for td
in FileProfile
.TypedefDefinitionList
:
238 if TdFuncPointerPattern
.match(td
.ToType
):
239 Modifier
= td
.FromType
240 LBPos
= td
.ToType
.find('(')
241 TmpStr
= td
.ToType
[LBPos
+1:].strip()
242 StarPos
= TmpStr
.find('*')
244 Modifier
+= ' ' + TmpStr
[0:StarPos
]
245 while TmpStr
[StarPos
] == '*':
246 # Modifier += ' ' + '*'
248 TmpStr
= TmpStr
[StarPos
:].strip()
249 RBPos
= TmpStr
.find(')')
250 Name
= TmpStr
[0:RBPos
]
251 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
253 while Name
.startswith('*'):
255 Name
= Name
.lstrip('*').strip()
257 if Name
.find('[') != -1:
258 LBPos
= Name
.find('[')
259 RBPos
= Name
.rfind(']')
260 Value
+= Name
[LBPos
: RBPos
+ 1]
261 Name
= Name
[0 : LBPos
]
263 IdTd
= DataClass
.IdentifierClass(-1, Modifier
, '', Name
, Value
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
, -1, -1, td
.StartPos
[0],td
.StartPos
[1],td
.EndPos
[0],td
.EndPos
[1])
266 for funcCall
in FileProfile
.FunctionCallingList
:
267 IdFC
= DataClass
.IdentifierClass(-1, '', '', funcCall
.FuncName
, funcCall
.ParamList
, DataClass
.MODEL_IDENTIFIER_FUNCTION_CALLING
, -1, -1, funcCall
.StartPos
[0],funcCall
.StartPos
[1],funcCall
.EndPos
[0],funcCall
.EndPos
[1])
271 def StripNonAlnumChars(Str
):
278 def GetParamList(FuncDeclarator
, FuncNameLine
= 0, FuncNameOffset
= 0):
279 FuncDeclarator
= StripComments(FuncDeclarator
)
281 #DeclSplitList = FuncDeclarator.split('(')
282 LBPos
= FuncDeclarator
.find('(')
283 #if len(DeclSplitList) < 2:
286 #FuncName = DeclSplitList[0]
287 FuncName
= FuncDeclarator
[0:LBPos
]
288 #ParamStr = DeclSplitList[1].rstrip(')')
289 ParamStr
= FuncDeclarator
[LBPos
+ 1:].rstrip(')')
292 TailChar
= FuncName
[-1]
293 while not TailChar
.isalpha() and TailChar
!= '_':
296 FuncName
= FuncName
.rstrip('\r\n').rstrip('\n')
299 elif TailChar
== '\r':
300 FuncName
= FuncName
.rstrip('\r')
303 elif TailChar
== ' ':
304 FuncName
= FuncName
.rstrip(' ')
306 elif TailChar
== '\t':
307 FuncName
= FuncName
.rstrip('\t')
310 FuncName
= FuncName
[:-1]
311 TailChar
= FuncName
[-1]
313 OffsetSkipped
+= 1 #skip '('
315 for p
in ParamStr
.split(','):
319 ParamName
= ListP
[-1]
320 DeclText
= ParamName
.strip()
321 RightSpacePos
= p
.rfind(ParamName
)
322 ParamModifier
= p
[0:RightSpacePos
]
323 if ParamName
== 'OPTIONAL':
324 if ParamModifier
== '':
325 ParamModifier
+= ' ' + 'OPTIONAL'
328 ParamName
= ListP
[-2]
329 DeclText
= ParamName
.strip()
330 RightSpacePos
= p
.rfind(ParamName
)
331 ParamModifier
= p
[0:RightSpacePos
]
332 ParamModifier
+= 'OPTIONAL'
333 while DeclText
.startswith('*'):
334 ParamModifier
+= ' ' + '*'
335 DeclText
= DeclText
.lstrip('*').strip()
337 # ignore array length if exists.
338 LBIndex
= ParamName
.find('[')
340 ParamName
= ParamName
[0:LBIndex
]
342 Start
= RightSpacePos
348 if FirstChar
== '\r':
352 elif FirstChar
== '\n':
357 elif FirstChar
== ' ':
360 elif FirstChar
== '\t':
368 ParamBeginLine
= FuncNameLine
+ LineSkipped
369 ParamBeginOffset
= FuncNameOffset
+ OffsetSkipped
371 Index
= Start
+ len(ParamName
)
373 while Index
< len(p
):
376 if FirstChar
== '\r':
380 elif FirstChar
== '\n':
385 elif FirstChar
== ' ':
388 elif FirstChar
== '\t':
396 ParamEndLine
= FuncNameLine
+ LineSkipped
397 ParamEndOffset
= FuncNameOffset
+ OffsetSkipped
398 if ParamName
!= '...':
399 ParamName
= StripNonAlnumChars(ParamName
)
400 IdParam
= DataClass
.IdentifierClass(-1, ParamModifier
, '', ParamName
, '', DataClass
.MODEL_IDENTIFIER_PARAMETER
, -1, -1, ParamBeginLine
, ParamBeginOffset
, ParamEndLine
, ParamEndOffset
)
401 ParamIdList
.append(IdParam
)
403 OffsetSkipped
+= 1 #skip ','
407 def GetFunctionList():
409 for FuncDef
in FileProfile
.FunctionDefinitionList
:
411 DeclText
= FuncDef
.Declarator
.lstrip()
412 FuncNameStartLine
= FuncDef
.NamePos
[0]
413 FuncNameStartColumn
= FuncDef
.NamePos
[1]
414 FirstChar
= DeclText
[0]
415 while not FirstChar
.isalpha() and FirstChar
!= '_':
417 FuncDef
.Modifier
+= '*'
418 FuncNameStartColumn
+= 1
419 DeclText
= DeclText
.lstrip('*')
420 elif FirstChar
== '\r':
421 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
422 FuncNameStartLine
+= 1
423 FuncNameStartColumn
= 0
424 elif FirstChar
== '\n':
425 DeclText
= DeclText
.lstrip('\n')
426 FuncNameStartLine
+= 1
427 FuncNameStartColumn
= 0
428 elif FirstChar
== ' ':
429 DeclText
= DeclText
.lstrip(' ')
430 FuncNameStartColumn
+= 1
431 elif FirstChar
== '\t':
432 DeclText
= DeclText
.lstrip('\t')
433 FuncNameStartColumn
+= 8
435 DeclText
= DeclText
[1:]
436 FuncNameStartColumn
+= 1
437 FirstChar
= DeclText
[0]
439 FuncDef
.Declarator
= DeclText
440 DeclSplitList
= FuncDef
.Declarator
.split('(')
441 if len(DeclSplitList
) < 2:
444 FuncName
= DeclSplitList
[0]
445 FuncNamePartList
= FuncName
.split()
446 if len(FuncNamePartList
) > 1:
447 FuncName
= FuncNamePartList
[-1]
448 NameStart
= DeclSplitList
[0].rfind(FuncName
)
450 FuncDef
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
453 while Index
< NameStart
:
454 FirstChar
= DeclSplitList
[0][Index
]
455 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
457 FuncNameStartColumn
+= 6
460 elif FirstChar
== '\r':
462 FuncNameStartLine
+= 1
463 FuncNameStartColumn
= 0
464 elif FirstChar
== '\n':
467 FuncNameStartLine
+= 1
468 FuncNameStartColumn
= 0
469 elif FirstChar
== ' ':
471 FuncNameStartColumn
+= 1
472 elif FirstChar
== '\t':
474 FuncNameStartColumn
+= 8
477 FuncNameStartColumn
+= 1
480 FuncObj
= DataClass
.FunctionClass(-1, FuncDef
.Declarator
, FuncDef
.Modifier
, FuncName
.strip(), '', FuncDef
.StartPos
[0],FuncDef
.StartPos
[1],FuncDef
.EndPos
[0],FuncDef
.EndPos
[1], FuncDef
.LeftBracePos
[0], FuncDef
.LeftBracePos
[1], -1, ParamIdList
, [], FuncNameStartLine
, FuncNameStartColumn
)
481 FuncObjList
.append(FuncObj
)
485 def GetFileModificationTimeFromDB(FullFileName
):
488 SqlStatement
= """ select TimeStamp
490 where FullPath = \'%s\'
492 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
493 for Result
in ResultSet
:
494 TimeValue
= Result
[0]
497 def CollectSourceCodeDataIntoDB(RootDir
):
499 tuple = os
.walk(RootDir
)
500 IgnoredPattern
= GetIgnoredDirListPattern()
501 ParseErrorFileList
= []
503 for dirpath
, dirnames
, filenames
in tuple:
504 if IgnoredPattern
.match(dirpath
.upper()):
508 Dirname
= os
.path
.join(dirpath
, Dir
)
509 if os
.path
.islink(Dirname
):
510 Dirname
= os
.path
.realpath(Dirname
)
511 if os
.path
.isdir(Dirname
):
512 # symlinks to directories are treated as directories
514 dirnames
.append(Dirname
)
518 FullName
= os
.path
.normpath(os
.path
.join(dirpath
, f
))
519 model
= DataClass
.MODEL_FILE_OTHERS
520 if os
.path
.splitext(f
)[1] in ('.h', '.c'):
521 EdkLogger
.info("Parsing " + FullName
)
522 model
= f
.endswith('c') and DataClass
.MODEL_FILE_C
or DataClass
.MODEL_FILE_H
523 collector
= CodeFragmentCollector
.CodeFragmentCollector(FullName
)
525 collector
.ParseFile()
527 ParseErrorFileList
.append(FullName
)
528 collector
.CleanFileProfileBuffer()
529 collector
.ParseFileWithClearedPPDirective()
530 # collector.PrintFragments()
531 BaseName
= os
.path
.basename(f
)
532 DirName
= os
.path
.dirname(FullName
)
533 Ext
= os
.path
.splitext(f
)[1].lstrip('.')
534 ModifiedTime
= os
.path
.getmtime(FullName
)
535 FileObj
= DataClass
.FileClass(-1, BaseName
, Ext
, DirName
, FullName
, model
, ModifiedTime
, GetFunctionList(), GetIdentifierList(), [])
536 FileObjList
.append(FileObj
)
538 collector
.CleanFileProfileBuffer()
540 if len(ParseErrorFileList
) > 0:
541 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
544 for file in FileObjList
:
545 if file.ExtName
.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
546 Db
.InsertOneFile(file)
548 Db
.UpdateIdentifierBelongsToFunction()
550 def GetTableID(FullFileName
, ErrorMsgList
= None):
551 if ErrorMsgList
== None:
555 SqlStatement
= """ select ID
557 where FullPath like '%s'
559 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
562 for Result
in ResultSet
:
564 ErrorMsgList
.append('Duplicate file ID found in DB for file %s' % FullFileName
)
568 ErrorMsgList
.append('NO file ID found in DB for file %s' % FullFileName
)
572 def GetIncludeFileList(FullFileName
):
573 if os
.path
.splitext(FullFileName
)[1].upper() not in ('.H'):
575 IFList
= IncludeFileListDict
.get(FullFileName
)
579 FileID
= GetTableID(FullFileName
)
584 FileTable
= 'Identifier' + str(FileID
)
585 SqlStatement
= """ select Value
588 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_INCLUDE
)
589 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
590 IncludeFileListDict
[FullFileName
] = ResultSet
593 def GetFullPathOfIncludeFile(Str
, IncludePathList
):
594 for IncludePath
in IncludePathList
:
595 FullPath
= os
.path
.join(IncludePath
, Str
)
596 FullPath
= os
.path
.normpath(FullPath
)
597 if os
.path
.exists(FullPath
):
601 def GetAllIncludeFiles(FullFileName
):
602 if AllIncludeFileListDict
.get(FullFileName
) != None:
603 return AllIncludeFileListDict
.get(FullFileName
)
605 FileDirName
= os
.path
.dirname(FullFileName
)
606 IncludePathList
= IncludePathListDict
.get(FileDirName
)
607 if IncludePathList
== None:
608 IncludePathList
= MetaDataParser
.GetIncludeListOfFile(EccGlobalData
.gWorkspace
, FullFileName
, GetDB())
609 if FileDirName
not in IncludePathList
:
610 IncludePathList
.insert(0, FileDirName
)
611 IncludePathListDict
[FileDirName
] = IncludePathList
612 IncludeFileQueue
= []
613 for IncludeFile
in GetIncludeFileList(FullFileName
):
614 FileName
= IncludeFile
[0].lstrip('#').strip()
615 FileName
= FileName
.lstrip('include').strip()
616 FileName
= FileName
.strip('\"')
617 FileName
= FileName
.lstrip('<').rstrip('>').strip()
618 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
620 IncludeFileQueue
.append(FullPath
)
623 while i
< len(IncludeFileQueue
):
624 for IncludeFile
in GetIncludeFileList(IncludeFileQueue
[i
]):
625 FileName
= IncludeFile
[0].lstrip('#').strip()
626 FileName
= FileName
.lstrip('include').strip()
627 FileName
= FileName
.strip('\"')
628 FileName
= FileName
.lstrip('<').rstrip('>').strip()
629 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
630 if FullPath
!= None and FullPath
not in IncludeFileQueue
:
631 IncludeFileQueue
.insert(i
+ 1, FullPath
)
634 AllIncludeFileListDict
[FullFileName
] = IncludeFileQueue
635 return IncludeFileQueue
637 def GetPredicateListFromPredicateExpStr(PES
):
644 p
= GetFuncDeclPattern()
645 while i
< len(PES
) - 1:
646 if (PES
[i
].isalnum() or PES
[i
] == '_' or PES
[i
] == '*') and LogicOpPos
> PredicateBegin
:
648 if (PES
[i
] == '&' and PES
[i
+1] == '&') or (PES
[i
] == '|' and PES
[i
+1] == '|'):
650 Exp
= PES
[PredicateBegin
:i
].strip()
651 # Exp may contain '.' or '->'
652 TmpExp
= Exp
.replace('.', '').replace('->', '')
654 PredicateList
.append(Exp
)
656 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
659 if PredicateBegin
> LogicOpPos
:
660 while PredicateBegin
< len(PES
):
661 if PES
[PredicateBegin
].isalnum() or PES
[PredicateBegin
] == '_' or PES
[PredicateBegin
] == '*':
664 Exp
= PES
[PredicateBegin
:len(PES
)].strip()
665 # Exp may contain '.' or '->'
666 TmpExp
= Exp
.replace('.', '').replace('->', '')
668 PredicateList
.append(Exp
)
670 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
673 def GetCNameList(Lvalue
, StarList
= []):
681 while SearchBegin
< len(Lvalue
):
682 while i
< len(Lvalue
):
683 if Lvalue
[i
].isalnum() or Lvalue
[i
] == '_':
689 VarList
.append(Lvalue
[VarStart
:VarEnd
+1])
693 if VarStart
== -1 and Lvalue
[i
] == '*':
700 DotIndex
= Lvalue
[VarEnd
:].find('.')
701 ArrowIndex
= Lvalue
[VarEnd
:].find('->')
702 if DotIndex
== -1 and ArrowIndex
== -1:
704 elif DotIndex
== -1 and ArrowIndex
!= -1:
705 SearchBegin
= VarEnd
+ ArrowIndex
706 elif ArrowIndex
== -1 and DotIndex
!= -1:
707 SearchBegin
= VarEnd
+ DotIndex
709 SearchBegin
= VarEnd
+ ((DotIndex
< ArrowIndex
) and DotIndex
or ArrowIndex
)
717 def SplitPredicateByOp(Str
, Op
, IsFuncCalling
= False):
726 while Index
< len(Str
):
727 while not LBFound
and Str
[Index
] != '_' and not Str
[Index
].isalnum():
730 while not LBFound
and (Str
[Index
].isalnum() or Str
[Index
] == '_'):
732 # maybe type-cast at the begining, skip it.
733 RemainingStr
= Str
[Index
:].lstrip()
734 if RemainingStr
.startswith(')') and not LBFound
:
738 if RemainingStr
.startswith('(') and not LBFound
:
741 if Str
[Index
] == '(':
742 UnmatchedLBCount
+= 1
746 if Str
[Index
] == ')':
747 UnmatchedLBCount
-= 1
749 if UnmatchedLBCount
== 0:
755 if UnmatchedLBCount
> 0:
758 IndexInRemainingStr
= Str
[Index
:].find(Op
)
759 if IndexInRemainingStr
== -1:
762 Name
= Str
[0:Index
+ IndexInRemainingStr
].strip()
763 Value
= Str
[Index
+IndexInRemainingStr
+len(Op
):].strip().strip(')')
766 TmpStr
= Str
.rstrip(';').rstrip(')')
768 Index
= TmpStr
.rfind(Op
)
772 if Str
[Index
- 1].isalnum() or Str
[Index
- 1].isspace() or Str
[Index
- 1] == ')':
773 Name
= Str
[0:Index
].strip()
774 Value
= Str
[Index
+ len(Op
):].strip()
777 TmpStr
= Str
[0:Index
- 1]
779 def SplitPredicateStr(Str
):
781 Str
= Str
.lstrip('(')
782 IsFuncCalling
= False
783 p
= GetFuncDeclPattern()
784 TmpStr
= Str
.replace('.', '').replace('->', '')
788 PredPartList
= SplitPredicateByOp(Str
, '==', IsFuncCalling
)
789 if len(PredPartList
) > 1:
790 return [PredPartList
, '==']
792 PredPartList
= SplitPredicateByOp(Str
, '!=', IsFuncCalling
)
793 if len(PredPartList
) > 1:
794 return [PredPartList
, '!=']
796 PredPartList
= SplitPredicateByOp(Str
, '>=', IsFuncCalling
)
797 if len(PredPartList
) > 1:
798 return [PredPartList
, '>=']
800 PredPartList
= SplitPredicateByOp(Str
, '<=', IsFuncCalling
)
801 if len(PredPartList
) > 1:
802 return [PredPartList
, '<=']
804 PredPartList
= SplitPredicateByOp(Str
, '>', IsFuncCalling
)
805 if len(PredPartList
) > 1:
806 return [PredPartList
, '>']
808 PredPartList
= SplitPredicateByOp(Str
, '<', IsFuncCalling
)
809 if len(PredPartList
) > 1:
810 return [PredPartList
, '<']
812 return [[Str
, None], None]
814 def GetFuncContainsPE(ExpLine
, ResultSet
):
815 for Result
in ResultSet
:
816 if Result
[0] < ExpLine
and Result
[1] > ExpLine
:
820 def PatternInModifier(Modifier
, SubStr
):
821 PartList
= Modifier
.split()
822 for Part
in PartList
:
827 def GetDataTypeFromModifier(ModifierStr
):
828 MList
= ModifierStr
.split()
830 if M
in EccGlobalData
.gConfig
.ModifierList
:
833 if M
.startswith('['):
838 ReturnType
+= M
+ ' '
840 ReturnType
= ReturnType
.strip()
841 if len(ReturnType
) == 0:
845 def DiffModifier(Str1
, Str2
):
846 PartList1
= Str1
.split()
847 PartList2
= Str2
.split()
848 if PartList1
== PartList2
:
853 def GetTypedefDict(FullFileName
):
855 Dict
= ComplexTypeDict
.get(FullFileName
)
859 FileID
= GetTableID(FullFileName
)
860 FileTable
= 'Identifier' + str(FileID
)
862 SqlStatement
= """ select Modifier, Name, Value, ID
865 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
866 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
869 for Result
in ResultSet
:
870 if len(Result
[0]) == 0:
871 Dict
[Result
[1]] = Result
[2]
873 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
874 for F
in IncludeFileList
:
875 FileID
= GetTableID(F
)
879 FileTable
= 'Identifier' + str(FileID
)
880 SqlStatement
= """ select Modifier, Name, Value, ID
883 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
884 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
886 for Result
in ResultSet
:
887 if not Result
[2].startswith('FP ('):
888 Dict
[Result
[1]] = Result
[2]
890 if len(Result
[0]) == 0:
891 Dict
[Result
[1]] = 'VOID'
893 Dict
[Result
[1]] = GetDataTypeFromModifier(Result
[0])
895 ComplexTypeDict
[FullFileName
] = Dict
898 def GetSUDict(FullFileName
):
900 Dict
= SUDict
.get(FullFileName
)
904 FileID
= GetTableID(FullFileName
)
905 FileTable
= 'Identifier' + str(FileID
)
907 SqlStatement
= """ select Name, Value, ID
909 where Model = %d or Model = %d
910 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
911 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
914 for Result
in ResultSet
:
915 if len(Result
[1]) > 0:
916 Dict
[Result
[0]] = Result
[1]
918 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
919 for F
in IncludeFileList
:
920 FileID
= GetTableID(F
)
924 FileTable
= 'Identifier' + str(FileID
)
925 SqlStatement
= """ select Name, Value, ID
927 where Model = %d or Model = %d
928 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
929 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
931 for Result
in ResultSet
:
932 if len(Result
[1]) > 0:
933 Dict
[Result
[0]] = Result
[1]
935 SUDict
[FullFileName
] = Dict
938 def StripComments(Str
):
940 ListFromStr
= list(Str
)
943 DoubleSlashComment
= False
945 while Index
< len(ListFromStr
):
946 # meet new line, then no longer in a comment for //
947 if ListFromStr
[Index
] == '\n':
948 if InComment
and DoubleSlashComment
:
950 DoubleSlashComment
= False
952 # check for */ comment end
953 elif InComment
and not DoubleSlashComment
and ListFromStr
[Index
] == '*' and ListFromStr
[Index
+1] == '/':
954 ListFromStr
[Index
] = ' '
956 ListFromStr
[Index
] = ' '
959 # set comments to spaces
961 ListFromStr
[Index
] = ' '
963 # check for // comment
964 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+1] == '/' and ListFromStr
[Index
+2] != '\n':
966 DoubleSlashComment
= True
968 # check for /* comment start
969 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+1] == '*':
970 ListFromStr
[Index
] = ' '
972 ListFromStr
[Index
] = ' '
978 # restore from List to String
979 Str
= "".join(ListFromStr
)
980 Str
= Str
.rstrip(' ')
984 def GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
):
985 Value
= TypedefDict
.get(Type
)
987 Value
= SUDict
.get(Type
)
991 LBPos
= Value
.find('{')
993 FTList
= Value
.split()
995 if FT
not in ('struct', 'union'):
996 Value
= TypedefDict
.get(FT
)
998 Value
= SUDict
.get(FT
)
1004 LBPos
= Value
.find('{')
1006 # RBPos = Value.find('}')
1007 Fields
= Value
[LBPos
+ 1:]
1008 Fields
= StripComments(Fields
)
1009 FieldsList
= Fields
.split(';')
1010 for Field
in FieldsList
:
1011 Field
= Field
.strip()
1012 Index
= Field
.rfind(FieldName
)
1015 if not Field
[Index
- 1].isalnum():
1016 if Index
+ len(FieldName
) == len(Field
):
1017 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1020 # For the condition that the field in struct is an array with [] sufixes...
1021 if not Field
[Index
+ len(FieldName
)].isalnum():
1022 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1027 def GetRealType(Type
, TypedefDict
, TargetType
= None):
1028 if TargetType
!= None and Type
== TargetType
:
1030 while TypedefDict
.get(Type
):
1031 Type
= TypedefDict
.get(Type
)
1032 if TargetType
!= None and Type
== TargetType
:
1036 def GetTypeInfo(RefList
, Modifier
, FullFileName
, TargetType
= None):
1037 TypedefDict
= GetTypedefDict(FullFileName
)
1038 SUDict
= GetSUDict(FullFileName
)
1039 Type
= GetDataTypeFromModifier(Modifier
).replace('*', '').strip()
1041 Type
= Type
.split()[-1]
1043 while Index
< len(RefList
):
1044 FieldName
= RefList
[Index
]
1045 FromType
= GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
)
1046 if FromType
== None:
1048 # we want to determine the exact type.
1049 if TargetType
!= None:
1050 Type
= FromType
.split()[0]
1051 # we only want to check if it is a pointer
1054 if Type
.find('*') != -1 and Index
== len(RefList
)-1:
1056 Type
= FromType
.split()[0]
1060 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1064 def GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
= False, TargetType
= None, StarList
= None):
1066 PredVar
= PredVarList
[0]
1067 FileID
= GetTableID(FullFileName
)
1070 FileTable
= 'Identifier' + str(FileID
)
1071 # search variable in include files
1073 # it is a function call, search function declarations and definitions
1075 SqlStatement
= """ select Modifier, ID
1077 where Model = %d and Value = \'%s\'
1078 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1079 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1081 for Result
in ResultSet
:
1082 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1083 TypedefDict
= GetTypedefDict(FullFileName
)
1084 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1087 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1088 for F
in IncludeFileList
:
1089 FileID
= GetTableID(F
)
1093 FileTable
= 'Identifier' + str(FileID
)
1094 SqlStatement
= """ select Modifier, ID
1096 where Model = %d and Value = \'%s\'
1097 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1098 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1100 for Result
in ResultSet
:
1101 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1102 TypedefDict
= GetTypedefDict(FullFileName
)
1103 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1106 FileID
= GetTableID(FullFileName
)
1107 SqlStatement
= """ select Modifier, ID
1109 where BelongsToFile = %d and Name = \'%s\'
1110 """ % (FileID
, PredVar
)
1111 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1113 for Result
in ResultSet
:
1114 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1115 TypedefDict
= GetTypedefDict(FullFileName
)
1116 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1119 for F
in IncludeFileList
:
1120 FileID
= GetTableID(F
)
1124 FileTable
= 'Identifier' + str(FileID
)
1125 SqlStatement
= """ select Modifier, ID
1127 where BelongsToFile = %d and Name = \'%s\'
1128 """ % (FileID
, PredVar
)
1129 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1131 for Result
in ResultSet
:
1132 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1133 TypedefDict
= GetTypedefDict(FullFileName
)
1134 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1139 # really variable, search local variable first
1140 SqlStatement
= """ select Modifier, ID
1142 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1143 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
, FuncRecord
[0], FuncRecord
[1])
1144 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1146 for Result
in ResultSet
:
1147 if len(PredVarList
) > 1:
1148 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1151 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1152 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1154 if len(TypeList
) > 1 and StarList
!= None:
1155 for Star
in StarList
:
1157 Type
= Type
.rstrip(Star
)
1158 # Get real type after de-reference pointers.
1159 if len(Type
.strip()) == 0:
1161 TypedefDict
= GetTypedefDict(FullFileName
)
1162 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1165 # search function parameters second
1166 ParamList
= GetParamList(FuncRecord
[2])
1167 for Param
in ParamList
:
1168 if Param
.Name
.strip() == PredVar
:
1169 if len(PredVarList
) > 1:
1170 Type
= GetTypeInfo(PredVarList
[1:], Param
.Modifier
, FullFileName
, TargetType
)
1173 TypeList
= GetDataTypeFromModifier(Param
.Modifier
).split()
1175 if len(TypeList
) > 1 and StarList
!= None:
1176 for Star
in StarList
:
1178 Type
= Type
.rstrip(Star
)
1179 # Get real type after de-reference pointers.
1180 if len(Type
.strip()) == 0:
1182 TypedefDict
= GetTypedefDict(FullFileName
)
1183 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1186 # search global variable next
1187 SqlStatement
= """ select Modifier, ID
1189 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1190 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1191 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1193 for Result
in ResultSet
:
1194 if len(PredVarList
) > 1:
1195 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1198 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1200 if len(TypeList
) > 1 and StarList
!= None:
1201 for Star
in StarList
:
1203 Type
= Type
.rstrip(Star
)
1204 # Get real type after de-reference pointers.
1205 if len(Type
.strip()) == 0:
1207 TypedefDict
= GetTypedefDict(FullFileName
)
1208 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1211 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1212 for F
in IncludeFileList
:
1213 FileID
= GetTableID(F
)
1217 FileTable
= 'Identifier' + str(FileID
)
1218 SqlStatement
= """ select Modifier, ID
1220 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1221 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1222 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1224 for Result
in ResultSet
:
1225 if len(PredVarList
) > 1:
1226 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1229 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1231 if len(TypeList
) > 1 and StarList
!= None:
1232 for Star
in StarList
:
1234 Type
= Type
.rstrip(Star
)
1235 # Get real type after de-reference pointers.
1236 if len(Type
.strip()) == 0:
1238 TypedefDict
= GetTypedefDict(FullFileName
)
1239 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1242 def GetTypeFromArray(Type
, Var
):
1243 Count
= Var
.count('[')
1247 Type
= Type
.rstrip('*')
1252 def CheckFuncLayoutReturnType(FullFileName
):
1255 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1260 FileTable
= 'Identifier' + str(FileID
)
1261 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1264 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1265 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1266 for Result
in ResultSet
:
1267 ReturnType
= GetDataTypeFromModifier(Result
[0])
1268 TypeStart
= ReturnType
.split()[0]
1269 FuncName
= Result
[5]
1270 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1272 Index
= Result
[0].find(TypeStart
)
1273 if Index
!= 0 or Result
[3] != 0:
1274 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1276 if Result
[2] == Result
[4]:
1277 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1279 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1281 where BelongsToFile = %d
1283 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1284 for Result
in ResultSet
:
1285 ReturnType
= GetDataTypeFromModifier(Result
[0])
1286 TypeStart
= ReturnType
.split()[0]
1287 FuncName
= Result
[5]
1288 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1290 Index
= Result
[0].find(ReturnType
)
1291 if Index
!= 0 or Result
[3] != 0:
1292 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1294 if Result
[2] == Result
[4]:
1295 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, 'Function', Result
[1])
1297 def CheckFuncLayoutModifier(FullFileName
):
1300 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1305 FileTable
= 'Identifier' + str(FileID
)
1306 SqlStatement
= """ select Modifier, ID
1309 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1310 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1311 for Result
in ResultSet
:
1312 ReturnType
= GetDataTypeFromModifier(Result
[0])
1313 TypeStart
= ReturnType
.split()[0]
1314 # if len(ReturnType) == 0:
1316 Index
= Result
[0].find(TypeStart
)
1318 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1320 SqlStatement
= """ select Modifier, ID
1322 where BelongsToFile = %d
1324 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1325 for Result
in ResultSet
:
1326 ReturnType
= GetDataTypeFromModifier(Result
[0])
1327 TypeStart
= ReturnType
.split()[0]
1328 # if len(ReturnType) == 0:
1330 Index
= Result
[0].find(TypeStart
)
1332 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1334 def CheckFuncLayoutName(FullFileName
):
1336 # Parameter variable format pattern.
1337 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1338 ParamIgnoreList
= ('VOID', '...')
1339 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1344 FileTable
= 'Identifier' + str(FileID
)
1345 SqlStatement
= """ select Name, ID, EndColumn, Value
1348 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1349 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1350 for Result
in ResultSet
:
1351 FuncName
= Result
[3]
1352 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1355 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1356 ParamList
= GetParamList(Result
[0])
1357 if len(ParamList
) == 0:
1360 for Param
in ParamList
:
1361 if Param
.StartLine
<= StartLine
:
1362 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1363 if Param
.StartLine
- StartLine
> 1:
1364 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1365 if not Pattern
.match(Param
.Name
) and not Param
.Name
in ParamIgnoreList
and not EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Param
.Name
):
1366 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1367 StartLine
= Param
.StartLine
1369 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1370 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1372 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1374 where BelongsToFile = %d
1376 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1377 for Result
in ResultSet
:
1378 FuncName
= Result
[3]
1379 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1382 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1383 ParamList
= GetParamList(Result
[0])
1384 if len(ParamList
) == 0:
1387 for Param
in ParamList
:
1388 if Param
.StartLine
<= StartLine
:
1389 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1390 if Param
.StartLine
- StartLine
> 1:
1391 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1392 if not Pattern
.match(Param
.Name
) and not Param
.Name
in ParamIgnoreList
and not EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Param
.Name
):
1393 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1394 StartLine
= Param
.StartLine
1395 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1396 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1398 def CheckFuncLayoutPrototype(FullFileName
):
1401 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1405 FileTable
= 'Identifier' + str(FileID
)
1407 SqlStatement
= """ select Modifier, Header, Name, ID
1409 where BelongsToFile = %d
1411 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1412 if len(ResultSet
) == 0:
1416 for Result
in ResultSet
:
1417 FuncDefList
.append(Result
)
1419 SqlStatement
= """ select Modifier, Name, ID
1422 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1423 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1425 for Result
in ResultSet
:
1426 FuncDeclList
.append(Result
)
1429 for FuncDef
in FuncDefList
:
1430 FuncName
= FuncDef
[2].strip()
1431 FuncModifier
= FuncDef
[0]
1432 FuncDefHeader
= FuncDef
[1]
1433 for FuncDecl
in FuncDeclList
:
1434 LBPos
= FuncDecl
[1].find('(')
1435 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1436 DeclModifier
= FuncDecl
[0]
1437 if DeclName
== FuncName
:
1438 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1439 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1440 ParamListOfDef
= GetParamList(FuncDefHeader
)
1441 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1442 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1443 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1447 while Index
< len(ParamListOfDef
):
1448 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1449 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, 'Parameter %s has different modifier with prototype in function [%s].' % (ParamListOfDef
[Index
].Name
, FuncName
), 'Function', FuncDef
[3])
1453 UndeclFuncList
.append(FuncDef
)
1455 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1457 for F
in IncludeFileList
:
1458 FileID
= GetTableID(F
, ErrorMsgList
)
1462 FileTable
= 'Identifier' + str(FileID
)
1463 SqlStatement
= """ select Modifier, Name, ID
1466 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1467 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1469 for Result
in ResultSet
:
1470 FuncDeclList
.append(Result
)
1472 for FuncDef
in UndeclFuncList
:
1473 FuncName
= FuncDef
[2].strip()
1474 FuncModifier
= FuncDef
[0]
1475 FuncDefHeader
= FuncDef
[1]
1476 for FuncDecl
in FuncDeclList
:
1477 LBPos
= FuncDecl
[1].find('(')
1478 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1479 DeclModifier
= FuncDecl
[0]
1480 if DeclName
== FuncName
:
1481 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1482 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1483 ParamListOfDef
= GetParamList(FuncDefHeader
)
1484 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1485 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1486 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1490 while Index
< len(ParamListOfDef
):
1491 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1492 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, 'Parameter %s has different modifier with prototype in function [%s].' % (ParamListOfDef
[Index
].Name
, FuncName
), 'Function', FuncDef
[3])
1496 def CheckFuncLayoutBody(FullFileName
):
1499 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1503 FileTable
= 'Identifier' + str(FileID
)
1505 SqlStatement
= """ select BodyStartColumn, EndColumn, ID
1507 where BelongsToFile = %d
1509 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1510 if len(ResultSet
) == 0:
1512 for Result
in ResultSet
:
1514 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'open brace should be at the very beginning of a line.', 'Function', Result
[2])
1516 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'close brace should be at the very beginning of a line.', 'Function', Result
[2])
1518 def CheckFuncLayoutLocalVariable(FullFileName
):
1521 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1526 FileTable
= 'Identifier' + str(FileID
)
1527 SqlStatement
= """ select ID
1529 where BelongsToFile = %d
1531 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1532 if len(ResultSet
) == 0:
1535 for Result
in ResultSet
:
1539 SqlStatement
= """ select Name, Value, ID
1541 where Model = %d and BelongsToFunction = %d
1542 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1543 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1544 if len(ResultSet
) == 0:
1547 for Result
in ResultSet
:
1548 if len(Result
[1]) > 0:
1549 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1551 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1553 # Member variable format pattern.
1554 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1556 LBPos
= Value
.find('{')
1557 RBPos
= Value
.rfind('}')
1558 if LBPos
== -1 or RBPos
== -1:
1561 Fields
= Value
[LBPos
+ 1 : RBPos
]
1562 Fields
= StripComments(Fields
).strip()
1563 NestPos
= Fields
.find ('struct')
1564 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)):
1565 if not Fields
[NestPos
+ len('struct') + 1].isalnum():
1566 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1567 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested struct in [%s].' % (Name
), FileTable
, TdId
)
1569 NestPos
= Fields
.find ('union')
1570 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1571 if not Fields
[NestPos
+ len('union') + 1].isalnum():
1572 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1573 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested union in [%s].' % (Name
), FileTable
, TdId
)
1575 NestPos
= Fields
.find ('enum')
1576 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1577 if not Fields
[NestPos
+ len('enum') + 1].isalnum():
1578 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1579 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested enum in [%s].' % (Name
), FileTable
, TdId
)
1582 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1583 FieldsList
= Fields
.split(',')
1584 # deal with enum is pre-assigned a value by function call ( , , , ...)
1587 RemoveCurrentElement
= False
1588 while Index
< len(FieldsList
):
1589 Field
= FieldsList
[Index
]
1591 if Field
.find('(') != -1:
1593 RemoveCurrentElement
= True
1597 if Field
.find(')') != -1 and QuoteCount
> 0:
1600 if RemoveCurrentElement
:
1601 FieldsList
.remove(Field
)
1603 RemoveCurrentElement
= False
1607 RemoveCurrentElement
= False
1611 FieldsList
= Fields
.split(';')
1613 for Field
in FieldsList
:
1614 Field
= Field
.strip()
1617 # For the condition that the field in struct is an array with [] sufixes...
1618 if Field
[-1] == ']':
1619 LBPos
= Field
.find('[')
1620 Field
= Field
[0:LBPos
]
1621 # For the condition that bit field ": Number"
1622 if Field
.find(':') != -1:
1623 ColonPos
= Field
.find(':')
1624 Field
= Field
[0:ColonPos
]
1626 Field
= Field
.strip()
1629 # Enum could directly assign value to variable
1630 Field
= Field
.split('=')[0].strip()
1631 TokenList
= Field
.split()
1632 # Remove pointers before variable
1633 if not Pattern
.match(TokenList
[-1].lstrip('*')):
1634 ErrMsgList
.append(TokenList
[-1].lstrip('*'))
1638 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1641 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1646 FileTable
= 'Identifier' + str(FileID
)
1647 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1650 """ % (FileTable
, ModelId
)
1651 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1653 for Result
in ResultSet
:
1654 ResultList
.append(Result
)
1656 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1657 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1658 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1659 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1660 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1661 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1662 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1664 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1667 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1668 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1672 # Check member variable name format that from typedefs of ONLY this file.
1674 Name
= Td
[1].strip()
1675 Value
= Td
[2].strip()
1676 if Value
.startswith('enum'):
1677 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1678 elif Value
.startswith('struct'):
1679 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1680 elif Value
.startswith('union'):
1681 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1685 if ValueModelId
!= ModelId
:
1687 # Check member variable format.
1688 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1689 for ErrMsg
in ErrMsgList
:
1690 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+'.'+ErrMsg
):
1692 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+'.'+ErrMsg
), FileTable
, Td
[5])
1694 # First check in current file to see whether struct/union/enum is typedef-ed.
1695 UntypedefedList
= []
1696 for Result
in ResultList
:
1697 # Check member variable format.
1698 Name
= Result
[0].strip()
1699 Value
= Result
[4].strip()
1700 if Value
.startswith('enum'):
1701 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1702 elif Value
.startswith('struct'):
1703 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1704 elif Value
.startswith('union'):
1705 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1709 if ValueModelId
!= ModelId
:
1711 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1712 for ErrMsg
in ErrMsgList
:
1713 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0]+'.'+ErrMsg
):
1715 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0]+'.'+ErrMsg
), FileTable
, Result
[3])
1716 # Check whether it is typedefed.
1719 # skip function pointer
1722 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1724 if not Td
[1].isupper():
1725 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1726 if Result
[0] in Td
[2].split():
1728 if not Td
[1].isupper():
1729 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1734 UntypedefedList
.append(Result
)
1737 if len(UntypedefedList
) == 0:
1740 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1742 for F
in IncludeFileList
:
1743 FileID
= GetTableID(F
, ErrorMsgList
)
1747 IncludeFileTable
= 'Identifier' + str(FileID
)
1748 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1751 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1752 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1753 TdList
.extend(ResultSet
)
1755 for Result
in UntypedefedList
:
1757 # Check whether it is typedefed.
1763 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1765 if not Td
[1].isupper():
1766 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1767 if Result
[0] in Td
[2].split():
1769 if not Td
[1].isupper():
1770 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1775 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1778 def CheckDeclStructTypedef(FullFileName
):
1779 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1781 def CheckDeclEnumTypedef(FullFileName
):
1782 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1784 def CheckDeclUnionTypedef(FullFileName
):
1785 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1787 def CheckDeclArgModifier(FullFileName
):
1790 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1795 FileTable
= 'Identifier' + str(FileID
)
1796 SqlStatement
= """ select Modifier, Name, ID
1799 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1800 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1801 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1802 MAX_MODIFIER_LENGTH
= 100
1803 for Result
in ResultSet
:
1804 for Modifier
in ModifierTuple
:
1805 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1806 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1809 SqlStatement
= """ select Modifier, Name, ID
1812 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1813 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1814 for Result
in ResultSet
:
1815 for Modifier
in ModifierTuple
:
1816 if PatternInModifier(Result
[0], Modifier
):
1817 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1820 SqlStatement
= """ select Modifier, Header, ID
1822 where BelongsToFile = %d
1824 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1825 for Result
in ResultSet
:
1826 for Modifier
in ModifierTuple
:
1827 if PatternInModifier(Result
[0], Modifier
):
1828 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1831 def CheckDeclNoUseCType(FullFileName
):
1834 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1839 FileTable
= 'Identifier' + str(FileID
)
1840 SqlStatement
= """ select Modifier, Name, ID
1843 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1844 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1845 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1846 for Result
in ResultSet
:
1847 for Type
in CTypeTuple
:
1848 if PatternInModifier(Result
[0], Type
):
1849 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Variable type %s' % Type
, FileTable
, Result
[2])
1852 SqlStatement
= """ select Modifier, Name, ID, Value
1855 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1856 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1857 for Result
in ResultSet
:
1858 ParamList
= GetParamList(Result
[1])
1859 FuncName
= Result
[3]
1860 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1862 for Type
in CTypeTuple
:
1863 if PatternInModifier(Result
[0], Type
):
1864 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1866 for Param
in ParamList
:
1867 if PatternInModifier(Param
.Modifier
, Type
):
1868 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1870 SqlStatement
= """ select Modifier, Header, ID, Name
1872 where BelongsToFile = %d
1874 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1875 for Result
in ResultSet
:
1876 ParamList
= GetParamList(Result
[1])
1877 FuncName
= Result
[3]
1878 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1880 for Type
in CTypeTuple
:
1881 if PatternInModifier(Result
[0], Type
):
1882 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1884 for Param
in ParamList
:
1885 if PatternInModifier(Param
.Modifier
, Type
):
1886 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1889 def CheckPointerNullComparison(FullFileName
):
1892 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1896 # cache the found function return type to accelerate later checking in this file.
1897 FuncReturnTypeDict
= {}
1900 FileTable
= 'Identifier' + str(FileID
)
1901 SqlStatement
= """ select Value, StartLine, ID
1904 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1905 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1906 if len(ResultSet
) == 0:
1909 for Result
in ResultSet
:
1910 PSL
.append([Result
[0], Result
[1], Result
[2]])
1912 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1914 where BelongsToFile = %d
1916 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1918 for Result
in ResultSet
:
1919 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1921 p
= GetFuncDeclPattern()
1923 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1924 if FuncRecord
== None:
1927 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1928 PredInfo
= SplitPredicateStr(Exp
)
1929 if PredInfo
[1] == None:
1930 PredVarStr
= PredInfo
[0][0].strip()
1932 SearchInCache
= False
1933 # PredVarStr may contain '.' or '->'
1934 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1936 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1937 SearchInCache
= True
1938 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1939 if TmpStr
.startswith(PredVarStr
):
1942 if PredVarStr
.strip() in IgnoredKeywordList
:
1945 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1946 # No variable found, maybe value first? like (0 == VarName)
1947 if len(PredVarList
) == 0:
1950 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1952 if Type
.find('*') != -1:
1953 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1956 if PredVarStr
in FuncReturnTypeDict
:
1959 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1961 FuncReturnTypeDict
[PredVarStr
] = Type
1964 Type
= GetTypeFromArray(Type
, PredVarStr
)
1965 if Type
.find('*') != -1:
1966 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1968 def CheckNonBooleanValueComparison(FullFileName
):
1971 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1975 # cache the found function return type to accelerate later checking in this file.
1976 FuncReturnTypeDict
= {}
1979 FileTable
= 'Identifier' + str(FileID
)
1980 SqlStatement
= """ select Value, StartLine, ID
1983 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1984 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1985 if len(ResultSet
) == 0:
1988 for Result
in ResultSet
:
1989 PSL
.append([Result
[0], Result
[1], Result
[2]])
1991 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1993 where BelongsToFile = %d
1995 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1997 for Result
in ResultSet
:
1998 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2000 p
= GetFuncDeclPattern()
2002 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2003 if FuncRecord
== None:
2006 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2009 PredInfo
= SplitPredicateStr(Exp
)
2010 if PredInfo
[1] == None:
2011 PredVarStr
= PredInfo
[0][0].strip()
2013 SearchInCache
= False
2014 # PredVarStr may contain '.' or '->'
2015 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2017 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2018 SearchInCache
= True
2019 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2020 if TmpStr
.startswith(PredVarStr
):
2023 if PredVarStr
.strip() in IgnoredKeywordList
:
2026 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2027 # No variable found, maybe value first? like (0 == VarName)
2028 if len(PredVarList
) == 0:
2032 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2034 if Type
.find('BOOLEAN') == -1:
2035 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2038 if PredVarStr
in FuncReturnTypeDict
:
2041 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2043 FuncReturnTypeDict
[PredVarStr
] = Type
2046 if Type
.find('BOOLEAN') == -1:
2047 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2050 def CheckBooleanValueComparison(FullFileName
):
2053 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2057 # cache the found function return type to accelerate later checking in this file.
2058 FuncReturnTypeDict
= {}
2061 FileTable
= 'Identifier' + str(FileID
)
2062 SqlStatement
= """ select Value, StartLine, ID
2065 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2066 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2067 if len(ResultSet
) == 0:
2070 for Result
in ResultSet
:
2071 PSL
.append([Result
[0], Result
[1], Result
[2]])
2073 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2075 where BelongsToFile = %d
2077 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2079 for Result
in ResultSet
:
2080 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2082 p
= GetFuncDeclPattern()
2084 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2085 if FuncRecord
== None:
2088 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2089 PredInfo
= SplitPredicateStr(Exp
)
2090 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2091 PredVarStr
= PredInfo
[0][0].strip()
2093 SearchInCache
= False
2094 # PredVarStr may contain '.' or '->'
2095 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2097 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2098 SearchInCache
= True
2099 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2100 if TmpStr
.startswith(PredVarStr
):
2103 if PredVarStr
.strip() in IgnoredKeywordList
:
2106 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2107 # No variable found, maybe value first? like (0 == VarName)
2108 if len(PredVarList
) == 0:
2112 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2114 if Type
.find('BOOLEAN') != -1:
2115 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2118 if PredVarStr
in FuncReturnTypeDict
:
2121 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2123 FuncReturnTypeDict
[PredVarStr
] = Type
2126 if Type
.find('BOOLEAN') != -1:
2127 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2130 def CheckHeaderFileData(FullFileName
):
2133 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2138 FileTable
= 'Identifier' + str(FileID
)
2139 SqlStatement
= """ select ID, Modifier
2142 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2143 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2144 for Result
in ResultSet
:
2145 if not Result
[1].startswith('extern'):
2146 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2148 SqlStatement
= """ select ID
2150 where BelongsToFile = %d
2152 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2153 for Result
in ResultSet
:
2154 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2158 def CheckHeaderFileIfndef(FullFileName
):
2161 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2166 FileTable
= 'Identifier' + str(FileID
)
2167 SqlStatement
= """ select Value, StartLine
2169 where Model = %d order by StartLine
2170 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2171 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2172 if len(ResultSet
) == 0:
2173 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2175 for Result
in ResultSet
:
2176 SqlStatement
= """ select Value, EndLine
2179 """ % (FileTable
, Result
[1])
2180 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2181 for Result
in ResultSet
:
2182 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2183 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2
, '', 'File', FileID
)
2186 SqlStatement
= """ select Value
2188 where StartLine > (select max(EndLine) from %s where Model = %d)
2189 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2190 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2191 for Result
in ResultSet
:
2192 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2193 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2196 def CheckDoxygenCommand(FullFileName
):
2199 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2204 FileTable
= 'Identifier' + str(FileID
)
2205 SqlStatement
= """ select Value, ID
2207 where Model = %d or Model = %d
2208 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2209 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2210 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval', 'return', 'sa', 'since', 'test', 'note', 'par']
2211 for Result
in ResultSet
:
2212 CommentStr
= Result
[0]
2213 CommentPartList
= CommentStr
.split()
2214 for Part
in CommentPartList
:
2215 if Part
.upper() == 'BUGBUG':
2216 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2217 if Part
.upper() == 'TODO':
2218 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2219 if Part
.startswith('@'):
2220 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2222 if Part
.lstrip('@').isalpha():
2223 if Part
.lstrip('@') not in DoxygenCommandList
:
2224 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2226 Index
= Part
.find('[')
2228 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2229 RealCmd
= Part
[1:Index
]
2230 if RealCmd
not in DoxygenCommandList
:
2231 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2234 def CheckDoxygenTripleForwardSlash(FullFileName
):
2237 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2243 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2245 where BelongsToFile = %d
2247 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2248 if len(ResultSet
) == 0:
2252 for Result
in ResultSet
:
2253 FuncDefSet
.append(Result
)
2256 FileTable
= 'Identifier' + str(FileID
)
2257 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2261 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2262 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2265 for Result
in ResultSet
:
2266 CommentSet
.append(Result
)
2268 print 'Unrecognized chars in comment of file %s', FullFileName
2271 for Result
in CommentSet
:
2272 CommentStr
= Result
[0]
2273 StartLine
= Result
[2]
2274 StartColumn
= Result
[3]
2276 EndColumn
= Result
[5]
2277 if not CommentStr
.startswith('///<'):
2281 for FuncDef
in FuncDefSet
:
2282 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2285 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2288 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2291 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2295 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2298 def CheckFileHeaderDoxygenComments(FullFileName
):
2301 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2306 FileTable
= 'Identifier' + str(FileID
)
2307 SqlStatement
= """ select Value, ID
2309 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2310 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2311 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2312 if len(ResultSet
) == 0:
2313 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No Comment appear at the very beginning of file.', 'File', FileID
)
2316 IsFoundError1
= True
2317 IsFoundError2
= True
2318 IsFoundError3
= True
2319 for Result
in ResultSet
:
2320 CommentStr
= Result
[0].strip()
2322 if CommentStr
.startswith('/** @file'):
2323 IsFoundError1
= False
2324 if CommentStr
.endswith('**/'):
2325 IsFoundError2
= False
2326 if CommentStr
.find('.') != -1:
2327 IsFoundError3
= False
2330 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, ID
)
2332 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with ""**/""', FileTable
, ID
)
2334 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period "".""', FileTable
, ID
)
2336 def CheckFuncHeaderDoxygenComments(FullFileName
):
2339 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2344 FileTable
= 'Identifier' + str(FileID
)
2345 SqlStatement
= """ select Value, StartLine, EndLine, ID
2348 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2350 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2353 for Result
in ResultSet
:
2354 CommentSet
.append(Result
)
2356 print 'Unrecognized chars in comment of file %s', FullFileName
2359 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2362 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2363 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2364 for Result
in ResultSet
:
2365 FuncName
= Result
[4]
2366 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2367 if FunctionHeaderComment
:
2368 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2370 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2372 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2373 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2376 SqlStatement
= """ select Value, StartLine, EndLine, ID
2379 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2381 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2384 for Result
in ResultSet
:
2385 CommentSet
.append(Result
)
2387 print 'Unrecognized chars in comment of file %s', FullFileName
2389 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2391 where BelongsToFile = %d
2393 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2394 for Result
in ResultSet
:
2395 FuncName
= Result
[4]
2396 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2397 if FunctionHeaderComment
:
2398 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2400 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2402 ErrorMsgList
.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2403 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), 'Function', Result
[3])
2406 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2408 for Comment
in CommentSet
:
2409 if Comment
[2] == FuncStartLine
- 1:
2413 def GetDoxygenStrFromComment(Str
):
2415 ParamTagList
= Str
.split('@param')
2416 if len(ParamTagList
) > 1:
2418 while i
< len(ParamTagList
):
2419 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2422 Str
= ParamTagList
[0]
2424 RetvalTagList
= ParamTagList
[-1].split('@retval')
2425 if len(RetvalTagList
) > 1:
2426 if len(ParamTagList
) > 1:
2427 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2429 while i
< len(RetvalTagList
):
2430 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2433 ReturnTagList
= RetvalTagList
[-1].split('@return')
2434 if len(ReturnTagList
) > 1:
2435 if len(RetvalTagList
) > 1:
2436 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2437 elif len(ParamTagList
) > 1:
2438 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2440 while i
< len(ReturnTagList
):
2441 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2444 if len(DoxygenStrList
) > 0:
2445 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2447 return DoxygenStrList
2449 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
= ''):
2450 #/** --*/ @retval after @param
2451 if not Str
.startswith('/**'):
2452 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2453 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2454 if not Str
.endswith('**/'):
2455 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2456 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2457 FirstRetvalIndex
= Str
.find('@retval')
2458 LastParamIndex
= Str
.rfind('@param')
2459 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2460 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2461 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2463 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
= ''):
2465 ParamList
= GetParamList(FuncHeader
)
2466 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2467 DescriptionStr
= CommentStr
2468 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2469 if DescriptionStr
.find('.') == -1:
2470 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2471 DoxygenTagNumber
= len(DoxygenStrList
)
2472 ParamNumber
= len(ParamList
)
2473 for Param
in ParamList
:
2474 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2477 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2478 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2479 ParamModifier
= ParamList
[Index
].Modifier
2480 ParamName
= ParamList
[Index
].Name
.strip()
2481 Tag
= DoxygenStrList
[Index
].strip(' ')
2482 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2483 ErrorMsgList
.append('Line %d : in Comment, \"%s\" does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2484 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, \"%s\" does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2485 TagPartList
= Tag
.split()
2486 if len(TagPartList
) < 2:
2487 ErrorMsgList
.append('Line %d : in Comment, \"%s\" does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2488 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, \"%s\" does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2491 LBPos
= Tag
.find('[')
2492 RBPos
= Tag
.find(']')
2493 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2494 if LBPos
> 0 and len(ParamToLBContent
)==0 and RBPos
> LBPos
:
2496 ModifierPartList
= ParamModifier
.split()
2497 for Part
in ModifierPartList
:
2498 if Part
.strip() == 'IN':
2500 if Part
.strip() == 'OUT':
2507 if Tag
.find('['+InOutStr
+']') == -1:
2508 ErrorMsgList
.append('Line %d : in Comment, \"%s\" does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' +TagPartList
[1]).replace('\n', '').replace('\r', ''), '['+InOutStr
+']'))
2509 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, \"%s\" does NOT have %s ' % ((TagPartList
[0] + ' ' +TagPartList
[1]).replace('\n', '').replace('\r', ''), '['+InOutStr
+']'), TableName
, CommentId
)
2510 if Tag
.find(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2511 ErrorMsgList
.append('Line %d : in Comment, \"%s\" does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' +TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2512 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
)
2515 if Index
< ParamNumber
:
2516 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2517 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2518 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2519 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2521 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2522 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2523 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2524 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2526 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2527 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2528 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2530 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
2531 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2532 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need NO doxygen tags in comment ', TableName
, CommentId
)
2533 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2534 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2535 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2537 if __name__
== '__main__':
2539 # EdkLogger.Initialize()
2540 # EdkLogger.SetLevel(EdkLogger.QUIET)
2541 # CollectSourceCodeDataIntoDB(sys.argv[1])
2542 MsgList
= CheckFuncHeaderDoxygenComments('C:\\Combo\\R9\\LakeportX64Dev\\FlashDevicePkg\\Library\\SpiFlashChipM25P64\\SpiFlashChipM25P64.c')