2 # This file is used to be the c coding style checking of ECC tool
4 # Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 from __future__
import print_function
15 from __future__
import absolute_import
17 import Common
.LongFilePathOs
as os
20 from . import CodeFragmentCollector
21 from . import FileProfile
22 from CommonDataClass
import DataClass
23 from . import Database
24 from Common
import EdkLogger
25 from .EccToolError
import *
26 from . import EccGlobalData
27 from . import MetaDataParser
29 IncludeFileListDict
= {}
30 AllIncludeFileListDict
= {}
31 IncludePathListDict
= {}
34 IgnoredKeywordList
= ['EFI_ERROR']
36 def GetIgnoredDirListPattern():
37 skipList
= list(EccGlobalData
.gConfig
.SkipDirList
) + ['.svn']
38 DirString
= string
.join(skipList
, '|')
39 p
= re
.compile(r
'.*[\\/](?:%s)[\\/]?.*' % DirString
)
42 def GetFuncDeclPattern():
43 p
= re
.compile(r
'(?:EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re
.DOTALL
)
46 def GetArrayPattern():
47 p
= re
.compile(r
'[_\w]*\s*[\[.*\]]+')
50 def GetTypedefFuncPointerPattern():
51 p
= re
.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re
.DOTALL
)
55 return EccGlobalData
.gDb
58 return EccGlobalData
.gConfig
60 def PrintErrorMsg(ErrorType
, Msg
, TableName
, ItemId
):
61 Msg
= Msg
.replace('\n', '').replace('\r', '')
62 MsgPartList
= Msg
.split()
64 for Part
in MsgPartList
:
67 GetDB().TblReport
.Insert(ErrorType
, OtherMsg
=Msg
, BelongsToTable
=TableName
, BelongsToItem
=ItemId
)
70 Type
= DataClass
.MODEL_UNKNOWN
71 Str
= Str
.replace('#', '# ')
73 if List
[1] == 'include':
74 Type
= DataClass
.MODEL_IDENTIFIER_INCLUDE
75 elif List
[1] == 'define':
76 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_DEFINE
77 elif List
[1] == 'ifdef':
78 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFDEF
79 elif List
[1] == 'ifndef':
80 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
81 elif List
[1] == 'endif':
82 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
83 elif List
[1] == 'pragma':
84 Type
= DataClass
.MODEL_IDENTIFIER_MACRO_PROGMA
86 Type
= DataClass
.MODEL_UNKNOWN
89 def SuOccurInTypedef (Su
, TdList
):
91 if Su
.StartPos
[0] == Td
.StartPos
[0] and Su
.EndPos
[0] == Td
.EndPos
[0]:
95 def GetIdentifierList():
97 for comment
in FileProfile
.CommentList
:
98 IdComment
= DataClass
.IdentifierClass(-1, '', '', '', comment
.Content
, DataClass
.MODEL_IDENTIFIER_COMMENT
, -1, -1, comment
.StartPos
[0], comment
.StartPos
[1], comment
.EndPos
[0], comment
.EndPos
[1])
99 IdList
.append(IdComment
)
101 for pp
in FileProfile
.PPDirectiveList
:
102 Type
= GetIdType(pp
.Content
)
103 IdPP
= DataClass
.IdentifierClass(-1, '', '', '', pp
.Content
, Type
, -1, -1, pp
.StartPos
[0], pp
.StartPos
[1], pp
.EndPos
[0], pp
.EndPos
[1])
106 for pe
in FileProfile
.PredicateExpressionList
:
107 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])
110 FuncDeclPattern
= GetFuncDeclPattern()
111 ArrayPattern
= GetArrayPattern()
112 for var
in FileProfile
.VariableDeclarationList
:
113 DeclText
= var
.Declarator
.lstrip()
114 FuncPointerPattern
= GetTypedefFuncPointerPattern()
115 if FuncPointerPattern
.match(DeclText
):
117 VarNameStartLine
= var
.NameStartPos
[0]
118 VarNameStartColumn
= var
.NameStartPos
[1]
119 FirstChar
= DeclText
[0]
120 while not FirstChar
.isalpha() and FirstChar
!= '_':
123 VarNameStartColumn
+= 1
124 DeclText
= DeclText
.lstrip('*')
125 elif FirstChar
== '\r':
126 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
127 VarNameStartLine
+= 1
128 VarNameStartColumn
= 0
129 elif FirstChar
== '\n':
130 DeclText
= DeclText
.lstrip('\n')
131 VarNameStartLine
+= 1
132 VarNameStartColumn
= 0
133 elif FirstChar
== ' ':
134 DeclText
= DeclText
.lstrip(' ')
135 VarNameStartColumn
+= 1
136 elif FirstChar
== '\t':
137 DeclText
= DeclText
.lstrip('\t')
138 VarNameStartColumn
+= 8
140 DeclText
= DeclText
[1:]
141 VarNameStartColumn
+= 1
142 FirstChar
= DeclText
[0]
144 var
.Declarator
= DeclText
145 if FuncDeclPattern
.match(var
.Declarator
):
146 DeclSplitList
= var
.Declarator
.split('(')
147 FuncName
= DeclSplitList
[0].strip()
148 FuncNamePartList
= FuncName
.split()
149 if len(FuncNamePartList
) > 1:
150 FuncName
= FuncNamePartList
[-1].strip()
151 NameStart
= DeclSplitList
[0].rfind(FuncName
)
152 var
.Declarator
= var
.Declarator
[NameStart
:]
154 var
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
157 while Index
< NameStart
:
158 FirstChar
= DeclSplitList
[0][Index
]
159 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
161 VarNameStartColumn
+= 6
164 elif FirstChar
== '\r':
166 VarNameStartLine
+= 1
167 VarNameStartColumn
= 0
168 elif FirstChar
== '\n':
171 VarNameStartLine
+= 1
172 VarNameStartColumn
= 0
173 elif FirstChar
== ' ':
175 VarNameStartColumn
+= 1
176 elif FirstChar
== '\t':
178 VarNameStartColumn
+= 8
181 VarNameStartColumn
+= 1
183 IdVar
= DataClass
.IdentifierClass(-1, var
.Modifier
, '', var
.Declarator
, FuncName
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, -1, -1, var
.StartPos
[0], var
.StartPos
[1], VarNameStartLine
, VarNameStartColumn
)
187 if var
.Declarator
.find('{') == -1:
188 for decl
in var
.Declarator
.split(','):
189 DeclList
= decl
.split('=')
190 Name
= DeclList
[0].strip()
191 if ArrayPattern
.match(Name
):
192 LSBPos
= var
.Declarator
.find('[')
193 var
.Modifier
+= ' ' + Name
[LSBPos
:]
194 Name
= Name
[0:LSBPos
]
196 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
)
199 DeclList
= var
.Declarator
.split('=')
200 Name
= DeclList
[0].strip()
201 if ArrayPattern
.match(Name
):
202 LSBPos
= var
.Declarator
.find('[')
203 var
.Modifier
+= ' ' + Name
[LSBPos
:]
204 Name
= Name
[0:LSBPos
]
205 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
)
208 for enum
in FileProfile
.EnumerationDefinitionList
:
209 LBPos
= enum
.Content
.find('{')
210 RBPos
= enum
.Content
.find('}')
211 Name
= enum
.Content
[4:LBPos
].strip()
212 Value
= enum
.Content
[LBPos
+ 1:RBPos
]
213 IdEnum
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
, -1, -1, enum
.StartPos
[0], enum
.StartPos
[1], enum
.EndPos
[0], enum
.EndPos
[1])
214 IdList
.append(IdEnum
)
216 for su
in FileProfile
.StructUnionDefinitionList
:
217 if SuOccurInTypedef(su
, FileProfile
.TypedefDefinitionList
):
219 Type
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
221 if su
.Content
.startswith('union'):
222 Type
= DataClass
.MODEL_IDENTIFIER_UNION
224 LBPos
= su
.Content
.find('{')
225 RBPos
= su
.Content
.find('}')
226 if LBPos
== -1 or RBPos
== -1:
227 Name
= su
.Content
[SkipLen
:].strip()
230 Name
= su
.Content
[SkipLen
:LBPos
].strip()
231 Value
= su
.Content
[LBPos
:RBPos
+ 1]
232 IdPE
= DataClass
.IdentifierClass(-1, '', '', Name
, Value
, Type
, -1, -1, su
.StartPos
[0], su
.StartPos
[1], su
.EndPos
[0], su
.EndPos
[1])
235 TdFuncPointerPattern
= GetTypedefFuncPointerPattern()
236 for td
in FileProfile
.TypedefDefinitionList
:
240 if TdFuncPointerPattern
.match(td
.ToType
):
241 Modifier
= td
.FromType
242 LBPos
= td
.ToType
.find('(')
243 TmpStr
= td
.ToType
[LBPos
+ 1:].strip()
244 StarPos
= TmpStr
.find('*')
246 Modifier
+= ' ' + TmpStr
[0:StarPos
]
247 while TmpStr
[StarPos
] == '*':
248 # Modifier += ' ' + '*'
250 TmpStr
= TmpStr
[StarPos
:].strip()
251 RBPos
= TmpStr
.find(')')
252 Name
= TmpStr
[0:RBPos
]
253 Value
= 'FP' + TmpStr
[RBPos
+ 1:]
255 while Name
.startswith('*'):
257 Name
= Name
.lstrip('*').strip()
259 if Name
.find('[') != -1:
260 LBPos
= Name
.find('[')
261 RBPos
= Name
.rfind(']')
262 Value
+= Name
[LBPos
: RBPos
+ 1]
263 Name
= Name
[0 : LBPos
]
265 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])
268 for funcCall
in FileProfile
.FunctionCallingList
:
269 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])
273 def StripNonAlnumChars(Str
):
276 if Char
.isalnum() or Char
== '_':
280 def GetParamList(FuncDeclarator
, FuncNameLine
=0, FuncNameOffset
=0):
281 FuncDeclarator
= StripComments(FuncDeclarator
)
283 #DeclSplitList = FuncDeclarator.split('(')
284 LBPos
= FuncDeclarator
.find('(')
285 #if len(DeclSplitList) < 2:
288 #FuncName = DeclSplitList[0]
289 FuncName
= FuncDeclarator
[0:LBPos
]
290 #ParamStr = DeclSplitList[1].rstrip(')')
291 ParamStr
= FuncDeclarator
[LBPos
+ 1:].rstrip(')')
294 TailChar
= FuncName
[-1]
295 while not TailChar
.isalpha() and TailChar
!= '_':
298 FuncName
= FuncName
.rstrip('\r\n').rstrip('\n')
301 elif TailChar
== '\r':
302 FuncName
= FuncName
.rstrip('\r')
305 elif TailChar
== ' ':
306 FuncName
= FuncName
.rstrip(' ')
308 elif TailChar
== '\t':
309 FuncName
= FuncName
.rstrip('\t')
312 FuncName
= FuncName
[:-1]
313 TailChar
= FuncName
[-1]
315 OffsetSkipped
+= 1 #skip '('
317 for p
in ParamStr
.split(','):
321 ParamName
= ListP
[-1]
322 DeclText
= ParamName
.strip()
323 RightSpacePos
= p
.rfind(ParamName
)
324 ParamModifier
= p
[0:RightSpacePos
]
325 if ParamName
== 'OPTIONAL':
326 if ParamModifier
== '':
327 ParamModifier
+= ' ' + 'OPTIONAL'
330 ParamName
= ListP
[-2]
331 DeclText
= ParamName
.strip()
332 RightSpacePos
= p
.rfind(ParamName
)
333 ParamModifier
= p
[0:RightSpacePos
]
334 ParamModifier
+= 'OPTIONAL'
335 while DeclText
.startswith('*'):
336 ParamModifier
+= ' ' + '*'
337 DeclText
= DeclText
.lstrip('*').strip()
339 # ignore array length if exists.
340 LBIndex
= ParamName
.find('[')
342 ParamName
= ParamName
[0:LBIndex
]
344 Start
= RightSpacePos
350 if FirstChar
== '\r':
354 elif FirstChar
== '\n':
359 elif FirstChar
== ' ':
362 elif FirstChar
== '\t':
370 ParamBeginLine
= FuncNameLine
+ LineSkipped
371 ParamBeginOffset
= FuncNameOffset
+ OffsetSkipped
373 Index
= Start
+ len(ParamName
)
375 while Index
< len(p
):
378 if FirstChar
== '\r':
382 elif FirstChar
== '\n':
387 elif FirstChar
== ' ':
390 elif FirstChar
== '\t':
398 ParamEndLine
= FuncNameLine
+ LineSkipped
399 ParamEndOffset
= FuncNameOffset
+ OffsetSkipped
400 if ParamName
!= '...':
401 ParamName
= StripNonAlnumChars(ParamName
)
402 IdParam
= DataClass
.IdentifierClass(-1, ParamModifier
, '', ParamName
, '', DataClass
.MODEL_IDENTIFIER_PARAMETER
, -1, -1, ParamBeginLine
, ParamBeginOffset
, ParamEndLine
, ParamEndOffset
)
403 ParamIdList
.append(IdParam
)
405 OffsetSkipped
+= 1 #skip ','
409 def GetFunctionList():
411 for FuncDef
in FileProfile
.FunctionDefinitionList
:
413 DeclText
= FuncDef
.Declarator
.lstrip()
414 FuncNameStartLine
= FuncDef
.NamePos
[0]
415 FuncNameStartColumn
= FuncDef
.NamePos
[1]
416 FirstChar
= DeclText
[0]
417 while not FirstChar
.isalpha() and FirstChar
!= '_':
419 FuncDef
.Modifier
+= '*'
420 FuncNameStartColumn
+= 1
421 DeclText
= DeclText
.lstrip('*')
422 elif FirstChar
== '\r':
423 DeclText
= DeclText
.lstrip('\r\n').lstrip('\r')
424 FuncNameStartLine
+= 1
425 FuncNameStartColumn
= 0
426 elif FirstChar
== '\n':
427 DeclText
= DeclText
.lstrip('\n')
428 FuncNameStartLine
+= 1
429 FuncNameStartColumn
= 0
430 elif FirstChar
== ' ':
431 DeclText
= DeclText
.lstrip(' ')
432 FuncNameStartColumn
+= 1
433 elif FirstChar
== '\t':
434 DeclText
= DeclText
.lstrip('\t')
435 FuncNameStartColumn
+= 8
437 DeclText
= DeclText
[1:]
438 FuncNameStartColumn
+= 1
439 FirstChar
= DeclText
[0]
441 FuncDef
.Declarator
= DeclText
442 DeclSplitList
= FuncDef
.Declarator
.split('(')
443 if len(DeclSplitList
) < 2:
446 FuncName
= DeclSplitList
[0]
447 FuncNamePartList
= FuncName
.split()
448 if len(FuncNamePartList
) > 1:
449 FuncName
= FuncNamePartList
[-1]
450 NameStart
= DeclSplitList
[0].rfind(FuncName
)
452 FuncDef
.Modifier
+= ' ' + DeclSplitList
[0][0:NameStart
]
455 while Index
< NameStart
:
456 FirstChar
= DeclSplitList
[0][Index
]
457 if DeclSplitList
[0][Index
:].startswith('EFIAPI'):
459 FuncNameStartColumn
+= 6
462 elif FirstChar
== '\r':
464 FuncNameStartLine
+= 1
465 FuncNameStartColumn
= 0
466 elif FirstChar
== '\n':
469 FuncNameStartLine
+= 1
470 FuncNameStartColumn
= 0
471 elif FirstChar
== ' ':
473 FuncNameStartColumn
+= 1
474 elif FirstChar
== '\t':
476 FuncNameStartColumn
+= 8
479 FuncNameStartColumn
+= 1
482 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
)
483 FuncObjList
.append(FuncObj
)
487 def GetFileModificationTimeFromDB(FullFileName
):
490 SqlStatement
= """ select TimeStamp
492 where FullPath = \'%s\'
494 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
495 for Result
in ResultSet
:
496 TimeValue
= Result
[0]
499 def CollectSourceCodeDataIntoDB(RootDir
):
501 tuple = os
.walk(RootDir
)
502 IgnoredPattern
= GetIgnoredDirListPattern()
503 ParseErrorFileList
= []
505 for dirpath
, dirnames
, filenames
in tuple:
506 if IgnoredPattern
.match(dirpath
.upper()):
510 Dirname
= os
.path
.join(dirpath
, Dir
)
511 if os
.path
.islink(Dirname
):
512 Dirname
= os
.path
.realpath(Dirname
)
513 if os
.path
.isdir(Dirname
):
514 # symlinks to directories are treated as directories
516 dirnames
.append(Dirname
)
519 if f
.lower() in EccGlobalData
.gConfig
.SkipFileList
:
522 FullName
= os
.path
.normpath(os
.path
.join(dirpath
, f
))
523 model
= DataClass
.MODEL_FILE_OTHERS
524 if os
.path
.splitext(f
)[1] in ('.h', '.c'):
525 EdkLogger
.info("Parsing " + FullName
)
526 model
= f
.endswith('c') and DataClass
.MODEL_FILE_C
or DataClass
.MODEL_FILE_H
527 collector
= CodeFragmentCollector
.CodeFragmentCollector(FullName
)
529 collector
.ParseFile()
531 ParseErrorFileList
.append(FullName
)
532 collector
.CleanFileProfileBuffer()
533 collector
.ParseFileWithClearedPPDirective()
534 # collector.PrintFragments()
535 BaseName
= os
.path
.basename(f
)
536 DirName
= os
.path
.dirname(FullName
)
537 Ext
= os
.path
.splitext(f
)[1].lstrip('.')
538 ModifiedTime
= os
.path
.getmtime(FullName
)
539 FileObj
= DataClass
.FileClass(-1, BaseName
, Ext
, DirName
, FullName
, model
, ModifiedTime
, GetFunctionList(), GetIdentifierList(), [])
540 FileObjList
.append(FileObj
)
542 collector
.CleanFileProfileBuffer()
544 if len(ParseErrorFileList
) > 0:
545 EdkLogger
.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList
))
548 for file in FileObjList
:
549 if file.ExtName
.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
550 Db
.InsertOneFile(file)
552 Db
.UpdateIdentifierBelongsToFunction()
554 def GetTableID(FullFileName
, ErrorMsgList
=None):
555 if ErrorMsgList
is None:
559 SqlStatement
= """ select ID
561 where FullPath like '%s'
563 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
566 for Result
in ResultSet
:
568 ErrorMsgList
.append('Duplicate file ID found in DB for file %s' % FullFileName
)
572 ErrorMsgList
.append('NO file ID found in DB for file %s' % FullFileName
)
576 def GetIncludeFileList(FullFileName
):
577 if os
.path
.splitext(FullFileName
)[1].upper() not in ('.H'):
579 IFList
= IncludeFileListDict
.get(FullFileName
)
580 if IFList
is not None:
583 FileID
= GetTableID(FullFileName
)
588 FileTable
= 'Identifier' + str(FileID
)
589 SqlStatement
= """ select Value
592 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_INCLUDE
)
593 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
594 IncludeFileListDict
[FullFileName
] = ResultSet
597 def GetFullPathOfIncludeFile(Str
, IncludePathList
):
598 for IncludePath
in IncludePathList
:
599 FullPath
= os
.path
.join(IncludePath
, Str
)
600 FullPath
= os
.path
.normpath(FullPath
)
601 if os
.path
.exists(FullPath
):
605 def GetAllIncludeFiles(FullFileName
):
606 if AllIncludeFileListDict
.get(FullFileName
) is not None:
607 return AllIncludeFileListDict
.get(FullFileName
)
609 FileDirName
= os
.path
.dirname(FullFileName
)
610 IncludePathList
= IncludePathListDict
.get(FileDirName
)
611 if IncludePathList
is None:
612 IncludePathList
= MetaDataParser
.GetIncludeListOfFile(EccGlobalData
.gWorkspace
, FullFileName
, GetDB())
613 if FileDirName
not in IncludePathList
:
614 IncludePathList
.insert(0, FileDirName
)
615 IncludePathListDict
[FileDirName
] = IncludePathList
616 IncludeFileQueue
= []
617 for IncludeFile
in GetIncludeFileList(FullFileName
):
618 FileName
= IncludeFile
[0].lstrip('#').strip()
619 FileName
= FileName
.lstrip('include').strip()
620 FileName
= FileName
.strip('\"')
621 FileName
= FileName
.lstrip('<').rstrip('>').strip()
622 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
623 if FullPath
is not None:
624 IncludeFileQueue
.append(FullPath
)
627 while i
< len(IncludeFileQueue
):
628 for IncludeFile
in GetIncludeFileList(IncludeFileQueue
[i
]):
629 FileName
= IncludeFile
[0].lstrip('#').strip()
630 FileName
= FileName
.lstrip('include').strip()
631 FileName
= FileName
.strip('\"')
632 FileName
= FileName
.lstrip('<').rstrip('>').strip()
633 FullPath
= GetFullPathOfIncludeFile(FileName
, IncludePathList
)
634 if FullPath
is not None and FullPath
not in IncludeFileQueue
:
635 IncludeFileQueue
.insert(i
+ 1, FullPath
)
638 AllIncludeFileListDict
[FullFileName
] = IncludeFileQueue
639 return IncludeFileQueue
641 def GetPredicateListFromPredicateExpStr(PES
):
648 p
= GetFuncDeclPattern()
649 while i
< len(PES
) - 1:
650 if (PES
[i
].isalnum() or PES
[i
] == '_' or PES
[i
] == '*') and LogicOpPos
> PredicateBegin
:
652 if (PES
[i
] == '&' and PES
[i
+ 1] == '&') or (PES
[i
] == '|' and PES
[i
+ 1] == '|'):
654 Exp
= PES
[PredicateBegin
:i
].strip()
655 # Exp may contain '.' or '->'
656 TmpExp
= Exp
.replace('.', '').replace('->', '')
658 PredicateList
.append(Exp
)
660 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
663 if PredicateBegin
> LogicOpPos
:
664 while PredicateBegin
< len(PES
):
665 if PES
[PredicateBegin
].isalnum() or PES
[PredicateBegin
] == '_' or PES
[PredicateBegin
] == '*':
668 Exp
= PES
[PredicateBegin
:len(PES
)].strip()
669 # Exp may contain '.' or '->'
670 TmpExp
= Exp
.replace('.', '').replace('->', '')
672 PredicateList
.append(Exp
)
674 PredicateList
.append(Exp
.rstrip(';').rstrip(')').strip())
677 def GetCNameList(Lvalue
, StarList
=[]):
685 while SearchBegin
< len(Lvalue
):
686 while i
< len(Lvalue
):
687 if Lvalue
[i
].isalnum() or Lvalue
[i
] == '_':
693 VarList
.append(Lvalue
[VarStart
:VarEnd
+ 1])
697 if VarStart
== -1 and Lvalue
[i
] == '*':
704 DotIndex
= Lvalue
[VarEnd
:].find('.')
705 ArrowIndex
= Lvalue
[VarEnd
:].find('->')
706 if DotIndex
== -1 and ArrowIndex
== -1:
708 elif DotIndex
== -1 and ArrowIndex
!= -1:
709 SearchBegin
= VarEnd
+ ArrowIndex
710 elif ArrowIndex
== -1 and DotIndex
!= -1:
711 SearchBegin
= VarEnd
+ DotIndex
713 SearchBegin
= VarEnd
+ ((DotIndex
< ArrowIndex
) and DotIndex
or ArrowIndex
)
721 def SplitPredicateByOp(Str
, Op
, IsFuncCalling
=False):
730 while Index
< len(Str
):
731 while not LBFound
and Str
[Index
] != '_' and not Str
[Index
].isalnum():
734 while not LBFound
and (Str
[Index
].isalnum() or Str
[Index
] == '_'):
736 # maybe type-cast at the begining, skip it.
737 RemainingStr
= Str
[Index
:].lstrip()
738 if RemainingStr
.startswith(')') and not LBFound
:
742 if RemainingStr
.startswith('(') and not LBFound
:
745 if Str
[Index
] == '(':
746 UnmatchedLBCount
+= 1
750 if Str
[Index
] == ')':
751 UnmatchedLBCount
-= 1
753 if UnmatchedLBCount
== 0:
759 if UnmatchedLBCount
> 0:
762 IndexInRemainingStr
= Str
[Index
:].find(Op
)
763 if IndexInRemainingStr
== -1:
766 Name
= Str
[0:Index
+ IndexInRemainingStr
].strip()
767 Value
= Str
[Index
+ IndexInRemainingStr
+ len(Op
):].strip().strip(')')
770 TmpStr
= Str
.rstrip(';').rstrip(')')
772 Index
= TmpStr
.rfind(Op
)
776 if Str
[Index
- 1].isalnum() or Str
[Index
- 1].isspace() or Str
[Index
- 1] == ')' or Str
[Index
- 1] == ']':
777 Name
= Str
[0:Index
].strip()
778 Value
= Str
[Index
+ len(Op
):].strip()
781 TmpStr
= Str
[0:Index
- 1]
783 def SplitPredicateStr(Str
):
785 Str
= Str
.lstrip('(')
786 IsFuncCalling
= False
787 p
= GetFuncDeclPattern()
788 TmpStr
= Str
.replace('.', '').replace('->', '')
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 PredPartList
= SplitPredicateByOp(Str
, '<', IsFuncCalling
)
813 if len(PredPartList
) > 1:
814 return [PredPartList
, '<']
816 return [[Str
, None], None]
818 def GetFuncContainsPE(ExpLine
, ResultSet
):
819 for Result
in ResultSet
:
820 if Result
[0] < ExpLine
and Result
[1] > ExpLine
:
824 def PatternInModifier(Modifier
, SubStr
):
825 PartList
= Modifier
.split()
826 for Part
in PartList
:
831 def GetDataTypeFromModifier(ModifierStr
):
832 MList
= ModifierStr
.split()
835 if M
in EccGlobalData
.gConfig
.ModifierSet
:
838 if M
.startswith('[') or M
.endswith(']'):
840 ReturnType
+= M
+ ' '
842 ReturnType
= ReturnType
.strip()
843 if len(ReturnType
) == 0:
847 def DiffModifier(Str1
, Str2
):
848 PartList1
= Str1
.split()
849 PartList2
= Str2
.split()
850 if PartList1
== PartList2
:
855 def GetTypedefDict(FullFileName
):
857 Dict
= ComplexTypeDict
.get(FullFileName
)
861 FileID
= GetTableID(FullFileName
)
862 FileTable
= 'Identifier' + str(FileID
)
864 SqlStatement
= """ select Modifier, Name, Value, ID
867 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
868 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
871 for Result
in ResultSet
:
872 if len(Result
[0]) == 0:
873 Dict
[Result
[1]] = Result
[2]
875 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
876 for F
in IncludeFileList
:
877 FileID
= GetTableID(F
)
881 FileTable
= 'Identifier' + str(FileID
)
882 SqlStatement
= """ select Modifier, Name, Value, ID
885 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
886 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
888 for Result
in ResultSet
:
889 if not Result
[2].startswith('FP ('):
890 Dict
[Result
[1]] = Result
[2]
892 if len(Result
[0]) == 0:
893 Dict
[Result
[1]] = 'VOID'
895 Dict
[Result
[1]] = GetDataTypeFromModifier(Result
[0])
897 ComplexTypeDict
[FullFileName
] = Dict
900 def GetSUDict(FullFileName
):
902 Dict
= SUDict
.get(FullFileName
)
906 FileID
= GetTableID(FullFileName
)
907 FileTable
= 'Identifier' + str(FileID
)
909 SqlStatement
= """ select Name, Value, ID
911 where Model = %d or Model = %d
912 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
913 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
916 for Result
in ResultSet
:
917 if len(Result
[1]) > 0:
918 Dict
[Result
[0]] = Result
[1]
920 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
921 for F
in IncludeFileList
:
922 FileID
= GetTableID(F
)
926 FileTable
= 'Identifier' + str(FileID
)
927 SqlStatement
= """ select Name, Value, ID
929 where Model = %d or Model = %d
930 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
, DataClass
.MODEL_IDENTIFIER_UNION
)
931 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
933 for Result
in ResultSet
:
934 if len(Result
[1]) > 0:
935 Dict
[Result
[0]] = Result
[1]
937 SUDict
[FullFileName
] = Dict
940 def StripComments(Str
):
942 ListFromStr
= list(Str
)
945 DoubleSlashComment
= False
947 while Index
< len(ListFromStr
):
948 # meet new line, then no longer in a comment for //
949 if ListFromStr
[Index
] == '\n':
950 if InComment
and DoubleSlashComment
:
952 DoubleSlashComment
= False
954 # check for */ comment end
955 elif InComment
and not DoubleSlashComment
and ListFromStr
[Index
] == '*' and ListFromStr
[Index
+ 1] == '/':
956 ListFromStr
[Index
] = ' '
958 ListFromStr
[Index
] = ' '
961 # set comments to spaces
963 ListFromStr
[Index
] = ' '
965 # check for // comment
966 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '/' and ListFromStr
[Index
+ 2] != '\n':
968 DoubleSlashComment
= True
970 # check for /* comment start
971 elif ListFromStr
[Index
] == '/' and ListFromStr
[Index
+ 1] == '*':
972 ListFromStr
[Index
] = ' '
974 ListFromStr
[Index
] = ' '
980 # restore from List to String
981 Str
= "".join(ListFromStr
)
982 Str
= Str
.rstrip(' ')
986 def GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
):
987 Value
= TypedefDict
.get(Type
)
989 Value
= SUDict
.get(Type
)
993 LBPos
= Value
.find('{')
995 FTList
= Value
.split()
997 if FT
not in ('struct', 'union'):
998 Value
= TypedefDict
.get(FT
)
1000 Value
= SUDict
.get(FT
)
1006 LBPos
= Value
.find('{')
1008 # RBPos = Value.find('}')
1009 Fields
= Value
[LBPos
+ 1:]
1010 Fields
= StripComments(Fields
)
1011 FieldsList
= Fields
.split(';')
1012 for Field
in FieldsList
:
1013 Field
= Field
.strip()
1014 Index
= Field
.rfind(FieldName
)
1017 if not Field
[Index
- 1].isalnum():
1018 if Index
+ len(FieldName
) == len(Field
):
1019 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1022 # For the condition that the field in struct is an array with [] sufixes...
1023 if not Field
[Index
+ len(FieldName
)].isalnum():
1024 Type
= GetDataTypeFromModifier(Field
[0:Index
])
1029 def GetRealType(Type
, TypedefDict
, TargetType
=None):
1030 if TargetType
is not None and Type
== TargetType
:
1032 while TypedefDict
.get(Type
):
1033 Type
= TypedefDict
.get(Type
)
1034 if TargetType
is not None and Type
== TargetType
:
1038 def GetTypeInfo(RefList
, Modifier
, FullFileName
, TargetType
=None):
1039 TypedefDict
= GetTypedefDict(FullFileName
)
1040 SUDict
= GetSUDict(FullFileName
)
1041 Type
= GetDataTypeFromModifier(Modifier
).replace('*', '').strip()
1043 Type
= Type
.split()[-1]
1045 while Index
< len(RefList
):
1046 FieldName
= RefList
[Index
]
1047 FromType
= GetFinalTypeValue(Type
, FieldName
, TypedefDict
, SUDict
)
1048 if FromType
is None:
1050 # we want to determine the exact type.
1051 if TargetType
is not None:
1052 Type
= FromType
.split()[0]
1053 # we only want to check if it is a pointer
1056 if Type
.find('*') != -1 and Index
== len(RefList
) - 1:
1058 Type
= FromType
.split()[0]
1062 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1066 def GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
=False, TargetType
=None, StarList
=None):
1068 PredVar
= PredVarList
[0]
1069 FileID
= GetTableID(FullFileName
)
1072 FileTable
= 'Identifier' + str(FileID
)
1073 # search variable in include files
1075 # it is a function call, search function declarations and definitions
1077 SqlStatement
= """ select Modifier, ID
1079 where Model = %d and Value = \'%s\'
1080 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1081 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1083 for Result
in ResultSet
:
1084 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1085 TypedefDict
= GetTypedefDict(FullFileName
)
1086 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1089 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1090 for F
in IncludeFileList
:
1091 FileID
= GetTableID(F
)
1095 FileTable
= 'Identifier' + str(FileID
)
1096 SqlStatement
= """ select Modifier, ID
1098 where Model = %d and Value = \'%s\'
1099 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
, PredVar
)
1100 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1102 for Result
in ResultSet
:
1103 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1104 TypedefDict
= GetTypedefDict(FullFileName
)
1105 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1108 FileID
= GetTableID(FullFileName
)
1109 SqlStatement
= """ select Modifier, ID
1111 where BelongsToFile = %d and Name = \'%s\'
1112 """ % (FileID
, PredVar
)
1113 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1115 for Result
in ResultSet
:
1116 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1117 TypedefDict
= GetTypedefDict(FullFileName
)
1118 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1121 for F
in IncludeFileList
:
1122 FileID
= GetTableID(F
)
1126 FileTable
= 'Identifier' + str(FileID
)
1127 SqlStatement
= """ select Modifier, ID
1129 where BelongsToFile = %d and Name = \'%s\'
1130 """ % (FileID
, PredVar
)
1131 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1133 for Result
in ResultSet
:
1134 Type
= GetDataTypeFromModifier(Result
[0]).split()[-1]
1135 TypedefDict
= GetTypedefDict(FullFileName
)
1136 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1141 # really variable, search local variable first
1142 SqlStatement
= """ select Modifier, ID
1144 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1145 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
, FuncRecord
[0], FuncRecord
[1])
1146 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1148 for Result
in ResultSet
:
1149 if len(PredVarList
) > 1:
1150 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1153 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1154 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1156 if len(TypeList
) > 1 and StarList
is not None:
1157 for Star
in StarList
:
1159 Type
= Type
.rstrip(Star
)
1160 # Get real type after de-reference pointers.
1161 if len(Type
.strip()) == 0:
1163 TypedefDict
= GetTypedefDict(FullFileName
)
1164 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1167 # search function parameters second
1168 ParamList
= GetParamList(FuncRecord
[2])
1169 for Param
in ParamList
:
1170 if Param
.Name
.strip() == PredVar
:
1171 if len(PredVarList
) > 1:
1172 Type
= GetTypeInfo(PredVarList
[1:], Param
.Modifier
, FullFileName
, TargetType
)
1175 TypeList
= GetDataTypeFromModifier(Param
.Modifier
).split()
1177 if Type
== '*' and len(TypeList
) >= 2:
1179 if len(TypeList
) > 1 and StarList
is not None:
1180 for Star
in StarList
:
1182 Type
= Type
.rstrip(Star
)
1183 # Get real type after de-reference pointers.
1184 if len(Type
.strip()) == 0:
1186 TypedefDict
= GetTypedefDict(FullFileName
)
1187 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1190 # search global variable next
1191 SqlStatement
= """ select Modifier, ID
1193 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1194 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1195 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1197 for Result
in ResultSet
:
1198 if len(PredVarList
) > 1:
1199 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1202 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1204 if len(TypeList
) > 1 and StarList
is not None:
1205 for Star
in StarList
:
1207 Type
= Type
.rstrip(Star
)
1208 # Get real type after de-reference pointers.
1209 if len(Type
.strip()) == 0:
1211 TypedefDict
= GetTypedefDict(FullFileName
)
1212 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1215 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1216 for F
in IncludeFileList
:
1217 FileID
= GetTableID(F
)
1221 FileTable
= 'Identifier' + str(FileID
)
1222 SqlStatement
= """ select Modifier, ID
1224 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1225 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, PredVar
)
1226 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1228 for Result
in ResultSet
:
1229 if len(PredVarList
) > 1:
1230 Type
= GetTypeInfo(PredVarList
[1:], Result
[0], FullFileName
, TargetType
)
1233 TypeList
= GetDataTypeFromModifier(Result
[0]).split()
1235 if len(TypeList
) > 1 and StarList
is not None:
1236 for Star
in StarList
:
1238 Type
= Type
.rstrip(Star
)
1239 # Get real type after de-reference pointers.
1240 if len(Type
.strip()) == 0:
1242 TypedefDict
= GetTypedefDict(FullFileName
)
1243 Type
= GetRealType(Type
, TypedefDict
, TargetType
)
1246 def GetTypeFromArray(Type
, Var
):
1247 Count
= Var
.count('[')
1251 Type
= Type
.rstrip('*')
1256 def CheckFuncLayoutReturnType(FullFileName
):
1259 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1264 FileTable
= 'Identifier' + str(FileID
)
1265 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1268 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1269 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1270 for Result
in ResultSet
:
1271 ReturnType
= GetDataTypeFromModifier(Result
[0])
1272 TypeStart
= ReturnType
.split()[0]
1273 FuncName
= Result
[5]
1274 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1277 if Result0
.upper().startswith('STATIC'):
1278 Result0
= Result0
[6:].strip()
1279 Index
= Result0
.find(TypeStart
)
1280 if Index
!= 0 or Result
[3] != 0:
1281 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, FileTable
, Result
[1])
1283 if Result
[2] == Result
[4]:
1284 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear on its own line' % FuncName
, FileTable
, Result
[1])
1286 SqlStatement
= """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1288 where BelongsToFile = %d
1290 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1291 for Result
in ResultSet
:
1292 ReturnType
= GetDataTypeFromModifier(Result
[0])
1293 TypeStart
= ReturnType
.split()[0]
1294 FuncName
= Result
[5]
1295 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, FuncName
):
1298 if Result0
.upper().startswith('STATIC'):
1299 Result0
= Result0
[6:].strip()
1300 Index
= Result0
.find(ReturnType
)
1301 if Index
!= 0 or Result
[3] != 0:
1302 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE
, '[%s] Return Type should appear at the start of line' % FuncName
, 'Function', Result
[1])
1304 def CheckFuncLayoutModifier(FullFileName
):
1307 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1312 FileTable
= 'Identifier' + str(FileID
)
1313 SqlStatement
= """ select Modifier, ID
1316 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1317 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1318 for Result
in ResultSet
:
1319 ReturnType
= GetDataTypeFromModifier(Result
[0])
1320 TypeStart
= ReturnType
.split()[0]
1322 if Result0
.upper().startswith('STATIC'):
1323 Result0
= Result0
[6:].strip()
1324 Index
= Result0
.find(TypeStart
)
1326 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', FileTable
, Result
[1])
1328 SqlStatement
= """ select Modifier, ID
1330 where BelongsToFile = %d
1332 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1333 for Result
in ResultSet
:
1334 ReturnType
= GetDataTypeFromModifier(Result
[0])
1335 TypeStart
= ReturnType
.split()[0]
1337 if Result0
.upper().startswith('STATIC'):
1338 Result0
= Result0
[6:].strip()
1339 Index
= Result0
.find(TypeStart
)
1341 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER
, '', 'Function', Result
[1])
1343 def CheckFuncLayoutName(FullFileName
):
1345 # Parameter variable format pattern.
1346 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1347 ParamIgnoreList
= ('VOID', '...')
1348 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1353 FileTable
= 'Identifier' + str(FileID
)
1354 SqlStatement
= """ select Name, ID, EndColumn, Value
1357 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1358 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1359 for Result
in ResultSet
:
1360 FuncName
= Result
[3]
1361 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1364 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, FileTable
, Result
[1])
1365 ParamList
= GetParamList(Result
[0])
1366 if len(ParamList
) == 0:
1369 for Param
in ParamList
:
1370 if Param
.StartLine
<= StartLine
:
1371 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, FileTable
, Result
[1])
1372 if Param
.StartLine
- StartLine
> 1:
1373 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, FileTable
, Result
[1])
1374 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
):
1375 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1376 StartLine
= Param
.StartLine
1378 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1379 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', FileTable
, Result
[1])
1381 SqlStatement
= """ select Modifier, ID, FunNameStartColumn, Name
1383 where BelongsToFile = %d
1385 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1386 for Result
in ResultSet
:
1387 FuncName
= Result
[3]
1388 if EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, FuncName
):
1391 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Function name [%s] should appear at the start of a line' % FuncName
, 'Function', Result
[1])
1392 ParamList
= GetParamList(Result
[0])
1393 if len(ParamList
) == 0:
1396 for Param
in ParamList
:
1397 if Param
.StartLine
<= StartLine
:
1398 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Parameter %s should be in its own line.' % Param
.Name
, 'Function', Result
[1])
1399 if Param
.StartLine
- StartLine
> 1:
1400 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, 'Empty line appears before Parameter %s.' % Param
.Name
, 'Function', Result
[1])
1401 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
):
1402 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Parameter [%s] NOT follow naming convention.' % Param
.Name
, FileTable
, Result
[1])
1403 StartLine
= Param
.StartLine
1404 if not Result
[0].endswith('\n )') and not Result
[0].endswith('\r )'):
1405 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME
, '\')\' should be on a new line and indented two spaces', 'Function', Result
[1])
1407 def CheckFuncLayoutPrototype(FullFileName
):
1410 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1414 FileTable
= 'Identifier' + str(FileID
)
1416 SqlStatement
= """ select Modifier, Header, Name, ID
1418 where BelongsToFile = %d
1420 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1421 if len(ResultSet
) == 0:
1425 for Result
in ResultSet
:
1426 FuncDefList
.append(Result
)
1428 SqlStatement
= """ select Modifier, Name, ID
1431 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1432 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1434 for Result
in ResultSet
:
1435 FuncDeclList
.append(Result
)
1438 for FuncDef
in FuncDefList
:
1439 FuncName
= FuncDef
[2].strip()
1440 FuncModifier
= FuncDef
[0]
1441 FuncDefHeader
= FuncDef
[1]
1442 for FuncDecl
in FuncDeclList
:
1443 LBPos
= FuncDecl
[1].find('(')
1444 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1445 DeclModifier
= FuncDecl
[0]
1446 if DeclName
== FuncName
:
1447 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1448 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1449 ParamListOfDef
= GetParamList(FuncDefHeader
)
1450 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1451 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1452 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1456 while Index
< len(ParamListOfDef
):
1457 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1458 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])
1462 UndeclFuncList
.append(FuncDef
)
1464 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1466 for F
in IncludeFileList
:
1467 FileID
= GetTableID(F
, ErrorMsgList
)
1471 FileTable
= 'Identifier' + str(FileID
)
1472 SqlStatement
= """ select Modifier, Name, ID
1475 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1476 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1478 for Result
in ResultSet
:
1479 FuncDeclList
.append(Result
)
1481 for FuncDef
in UndeclFuncList
:
1482 FuncName
= FuncDef
[2].strip()
1483 FuncModifier
= FuncDef
[0]
1484 FuncDefHeader
= FuncDef
[1]
1485 for FuncDecl
in FuncDeclList
:
1486 LBPos
= FuncDecl
[1].find('(')
1487 DeclName
= FuncDecl
[1][0:LBPos
].strip()
1488 DeclModifier
= FuncDecl
[0]
1489 if DeclName
== FuncName
:
1490 if DiffModifier(FuncModifier
, DeclModifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, FuncName
):
1491 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE
, 'Function [%s] modifier different with prototype.' % FuncName
, 'Function', FuncDef
[3])
1492 ParamListOfDef
= GetParamList(FuncDefHeader
)
1493 ParamListOfDecl
= GetParamList(FuncDecl
[1])
1494 if len(ParamListOfDef
) != len(ParamListOfDecl
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, FuncName
):
1495 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2
, 'Parameter number different in function [%s].' % FuncName
, 'Function', FuncDef
[3])
1499 while Index
< len(ParamListOfDef
):
1500 if DiffModifier(ParamListOfDef
[Index
].Modifier
, ParamListOfDecl
[Index
].Modifier
) and not EccGlobalData
.gException
.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3
, FuncName
):
1501 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])
1505 def CheckFuncLayoutBody(FullFileName
):
1508 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1512 FileTable
= 'Identifier' + str(FileID
)
1514 SqlStatement
= """ select BodyStartColumn, EndColumn, ID
1516 where BelongsToFile = %d
1518 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1519 if len(ResultSet
) == 0:
1521 for Result
in ResultSet
:
1523 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'open brace should be at the very beginning of a line.', 'Function', Result
[2])
1525 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY
, 'close brace should be at the very beginning of a line.', 'Function', Result
[2])
1527 def CheckFuncLayoutLocalVariable(FullFileName
):
1530 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1535 FileTable
= 'Identifier' + str(FileID
)
1536 SqlStatement
= """ select ID
1538 where BelongsToFile = %d
1540 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1541 if len(ResultSet
) == 0:
1544 for Result
in ResultSet
:
1548 SqlStatement
= """ select Name, Value, ID, Modifier
1550 where Model = %d and BelongsToFunction = %d
1551 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
, F
[0])
1552 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1553 if len(ResultSet
) == 0:
1556 for Result
in ResultSet
:
1557 if len(Result
[1]) > 0 and 'CONST' not in Result
[3]:
1558 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE
, 'Variable Name: %s' % Result
[0], FileTable
, Result
[2])
1560 def CheckMemberVariableFormat(Name
, Value
, FileTable
, TdId
, ModelId
):
1562 # Member variable format pattern.
1563 Pattern
= re
.compile(r
'^[A-Z]+\S*[a-z]\S*$')
1565 LBPos
= Value
.find('{')
1566 RBPos
= Value
.rfind('}')
1567 if LBPos
== -1 or RBPos
== -1:
1570 Fields
= Value
[LBPos
+ 1 : RBPos
]
1571 Fields
= StripComments(Fields
).strip()
1572 NestPos
= Fields
.find ('struct')
1573 if NestPos
!= -1 and (NestPos
+ len('struct') < len(Fields
)) and ModelId
!= DataClass
.MODEL_IDENTIFIER_UNION
:
1574 if not Fields
[NestPos
+ len('struct') + 1].isalnum():
1575 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1576 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested struct in [%s].' % (Name
), FileTable
, TdId
)
1578 NestPos
= Fields
.find ('union')
1579 if NestPos
!= -1 and (NestPos
+ len('union') < len(Fields
)):
1580 if not Fields
[NestPos
+ len('union') + 1].isalnum():
1581 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1582 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested union in [%s].' % (Name
), FileTable
, TdId
)
1584 NestPos
= Fields
.find ('enum')
1585 if NestPos
!= -1 and (NestPos
+ len('enum') < len(Fields
)):
1586 if not Fields
[NestPos
+ len('enum') + 1].isalnum():
1587 if not EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, Name
):
1588 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE
, 'Nested enum in [%s].' % (Name
), FileTable
, TdId
)
1591 if ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1592 FieldsList
= Fields
.split(',')
1593 # deal with enum is pre-assigned a value by function call ( , , , ...)
1596 RemoveCurrentElement
= False
1597 while Index
< len(FieldsList
):
1598 Field
= FieldsList
[Index
]
1600 if Field
.find('(') != -1:
1602 RemoveCurrentElement
= True
1606 if Field
.find(')') != -1 and QuoteCount
> 0:
1609 if RemoveCurrentElement
:
1610 FieldsList
.remove(Field
)
1612 RemoveCurrentElement
= False
1616 RemoveCurrentElement
= False
1620 FieldsList
= Fields
.split(';')
1622 for Field
in FieldsList
:
1623 Field
= Field
.strip()
1626 # For the condition that the field in struct is an array with [] sufixes...
1627 if Field
[-1] == ']':
1628 LBPos
= Field
.find('[')
1629 Field
= Field
[0:LBPos
]
1630 # For the condition that bit field ": Number"
1631 if Field
.find(':') != -1:
1632 ColonPos
= Field
.find(':')
1633 Field
= Field
[0:ColonPos
]
1635 Field
= Field
.strip()
1638 if Field
.startswith("#"):
1640 # Enum could directly assign value to variable
1641 Field
= Field
.split('=')[0].strip()
1642 TokenList
= Field
.split()
1643 # Remove pointers before variable
1644 Token
= TokenList
[-1]
1645 if Token
in ['OPTIONAL']:
1646 Token
= TokenList
[-2]
1647 if not Pattern
.match(Token
.lstrip('*')):
1648 ErrMsgList
.append(Token
.lstrip('*'))
1652 def CheckDeclTypedefFormat(FullFileName
, ModelId
):
1655 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1660 FileTable
= 'Identifier' + str(FileID
)
1661 SqlStatement
= """ select Name, StartLine, EndLine, ID, Value
1664 """ % (FileTable
, ModelId
)
1665 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1667 for Result
in ResultSet
:
1668 ResultList
.append(Result
)
1670 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1671 if ModelId
== DataClass
.MODEL_IDENTIFIER_STRUCTURE
:
1672 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1673 elif ModelId
== DataClass
.MODEL_IDENTIFIER_ENUMERATE
:
1674 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1675 elif ModelId
== DataClass
.MODEL_IDENTIFIER_UNION
:
1676 ErrorType
= ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1678 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1681 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1682 TdSet
= Db
.TblFile
.Exec(SqlStatement
)
1686 # Check member variable name format that from typedefs of ONLY this file.
1688 Name
= Td
[1].strip()
1689 Value
= Td
[2].strip()
1690 if Value
.startswith('enum'):
1691 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1692 elif Value
.startswith('struct'):
1693 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1694 elif Value
.startswith('union'):
1695 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1699 if ValueModelId
!= ModelId
:
1701 # Check member variable format.
1702 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Td
[5], ModelId
)
1703 for ErrMsg
in ErrMsgList
:
1704 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Name
+ '.' + ErrMsg
):
1706 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Name
+ '.' + ErrMsg
), FileTable
, Td
[5])
1708 # First check in current file to see whether struct/union/enum is typedef-ed.
1709 UntypedefedList
= []
1710 for Result
in ResultList
:
1711 # Check member variable format.
1712 Name
= Result
[0].strip()
1713 Value
= Result
[4].strip()
1714 if Value
.startswith('enum'):
1715 ValueModelId
= DataClass
.MODEL_IDENTIFIER_ENUMERATE
1716 elif Value
.startswith('struct'):
1717 ValueModelId
= DataClass
.MODEL_IDENTIFIER_STRUCTURE
1718 elif Value
.startswith('union'):
1719 ValueModelId
= DataClass
.MODEL_IDENTIFIER_UNION
1723 if ValueModelId
!= ModelId
:
1725 ErrMsgList
= CheckMemberVariableFormat(Name
, Value
, FileTable
, Result
[3], ModelId
)
1726 for ErrMsg
in ErrMsgList
:
1727 if EccGlobalData
.gException
.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, Result
[0] + '.' + ErrMsg
):
1729 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME
, 'Member variable [%s] NOT follow naming convention.' % (Result
[0] + '.' + ErrMsg
), FileTable
, Result
[3])
1730 # Check whether it is typedefed.
1733 # skip function pointer
1736 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1738 if not Td
[1].isupper():
1739 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1740 if Result
[0] in Td
[2].split():
1742 if not Td
[1].isupper():
1743 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1748 UntypedefedList
.append(Result
)
1751 if len(UntypedefedList
) == 0:
1754 IncludeFileList
= GetAllIncludeFiles(FullFileName
)
1756 for F
in IncludeFileList
:
1757 FileID
= GetTableID(F
, ErrorMsgList
)
1761 IncludeFileTable
= 'Identifier' + str(FileID
)
1762 SqlStatement
= """ select Modifier, Name, Value, StartLine, EndLine, ID
1765 """ % (IncludeFileTable
, DataClass
.MODEL_IDENTIFIER_TYPEDEF
)
1766 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1767 TdList
.extend(ResultSet
)
1769 for Result
in UntypedefedList
:
1771 # Check whether it is typedefed.
1777 if Result
[1] >= Td
[3] and Td
[4] >= Result
[2]:
1779 if not Td
[1].isupper():
1780 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1781 if Result
[0] in Td
[2].split():
1783 if not Td
[1].isupper():
1784 PrintErrorMsg(ErrorType
, 'Typedef should be UPPER case', FileTable
, Td
[5])
1789 PrintErrorMsg(ErrorType
, 'No Typedef for %s' % Result
[0], FileTable
, Result
[3])
1792 def CheckDeclStructTypedef(FullFileName
):
1793 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_STRUCTURE
)
1795 def CheckDeclEnumTypedef(FullFileName
):
1796 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_ENUMERATE
)
1798 def CheckDeclUnionTypedef(FullFileName
):
1799 CheckDeclTypedefFormat(FullFileName
, DataClass
.MODEL_IDENTIFIER_UNION
)
1801 def CheckDeclArgModifier(FullFileName
):
1804 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1809 FileTable
= 'Identifier' + str(FileID
)
1810 SqlStatement
= """ select Modifier, Name, ID
1813 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1814 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1815 ModifierTuple
= ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1816 MAX_MODIFIER_LENGTH
= 100
1817 for Result
in ResultSet
:
1818 for Modifier
in ModifierTuple
:
1819 if PatternInModifier(Result
[0], Modifier
) and len(Result
[0]) < MAX_MODIFIER_LENGTH
:
1820 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Variable Modifier %s' % Result
[0], FileTable
, Result
[2])
1823 SqlStatement
= """ select Modifier, Name, ID
1826 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1827 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1828 for Result
in ResultSet
:
1829 for Modifier
in ModifierTuple
:
1830 if PatternInModifier(Result
[0], Modifier
):
1831 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1834 SqlStatement
= """ select Modifier, Header, ID
1836 where BelongsToFile = %d
1838 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1839 for Result
in ResultSet
:
1840 for Modifier
in ModifierTuple
:
1841 if PatternInModifier(Result
[0], Modifier
):
1842 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER
, 'Return Type Modifier %s' % Result
[0], FileTable
, Result
[2])
1845 def CheckDeclNoUseCType(FullFileName
):
1848 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1853 FileTable
= 'Identifier' + str(FileID
)
1854 SqlStatement
= """ select Modifier, Name, ID
1857 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
1858 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1859 CTypeTuple
= ('int', 'unsigned', 'char', 'void', 'static', 'long')
1860 for Result
in ResultSet
:
1861 for Type
in CTypeTuple
:
1862 if PatternInModifier(Result
[0], Type
):
1863 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1864 Result
[0] + ' ' + Result
[1]):
1866 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
,
1867 'Invalid variable type (%s) in definition [%s]' % (Type
, Result
[0] + ' ' + Result
[1]),
1872 SqlStatement
= """ select Modifier, Name, ID, Value
1875 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
1876 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1877 for Result
in ResultSet
:
1878 ParamList
= GetParamList(Result
[1])
1879 FuncName
= Result
[3]
1880 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1882 for Type
in CTypeTuple
:
1883 if PatternInModifier(Result
[0], Type
):
1884 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '%s Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1886 for Param
in ParamList
:
1887 if PatternInModifier(Param
.Modifier
, Type
):
1888 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1890 SqlStatement
= """ select Modifier, Header, ID, Name
1892 where BelongsToFile = %d
1894 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1895 for Result
in ResultSet
:
1896 ParamList
= GetParamList(Result
[1])
1897 FuncName
= Result
[3]
1898 if EccGlobalData
.gException
.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, FuncName
):
1900 for Type
in CTypeTuple
:
1901 if PatternInModifier(Result
[0], Type
):
1902 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, '[%s] Return type %s' % (FuncName
, Result
[0]), FileTable
, Result
[2])
1904 for Param
in ParamList
:
1905 if PatternInModifier(Param
.Modifier
, Type
):
1906 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE
, 'Parameter %s' % Param
.Name
, FileTable
, Result
[2])
1909 def CheckPointerNullComparison(FullFileName
):
1912 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1916 # cache the found function return type to accelerate later checking in this file.
1917 FuncReturnTypeDict
= {}
1920 FileTable
= 'Identifier' + str(FileID
)
1921 SqlStatement
= """ select Value, StartLine, ID
1924 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
1925 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1926 if len(ResultSet
) == 0:
1929 for Result
in ResultSet
:
1930 PSL
.append([Result
[0], Result
[1], Result
[2]])
1932 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
1934 where BelongsToFile = %d
1936 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
1938 for Result
in ResultSet
:
1939 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
1941 p
= GetFuncDeclPattern()
1943 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
1944 if FuncRecord
is None:
1947 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
1948 PredInfo
= SplitPredicateStr(Exp
)
1949 if PredInfo
[1] is None:
1950 PredVarStr
= PredInfo
[0][0].strip()
1952 SearchInCache
= False
1953 # PredVarStr may contain '.' or '->'
1954 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
1956 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
1957 SearchInCache
= True
1958 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1959 if TmpStr
.startswith(PredVarStr
):
1962 if PredVarStr
.strip() in IgnoredKeywordList
:
1965 PredVarList
= GetCNameList(PredVarStr
, StarList
)
1966 # No variable found, maybe value first? like (0 == VarName)
1967 if len(PredVarList
) == 0:
1970 Type
= FuncReturnTypeDict
.get(PredVarStr
)
1971 if Type
is not None:
1972 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1973 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1976 if PredVarStr
in FuncReturnTypeDict
:
1979 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, None, StarList
)
1981 FuncReturnTypeDict
[PredVarStr
] = Type
1984 Type
= GetTypeFromArray(Type
, PredVarStr
)
1985 if Type
.find('*') != -1 and Type
!= 'BOOLEAN*':
1986 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
1988 def CheckNonBooleanValueComparison(FullFileName
):
1991 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
1995 # cache the found function return type to accelerate later checking in this file.
1996 FuncReturnTypeDict
= {}
1999 FileTable
= 'Identifier' + str(FileID
)
2000 SqlStatement
= """ select Value, StartLine, ID
2003 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2004 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2005 if len(ResultSet
) == 0:
2008 for Result
in ResultSet
:
2009 PSL
.append([Result
[0], Result
[1], Result
[2]])
2011 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2013 where BelongsToFile = %d
2015 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2017 for Result
in ResultSet
:
2018 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2020 p
= GetFuncDeclPattern()
2022 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2023 if FuncRecord
is None:
2026 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2027 PredInfo
= SplitPredicateStr(Exp
)
2028 if PredInfo
[1] is None:
2029 PredVarStr
= PredInfo
[0][0].strip()
2031 SearchInCache
= False
2032 # PredVarStr may contain '.' or '->'
2033 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2035 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2036 SearchInCache
= True
2037 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2038 if TmpStr
.startswith(PredVarStr
):
2041 if PredVarStr
.strip() in IgnoredKeywordList
:
2044 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2045 # No variable found, maybe value first? like (0 == VarName)
2046 if len(PredVarList
) == 0:
2050 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2051 if Type
is not None:
2052 if Type
.find('BOOLEAN') == -1:
2053 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2056 if PredVarStr
in FuncReturnTypeDict
:
2058 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2060 FuncReturnTypeDict
[PredVarStr
] = Type
2063 if Type
.find('BOOLEAN') == -1:
2064 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2067 def CheckBooleanValueComparison(FullFileName
):
2070 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2074 # cache the found function return type to accelerate later checking in this file.
2075 FuncReturnTypeDict
= {}
2078 FileTable
= 'Identifier' + str(FileID
)
2079 SqlStatement
= """ select Value, StartLine, ID
2082 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_PREDICATE_EXPRESSION
)
2083 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2084 if len(ResultSet
) == 0:
2087 for Result
in ResultSet
:
2088 PSL
.append([Result
[0], Result
[1], Result
[2]])
2090 SqlStatement
= """ select BodyStartLine, EndLine, Header, Modifier, ID
2092 where BelongsToFile = %d
2094 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2096 for Result
in ResultSet
:
2097 FL
.append([Result
[0], Result
[1], Result
[2], Result
[3], Result
[4]])
2099 p
= GetFuncDeclPattern()
2101 FuncRecord
= GetFuncContainsPE(Str
[1], FL
)
2102 if FuncRecord
is None:
2105 for Exp
in GetPredicateListFromPredicateExpStr(Str
[0]):
2106 PredInfo
= SplitPredicateStr(Exp
)
2107 if PredInfo
[1] in ('==', '!=') and PredInfo
[0][1] in ('TRUE', 'FALSE'):
2108 PredVarStr
= PredInfo
[0][0].strip()
2110 SearchInCache
= False
2111 # PredVarStr may contain '.' or '->'
2112 TmpStr
= PredVarStr
.replace('.', '').replace('->', '')
2114 PredVarStr
= PredVarStr
[0:PredVarStr
.find('(')]
2115 SearchInCache
= True
2116 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2117 if TmpStr
.startswith(PredVarStr
):
2120 if PredVarStr
.strip() in IgnoredKeywordList
:
2123 PredVarList
= GetCNameList(PredVarStr
, StarList
)
2124 # No variable found, maybe value first? like (0 == VarName)
2125 if len(PredVarList
) == 0:
2129 Type
= FuncReturnTypeDict
.get(PredVarStr
)
2130 if Type
is not None:
2131 if Type
.find('BOOLEAN') != -1:
2132 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2135 if PredVarStr
in FuncReturnTypeDict
:
2138 Type
= GetVarInfo(PredVarList
, FuncRecord
, FullFileName
, IsFuncCall
, 'BOOLEAN', StarList
)
2140 FuncReturnTypeDict
[PredVarStr
] = Type
2143 if Type
.find('BOOLEAN') != -1:
2144 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE
, 'Predicate Expression: %s' % Exp
, FileTable
, Str
[2])
2147 def CheckHeaderFileData(FullFileName
):
2150 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2155 FileTable
= 'Identifier' + str(FileID
)
2156 SqlStatement
= """ select ID, Modifier
2159 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_VARIABLE
)
2160 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2161 for Result
in ResultSet
:
2162 if not Result
[1].startswith('extern'):
2163 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Variable definition appears in header file', FileTable
, Result
[0])
2165 SqlStatement
= """ select ID
2167 where BelongsToFile = %d
2169 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2170 for Result
in ResultSet
:
2171 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA
, 'Function definition appears in header file', 'Function', Result
[0])
2175 def CheckHeaderFileIfndef(FullFileName
):
2178 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2183 FileTable
= 'Identifier' + str(FileID
)
2184 SqlStatement
= """ select Value, StartLine
2186 where Model = %d order by StartLine
2187 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_IFNDEF
)
2188 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2189 if len(ResultSet
) == 0:
2190 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1
, '', 'File', FileID
)
2192 for Result
in ResultSet
:
2193 SqlStatement
= """ select Value, EndLine
2196 """ % (FileTable
, Result
[1])
2197 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2198 for Result
in ResultSet
:
2199 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2200 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2
, '', 'File', FileID
)
2203 SqlStatement
= """ select Value
2205 where StartLine > (select max(EndLine) from %s where Model = %d)
2206 """ % (FileTable
, FileTable
, DataClass
.MODEL_IDENTIFIER_MACRO_ENDIF
)
2207 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2208 for Result
in ResultSet
:
2209 if not Result
[0].startswith('/*') and not Result
[0].startswith('//'):
2210 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3
, '', 'File', FileID
)
2213 def CheckDoxygenCommand(FullFileName
):
2216 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2221 FileTable
= 'Identifier' + str(FileID
)
2222 SqlStatement
= """ select Value, ID
2224 where Model = %d or Model = %d
2225 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2226 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2227 DoxygenCommandList
= ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval',
2228 'return', 'sa', 'since', 'test', 'note', 'par', 'endcode', 'code']
2229 for Result
in ResultSet
:
2230 CommentStr
= Result
[0]
2231 CommentPartList
= CommentStr
.split()
2232 for Part
in CommentPartList
:
2233 if Part
.upper() == 'BUGBUG':
2234 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Bug should be marked with doxygen tag @bug', FileTable
, Result
[1])
2235 if Part
.upper() == 'TODO':
2236 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'ToDo should be marked with doxygen tag @todo', FileTable
, Result
[1])
2237 if Part
.startswith('@'):
2238 if EccGlobalData
.gException
.IsException(ERROR_DOXYGEN_CHECK_COMMAND
, Part
):
2240 if not Part
.replace('@', '').strip():
2242 if Part
.lstrip('@') in ['{', '}']:
2244 if Part
.lstrip('@').isalpha():
2245 if Part
.lstrip('@') not in DoxygenCommandList
:
2246 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2248 Index
= Part
.find('[')
2250 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2251 RealCmd
= Part
[1:Index
]
2252 if RealCmd
not in DoxygenCommandList
:
2253 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND
, 'Unknown doxygen command %s' % Part
, FileTable
, Result
[1])
2256 def CheckDoxygenTripleForwardSlash(FullFileName
):
2259 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2265 SqlStatement
= """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2267 where BelongsToFile = %d
2269 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2270 if len(ResultSet
) == 0:
2274 for Result
in ResultSet
:
2275 FuncDefSet
.append(Result
)
2278 FileTable
= 'Identifier' + str(FileID
)
2279 SqlStatement
= """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2283 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2284 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2287 for Result
in ResultSet
:
2288 CommentSet
.append(Result
)
2290 print('Unrecognized chars in comment of file %s', FullFileName
)
2293 for Result
in CommentSet
:
2294 CommentStr
= Result
[0]
2295 StartLine
= Result
[2]
2296 StartColumn
= Result
[3]
2298 EndColumn
= Result
[5]
2299 if not CommentStr
.startswith('///<'):
2303 for FuncDef
in FuncDefSet
:
2304 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2307 if StartLine
> FuncDef
[1] and EndLine
< FuncDef
[3]:
2310 if StartLine
== FuncDef
[1] and StartColumn
> FuncDef
[2] and EndLine
< FuncDef
[3]:
2313 if StartLine
> FuncDef
[1] and EndLine
== FuncDef
[3] and EndColumn
< FuncDef
[4]:
2317 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT
, '', FileTable
, Result
[1])
2320 def CheckFileHeaderDoxygenComments(FullFileName
):
2323 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2328 FileTable
= 'Identifier' + str(FileID
)
2329 SqlStatement
= """ select Value, ID
2331 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2332 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2333 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2334 if len(ResultSet
) == 0:
2335 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'No File License header appear at the very beginning of file.', 'File', FileID
)
2338 NoHeaderCommentStartFlag
= True
2339 NoHeaderCommentEndFlag
= True
2340 NoHeaderCommentPeriodFlag
= True
2341 NoCopyrightFlag
= True
2342 NoLicenseFlag
= True
2343 NoRevReferFlag
= True
2345 for Result
in ResultSet
:
2346 FileStartFlag
= False
2348 CommentStr
= Result
[0].strip()
2349 CommentStrListTemp
= CommentStr
.split('\n')
2350 if (len(CommentStrListTemp
) <= 1):
2352 CommentStrListTemp
= CommentStr
.split('\r')
2353 # Skip the content before the file header
2354 for CommentLine
in CommentStrListTemp
:
2355 if CommentLine
.strip().startswith('/** @file'):
2356 FileStartFlag
= True
2357 if FileStartFlag
== True:
2358 CommentStrList
.append(CommentLine
)
2362 if CommentStrList
and CommentStrList
[0].strip().startswith('/** @file'):
2363 NoHeaderCommentStartFlag
= False
2366 if CommentStrList
and CommentStrList
[-1].strip().endswith('**/'):
2367 NoHeaderCommentEndFlag
= False
2371 for CommentLine
in CommentStrList
:
2373 NextLineIndex
= Index
2374 if CommentLine
.startswith('/** @file'):
2376 if CommentLine
.startswith('**/'):
2378 # Check whether C File header Comment content start with two spaces.
2379 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentStartSpacesNum
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2380 if CommentLine
.startswith('/** @file') == False and CommentLine
.startswith('**/') == False and CommentLine
.strip() and CommentLine
.startswith(' ') == False:
2381 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment content should start with two spaces at each line', FileTable
, ID
)
2383 CommentLine
= CommentLine
.strip()
2384 if CommentLine
.startswith('Copyright'):
2385 NoCopyrightFlag
= False
2386 if CommentLine
.find('All rights reserved') == -1:
2387 for Copyright
in EccGlobalData
.gConfig
.Copyright
:
2388 if CommentLine
.find(Copyright
) > -1:
2389 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable
, ID
)
2391 if CommentLine
.endswith('<BR>') == -1:
2392 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'The ""<BR>"" at the end of the Copyright line is required', FileTable
, ID
)
2393 if NextLineIndex
< len(CommentStrList
) and CommentStrList
[NextLineIndex
].strip().startswith('Copyright') == False and CommentStrList
[NextLineIndex
].strip():
2394 NoLicenseFlag
= False
2395 if CommentLine
.startswith('@par Revision Reference:'):
2396 NoRevReferFlag
= False
2398 for RefLine
in CommentStrList
[NextLineIndex
:]:
2399 if RefLine
.strip() and (NextLineIndex
+ 1) < len(CommentStrList
) and CommentStrList
[NextLineIndex
+1].strip() and CommentStrList
[NextLineIndex
+1].strip().startswith('**/') == False:
2401 if RefLine
.strip() == False or RefLine
.strip().startswith('**/'):
2404 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2405 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentReferenceFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2406 if RefListFlag
== True:
2407 if RefLine
.strip() and RefLine
.strip().startswith('**/') == False and RefLine
.startswith(' -') == False:
2408 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable
, ID
)
2410 if NoHeaderCommentStartFlag
:
2411 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER
, 'File header comment should begin with ""/** @file""', FileTable
, ID
)
2413 if NoHeaderCommentEndFlag
:
2414 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should end with ""**/""', FileTable
, ID
)
2417 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment missing the ""Copyright""', FileTable
, ID
)
2418 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2419 if EccGlobalData
.gConfig
.HeaderCheckCFileCommentLicenseFormat
== '1' or EccGlobalData
.gConfig
.HeaderCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
2421 PrintErrorMsg(ERROR_HEADER_CHECK_FILE
, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable
, ID
)
2423 def CheckFuncHeaderDoxygenComments(FullFileName
):
2426 FileID
= GetTableID(FullFileName
, ErrorMsgList
)
2431 FileTable
= 'Identifier' + str(FileID
)
2432 SqlStatement
= """ select Value, StartLine, EndLine, ID
2435 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_COMMENT
)
2437 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2440 for Result
in ResultSet
:
2441 CommentSet
.append(Result
)
2443 print('Unrecognized chars in comment of file %s', FullFileName
)
2446 SqlStatement
= """ select Modifier, Name, StartLine, ID, Value
2449 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_DECLARATION
)
2450 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2451 for Result
in ResultSet
:
2452 FuncName
= Result
[4]
2453 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2454 if FunctionHeaderComment
:
2455 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2457 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2459 ErrorMsgList
.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2460 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), FileTable
, Result
[3])
2463 SqlStatement
= """ select Value, StartLine, EndLine, ID
2466 """ % (FileTable
, DataClass
.MODEL_IDENTIFIER_FUNCTION_HEADER
)
2468 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2471 for Result
in ResultSet
:
2472 CommentSet
.append(Result
)
2474 print('Unrecognized chars in comment of file %s', FullFileName
)
2476 SqlStatement
= """ select Modifier, Header, StartLine, ID, Name
2478 where BelongsToFile = %d
2480 ResultSet
= Db
.TblFile
.Exec(SqlStatement
)
2481 for Result
in ResultSet
:
2482 FuncName
= Result
[4]
2483 FunctionHeaderComment
= CheckCommentImmediatelyPrecedeFunctionHeader(Result
[1], Result
[2], CommentSet
)
2484 if FunctionHeaderComment
:
2485 CheckFunctionHeaderConsistentWithDoxygenComment(Result
[0], Result
[1], Result
[2], FunctionHeaderComment
[0], FunctionHeaderComment
[1], ErrorMsgList
, FunctionHeaderComment
[3], FileTable
)
2487 if EccGlobalData
.gException
.IsException(ERROR_HEADER_CHECK_FUNCTION
, FuncName
):
2489 ErrorMsgList
.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result
[2], Result
[1]))
2490 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'Function [%s] has NO comment immediately preceding it.' % (FuncName
), 'Function', Result
[3])
2493 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName
, FuncStartLine
, CommentSet
):
2495 for Comment
in CommentSet
:
2496 if Comment
[2] == FuncStartLine
- 1:
2500 def GetDoxygenStrFromComment(Str
):
2502 ParamTagList
= Str
.split('@param')
2503 if len(ParamTagList
) > 1:
2505 while i
< len(ParamTagList
):
2506 DoxygenStrList
.append('@param' + ParamTagList
[i
])
2509 Str
= ParamTagList
[0]
2511 RetvalTagList
= ParamTagList
[-1].split('@retval')
2512 if len(RetvalTagList
) > 1:
2513 if len(ParamTagList
) > 1:
2514 DoxygenStrList
[-1] = '@param' + RetvalTagList
[0]
2516 while i
< len(RetvalTagList
):
2517 DoxygenStrList
.append('@retval' + RetvalTagList
[i
])
2520 ReturnTagList
= RetvalTagList
[-1].split('@return')
2521 if len(ReturnTagList
) > 1:
2522 if len(RetvalTagList
) > 1:
2523 DoxygenStrList
[-1] = '@retval' + ReturnTagList
[0]
2524 elif len(ParamTagList
) > 1:
2525 DoxygenStrList
[-1] = '@param' + ReturnTagList
[0]
2527 while i
< len(ReturnTagList
):
2528 DoxygenStrList
.append('@return' + ReturnTagList
[i
])
2531 if len(DoxygenStrList
) > 0:
2532 DoxygenStrList
[-1] = DoxygenStrList
[-1].rstrip('--*/')
2534 return DoxygenStrList
2536 def CheckGeneralDoxygenCommentLayout(Str
, StartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2537 #/** --*/ @retval after @param
2538 if not Str
.startswith('/**'):
2539 ErrorMsgList
.append('Line %d : Comment does NOT have prefix /** ' % StartLine
)
2540 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have prefix /** ', TableName
, CommentId
)
2541 if not Str
.endswith('**/'):
2542 ErrorMsgList
.append('Line %d : Comment does NOT have tail **/ ' % StartLine
)
2543 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Comment does NOT have tail **/ ', TableName
, CommentId
)
2544 FirstRetvalIndex
= Str
.find('@retval')
2545 LastParamIndex
= Str
.rfind('@param')
2546 if (FirstRetvalIndex
> 0) and (LastParamIndex
> 0) and (FirstRetvalIndex
< LastParamIndex
):
2547 ErrorMsgList
.append('Line %d : @retval appear before @param ' % StartLine
)
2548 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, @retval appear before @param ', TableName
, CommentId
)
2550 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier
, FuncHeader
, FuncStartLine
, CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
= -1, TableName
=''):
2552 ParamList
= GetParamList(FuncHeader
)
2553 CheckGeneralDoxygenCommentLayout(CommentStr
, CommentStartLine
, ErrorMsgList
, CommentId
, TableName
)
2554 DescriptionStr
= CommentStr
2555 DoxygenStrList
= GetDoxygenStrFromComment(DescriptionStr
)
2556 if DescriptionStr
.find('.') == -1:
2557 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION
, 'Comment description should end with period \'.\'', TableName
, CommentId
)
2558 DoxygenTagNumber
= len(DoxygenStrList
)
2559 ParamNumber
= len(ParamList
)
2560 for Param
in ParamList
:
2561 if Param
.Name
.upper() == 'VOID' and ParamNumber
== 1:
2564 if ParamNumber
> 0 and DoxygenTagNumber
> 0:
2565 while Index
< ParamNumber
and Index
< DoxygenTagNumber
:
2566 ParamModifier
= ParamList
[Index
].Modifier
2567 ParamName
= ParamList
[Index
].Name
.strip()
2568 Tag
= DoxygenStrList
[Index
].strip(' ')
2569 if (not Tag
[-1] == ('\n')) and (not Tag
[-1] == ('\r')):
2570 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2571 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION
, 'in Comment, <%s> does NOT end with new line ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2572 TagPartList
= Tag
.split()
2573 if len(TagPartList
) < 2:
2574 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine
, Tag
.replace('\n', '').replace('\r', '')))
2575 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag
.replace('\n', '').replace('\r', '')), TableName
, CommentId
)
2578 LBPos
= Tag
.find('[')
2579 RBPos
= Tag
.find(']')
2580 ParamToLBContent
= Tag
[len('@param'):LBPos
].strip()
2581 if LBPos
> 0 and len(ParamToLBContent
) == 0 and RBPos
> LBPos
:
2583 ModifierPartList
= ParamModifier
.split()
2584 for Part
in ModifierPartList
:
2585 if Part
.strip() == 'IN':
2587 if Part
.strip() == 'OUT':
2594 if Tag
.find('[' + InOutStr
+ ']') == -1:
2595 if InOutStr
!= 'in, out':
2596 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2597 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2599 if Tag
.find('[in,out]') == -1:
2600 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'))
2601 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'in Comment, <%s> does NOT have %s ' % ((TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr
+ ']'), TableName
, CommentId
)
2604 if Tag
.find(ParamName
) == -1 and ParamName
!= 'VOID' and ParamName
!= 'void':
2605 ErrorMsgList
.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine
, (TagPartList
[0] + ' ' + TagPartList
[1]).replace('\n', '').replace('\r', ''), ParamName
))
2606 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
)
2609 if Index
< ParamNumber
:
2610 ErrorMsgList
.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine
)
2611 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of doxygen tags in comment less than number of function parameters ', TableName
, CommentId
)
2612 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2613 if (FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1:
2615 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2616 if Index
< DoxygenTagNumber
- 1 or (Index
< DoxygenTagNumber
and DoxygenStrList
[Index
].startswith('@retval')):
2617 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2618 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need no doxygen tags in comment ', TableName
, CommentId
)
2620 if Index
< DoxygenTagNumber
and not DoxygenStrList
[Index
].startswith('@retval') and not DoxygenStrList
[Index
].startswith('@return'):
2621 ErrorMsgList
.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine
)
2622 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName
, CommentId
)
2624 if ParamNumber
== 0 and DoxygenTagNumber
!= 0 and ((FuncModifier
.find('VOID') != -1 or FuncModifier
.find('void') != -1) and FuncModifier
.find('*') == -1):
2625 ErrorMsgList
.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine
)
2626 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'VOID return type need NO doxygen tags in comment ', TableName
, CommentId
)
2627 if ParamNumber
!= 0 and DoxygenTagNumber
== 0:
2628 ErrorMsgList
.append('Line %d : No doxygen tags in comment' % CommentStartLine
)
2629 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER
, 'No doxygen tags in comment ', TableName
, CommentId
)
2631 if __name__
== '__main__':
2633 # EdkLogger.Initialize()
2634 # EdkLogger.SetLevel(EdkLogger.QUIET)
2635 # CollectSourceCodeDataIntoDB(sys.argv[1])
2637 test_file
= sys
.argv
[1]
2638 except IndexError as v
:
2639 print("Usage: %s filename" % sys
.argv
[0])
2641 MsgList
= CheckFuncHeaderDoxygenComments(test_file
)