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
)
517 FullName
= os
.path
.normpath(os
.path
.join(dirpath
, f
))
518 if os
.path
.splitext(f
)[1] in ('.h', '.c'):
519 EdkLogger
.info("Parsing " + FullName
)
520 model
= f
.endswith('c') and DataClass
.MODEL_FILE_C
or DataClass
.MODEL_FILE_H
521 collector
= CodeFragmentCollector
.CodeFragmentCollector(FullName
)
523 collector
.ParseFile()
525 ParseErrorFileList
.append(FullName
)
526 collector
.CleanFileProfileBuffer()
527 collector
.ParseFileWithClearedPPDirective()
528 # collector.PrintFragments()
529 BaseName
= os
.path
.basename(f
)
530 DirName
= os
.path
.dirname(FullName
)
531 Ext
= os
.path
.splitext(f
)[1].lstrip('.')
532 ModifiedTime
= os
.path
.getmtime(FullName
)
533 FileObj
= DataClass
.FileClass(-1, BaseName
, Ext
, DirName
, FullName
, model
, ModifiedTime
, GetFunctionList(), GetIdentifierList(), [])
534 FileObjList
.append(FileObj
)
535 collector
.CleanFileProfileBuffer()
537 if len(ParseErrorFileList
) > 0:
538 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
541 for file in FileObjList
:
542 Db
.InsertOneFile(file)
544 Db
.UpdateIdentifierBelongsToFunction()
546 def GetTableID(FullFileName
, ErrorMsgList
= None):
547 if ErrorMsgList
== None:
551 SqlStatement
= """ select ID
553 where FullPath like '%s'
556 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
559 for Result
in ResultSet
:
561 ErrorMsgList
.append('Duplicate file ID found in DB for file %s' % FullFileName
)
565 ErrorMsgList
.append('NO file ID found in DB for file %s' % FullFileName
)
569 def GetIncludeFileList(FullFileName
):
570 IFList
= IncludeFileListDict
.get(FullFileName
)
574 FileID
= GetTableID(FullFileName
)
579 FileTable
= 'Identifier' + str(FileID
)
580 SqlStatement
= """ select Value
583 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_INCLUDE
)
584 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
585 IncludeFileListDict
[FullFileName
] = ResultSet
588 def GetFullPathOfIncludeFile(Str
, IncludePathList
):
589 for IncludePath
in IncludePathList
:
590 FullPath
= os
.path
.join(IncludePath
, Str
)
591 FullPath
= os
.path
.normpath(FullPath
)
592 if os
.path
.exists(FullPath
):
596 def GetAllIncludeFiles(FullFileName
):
597 if AllIncludeFileListDict
.get(FullFileName
) != None:
598 return AllIncludeFileListDict
.get(FullFileName
)
600 FileDirName
= os
.path
.dirname(FullFileName
)
601 IncludePathList
= IncludePathListDict
.get(FileDirName
)
602 if IncludePathList
== None:
603 IncludePathList
= MetaDataParser
.GetIncludeListOfFile(EccGlobalData
.gWorkspace
, FullFileName
, GetDB())
604 if FileDirName
not in IncludePathList
:
605 IncludePathList
.insert(0, FileDirName
)
606 IncludePathListDict
[FileDirName
] = IncludePathList
607 IncludeFileQueue
= []
608 for IncludeFile
in GetIncludeFileList(FullFileName
):
609 FileName
= IncludeFile
[0].lstrip('#').strip()
610 FileName
= FileName
.lstrip('include').strip()
611 FileName
= FileName
.strip('\"')
612 FileName
= FileName
.lstrip('<').rstrip('>').strip()
613 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
615 IncludeFileQueue
.append(FullPath
)
618 while i
< len(IncludeFileQueue
):
619 for IncludeFile
in GetIncludeFileList(IncludeFileQueue
[i
]):
620 FileName
= IncludeFile
[0].lstrip('#').strip()
621 FileName
= FileName
.lstrip('include').strip()
622 FileName
= FileName
.strip('\"')
623 FileName
= FileName
.lstrip('<').rstrip('>').strip()
624 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
625 if FullPath
!= None and FullPath
not in IncludeFileQueue
:
626 IncludeFileQueue
.insert(i
+ 1, FullPath
)
629 AllIncludeFileListDict
[FullFileName
] = IncludeFileQueue
630 return IncludeFileQueue
632 def GetPredicateListFromPredicateExpStr(PES
):
639 p
= GetFuncDeclPattern()
640 while i
< len(PES
) - 1:
641 if (PES
[i
].isalnum() or PES
[i
] == '_' or PES
[i
] == '*') and LogicOpPos
> PredicateBegin
:
643 if (PES
[i
] == '&' and PES
[i
+1] == '&') or (PES
[i
] == '|' and PES
[i
+1] == '|'):
645 Exp
= PES
[PredicateBegin
:i
].strip()
646 # Exp may contain '.' or '->'
647 TmpExp
= Exp
.replace('.', '').replace('->', '')
649 PredicateList
.append(Exp
)
651 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
654 if PredicateBegin
> LogicOpPos
:
655 while PredicateBegin
< len(PES
):
656 if PES
[PredicateBegin
].isalnum() or PES
[PredicateBegin
] == '_' or PES
[PredicateBegin
] == '*':
659 Exp
= PES
[PredicateBegin
:len(PES
)].strip()
660 # Exp may contain '.' or '->'
661 TmpExp
= Exp
.replace('.', '').replace('->', '')
663 PredicateList
.append(Exp
)
665 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
668 def GetCNameList(Lvalue
, StarList
= []):
676 while SearchBegin
< len(Lvalue
):
677 while i
< len(Lvalue
):
678 if Lvalue
[i
].isalnum() or Lvalue
[i
] == '_':
684 VarList
.append(Lvalue
[VarStart
:VarEnd
+1])
688 if VarStart
== -1 and Lvalue
[i
] == '*':
695 DotIndex
= Lvalue
[VarEnd
:].find('.')
696 ArrowIndex
= Lvalue
[VarEnd
:].find('->')
697 if DotIndex
== -1 and ArrowIndex
== -1:
699 elif DotIndex
== -1 and ArrowIndex
!= -1:
700 SearchBegin
= VarEnd
+ ArrowIndex
701 elif ArrowIndex
== -1 and DotIndex
!= -1:
702 SearchBegin
= VarEnd
+ DotIndex
704 SearchBegin
= VarEnd
+ ((DotIndex
< ArrowIndex
) and DotIndex
or ArrowIndex
)
712 def SplitPredicateByOp(Str
, Op
, IsFuncCalling
= False):
721 while Index
< len(Str
):
722 while not LBFound
and Str
[Index
] != '_' and not Str
[Index
].isalnum():
725 while not LBFound
and (Str
[Index
].isalnum() or Str
[Index
] == '_'):
727 # maybe type-cast at the begining, skip it.
728 RemainingStr
= Str
[Index
:].lstrip()
729 if RemainingStr
.startswith(')') and not LBFound
:
733 if RemainingStr
.startswith('(') and not LBFound
:
736 if Str
[Index
] == '(':
737 UnmatchedLBCount
+= 1
741 if Str
[Index
] == ')':
742 UnmatchedLBCount
-= 1
744 if UnmatchedLBCount
== 0:
750 if UnmatchedLBCount
> 0:
753 IndexInRemainingStr
= Str
[Index
:].find(Op
)
754 if IndexInRemainingStr
== -1:
757 Name
= Str
[0:Index
+ IndexInRemainingStr
].strip()
758 Value
= Str
[Index
+IndexInRemainingStr
+len(Op
):].strip().strip(')')
761 TmpStr
= Str
.rstrip(';').rstrip(')')
763 Index
= TmpStr
.rfind(Op
)
767 if Str
[Index
- 1].isalnum() or Str
[Index
- 1].isspace() or Str
[Index
- 1] == ')':
768 Name
= Str
[0:Index
].strip()
769 Value
= Str
[Index
+ len(Op
):].strip()
772 TmpStr
= Str
[0:Index
- 1]
774 def SplitPredicateStr(Str
):
776 Str
= Str
.lstrip('(')
777 IsFuncCalling
= False
778 p
= GetFuncDeclPattern()
779 TmpStr
= Str
.replace('.', '').replace('->', '')
783 PredPartList
= SplitPredicateByOp(Str
, '==', IsFuncCalling
)
784 if len(PredPartList
) > 1:
785 return [PredPartList
, '==']
787 PredPartList
= SplitPredicateByOp(Str
, '!=', IsFuncCalling
)
788 if len(PredPartList
) > 1:
789 return [PredPartList
, '!=']
791 PredPartList
= SplitPredicateByOp(Str
, '>=', IsFuncCalling
)
792 if len(PredPartList
) > 1:
793 return [PredPartList
, '>=']
795 PredPartList
= SplitPredicateByOp(Str
, '<=', IsFuncCalling
)
796 if len(PredPartList
) > 1:
797 return [PredPartList
, '<=']
799 PredPartList
= SplitPredicateByOp(Str
, '>', IsFuncCalling
)
800 if len(PredPartList
) > 1:
801 return [PredPartList
, '>']
803 PredPartList
= SplitPredicateByOp(Str
, '<', IsFuncCalling
)
804 if len(PredPartList
) > 1:
805 return [PredPartList
, '<']
807 return [[Str
, None], None]
809 def GetFuncContainsPE(ExpLine
, ResultSet
):
810 for Result
in ResultSet
:
811 if Result
[0] < ExpLine
and Result
[1] > ExpLine
:
815 def PatternInModifier(Modifier
, SubStr
):
816 PartList
= Modifier
.split()
817 for Part
in PartList
:
822 def GetDataTypeFromModifier(ModifierStr
):
823 MList
= ModifierStr
.split()
825 if M
in EccGlobalData
.gConfig
.ModifierList
:
828 if M
.startswith('['):
833 ReturnType
+= M
+ ' '
835 ReturnType
= ReturnType
.strip()
836 if len(ReturnType
) == 0:
840 def DiffModifier(Str1
, Str2
):
841 PartList1
= Str1
.split()
842 PartList2
= Str2
.split()
843 if PartList1
== PartList2
:
848 def GetTypedefDict(FullFileName
):
850 Dict
= ComplexTypeDict
.get(FullFileName
)
854 FileID
= GetTableID(FullFileName
)
855 FileTable
= 'Identifier' + str(FileID
)
857 SqlStatement
= """ select Modifier, Name, Value, ID
860 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
861 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
864 for Result
in ResultSet
:
865 if len(Result
[0]) == 0:
866 Dict
[Result
[1]] = Result
[2]
868 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
869 for F
in IncludeFileList
:
870 FileID
= GetTableID(F
)
874 FileTable
= 'Identifier' + str(FileID
)
875 SqlStatement
= """ select Modifier, Name, Value, ID
878 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
879 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
881 for Result
in ResultSet
:
882 if not Result
[2].startswith('FP ('):
883 Dict
[Result
[1]] = Result
[2]
885 if len(Result
[0]) == 0:
886 Dict
[Result
[1]] = 'VOID'
888 Dict
[Result
[1]] = GetDataTypeFromModifier(Result
[0])
890 ComplexTypeDict
[FullFileName
] = Dict
893 def GetSUDict(FullFileName
):
895 Dict
= SUDict
.get(FullFileName
)
899 FileID
= GetTableID(FullFileName
)
900 FileTable
= 'Identifier' + str(FileID
)
902 SqlStatement
= """ select Name, Value, ID
904 where Model = %d or Model = %d
905 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
906 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
909 for Result
in ResultSet
:
910 if len(Result
[1]) > 0:
911 Dict
[Result
[0]] = Result
[1]
913 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
914 for F
in IncludeFileList
:
915 FileID
= GetTableID(F
)
919 FileTable
= 'Identifier' + str(FileID
)
920 SqlStatement
= """ select Name, Value, ID
922 where Model = %d or Model = %d
923 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
924 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
926 for Result
in ResultSet
:
927 if len(Result
[1]) > 0:
928 Dict
[Result
[0]] = Result
[1]
930 SUDict
[FullFileName
] = Dict
933 def StripComments(Str
):
935 ListFromStr
= list(Str
)
938 DoubleSlashComment
= False
940 while Index
< len(ListFromStr
):
941 # meet new line, then no longer in a comment for //
942 if ListFromStr
[Index
] == '\n':
943 if InComment
and DoubleSlashComment
:
945 DoubleSlashComment
= False
947 # check for */ comment end
948 elif InComment
and not DoubleSlashComment
and ListFromStr
[Index
] == '*' and ListFromStr
[Index
+1] == '/':
949 ListFromStr
[Index
] = ' '
951 ListFromStr
[Index
] = ' '
954 # set comments to spaces
956 ListFromStr
[Index
] = ' '
958 # check for // comment
959 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+1] == '/' and ListFromStr
[Index
+2] != '\n':
961 DoubleSlashComment
= True
963 # check for /* comment start
964 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+1] == '*':
965 ListFromStr
[Index
] = ' '
967 ListFromStr
[Index
] = ' '
973 # restore from List to String
974 Str
= "".join(ListFromStr
)
975 Str
= Str
.rstrip(' ')
979 def GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
):
980 Value
= TypedefDict
.get(Type
)
982 Value
= SUDict
.get(Type
)
986 LBPos
= Value
.find('{')
988 FTList
= Value
.split()
990 if FT
not in ('struct', 'union'):
991 Value
= TypedefDict
.get(FT
)
993 Value
= SUDict
.get(FT
)
999 LBPos
= Value
.find('{')
1001 # RBPos = Value.find('}')
1002 Fields
= Value
[LBPos
+ 1:]
1003 Fields
= StripComments(Fields
)
1004 FieldsList
= Fields
.split(';')
1005 for Field
in FieldsList
:
1006 Field
= Field
.strip()
1007 Index
= Field
.rfind(FieldName
)
1010 if not Field
[Index
- 1].isalnum():
1011 if Index
+ len(FieldName
) == len(Field
):
1012 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1015 # For the condition that the field in struct is an array with [] sufixes...
1016 if not Field
[Index
+ len(FieldName
)].isalnum():
1017 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1022 def GetRealType(Type
, TypedefDict
, TargetType
= None):
1023 if TargetType
!= None and Type
== TargetType
:
1025 while TypedefDict
.get(Type
):
1026 Type
= TypedefDict
.get(Type
)
1027 if TargetType
!= None and Type
== TargetType
:
1031 def GetTypeInfo(RefList
, Modifier
, FullFileName
, TargetType
= None):
1032 TypedefDict
= GetTypedefDict(FullFileName
)
1033 SUDict
= GetSUDict(FullFileName
)
1034 Type
= GetDataTypeFromModifier(Modifier
).replace('*', '').strip()
1036 Type
= Type
.split()[-1]
1038 while Index
< len(RefList
):
1039 FieldName
= RefList
[Index
]
1040 FromType
= GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
)
1041 if FromType
== None:
1043 # we want to determine the exact type.
1044 if TargetType
!= None:
1045 Type
= FromType
.split()[0]
1046 # we only want to check if it is a pointer
1049 if Type
.find('*') != -1 and Index
== len(RefList
)-1:
1051 Type
= FromType
.split()[0]
1055 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1059 def GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
= False, TargetType
= None, StarList
= None):
1061 PredVar
= PredVarList
[0]
1062 FileID
= GetTableID(FullFileName
)
1065 FileTable
= 'Identifier' + str(FileID
)
1066 # search variable in include files
1068 # it is a function call, search function declarations and definitions
1070 SqlStatement
= """ select Modifier, ID
1072 where Model = %d and Value = \'%s\'
1073 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1074 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1076 for Result
in ResultSet
:
1077 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1078 TypedefDict
= GetTypedefDict(FullFileName
)
1079 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1082 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1083 for F
in IncludeFileList
:
1084 FileID
= GetTableID(F
)
1088 FileTable
= 'Identifier' + str(FileID
)
1089 SqlStatement
= """ select Modifier, ID
1091 where Model = %d and Value = \'%s\'
1092 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1093 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1095 for Result
in ResultSet
:
1096 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1097 TypedefDict
= GetTypedefDict(FullFileName
)
1098 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1101 FileID
= GetTableID(FullFileName
)
1102 SqlStatement
= """ select Modifier, ID
1104 where BelongsToFile = %d and Name = \'%s\'
1105 """ % (FileID
, PredVar
)
1106 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1108 for Result
in ResultSet
:
1109 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1110 TypedefDict
= GetTypedefDict(FullFileName
)
1111 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1114 for F
in IncludeFileList
:
1115 FileID
= GetTableID(F
)
1119 FileTable
= 'Identifier' + str(FileID
)
1120 SqlStatement
= """ select Modifier, ID
1122 where BelongsToFile = %d and Name = \'%s\'
1123 """ % (FileID
, PredVar
)
1124 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1126 for Result
in ResultSet
:
1127 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1128 TypedefDict
= GetTypedefDict(FullFileName
)
1129 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1134 # really variable, search local variable first
1135 SqlStatement
= """ select Modifier, ID
1137 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1138 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
, FuncRecord
[0], FuncRecord
[1])
1139 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1141 for Result
in ResultSet
:
1142 if len(PredVarList
) > 1:
1143 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1146 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1147 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1149 if len(TypeList
) > 1 and StarList
!= None:
1150 for Star
in StarList
:
1152 Type
= Type
.rstrip(Star
)
1153 # Get real type after de-reference pointers.
1154 if len(Type
.strip()) == 0:
1156 TypedefDict
= GetTypedefDict(FullFileName
)
1157 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1160 # search function parameters second
1161 ParamList
= GetParamList(FuncRecord
[2])
1162 for Param
in ParamList
:
1163 if Param
.Name
.strip() == PredVar
:
1164 if len(PredVarList
) > 1:
1165 Type
= GetTypeInfo(PredVarList
[1:], Param
.Modifier
, FullFileName
, TargetType
)
1168 TypeList
= GetDataTypeFromModifier(Param
.Modifier
).split()
1170 if len(TypeList
) > 1 and StarList
!= None:
1171 for Star
in StarList
:
1173 Type
= Type
.rstrip(Star
)
1174 # Get real type after de-reference pointers.
1175 if len(Type
.strip()) == 0:
1177 TypedefDict
= GetTypedefDict(FullFileName
)
1178 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1181 # search global variable next
1182 SqlStatement
= """ select Modifier, ID
1184 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1185 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1186 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1188 for Result
in ResultSet
:
1189 if len(PredVarList
) > 1:
1190 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1193 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1195 if len(TypeList
) > 1 and StarList
!= None:
1196 for Star
in StarList
:
1198 Type
= Type
.rstrip(Star
)
1199 # Get real type after de-reference pointers.
1200 if len(Type
.strip()) == 0:
1202 TypedefDict
= GetTypedefDict(FullFileName
)
1203 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1206 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1207 for F
in IncludeFileList
:
1208 FileID
= GetTableID(F
)
1212 FileTable
= 'Identifier' + str(FileID
)
1213 SqlStatement
= """ select Modifier, ID
1215 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1216 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1217 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1219 for Result
in ResultSet
:
1220 if len(PredVarList
) > 1:
1221 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1224 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1226 if len(TypeList
) > 1 and StarList
!= None:
1227 for Star
in StarList
:
1229 Type
= Type
.rstrip(Star
)
1230 # Get real type after de-reference pointers.
1231 if len(Type
.strip()) == 0:
1233 TypedefDict
= GetTypedefDict(FullFileName
)
1234 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1237 def GetTypeFromArray(Type
, Var
):
1238 Count
= Var
.count('[')
1242 Type
= Type
.rstrip('*')
1247 def CheckFuncLayoutReturnType(FullFileName
):
1250 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1255 FileTable
= 'Identifier' + str(FileID
)
1256 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1259 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1260 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1261 for Result
in ResultSet
:
1262 ReturnType
= GetDataTypeFromModifier(Result
[0])
1263 TypeStart
= ReturnType
.split()[0]
1264 FuncName
= Result
[5]
1265 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1267 Index
= Result
[0].find(TypeStart
)
1268 if Index
!= 0 or Result
[3] != 0:
1269 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1271 if Result
[2] == Result
[4]:
1272 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1274 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1276 where BelongsToFile = %d
1278 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1279 for Result
in ResultSet
:
1280 ReturnType
= GetDataTypeFromModifier(Result
[0])
1281 TypeStart
= ReturnType
.split()[0]
1282 FuncName
= Result
[5]
1283 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1285 Index
= Result
[0].find(ReturnType
)
1286 if Index
!= 0 or Result
[3] != 0:
1287 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1289 if Result
[2] == Result
[4]:
1290 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, 'Function', Result
[1])
1292 def CheckFuncLayoutModifier(FullFileName
):
1295 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1300 FileTable
= 'Identifier' + str(FileID
)
1301 SqlStatement
= """ select Modifier, ID
1304 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1305 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1306 for Result
in ResultSet
:
1307 ReturnType
= GetDataTypeFromModifier(Result
[0])
1308 TypeStart
= ReturnType
.split()[0]
1309 # if len(ReturnType) == 0:
1311 Index
= Result
[0].find(TypeStart
)
1313 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1315 SqlStatement
= """ select Modifier, ID
1317 where BelongsToFile = %d
1319 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1320 for Result
in ResultSet
:
1321 ReturnType
= GetDataTypeFromModifier(Result
[0])
1322 TypeStart
= ReturnType
.split()[0]
1323 # if len(ReturnType) == 0:
1325 Index
= Result
[0].find(TypeStart
)
1327 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1329 def CheckFuncLayoutName(FullFileName
):
1331 # Parameter variable format pattern.
1332 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1333 ParamIgnoreList
= ('VOID', '...')
1334 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1339 FileTable
= 'Identifier' + str(FileID
)
1340 SqlStatement
= """ select Name, ID, EndColumn, Value
1343 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1344 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1345 for Result
in ResultSet
:
1346 FuncName
= Result
[3]
1347 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1350 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1351 ParamList
= GetParamList(Result
[0])
1352 if len(ParamList
) == 0:
1355 for Param
in ParamList
:
1356 if Param
.StartLine
<= StartLine
:
1357 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1358 if Param
.StartLine
- StartLine
> 1:
1359 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1360 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
):
1361 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1362 StartLine
= Param
.StartLine
1364 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1365 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1367 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1369 where BelongsToFile = %d
1371 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1372 for Result
in ResultSet
:
1373 FuncName
= Result
[3]
1374 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1377 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1378 ParamList
= GetParamList(Result
[0])
1379 if len(ParamList
) == 0:
1382 for Param
in ParamList
:
1383 if Param
.StartLine
<= StartLine
:
1384 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1385 if Param
.StartLine
- StartLine
> 1:
1386 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1387 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
):
1388 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1389 StartLine
= Param
.StartLine
1390 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1391 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1393 def CheckFuncLayoutPrototype(FullFileName
):
1396 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1400 FileTable
= 'Identifier' + str(FileID
)
1402 SqlStatement
= """ select Modifier, Header, Name, ID
1404 where BelongsToFile = %d
1406 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1407 if len(ResultSet
) == 0:
1411 for Result
in ResultSet
:
1412 FuncDefList
.append(Result
)
1414 SqlStatement
= """ select Modifier, Name, ID
1417 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1418 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1420 for Result
in ResultSet
:
1421 FuncDeclList
.append(Result
)
1424 for FuncDef
in FuncDefList
:
1425 FuncName
= FuncDef
[2].strip()
1426 FuncModifier
= FuncDef
[0]
1427 FuncDefHeader
= FuncDef
[1]
1428 for FuncDecl
in FuncDeclList
:
1429 LBPos
= FuncDecl
[1].find('(')
1430 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1431 DeclModifier
= FuncDecl
[0]
1432 if DeclName
== FuncName
:
1433 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1434 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1435 ParamListOfDef
= GetParamList(FuncDefHeader
)
1436 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1437 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1438 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1442 while Index
< len(ParamListOfDef
):
1443 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1444 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])
1448 UndeclFuncList
.append(FuncDef
)
1450 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1452 for F
in IncludeFileList
:
1453 FileID
= GetTableID(F
, ErrorMsgList
)
1457 FileTable
= 'Identifier' + str(FileID
)
1458 SqlStatement
= """ select Modifier, Name, ID
1461 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1462 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1464 for Result
in ResultSet
:
1465 FuncDeclList
.append(Result
)
1467 for FuncDef
in UndeclFuncList
:
1468 FuncName
= FuncDef
[2].strip()
1469 FuncModifier
= FuncDef
[0]
1470 FuncDefHeader
= FuncDef
[1]
1471 for FuncDecl
in FuncDeclList
:
1472 LBPos
= FuncDecl
[1].find('(')
1473 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1474 DeclModifier
= FuncDecl
[0]
1475 if DeclName
== FuncName
:
1476 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1477 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1478 ParamListOfDef
= GetParamList(FuncDefHeader
)
1479 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1480 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1481 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1485 while Index
< len(ParamListOfDef
):
1486 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1487 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])
1491 def CheckFuncLayoutBody(FullFileName
):
1494 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1498 FileTable
= 'Identifier' + str(FileID
)
1500 SqlStatement
= """ select BodyStartColumn, EndColumn, ID
1502 where BelongsToFile = %d
1504 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1505 if len(ResultSet
) == 0:
1507 for Result
in ResultSet
:
1509 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'open brace should be at the very beginning of a line.', 'Function', Result
[2])
1511 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'close brace should be at the very beginning of a line.', 'Function', Result
[2])
1513 def CheckFuncLayoutLocalVariable(FullFileName
):
1516 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1521 FileTable
= 'Identifier' + str(FileID
)
1522 SqlStatement
= """ select ID
1524 where BelongsToFile = %d
1526 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1527 if len(ResultSet
) == 0:
1530 for Result
in ResultSet
:
1534 SqlStatement
= """ select Name, Value, ID
1536 where Model = %d and BelongsToFunction = %d
1537 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1538 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1539 if len(ResultSet
) == 0:
1542 for Result
in ResultSet
:
1543 if len(Result
[1]) > 0:
1544 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1546 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1548 # Member variable format pattern.
1549 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1551 LBPos
= Value
.find('{')
1552 RBPos
= Value
.rfind('}')
1553 if LBPos
== -1 or RBPos
== -1:
1556 Fields
= Value
[LBPos
+ 1 : RBPos
]
1557 Fields
= StripComments(Fields
).strip()
1558 NestPos
= Fields
.find ('struct')
1559 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)):
1560 if not Fields
[NestPos
+ len('struct') + 1].isalnum():
1561 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1562 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested struct in [%s].' % (Name
), FileTable
, TdId
)
1564 NestPos
= Fields
.find ('union')
1565 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1566 if not Fields
[NestPos
+ len('union') + 1].isalnum():
1567 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1568 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested union in [%s].' % (Name
), FileTable
, TdId
)
1570 NestPos
= Fields
.find ('enum')
1571 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1572 if not Fields
[NestPos
+ len('enum') + 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 enum in [%s].' % (Name
), FileTable
, TdId
)
1577 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1578 FieldsList
= Fields
.split(',')
1579 # deal with enum is pre-assigned a value by function call ( , , , ...)
1582 RemoveCurrentElement
= False
1583 while Index
< len(FieldsList
):
1584 Field
= FieldsList
[Index
]
1586 if Field
.find('(') != -1:
1588 RemoveCurrentElement
= True
1592 if Field
.find(')') != -1 and QuoteCount
> 0:
1595 if RemoveCurrentElement
:
1596 FieldsList
.remove(Field
)
1598 RemoveCurrentElement
= False
1602 RemoveCurrentElement
= False
1606 FieldsList
= Fields
.split(';')
1608 for Field
in FieldsList
:
1609 Field
= Field
.strip()
1612 # For the condition that the field in struct is an array with [] sufixes...
1613 if Field
[-1] == ']':
1614 LBPos
= Field
.find('[')
1615 Field
= Field
[0:LBPos
]
1616 # For the condition that bit field ": Number"
1617 if Field
.find(':') != -1:
1618 ColonPos
= Field
.find(':')
1619 Field
= Field
[0:ColonPos
]
1621 Field
= Field
.strip()
1624 # Enum could directly assign value to variable
1625 Field
= Field
.split('=')[0].strip()
1626 TokenList
= Field
.split()
1627 # Remove pointers before variable
1628 if not Pattern
.match(TokenList
[-1].lstrip('*')):
1629 ErrMsgList
.append(TokenList
[-1].lstrip('*'))
1633 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1636 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1641 FileTable
= 'Identifier' + str(FileID
)
1642 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1645 """ % (FileTable
, ModelId
)
1646 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1648 for Result
in ResultSet
:
1649 ResultList
.append(Result
)
1651 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1652 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1653 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1654 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1655 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1656 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1657 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1659 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1662 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1663 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1667 # Check member variable name format that from typedefs of ONLY this file.
1669 Name
= Td
[1].strip()
1670 Value
= Td
[2].strip()
1671 if Value
.startswith('enum'):
1672 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1673 elif Value
.startswith('struct'):
1674 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1675 elif Value
.startswith('union'):
1676 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1680 if ValueModelId
!= ModelId
:
1682 # Check member variable format.
1683 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1684 for ErrMsg
in ErrMsgList
:
1685 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+'.'+ErrMsg
):
1687 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+'.'+ErrMsg
), FileTable
, Td
[5])
1689 # First check in current file to see whether struct/union/enum is typedef-ed.
1690 UntypedefedList
= []
1691 for Result
in ResultList
:
1692 # Check member variable format.
1693 Name
= Result
[0].strip()
1694 Value
= Result
[4].strip()
1695 if Value
.startswith('enum'):
1696 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1697 elif Value
.startswith('struct'):
1698 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1699 elif Value
.startswith('union'):
1700 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1704 if ValueModelId
!= ModelId
:
1706 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1707 for ErrMsg
in ErrMsgList
:
1708 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0]+'.'+ErrMsg
):
1710 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0]+'.'+ErrMsg
), FileTable
, Result
[3])
1711 # Check whether it is typedefed.
1714 # skip function pointer
1717 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1719 if not Td
[1].isupper():
1720 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1721 if Result
[0] in Td
[2].split():
1723 if not Td
[1].isupper():
1724 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1729 UntypedefedList
.append(Result
)
1732 if len(UntypedefedList
) == 0:
1735 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1737 for F
in IncludeFileList
:
1738 FileID
= GetTableID(F
, ErrorMsgList
)
1742 IncludeFileTable
= 'Identifier' + str(FileID
)
1743 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1746 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1747 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1748 TdList
.extend(ResultSet
)
1750 for Result
in UntypedefedList
:
1752 # Check whether it is typedefed.
1758 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1760 if not Td
[1].isupper():
1761 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1762 if Result
[0] in Td
[2].split():
1764 if not Td
[1].isupper():
1765 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1770 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1773 def CheckDeclStructTypedef(FullFileName
):
1774 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1776 def CheckDeclEnumTypedef(FullFileName
):
1777 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1779 def CheckDeclUnionTypedef(FullFileName
):
1780 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1782 def CheckDeclArgModifier(FullFileName
):
1785 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1790 FileTable
= 'Identifier' + str(FileID
)
1791 SqlStatement
= """ select Modifier, Name, ID
1794 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1795 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1796 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1797 MAX_MODIFIER_LENGTH
= 100
1798 for Result
in ResultSet
:
1799 for Modifier
in ModifierTuple
:
1800 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1801 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1804 SqlStatement
= """ select Modifier, Name, ID
1807 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1808 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1809 for Result
in ResultSet
:
1810 for Modifier
in ModifierTuple
:
1811 if PatternInModifier(Result
[0], Modifier
):
1812 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1815 SqlStatement
= """ select Modifier, Header, ID
1817 where BelongsToFile = %d
1819 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1820 for Result
in ResultSet
:
1821 for Modifier
in ModifierTuple
:
1822 if PatternInModifier(Result
[0], Modifier
):
1823 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1826 def CheckDeclNoUseCType(FullFileName
):
1829 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1834 FileTable
= 'Identifier' + str(FileID
)
1835 SqlStatement
= """ select Modifier, Name, ID
1838 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1839 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1840 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1841 for Result
in ResultSet
:
1842 for Type
in CTypeTuple
:
1843 if PatternInModifier(Result
[0], Type
):
1844 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Variable type %s' % Type
, FileTable
, Result
[2])
1847 SqlStatement
= """ select Modifier, Name, ID, Value
1850 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1851 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1852 for Result
in ResultSet
:
1853 ParamList
= GetParamList(Result
[1])
1854 FuncName
= Result
[3]
1855 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1857 for Type
in CTypeTuple
:
1858 if PatternInModifier(Result
[0], Type
):
1859 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1861 for Param
in ParamList
:
1862 if PatternInModifier(Param
.Modifier
, Type
):
1863 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1865 SqlStatement
= """ select Modifier, Header, ID, Name
1867 where BelongsToFile = %d
1869 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1870 for Result
in ResultSet
:
1871 ParamList
= GetParamList(Result
[1])
1872 FuncName
= Result
[3]
1873 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1875 for Type
in CTypeTuple
:
1876 if PatternInModifier(Result
[0], Type
):
1877 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1879 for Param
in ParamList
:
1880 if PatternInModifier(Param
.Modifier
, Type
):
1881 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1884 def CheckPointerNullComparison(FullFileName
):
1887 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1891 # cache the found function return type to accelerate later checking in this file.
1892 FuncReturnTypeDict
= {}
1895 FileTable
= 'Identifier' + str(FileID
)
1896 SqlStatement
= """ select Value, StartLine, ID
1899 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1900 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1901 if len(ResultSet
) == 0:
1904 for Result
in ResultSet
:
1905 PSL
.append([Result
[0], Result
[1], Result
[2]])
1907 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1909 where BelongsToFile = %d
1911 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1913 for Result
in ResultSet
:
1914 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1916 p
= GetFuncDeclPattern()
1918 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1919 if FuncRecord
== None:
1922 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1923 PredInfo
= SplitPredicateStr(Exp
)
1924 if PredInfo
[1] == None:
1925 PredVarStr
= PredInfo
[0][0].strip()
1927 SearchInCache
= False
1928 # PredVarStr may contain '.' or '->'
1929 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1931 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1932 SearchInCache
= True
1933 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1934 if TmpStr
.startswith(PredVarStr
):
1937 if PredVarStr
.strip() in IgnoredKeywordList
:
1940 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1941 # No variable found, maybe value first? like (0 == VarName)
1942 if len(PredVarList
) == 0:
1945 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1947 if Type
.find('*') != -1:
1948 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1951 if PredVarStr
in FuncReturnTypeDict
:
1954 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1956 FuncReturnTypeDict
[PredVarStr
] = Type
1959 Type
= GetTypeFromArray(Type
, PredVarStr
)
1960 if Type
.find('*') != -1:
1961 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1963 def CheckNonBooleanValueComparison(FullFileName
):
1966 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1970 # cache the found function return type to accelerate later checking in this file.
1971 FuncReturnTypeDict
= {}
1974 FileTable
= 'Identifier' + str(FileID
)
1975 SqlStatement
= """ select Value, StartLine, ID
1978 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1979 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1980 if len(ResultSet
) == 0:
1983 for Result
in ResultSet
:
1984 PSL
.append([Result
[0], Result
[1], Result
[2]])
1986 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1988 where BelongsToFile = %d
1990 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1992 for Result
in ResultSet
:
1993 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1995 p
= GetFuncDeclPattern()
1997 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1998 if FuncRecord
== None:
2001 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2004 PredInfo
= SplitPredicateStr(Exp
)
2005 if PredInfo
[1] == None:
2006 PredVarStr
= PredInfo
[0][0].strip()
2008 SearchInCache
= False
2009 # PredVarStr may contain '.' or '->'
2010 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2012 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2013 SearchInCache
= True
2014 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2015 if TmpStr
.startswith(PredVarStr
):
2018 if PredVarStr
.strip() in IgnoredKeywordList
:
2021 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2022 # No variable found, maybe value first? like (0 == VarName)
2023 if len(PredVarList
) == 0:
2027 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2029 if Type
.find('BOOLEAN') == -1:
2030 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2033 if PredVarStr
in FuncReturnTypeDict
:
2036 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2038 FuncReturnTypeDict
[PredVarStr
] = Type
2041 if Type
.find('BOOLEAN') == -1:
2042 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2045 def CheckBooleanValueComparison(FullFileName
):
2048 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2052 # cache the found function return type to accelerate later checking in this file.
2053 FuncReturnTypeDict
= {}
2056 FileTable
= 'Identifier' + str(FileID
)
2057 SqlStatement
= """ select Value, StartLine, ID
2060 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2061 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2062 if len(ResultSet
) == 0:
2065 for Result
in ResultSet
:
2066 PSL
.append([Result
[0], Result
[1], Result
[2]])
2068 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2070 where BelongsToFile = %d
2072 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2074 for Result
in ResultSet
:
2075 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2077 p
= GetFuncDeclPattern()
2079 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2080 if FuncRecord
== None:
2083 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2084 PredInfo
= SplitPredicateStr(Exp
)
2085 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2086 PredVarStr
= PredInfo
[0][0].strip()
2088 SearchInCache
= False
2089 # PredVarStr may contain '.' or '->'
2090 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2092 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2093 SearchInCache
= True
2094 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2095 if TmpStr
.startswith(PredVarStr
):
2098 if PredVarStr
.strip() in IgnoredKeywordList
:
2101 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2102 # No variable found, maybe value first? like (0 == VarName)
2103 if len(PredVarList
) == 0:
2107 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2109 if Type
.find('BOOLEAN') != -1:
2110 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2113 if PredVarStr
in FuncReturnTypeDict
:
2116 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2118 FuncReturnTypeDict
[PredVarStr
] = Type
2121 if Type
.find('BOOLEAN') != -1:
2122 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2125 def CheckHeaderFileData(FullFileName
):
2128 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2133 FileTable
= 'Identifier' + str(FileID
)
2134 SqlStatement
= """ select ID, Modifier
2137 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2138 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2139 for Result
in ResultSet
:
2140 if not Result
[1].startswith('extern'):
2141 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2143 SqlStatement
= """ select ID
2145 where BelongsToFile = %d
2147 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2148 for Result
in ResultSet
:
2149 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2153 def CheckHeaderFileIfndef(FullFileName
):
2156 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2161 FileTable
= 'Identifier' + str(FileID
)
2162 SqlStatement
= """ select Value, StartLine
2164 where Model = %d order by StartLine
2165 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2166 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2167 if len(ResultSet
) == 0:
2168 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2170 for Result
in ResultSet
:
2171 SqlStatement
= """ select Value, EndLine
2174 """ % (FileTable
, Result
[1])
2175 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2176 for Result
in ResultSet
:
2177 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2178 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2
, '', 'File', FileID
)
2181 SqlStatement
= """ select Value
2183 where StartLine > (select max(EndLine) from %s where Model = %d)
2184 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2185 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2186 for Result
in ResultSet
:
2187 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2188 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2191 def CheckDoxygenCommand(FullFileName
):
2194 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2199 FileTable
= 'Identifier' + str(FileID
)
2200 SqlStatement
= """ select Value, ID
2202 where Model = %d or Model = %d
2203 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2204 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2205 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval', 'return', 'sa', 'since', 'test', 'note', 'par']
2206 for Result
in ResultSet
:
2207 CommentStr
= Result
[0]
2208 CommentPartList
= CommentStr
.split()
2209 for Part
in CommentPartList
:
2210 if Part
.upper() == 'BUGBUG':
2211 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2212 if Part
.upper() == 'TODO':
2213 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2214 if Part
.startswith('@'):
2215 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2217 if Part
.lstrip('@').isalpha():
2218 if Part
.lstrip('@') not in DoxygenCommandList
:
2219 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2221 Index
= Part
.find('[')
2223 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2224 RealCmd
= Part
[1:Index
]
2225 if RealCmd
not in DoxygenCommandList
:
2226 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2229 def CheckDoxygenTripleForwardSlash(FullFileName
):
2232 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2238 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2240 where BelongsToFile = %d
2242 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2243 if len(ResultSet
) == 0:
2247 for Result
in ResultSet
:
2248 FuncDefSet
.append(Result
)
2251 FileTable
= 'Identifier' + str(FileID
)
2252 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2256 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2257 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2260 for Result
in ResultSet
:
2261 CommentSet
.append(Result
)
2263 print 'Unrecognized chars in comment of file %s', FullFileName
2266 for Result
in CommentSet
:
2267 CommentStr
= Result
[0]
2268 StartLine
= Result
[2]
2269 StartColumn
= Result
[3]
2271 EndColumn
= Result
[5]
2272 if not CommentStr
.startswith('///<'):
2276 for FuncDef
in FuncDefSet
:
2277 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2280 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2283 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2286 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2290 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2293 def CheckFileHeaderDoxygenComments(FullFileName
):
2296 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2301 FileTable
= 'Identifier' + str(FileID
)
2302 SqlStatement
= """ select Value, ID
2304 where Model = %d and StartLine = 1 and StartColumn = 0
2305 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2306 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2307 if len(ResultSet
) == 0:
2308 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No Comment appear at the very beginning of file.', 'File', FileID
)
2311 for Result
in ResultSet
:
2312 CommentStr
= Result
[0]
2313 if not CommentStr
.startswith('/** @file'):
2314 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, Result
[1])
2315 if not CommentStr
.endswith('**/'):
2316 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with **/', FileTable
, Result
[1])
2317 if CommentStr
.find('.') == -1:
2318 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', FileTable
, Result
[1])
2320 def CheckFuncHeaderDoxygenComments(FullFileName
):
2323 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2328 FileTable
= 'Identifier' + str(FileID
)
2329 SqlStatement
= """ select Value, StartLine, EndLine, ID
2332 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2334 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2337 for Result
in ResultSet
:
2338 CommentSet
.append(Result
)
2340 print 'Unrecognized chars in comment of file %s', FullFileName
2343 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2346 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2347 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2348 for Result
in ResultSet
:
2349 FuncName
= Result
[4]
2350 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2351 if FunctionHeaderComment
:
2352 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2354 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2356 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2357 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2360 SqlStatement
= """ select Value, StartLine, EndLine, ID
2363 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2365 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2368 for Result
in ResultSet
:
2369 CommentSet
.append(Result
)
2371 print 'Unrecognized chars in comment of file %s', FullFileName
2373 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2375 where BelongsToFile = %d
2377 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2378 for Result
in ResultSet
:
2379 FuncName
= Result
[4]
2380 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2381 if FunctionHeaderComment
:
2382 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2384 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2386 ErrorMsgList
.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2387 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), 'Function', Result
[3])
2390 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2392 for Comment
in CommentSet
:
2393 if Comment
[2] == FuncStartLine
- 1:
2397 def GetDoxygenStrFromComment(Str
):
2399 ParamTagList
= Str
.split('@param')
2400 if len(ParamTagList
) > 1:
2402 while i
< len(ParamTagList
):
2403 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2406 Str
= ParamTagList
[0]
2408 RetvalTagList
= ParamTagList
[-1].split('@retval')
2409 if len(RetvalTagList
) > 1:
2410 if len(ParamTagList
) > 1:
2411 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2413 while i
< len(RetvalTagList
):
2414 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2417 ReturnTagList
= RetvalTagList
[-1].split('@return')
2418 if len(ReturnTagList
) > 1:
2419 if len(RetvalTagList
) > 1:
2420 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2421 elif len(ParamTagList
) > 1:
2422 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2424 while i
< len(ReturnTagList
):
2425 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2428 if len(DoxygenStrList
) > 0:
2429 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2431 return DoxygenStrList
2433 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
= ''):
2434 #/** --*/ @retval after @param
2435 if not Str
.startswith('/**'):
2436 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2437 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2438 if not Str
.endswith('**/'):
2439 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2440 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2441 FirstRetvalIndex
= Str
.find('@retval')
2442 LastParamIndex
= Str
.rfind('@param')
2443 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2444 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2445 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2447 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
= ''):
2449 ParamList
= GetParamList(FuncHeader
)
2450 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2451 DescriptionStr
= CommentStr
2452 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2453 if DescriptionStr
.find('.') == -1:
2454 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2455 DoxygenTagNumber
= len(DoxygenStrList
)
2456 ParamNumber
= len(ParamList
)
2457 for Param
in ParamList
:
2458 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2461 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2462 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2463 ParamModifier
= ParamList
[Index
].Modifier
2464 ParamName
= ParamList
[Index
].Name
.strip()
2465 Tag
= DoxygenStrList
[Index
].strip(' ')
2466 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2467 ErrorMsgList
.append('Line %d : in Comment, \"%s\" does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2468 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, \"%s\" does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2469 TagPartList
= Tag
.split()
2470 if len(TagPartList
) < 2:
2471 ErrorMsgList
.append('Line %d : in Comment, \"%s\" does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2472 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, \"%s\" does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2475 LBPos
= Tag
.find('[')
2476 RBPos
= Tag
.find(']')
2477 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2478 if LBPos
> 0 and len(ParamToLBContent
)==0 and RBPos
> LBPos
:
2480 ModifierPartList
= ParamModifier
.split()
2481 for Part
in ModifierPartList
:
2482 if Part
.strip() == 'IN':
2484 if Part
.strip() == 'OUT':
2491 if Tag
.find('['+InOutStr
+']') == -1:
2492 ErrorMsgList
.append('Line %d : in Comment, \"%s\" does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' +TagPartList
[1]).replace('\n', '').replace('\r', ''), '['+InOutStr
+']'))
2493 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, \"%s\" does NOT have %s ' % ((TagPartList
[0] + ' ' +TagPartList
[1]).replace('\n', '').replace('\r', ''), '['+InOutStr
+']'), TableName
, CommentId
)
2494 if Tag
.find(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2495 ErrorMsgList
.append('Line %d : in Comment, \"%s\" does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' +TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2496 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
)
2499 if Index
< ParamNumber
:
2500 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2501 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2502 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2503 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2505 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2506 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2507 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2508 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2510 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2511 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2512 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2514 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
2515 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2516 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need NO doxygen tags in comment ', TableName
, CommentId
)
2517 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2518 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2519 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2521 if __name__
== '__main__':
2523 # EdkLogger.Initialize()
2524 # EdkLogger.SetLevel(EdkLogger.QUIET)
2525 # CollectSourceCodeDataIntoDB(sys.argv[1])
2526 MsgList
= CheckFuncHeaderDoxygenComments('C:\\Combo\\R9\\LakeportX64Dev\\FlashDevicePkg\\Library\\SpiFlashChipM25P64\\SpiFlashChipM25P64.c')