]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Ecc/c.py
BaseTools:Ecc handle another copyright format
[mirror_edk2.git] / BaseTools / Source / Python / Ecc / c.py
1 ## @file
2 # This file is used to be the c coding style checking of ECC tool
3 #
4 # Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
5 # SPDX-License-Identifier: BSD-2-Clause-Patent
6 #
7
8 from __future__ import print_function
9 from __future__ import absolute_import
10 import sys
11 import Common.LongFilePathOs as os
12 import re
13 import string
14 from Ecc import CodeFragmentCollector
15 from Ecc import FileProfile
16 from CommonDataClass import DataClass
17 from Ecc import Database
18 from Common import EdkLogger
19 from Ecc.EccToolError import *
20 from Ecc import EccGlobalData
21 from Ecc import MetaDataParser
22
23 IncludeFileListDict = {}
24 AllIncludeFileListDict = {}
25 IncludePathListDict = {}
26 ComplexTypeDict = {}
27 SUDict = {}
28 IgnoredKeywordList = ['EFI_ERROR']
29
30 def GetIgnoredDirListPattern():
31 skipList = list(EccGlobalData.gConfig.SkipDirList) + ['.svn']
32 DirString = '|'.join(skipList)
33 p = re.compile(r'.*[\\/](?:%s)[\\/]?.*' % DirString)
34 return p
35
36 def GetFuncDeclPattern():
37 p = re.compile(r'(?:EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re.DOTALL)
38 return p
39
40 def GetArrayPattern():
41 p = re.compile(r'[_\w]*\s*[\[.*\]]+')
42 return p
43
44 def GetTypedefFuncPointerPattern():
45 p = re.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re.DOTALL)
46 return p
47
48 def GetDB():
49 return EccGlobalData.gDb
50
51 def GetConfig():
52 return EccGlobalData.gConfig
53
54 def PrintErrorMsg(ErrorType, Msg, TableName, ItemId):
55 Msg = Msg.replace('\n', '').replace('\r', '')
56 MsgPartList = Msg.split()
57 Msg = ''
58 for Part in MsgPartList:
59 Msg += Part
60 Msg += ' '
61 GetDB().TblReport.Insert(ErrorType, OtherMsg=Msg, BelongsToTable=TableName, BelongsToItem=ItemId)
62
63 def GetIdType(Str):
64 Type = DataClass.MODEL_UNKNOWN
65 Str = Str.replace('#', '# ')
66 List = Str.split()
67 if List[1] == 'include':
68 Type = DataClass.MODEL_IDENTIFIER_INCLUDE
69 elif List[1] == 'define':
70 Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE
71 elif List[1] == 'ifdef':
72 Type = DataClass.MODEL_IDENTIFIER_MACRO_IFDEF
73 elif List[1] == 'ifndef':
74 Type = DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF
75 elif List[1] == 'endif':
76 Type = DataClass.MODEL_IDENTIFIER_MACRO_ENDIF
77 elif List[1] == 'pragma':
78 Type = DataClass.MODEL_IDENTIFIER_MACRO_PROGMA
79 else:
80 Type = DataClass.MODEL_UNKNOWN
81 return Type
82
83 def SuOccurInTypedef (Su, TdList):
84 for Td in TdList:
85 if Su.StartPos[0] == Td.StartPos[0] and Su.EndPos[0] == Td.EndPos[0]:
86 return True
87 return False
88
89 def GetIdentifierList():
90 IdList = []
91 for comment in FileProfile.CommentList:
92 IdComment = DataClass.IdentifierClass(-1, '', '', '', comment.Content, DataClass.MODEL_IDENTIFIER_COMMENT, -1, -1, comment.StartPos[0], comment.StartPos[1], comment.EndPos[0], comment.EndPos[1])
93 IdList.append(IdComment)
94
95 for pp in FileProfile.PPDirectiveList:
96 Type = GetIdType(pp.Content)
97 IdPP = DataClass.IdentifierClass(-1, '', '', '', pp.Content, Type, -1, -1, pp.StartPos[0], pp.StartPos[1], pp.EndPos[0], pp.EndPos[1])
98 IdList.append(IdPP)
99
100 for pe in FileProfile.PredicateExpressionList:
101 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])
102 IdList.append(IdPE)
103
104 FuncDeclPattern = GetFuncDeclPattern()
105 ArrayPattern = GetArrayPattern()
106 for var in FileProfile.VariableDeclarationList:
107 DeclText = var.Declarator.lstrip()
108 FuncPointerPattern = GetTypedefFuncPointerPattern()
109 if FuncPointerPattern.match(DeclText):
110 continue
111 VarNameStartLine = var.NameStartPos[0]
112 VarNameStartColumn = var.NameStartPos[1]
113 FirstChar = DeclText[0]
114 while not FirstChar.isalpha() and FirstChar != '_':
115 if FirstChar == '*':
116 var.Modifier += '*'
117 VarNameStartColumn += 1
118 DeclText = DeclText.lstrip('*')
119 elif FirstChar == '\r':
120 DeclText = DeclText.lstrip('\r\n').lstrip('\r')
121 VarNameStartLine += 1
122 VarNameStartColumn = 0
123 elif FirstChar == '\n':
124 DeclText = DeclText.lstrip('\n')
125 VarNameStartLine += 1
126 VarNameStartColumn = 0
127 elif FirstChar == ' ':
128 DeclText = DeclText.lstrip(' ')
129 VarNameStartColumn += 1
130 elif FirstChar == '\t':
131 DeclText = DeclText.lstrip('\t')
132 VarNameStartColumn += 8
133 else:
134 DeclText = DeclText[1:]
135 VarNameStartColumn += 1
136 FirstChar = DeclText[0]
137
138 var.Declarator = DeclText
139 if FuncDeclPattern.match(var.Declarator):
140 DeclSplitList = var.Declarator.split('(')
141 FuncName = DeclSplitList[0].strip()
142 FuncNamePartList = FuncName.split()
143 if len(FuncNamePartList) > 1:
144 FuncName = FuncNamePartList[-1].strip()
145 NameStart = DeclSplitList[0].rfind(FuncName)
146 var.Declarator = var.Declarator[NameStart:]
147 if NameStart > 0:
148 var.Modifier += ' ' + DeclSplitList[0][0:NameStart]
149 Index = 0
150 PreChar = ''
151 while Index < NameStart:
152 FirstChar = DeclSplitList[0][Index]
153 if DeclSplitList[0][Index:].startswith('EFIAPI'):
154 Index += 6
155 VarNameStartColumn += 6
156 PreChar = ''
157 continue
158 elif FirstChar == '\r':
159 Index += 1
160 VarNameStartLine += 1
161 VarNameStartColumn = 0
162 elif FirstChar == '\n':
163 Index += 1
164 if PreChar != '\r':
165 VarNameStartLine += 1
166 VarNameStartColumn = 0
167 elif FirstChar == ' ':
168 Index += 1
169 VarNameStartColumn += 1
170 elif FirstChar == '\t':
171 Index += 1
172 VarNameStartColumn += 8
173 else:
174 Index += 1
175 VarNameStartColumn += 1
176 PreChar = FirstChar
177 IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', var.Declarator, FuncName, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, -1, -1, var.StartPos[0], var.StartPos[1], VarNameStartLine, VarNameStartColumn)
178 IdList.append(IdVar)
179 continue
180
181 if var.Declarator.find('{') == -1:
182 for decl in var.Declarator.split(','):
183 DeclList = decl.split('=')
184 Name = DeclList[0].strip()
185 if ArrayPattern.match(Name):
186 LSBPos = var.Declarator.find('[')
187 var.Modifier += ' ' + Name[LSBPos:]
188 Name = Name[0:LSBPos]
189
190 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)
191 IdList.append(IdVar)
192 else:
193 DeclList = var.Declarator.split('=')
194 Name = DeclList[0].strip()
195 if ArrayPattern.match(Name):
196 LSBPos = var.Declarator.find('[')
197 var.Modifier += ' ' + Name[LSBPos:]
198 Name = Name[0:LSBPos]
199 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)
200 IdList.append(IdVar)
201
202 for enum in FileProfile.EnumerationDefinitionList:
203 LBPos = enum.Content.find('{')
204 RBPos = enum.Content.find('}')
205 Name = enum.Content[4:LBPos].strip()
206 Value = enum.Content[LBPos + 1:RBPos]
207 IdEnum = DataClass.IdentifierClass(-1, '', '', Name, Value, DataClass.MODEL_IDENTIFIER_ENUMERATE, -1, -1, enum.StartPos[0], enum.StartPos[1], enum.EndPos[0], enum.EndPos[1])
208 IdList.append(IdEnum)
209
210 for su in FileProfile.StructUnionDefinitionList:
211 if SuOccurInTypedef(su, FileProfile.TypedefDefinitionList):
212 continue
213 Type = DataClass.MODEL_IDENTIFIER_STRUCTURE
214 SkipLen = 6
215 if su.Content.startswith('union'):
216 Type = DataClass.MODEL_IDENTIFIER_UNION
217 SkipLen = 5
218 LBPos = su.Content.find('{')
219 RBPos = su.Content.find('}')
220 if LBPos == -1 or RBPos == -1:
221 Name = su.Content[SkipLen:].strip()
222 Value = ''
223 else:
224 Name = su.Content[SkipLen:LBPos].strip()
225 Value = su.Content[LBPos:RBPos + 1]
226 IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0], su.StartPos[1], su.EndPos[0], su.EndPos[1])
227 IdList.append(IdPE)
228
229 TdFuncPointerPattern = GetTypedefFuncPointerPattern()
230 for td in FileProfile.TypedefDefinitionList:
231 Modifier = ''
232 Name = td.ToType
233 Value = td.FromType
234 if TdFuncPointerPattern.match(td.ToType):
235 Modifier = td.FromType
236 LBPos = td.ToType.find('(')
237 TmpStr = td.ToType[LBPos + 1:].strip()
238 StarPos = TmpStr.find('*')
239 if StarPos != -1:
240 Modifier += ' ' + TmpStr[0:StarPos]
241 while TmpStr[StarPos] == '*':
242 # Modifier += ' ' + '*'
243 StarPos += 1
244 TmpStr = TmpStr[StarPos:].strip()
245 RBPos = TmpStr.find(')')
246 Name = TmpStr[0:RBPos]
247 Value = 'FP' + TmpStr[RBPos + 1:]
248 else:
249 while Name.startswith('*'):
250 Value += ' ' + '*'
251 Name = Name.lstrip('*').strip()
252
253 if Name.find('[') != -1:
254 LBPos = Name.find('[')
255 RBPos = Name.rfind(']')
256 Value += Name[LBPos : RBPos + 1]
257 Name = Name[0 : LBPos]
258
259 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])
260 IdList.append(IdTd)
261
262 for funcCall in FileProfile.FunctionCallingList:
263 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])
264 IdList.append(IdFC)
265 return IdList
266
267 def StripNonAlnumChars(Str):
268 StrippedStr = ''
269 for Char in Str:
270 if Char.isalnum() or Char == '_':
271 StrippedStr += Char
272 return StrippedStr
273
274 def GetParamList(FuncDeclarator, FuncNameLine=0, FuncNameOffset=0):
275 FuncDeclarator = StripComments(FuncDeclarator)
276 ParamIdList = []
277 #DeclSplitList = FuncDeclarator.split('(')
278 LBPos = FuncDeclarator.find('(')
279 #if len(DeclSplitList) < 2:
280 if LBPos == -1:
281 return ParamIdList
282 #FuncName = DeclSplitList[0]
283 FuncName = FuncDeclarator[0:LBPos]
284 #ParamStr = DeclSplitList[1].rstrip(')')
285 ParamStr = FuncDeclarator[LBPos + 1:].rstrip(')')
286 LineSkipped = 0
287 OffsetSkipped = 0
288 TailChar = FuncName[-1]
289 while not TailChar.isalpha() and TailChar != '_':
290
291 if TailChar == '\n':
292 FuncName = FuncName.rstrip('\r\n').rstrip('\n')
293 LineSkipped += 1
294 OffsetSkipped = 0
295 elif TailChar == '\r':
296 FuncName = FuncName.rstrip('\r')
297 LineSkipped += 1
298 OffsetSkipped = 0
299 elif TailChar == ' ':
300 FuncName = FuncName.rstrip(' ')
301 OffsetSkipped += 1
302 elif TailChar == '\t':
303 FuncName = FuncName.rstrip('\t')
304 OffsetSkipped += 8
305 else:
306 FuncName = FuncName[:-1]
307 TailChar = FuncName[-1]
308
309 OffsetSkipped += 1 #skip '('
310
311 for p in ParamStr.split(','):
312 ListP = p.split()
313 if len(ListP) == 0:
314 continue
315 ParamName = ListP[-1]
316 DeclText = ParamName.strip()
317 RightSpacePos = p.rfind(ParamName)
318 ParamModifier = p[0:RightSpacePos]
319 if ParamName == 'OPTIONAL':
320 if ParamModifier == '':
321 ParamModifier += ' ' + 'OPTIONAL'
322 DeclText = ''
323 else:
324 ParamName = ListP[-2]
325 DeclText = ParamName.strip()
326 RightSpacePos = p.rfind(ParamName)
327 ParamModifier = p[0:RightSpacePos]
328 ParamModifier += 'OPTIONAL'
329 while DeclText.startswith('*'):
330 ParamModifier += ' ' + '*'
331 DeclText = DeclText.lstrip('*').strip()
332 ParamName = DeclText
333 # ignore array length if exists.
334 LBIndex = ParamName.find('[')
335 if LBIndex != -1:
336 ParamName = ParamName[0:LBIndex]
337
338 Start = RightSpacePos
339 Index = 0
340 PreChar = ''
341 while Index < Start:
342 FirstChar = p[Index]
343
344 if FirstChar == '\r':
345 Index += 1
346 LineSkipped += 1
347 OffsetSkipped = 0
348 elif FirstChar == '\n':
349 Index += 1
350 if PreChar != '\r':
351 LineSkipped += 1
352 OffsetSkipped = 0
353 elif FirstChar == ' ':
354 Index += 1
355 OffsetSkipped += 1
356 elif FirstChar == '\t':
357 Index += 1
358 OffsetSkipped += 8
359 else:
360 Index += 1
361 OffsetSkipped += 1
362 PreChar = FirstChar
363
364 ParamBeginLine = FuncNameLine + LineSkipped
365 ParamBeginOffset = FuncNameOffset + OffsetSkipped
366
367 Index = Start + len(ParamName)
368 PreChar = ''
369 while Index < len(p):
370 FirstChar = p[Index]
371
372 if FirstChar == '\r':
373 Index += 1
374 LineSkipped += 1
375 OffsetSkipped = 0
376 elif FirstChar == '\n':
377 Index += 1
378 if PreChar != '\r':
379 LineSkipped += 1
380 OffsetSkipped = 0
381 elif FirstChar == ' ':
382 Index += 1
383 OffsetSkipped += 1
384 elif FirstChar == '\t':
385 Index += 1
386 OffsetSkipped += 8
387 else:
388 Index += 1
389 OffsetSkipped += 1
390 PreChar = FirstChar
391
392 ParamEndLine = FuncNameLine + LineSkipped
393 ParamEndOffset = FuncNameOffset + OffsetSkipped
394 if ParamName != '...':
395 ParamName = StripNonAlnumChars(ParamName)
396 IdParam = DataClass.IdentifierClass(-1, ParamModifier, '', ParamName, '', DataClass.MODEL_IDENTIFIER_PARAMETER, -1, -1, ParamBeginLine, ParamBeginOffset, ParamEndLine, ParamEndOffset)
397 ParamIdList.append(IdParam)
398
399 OffsetSkipped += 1 #skip ','
400
401 return ParamIdList
402
403 def GetFunctionList():
404 FuncObjList = []
405 for FuncDef in FileProfile.FunctionDefinitionList:
406 ParamIdList = []
407 DeclText = FuncDef.Declarator.lstrip()
408 FuncNameStartLine = FuncDef.NamePos[0]
409 FuncNameStartColumn = FuncDef.NamePos[1]
410 FirstChar = DeclText[0]
411 while not FirstChar.isalpha() and FirstChar != '_':
412 if FirstChar == '*':
413 FuncDef.Modifier += '*'
414 FuncNameStartColumn += 1
415 DeclText = DeclText.lstrip('*')
416 elif FirstChar == '\r':
417 DeclText = DeclText.lstrip('\r\n').lstrip('\r')
418 FuncNameStartLine += 1
419 FuncNameStartColumn = 0
420 elif FirstChar == '\n':
421 DeclText = DeclText.lstrip('\n')
422 FuncNameStartLine += 1
423 FuncNameStartColumn = 0
424 elif FirstChar == ' ':
425 DeclText = DeclText.lstrip(' ')
426 FuncNameStartColumn += 1
427 elif FirstChar == '\t':
428 DeclText = DeclText.lstrip('\t')
429 FuncNameStartColumn += 8
430 else:
431 DeclText = DeclText[1:]
432 FuncNameStartColumn += 1
433 FirstChar = DeclText[0]
434
435 FuncDef.Declarator = DeclText
436 DeclSplitList = FuncDef.Declarator.split('(')
437 if len(DeclSplitList) < 2:
438 continue
439
440 FuncName = DeclSplitList[0]
441 FuncNamePartList = FuncName.split()
442 if len(FuncNamePartList) > 1:
443 FuncName = FuncNamePartList[-1]
444 NameStart = DeclSplitList[0].rfind(FuncName)
445 if NameStart > 0:
446 FuncDef.Modifier += ' ' + DeclSplitList[0][0:NameStart]
447 Index = 0
448 PreChar = ''
449 while Index < NameStart:
450 FirstChar = DeclSplitList[0][Index]
451 if DeclSplitList[0][Index:].startswith('EFIAPI'):
452 Index += 6
453 FuncNameStartColumn += 6
454 PreChar = ''
455 continue
456 elif FirstChar == '\r':
457 Index += 1
458 FuncNameStartLine += 1
459 FuncNameStartColumn = 0
460 elif FirstChar == '\n':
461 Index += 1
462 if PreChar != '\r':
463 FuncNameStartLine += 1
464 FuncNameStartColumn = 0
465 elif FirstChar == ' ':
466 Index += 1
467 FuncNameStartColumn += 1
468 elif FirstChar == '\t':
469 Index += 1
470 FuncNameStartColumn += 8
471 else:
472 Index += 1
473 FuncNameStartColumn += 1
474 PreChar = FirstChar
475
476 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)
477 FuncObjList.append(FuncObj)
478
479 return FuncObjList
480
481 def GetFileModificationTimeFromDB(FullFileName):
482 TimeValue = 0.0
483 Db = GetDB()
484 SqlStatement = """ select TimeStamp
485 from File
486 where FullPath = \'%s\'
487 """ % (FullFileName)
488 ResultSet = Db.TblFile.Exec(SqlStatement)
489 for Result in ResultSet:
490 TimeValue = Result[0]
491 return TimeValue
492
493 def CollectSourceCodeDataIntoDB(RootDir):
494 FileObjList = []
495 tuple = os.walk(RootDir)
496 IgnoredPattern = GetIgnoredDirListPattern()
497 ParseErrorFileList = []
498 TokenReleaceList = EccGlobalData.gConfig.TokenReleaceList
499 TokenReleaceList.extend(['L",\\\""'])
500
501 for dirpath, dirnames, filenames in tuple:
502 if IgnoredPattern.match(dirpath.upper()):
503 continue
504
505 for Dir in dirnames:
506 Dirname = os.path.join(dirpath, Dir)
507 if os.path.islink(Dirname):
508 Dirname = os.path.realpath(Dirname)
509 if os.path.isdir(Dirname):
510 # symlinks to directories are treated as directories
511 dirnames.remove(Dir)
512 dirnames.append(Dirname)
513
514 for f in filenames:
515 if f.lower() in EccGlobalData.gConfig.SkipFileList:
516 continue
517 collector = None
518 FullName = os.path.normpath(os.path.join(dirpath, f))
519 model = DataClass.MODEL_FILE_OTHERS
520 if os.path.splitext(f)[1] in ('.h', '.c'):
521 EdkLogger.info("Parsing " + FullName)
522 model = f.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H
523 collector = CodeFragmentCollector.CodeFragmentCollector(FullName)
524 collector.TokenReleaceList = TokenReleaceList
525 try:
526 collector.ParseFile()
527 except UnicodeError:
528 ParseErrorFileList.append(FullName)
529 collector.CleanFileProfileBuffer()
530 collector.ParseFileWithClearedPPDirective()
531 # collector.PrintFragments()
532 BaseName = os.path.basename(f)
533 DirName = os.path.dirname(FullName)
534 Ext = os.path.splitext(f)[1].lstrip('.')
535 ModifiedTime = os.path.getmtime(FullName)
536 FileObj = DataClass.FileClass(-1, BaseName, Ext, DirName, FullName, model, ModifiedTime, GetFunctionList(), GetIdentifierList(), [])
537 FileObjList.append(FileObj)
538 if collector:
539 collector.CleanFileProfileBuffer()
540
541 if len(ParseErrorFileList) > 0:
542 EdkLogger.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList))
543
544 Db = GetDB()
545 for file in FileObjList:
546 if file.ExtName.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
547 Db.InsertOneFile(file)
548
549 Db.UpdateIdentifierBelongsToFunction()
550
551 def GetTableID(FullFileName, ErrorMsgList=None):
552 if ErrorMsgList is None:
553 ErrorMsgList = []
554
555 Db = GetDB()
556 SqlStatement = """ select ID
557 from File
558 where FullPath like '%s'
559 """ % FullFileName
560 ResultSet = Db.TblFile.Exec(SqlStatement)
561
562 FileID = -1
563 for Result in ResultSet:
564 if FileID != -1:
565 ErrorMsgList.append('Duplicate file ID found in DB for file %s' % FullFileName)
566 return - 2
567 FileID = Result[0]
568 if FileID == -1:
569 ErrorMsgList.append('NO file ID found in DB for file %s' % FullFileName)
570 return - 1
571 return FileID
572
573 def GetIncludeFileList(FullFileName):
574 if os.path.splitext(FullFileName)[1].upper() not in ('.H'):
575 return []
576 IFList = IncludeFileListDict.get(FullFileName)
577 if IFList is not None:
578 return IFList
579
580 FileID = GetTableID(FullFileName)
581 if FileID < 0:
582 return []
583
584 Db = GetDB()
585 FileTable = 'Identifier' + str(FileID)
586 SqlStatement = """ select Value
587 from %s
588 where Model = %d
589 """ % (FileTable, DataClass.MODEL_IDENTIFIER_INCLUDE)
590 ResultSet = Db.TblFile.Exec(SqlStatement)
591 IncludeFileListDict[FullFileName] = ResultSet
592 return ResultSet
593
594 def GetFullPathOfIncludeFile(Str, IncludePathList):
595 for IncludePath in IncludePathList:
596 FullPath = os.path.join(IncludePath, Str)
597 FullPath = os.path.normpath(FullPath)
598 if os.path.exists(FullPath):
599 return FullPath
600 return None
601
602 def GetAllIncludeFiles(FullFileName):
603 if AllIncludeFileListDict.get(FullFileName) is not None:
604 return AllIncludeFileListDict.get(FullFileName)
605
606 FileDirName = os.path.dirname(FullFileName)
607 IncludePathList = IncludePathListDict.get(FileDirName)
608 if IncludePathList is None:
609 IncludePathList = MetaDataParser.GetIncludeListOfFile(EccGlobalData.gWorkspace, FullFileName, GetDB())
610 if FileDirName not in IncludePathList:
611 IncludePathList.insert(0, FileDirName)
612 IncludePathListDict[FileDirName] = IncludePathList
613 IncludeFileQueue = []
614 for IncludeFile in GetIncludeFileList(FullFileName):
615 FileName = IncludeFile[0].lstrip('#').strip()
616 FileName = FileName.lstrip('include').strip()
617 FileName = FileName.strip('\"')
618 FileName = FileName.lstrip('<').rstrip('>').strip()
619 FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList)
620 if FullPath is not None:
621 IncludeFileQueue.append(FullPath)
622
623 i = 0
624 while i < len(IncludeFileQueue):
625 for IncludeFile in GetIncludeFileList(IncludeFileQueue[i]):
626 FileName = IncludeFile[0].lstrip('#').strip()
627 FileName = FileName.lstrip('include').strip()
628 FileName = FileName.strip('\"')
629 FileName = FileName.lstrip('<').rstrip('>').strip()
630 FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList)
631 if FullPath is not None and FullPath not in IncludeFileQueue:
632 IncludeFileQueue.insert(i + 1, FullPath)
633 i += 1
634
635 AllIncludeFileListDict[FullFileName] = IncludeFileQueue
636 return IncludeFileQueue
637
638 def GetPredicateListFromPredicateExpStr(PES):
639
640 PredicateList = []
641 i = 0
642 PredicateBegin = 0
643 #PredicateEnd = 0
644 LogicOpPos = -1
645 p = GetFuncDeclPattern()
646 while i < len(PES) - 1:
647 if (PES[i].isalnum() or PES[i] == '_' or PES[i] == '*') and LogicOpPos > PredicateBegin:
648 PredicateBegin = i
649 if (PES[i] == '&' and PES[i + 1] == '&') or (PES[i] == '|' and PES[i + 1] == '|'):
650 LogicOpPos = i
651 Exp = PES[PredicateBegin:i].strip()
652 # Exp may contain '.' or '->'
653 TmpExp = Exp.replace('.', '').replace('->', '')
654 if p.match(TmpExp):
655 PredicateList.append(Exp)
656 else:
657 PredicateList.append(Exp.rstrip(';').rstrip(')').strip())
658 i += 1
659
660 if PredicateBegin > LogicOpPos:
661 while PredicateBegin < len(PES):
662 if PES[PredicateBegin].isalnum() or PES[PredicateBegin] == '_' or PES[PredicateBegin] == '*':
663 break
664 PredicateBegin += 1
665 Exp = PES[PredicateBegin:len(PES)].strip()
666 # Exp may contain '.' or '->'
667 TmpExp = Exp.replace('.', '').replace('->', '')
668 if p.match(TmpExp):
669 PredicateList.append(Exp)
670 else:
671 PredicateList.append(Exp.rstrip(';').rstrip(')').strip())
672 return PredicateList
673
674 def GetCNameList(Lvalue, StarList=[]):
675 Lvalue += ' '
676 i = 0
677 SearchBegin = 0
678 VarStart = -1
679 VarEnd = -1
680 VarList = []
681
682 while SearchBegin < len(Lvalue):
683 while i < len(Lvalue):
684 if Lvalue[i].isalnum() or Lvalue[i] == '_':
685 if VarStart == -1:
686 VarStart = i
687 VarEnd = i
688 i += 1
689 elif VarEnd != -1:
690 VarList.append(Lvalue[VarStart:VarEnd + 1])
691 i += 1
692 break
693 else:
694 if VarStart == -1 and Lvalue[i] == '*':
695 StarList.append('*')
696 i += 1
697 if VarEnd == -1:
698 break
699
700
701 DotIndex = Lvalue[VarEnd:].find('.')
702 ArrowIndex = Lvalue[VarEnd:].find('->')
703 if DotIndex == -1 and ArrowIndex == -1:
704 break
705 elif DotIndex == -1 and ArrowIndex != -1:
706 SearchBegin = VarEnd + ArrowIndex
707 elif ArrowIndex == -1 and DotIndex != -1:
708 SearchBegin = VarEnd + DotIndex
709 else:
710 SearchBegin = VarEnd + ((DotIndex < ArrowIndex) and DotIndex or ArrowIndex)
711
712 i = SearchBegin
713 VarStart = -1
714 VarEnd = -1
715
716 return VarList
717
718 def SplitPredicateByOp(Str, Op, IsFuncCalling=False):
719
720 Name = Str.strip()
721 Value = None
722
723 if IsFuncCalling:
724 Index = 0
725 LBFound = False
726 UnmatchedLBCount = 0
727 while Index < len(Str):
728 while not LBFound and Str[Index] != '_' and not Str[Index].isalnum():
729 Index += 1
730
731 while not LBFound and (Str[Index].isalnum() or Str[Index] == '_'):
732 Index += 1
733 # maybe type-cast at the beginning, skip it.
734 RemainingStr = Str[Index:].lstrip()
735 if RemainingStr.startswith(')') and not LBFound:
736 Index += 1
737 continue
738
739 if RemainingStr.startswith('(') and not LBFound:
740 LBFound = True
741
742 if Str[Index] == '(':
743 UnmatchedLBCount += 1
744 Index += 1
745 continue
746
747 if Str[Index] == ')':
748 UnmatchedLBCount -= 1
749 Index += 1
750 if UnmatchedLBCount == 0:
751 break
752 continue
753
754 Index += 1
755
756 if UnmatchedLBCount > 0:
757 return [Name]
758
759 IndexInRemainingStr = Str[Index:].find(Op)
760 if IndexInRemainingStr == -1:
761 return [Name]
762
763 Name = Str[0:Index + IndexInRemainingStr].strip()
764 Value = Str[Index + IndexInRemainingStr + len(Op):].strip().strip(')')
765 return [Name, Value]
766
767 TmpStr = Str.rstrip(';').rstrip(')')
768 while True:
769 Index = TmpStr.rfind(Op)
770 if Index == -1:
771 return [Name]
772
773 if Str[Index - 1].isalnum() or Str[Index - 1].isspace() or Str[Index - 1] == ')' or Str[Index - 1] == ']':
774 Name = Str[0:Index].strip()
775 Value = Str[Index + len(Op):].strip()
776 return [Name, Value]
777
778 TmpStr = Str[0:Index - 1]
779
780 def SplitPredicateStr(Str):
781
782 Str = Str.lstrip('(')
783 IsFuncCalling = False
784 p = GetFuncDeclPattern()
785 TmpStr = Str.replace('.', '').replace('->', '')
786 if p.match(TmpStr):
787 IsFuncCalling = True
788
789 PredPartList = SplitPredicateByOp(Str, '==', IsFuncCalling)
790 if len(PredPartList) > 1:
791 return [PredPartList, '==']
792
793 PredPartList = SplitPredicateByOp(Str, '!=', IsFuncCalling)
794 if len(PredPartList) > 1:
795 return [PredPartList, '!=']
796
797 PredPartList = SplitPredicateByOp(Str, '>=', IsFuncCalling)
798 if len(PredPartList) > 1:
799 return [PredPartList, '>=']
800
801 PredPartList = SplitPredicateByOp(Str, '<=', IsFuncCalling)
802 if len(PredPartList) > 1:
803 return [PredPartList, '<=']
804
805 PredPartList = SplitPredicateByOp(Str, '>', IsFuncCalling)
806 if len(PredPartList) > 1:
807 return [PredPartList, '>']
808
809 PredPartList = SplitPredicateByOp(Str, '<', IsFuncCalling)
810 if len(PredPartList) > 1:
811 return [PredPartList, '<']
812
813 return [[Str, None], None]
814
815 def GetFuncContainsPE(ExpLine, ResultSet):
816 for Result in ResultSet:
817 if Result[0] < ExpLine and Result[1] > ExpLine:
818 return Result
819 return None
820
821 def PatternInModifier(Modifier, SubStr):
822 PartList = Modifier.split()
823 for Part in PartList:
824 if Part == SubStr:
825 return True
826 return False
827
828 def GetDataTypeFromModifier(ModifierStr):
829 MList = ModifierStr.split()
830 ReturnType = ''
831 for M in MList:
832 if M in EccGlobalData.gConfig.ModifierSet:
833 continue
834 # remove array suffix
835 if M.startswith('[') or M.endswith(']'):
836 continue
837 ReturnType += M + ' '
838
839 ReturnType = ReturnType.strip()
840 if len(ReturnType) == 0:
841 ReturnType = 'VOID'
842 return ReturnType
843
844 def DiffModifier(Str1, Str2):
845 PartList1 = Str1.split()
846 PartList2 = Str2.split()
847 if PartList1 == PartList2:
848 return False
849 else:
850 return True
851
852 def GetTypedefDict(FullFileName):
853
854 Dict = ComplexTypeDict.get(FullFileName)
855 if Dict is not None:
856 return Dict
857
858 FileID = GetTableID(FullFileName)
859 FileTable = 'Identifier' + str(FileID)
860 Db = GetDB()
861 SqlStatement = """ select Modifier, Name, Value, ID
862 from %s
863 where Model = %d
864 """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
865 ResultSet = Db.TblFile.Exec(SqlStatement)
866
867 Dict = {}
868 for Result in ResultSet:
869 if len(Result[0]) == 0:
870 Dict[Result[1]] = Result[2]
871
872 IncludeFileList = GetAllIncludeFiles(FullFileName)
873 for F in IncludeFileList:
874 FileID = GetTableID(F)
875 if FileID < 0:
876 continue
877
878 FileTable = 'Identifier' + str(FileID)
879 SqlStatement = """ select Modifier, Name, Value, ID
880 from %s
881 where Model = %d
882 """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
883 ResultSet = Db.TblFile.Exec(SqlStatement)
884
885 for Result in ResultSet:
886 if not Result[2].startswith('FP ('):
887 Dict[Result[1]] = Result[2]
888 else:
889 if len(Result[0]) == 0:
890 Dict[Result[1]] = 'VOID'
891 else:
892 Dict[Result[1]] = GetDataTypeFromModifier(Result[0])
893
894 ComplexTypeDict[FullFileName] = Dict
895 return Dict
896
897 def GetSUDict(FullFileName):
898
899 Dict = SUDict.get(FullFileName)
900 if Dict is not None:
901 return Dict
902
903 FileID = GetTableID(FullFileName)
904 FileTable = 'Identifier' + str(FileID)
905 Db = GetDB()
906 SqlStatement = """ select Name, Value, ID
907 from %s
908 where Model = %d or Model = %d
909 """ % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION)
910 ResultSet = Db.TblFile.Exec(SqlStatement)
911
912 Dict = {}
913 for Result in ResultSet:
914 if len(Result[1]) > 0:
915 Dict[Result[0]] = Result[1]
916
917 IncludeFileList = GetAllIncludeFiles(FullFileName)
918 for F in IncludeFileList:
919 FileID = GetTableID(F)
920 if FileID < 0:
921 continue
922
923 FileTable = 'Identifier' + str(FileID)
924 SqlStatement = """ select Name, Value, ID
925 from %s
926 where Model = %d or Model = %d
927 """ % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION)
928 ResultSet = Db.TblFile.Exec(SqlStatement)
929
930 for Result in ResultSet:
931 if len(Result[1]) > 0:
932 Dict[Result[0]] = Result[1]
933
934 SUDict[FullFileName] = Dict
935 return Dict
936
937 def StripComments(Str):
938 Str += ' '
939 ListFromStr = list(Str)
940
941 InComment = False
942 DoubleSlashComment = False
943 Index = 0
944 while Index < len(ListFromStr):
945 # meet new line, then no longer in a comment for //
946 if ListFromStr[Index] == '\n':
947 if InComment and DoubleSlashComment:
948 InComment = False
949 DoubleSlashComment = False
950 Index += 1
951 # check for */ comment end
952 elif InComment and not DoubleSlashComment and ListFromStr[Index] == '*' and ListFromStr[Index + 1] == '/':
953 ListFromStr[Index] = ' '
954 Index += 1
955 ListFromStr[Index] = ' '
956 Index += 1
957 InComment = False
958 # set comments to spaces
959 elif InComment:
960 ListFromStr[Index] = ' '
961 Index += 1
962 # check for // comment
963 elif ListFromStr[Index] == '/' and ListFromStr[Index + 1] == '/':
964 InComment = True
965 DoubleSlashComment = True
966
967 # check for /* comment start
968 elif ListFromStr[Index] == '/' and ListFromStr[Index + 1] == '*':
969 ListFromStr[Index] = ' '
970 Index += 1
971 ListFromStr[Index] = ' '
972 Index += 1
973 InComment = True
974 else:
975 Index += 1
976
977 # restore from List to String
978 Str = "".join(ListFromStr)
979 Str = Str.rstrip(' ')
980
981 return Str
982
983 def GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict):
984 Value = TypedefDict.get(Type)
985 if Value is None:
986 Value = SUDict.get(Type)
987 if Value is None:
988 return None
989
990 LBPos = Value.find('{')
991 while LBPos == -1:
992 FTList = Value.split()
993 for FT in FTList:
994 if FT not in ('struct', 'union'):
995 Value = TypedefDict.get(FT)
996 if Value is None:
997 Value = SUDict.get(FT)
998 break
999
1000 if Value is None:
1001 return None
1002
1003 LBPos = Value.find('{')
1004
1005 # RBPos = Value.find('}')
1006 Fields = Value[LBPos + 1:]
1007 Fields = StripComments(Fields)
1008 FieldsList = Fields.split(';')
1009 for Field in FieldsList:
1010 Field = Field.strip()
1011 Index = Field.rfind(FieldName)
1012 if Index < 1:
1013 continue
1014 if not Field[Index - 1].isalnum():
1015 if Index + len(FieldName) == len(Field):
1016 Type = GetDataTypeFromModifier(Field[0:Index])
1017 return Type.strip()
1018 else:
1019 # For the condition that the field in struct is an array with [] suffixes...
1020 if not Field[Index + len(FieldName)].isalnum():
1021 Type = GetDataTypeFromModifier(Field[0:Index])
1022 return Type.strip()
1023
1024 return None
1025
1026 def GetRealType(Type, TypedefDict, TargetType=None):
1027 if TargetType is not None and Type == TargetType:
1028 return Type
1029 while TypedefDict.get(Type):
1030 Type = TypedefDict.get(Type)
1031 if TargetType is not None and Type == TargetType:
1032 return Type
1033 return Type
1034
1035 def GetTypeInfo(RefList, Modifier, FullFileName, TargetType=None):
1036 TypedefDict = GetTypedefDict(FullFileName)
1037 SUDict = GetSUDict(FullFileName)
1038 Type = GetDataTypeFromModifier(Modifier).replace('*', '').strip()
1039
1040 Type = Type.split()[-1]
1041 Index = 0
1042 while Index < len(RefList):
1043 FieldName = RefList[Index]
1044 FromType = GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict)
1045 if FromType is None:
1046 return None
1047 # we want to determine the exact type.
1048 if TargetType is not None:
1049 Type = FromType.split()[0]
1050 # we only want to check if it is a pointer
1051 else:
1052 Type = FromType
1053 if Type.find('*') != -1 and Index == len(RefList) - 1:
1054 return Type
1055 Type = FromType.split()[0]
1056
1057 Index += 1
1058
1059 Type = GetRealType(Type, TypedefDict, TargetType)
1060
1061 return Type
1062
1063 def GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall=False, TargetType=None, StarList=None):
1064
1065 PredVar = PredVarList[0]
1066 FileID = GetTableID(FullFileName)
1067
1068 Db = GetDB()
1069 FileTable = 'Identifier' + str(FileID)
1070 # search variable in include files
1071
1072 # it is a function call, search function declarations and definitions
1073 if IsFuncCall:
1074 SqlStatement = """ select Modifier, ID
1075 from %s
1076 where Model = %d and Value = \'%s\'
1077 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar)
1078 ResultSet = Db.TblFile.Exec(SqlStatement)
1079
1080 for Result in ResultSet:
1081 Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1082 TypedefDict = GetTypedefDict(FullFileName)
1083 Type = GetRealType(Type, TypedefDict, TargetType)
1084 return Type
1085
1086 IncludeFileList = GetAllIncludeFiles(FullFileName)
1087 for F in IncludeFileList:
1088 FileID = GetTableID(F)
1089 if FileID < 0:
1090 continue
1091
1092 FileTable = 'Identifier' + str(FileID)
1093 SqlStatement = """ select Modifier, ID
1094 from %s
1095 where Model = %d and Value = \'%s\'
1096 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar)
1097 ResultSet = Db.TblFile.Exec(SqlStatement)
1098
1099 for Result in ResultSet:
1100 Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1101 TypedefDict = GetTypedefDict(FullFileName)
1102 Type = GetRealType(Type, TypedefDict, TargetType)
1103 return Type
1104
1105 FileID = GetTableID(FullFileName)
1106 SqlStatement = """ select Modifier, ID
1107 from Function
1108 where BelongsToFile = %d and Name = \'%s\'
1109 """ % (FileID, PredVar)
1110 ResultSet = Db.TblFile.Exec(SqlStatement)
1111
1112 for Result in ResultSet:
1113 Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1114 TypedefDict = GetTypedefDict(FullFileName)
1115 Type = GetRealType(Type, TypedefDict, TargetType)
1116 return Type
1117
1118 for F in IncludeFileList:
1119 FileID = GetTableID(F)
1120 if FileID < 0:
1121 continue
1122
1123 FileTable = 'Identifier' + str(FileID)
1124 SqlStatement = """ select Modifier, ID
1125 from Function
1126 where BelongsToFile = %d and Name = \'%s\'
1127 """ % (FileID, PredVar)
1128 ResultSet = Db.TblFile.Exec(SqlStatement)
1129
1130 for Result in ResultSet:
1131 Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1132 TypedefDict = GetTypedefDict(FullFileName)
1133 Type = GetRealType(Type, TypedefDict, TargetType)
1134 return Type
1135
1136 return None
1137
1138 # really variable, search local variable first
1139 SqlStatement = """ select Modifier, ID
1140 from %s
1141 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1142 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar, FuncRecord[0], FuncRecord[1])
1143 ResultSet = Db.TblFile.Exec(SqlStatement)
1144 VarFound = False
1145 for Result in ResultSet:
1146 if len(PredVarList) > 1:
1147 Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)
1148 return Type
1149 else:
1150 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1151 TypeList = GetDataTypeFromModifier(Result[0]).split()
1152 Type = TypeList[-1]
1153 if len(TypeList) > 1 and StarList is not None:
1154 for Star in StarList:
1155 Type = Type.strip()
1156 Type = Type.rstrip(Star)
1157 # Get real type after de-reference pointers.
1158 if len(Type.strip()) == 0:
1159 Type = TypeList[-2]
1160 TypedefDict = GetTypedefDict(FullFileName)
1161 Type = GetRealType(Type, TypedefDict, TargetType)
1162 return Type
1163
1164 # search function parameters second
1165 ParamList = GetParamList(FuncRecord[2])
1166 for Param in ParamList:
1167 if Param.Name.strip() == PredVar:
1168 if len(PredVarList) > 1:
1169 Type = GetTypeInfo(PredVarList[1:], Param.Modifier, FullFileName, TargetType)
1170 return Type
1171 else:
1172 TypeList = GetDataTypeFromModifier(Param.Modifier).split()
1173 Type = TypeList[-1]
1174 if Type == '*' and len(TypeList) >= 2:
1175 Type = TypeList[-2]
1176 if len(TypeList) > 1 and StarList is not None:
1177 for Star in StarList:
1178 Type = Type.strip()
1179 Type = Type.rstrip(Star)
1180 # Get real type after de-reference pointers.
1181 if len(Type.strip()) == 0:
1182 Type = TypeList[-2]
1183 TypedefDict = GetTypedefDict(FullFileName)
1184 Type = GetRealType(Type, TypedefDict, TargetType)
1185 return Type
1186
1187 # search global variable next
1188 SqlStatement = """ select Modifier, ID
1189 from %s
1190 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1191 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar)
1192 ResultSet = Db.TblFile.Exec(SqlStatement)
1193
1194 for Result in ResultSet:
1195 if len(PredVarList) > 1:
1196 Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)
1197 return Type
1198 else:
1199 TypeList = GetDataTypeFromModifier(Result[0]).split()
1200 Type = TypeList[-1]
1201 if len(TypeList) > 1 and StarList is not None:
1202 for Star in StarList:
1203 Type = Type.strip()
1204 Type = Type.rstrip(Star)
1205 # Get real type after de-reference pointers.
1206 if len(Type.strip()) == 0:
1207 Type = TypeList[-2]
1208 TypedefDict = GetTypedefDict(FullFileName)
1209 Type = GetRealType(Type, TypedefDict, TargetType)
1210 return Type
1211
1212 IncludeFileList = GetAllIncludeFiles(FullFileName)
1213 for F in IncludeFileList:
1214 FileID = GetTableID(F)
1215 if FileID < 0:
1216 continue
1217
1218 FileTable = 'Identifier' + str(FileID)
1219 SqlStatement = """ select Modifier, ID
1220 from %s
1221 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1222 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar)
1223 ResultSet = Db.TblFile.Exec(SqlStatement)
1224
1225 for Result in ResultSet:
1226 if len(PredVarList) > 1:
1227 Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)
1228 return Type
1229 else:
1230 TypeList = GetDataTypeFromModifier(Result[0]).split()
1231 Type = TypeList[-1]
1232 if len(TypeList) > 1 and StarList is not None:
1233 for Star in StarList:
1234 Type = Type.strip()
1235 Type = Type.rstrip(Star)
1236 # Get real type after de-reference pointers.
1237 if len(Type.strip()) == 0:
1238 Type = TypeList[-2]
1239 TypedefDict = GetTypedefDict(FullFileName)
1240 Type = GetRealType(Type, TypedefDict, TargetType)
1241 return Type
1242
1243 def GetTypeFromArray(Type, Var):
1244 Count = Var.count('[')
1245
1246 while Count > 0:
1247 Type = Type.strip()
1248 Type = Type.rstrip('*')
1249 Count = Count - 1
1250
1251 return Type
1252
1253 def CheckFuncLayoutReturnType(FullFileName):
1254 ErrorMsgList = []
1255
1256 FileID = GetTableID(FullFileName, ErrorMsgList)
1257 if FileID < 0:
1258 return ErrorMsgList
1259
1260 Db = GetDB()
1261 FileTable = 'Identifier' + str(FileID)
1262 SqlStatement = """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1263 from %s
1264 where Model = %d
1265 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1266 ResultSet = Db.TblFile.Exec(SqlStatement)
1267 for Result in ResultSet:
1268 ReturnType = GetDataTypeFromModifier(Result[0])
1269 TypeStart = ReturnType.split()[0]
1270 FuncName = Result[5]
1271 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, FuncName):
1272 continue
1273 Result0 = Result[0]
1274 if Result0.upper().startswith('STATIC'):
1275 Result0 = Result0[6:].strip()
1276 Index = Result0.find(TypeStart)
1277 if Index != 0 or Result[3] != 0:
1278 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, FileTable, Result[1])
1279
1280 if Result[2] == Result[4]:
1281 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear on its own line' % FuncName, FileTable, Result[1])
1282
1283 SqlStatement = """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1284 from Function
1285 where BelongsToFile = %d
1286 """ % (FileID)
1287 ResultSet = Db.TblFile.Exec(SqlStatement)
1288 for Result in ResultSet:
1289 ReturnType = GetDataTypeFromModifier(Result[0])
1290 TypeStart = ReturnType.split()[0]
1291 FuncName = Result[5]
1292 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, FuncName):
1293 continue
1294 Result0 = Result[0]
1295 if Result0.upper().startswith('STATIC'):
1296 Result0 = Result0[6:].strip()
1297 Index = Result0.find(TypeStart)
1298 if Index != 0 or Result[3] != 0:
1299 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, 'Function', Result[1])
1300
1301 def CheckFuncLayoutModifier(FullFileName):
1302 ErrorMsgList = []
1303
1304 FileID = GetTableID(FullFileName, ErrorMsgList)
1305 if FileID < 0:
1306 return ErrorMsgList
1307
1308 Db = GetDB()
1309 FileTable = 'Identifier' + str(FileID)
1310 SqlStatement = """ select Modifier, ID
1311 from %s
1312 where Model = %d
1313 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1314 ResultSet = Db.TblFile.Exec(SqlStatement)
1315 for Result in ResultSet:
1316 ReturnType = GetDataTypeFromModifier(Result[0])
1317 TypeStart = ReturnType.split()[0]
1318 Result0 = Result[0]
1319 if Result0.upper().startswith('STATIC'):
1320 Result0 = Result0[6:].strip()
1321 Index = Result0.find(TypeStart)
1322 if Index != 0:
1323 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', FileTable, Result[1])
1324
1325 SqlStatement = """ select Modifier, ID
1326 from Function
1327 where BelongsToFile = %d
1328 """ % (FileID)
1329 ResultSet = Db.TblFile.Exec(SqlStatement)
1330 for Result in ResultSet:
1331 ReturnType = GetDataTypeFromModifier(Result[0])
1332 TypeStart = ReturnType.split()[0]
1333 Result0 = Result[0]
1334 if Result0.upper().startswith('STATIC'):
1335 Result0 = Result0[6:].strip()
1336 Index = Result0.find(TypeStart)
1337 if Index != 0:
1338 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', 'Function', Result[1])
1339
1340 def CheckFuncLayoutName(FullFileName):
1341 ErrorMsgList = []
1342 # Parameter variable format pattern.
1343 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
1344 ParamIgnoreList = ('VOID', '...')
1345 FileID = GetTableID(FullFileName, ErrorMsgList)
1346 if FileID < 0:
1347 return ErrorMsgList
1348
1349 Db = GetDB()
1350 FileTable = 'Identifier' + str(FileID)
1351 SqlStatement = """ select Name, ID, EndColumn, Value
1352 from %s
1353 where Model = %d
1354 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1355 ResultSet = Db.TblFile.Exec(SqlStatement)
1356 for Result in ResultSet:
1357 FuncName = Result[3]
1358 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName):
1359 continue
1360 if Result[2] != 0:
1361 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, FileTable, Result[1])
1362 ParamList = GetParamList(Result[0])
1363 if len(ParamList) == 0:
1364 continue
1365 StartLine = 0
1366 for Param in ParamList:
1367 if Param.StartLine <= StartLine:
1368 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, FileTable, Result[1])
1369 if Param.StartLine - StartLine > 1:
1370 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, FileTable, Result[1])
1371 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):
1372 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1])
1373 StartLine = Param.StartLine
1374
1375 if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'):
1376 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', FileTable, Result[1])
1377
1378 SqlStatement = """ select Modifier, ID, FunNameStartColumn, Name
1379 from Function
1380 where BelongsToFile = %d
1381 """ % (FileID)
1382 ResultSet = Db.TblFile.Exec(SqlStatement)
1383 for Result in ResultSet:
1384 FuncName = Result[3]
1385 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName):
1386 continue
1387 if Result[2] != 0:
1388 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, 'Function', Result[1])
1389 ParamList = GetParamList(Result[0])
1390 if len(ParamList) == 0:
1391 continue
1392 StartLine = 0
1393 for Param in ParamList:
1394 if Param.StartLine <= StartLine:
1395 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, 'Function', Result[1])
1396 if Param.StartLine - StartLine > 1:
1397 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, 'Function', Result[1])
1398 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):
1399 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1])
1400 StartLine = Param.StartLine
1401 if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'):
1402 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', 'Function', Result[1])
1403
1404 def CheckFuncLayoutPrototype(FullFileName):
1405 ErrorMsgList = []
1406
1407 FileID = GetTableID(FullFileName, ErrorMsgList)
1408 if FileID < 0:
1409 return ErrorMsgList
1410
1411 FileTable = 'Identifier' + str(FileID)
1412 Db = GetDB()
1413 SqlStatement = """ select Modifier, Header, Name, ID
1414 from Function
1415 where BelongsToFile = %d
1416 """ % (FileID)
1417 ResultSet = Db.TblFile.Exec(SqlStatement)
1418 if len(ResultSet) == 0:
1419 return ErrorMsgList
1420
1421 FuncDefList = []
1422 for Result in ResultSet:
1423 FuncDefList.append(Result)
1424
1425 SqlStatement = """ select Modifier, Name, ID
1426 from %s
1427 where Model = %d
1428 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1429 ResultSet = Db.TblFile.Exec(SqlStatement)
1430 FuncDeclList = []
1431 for Result in ResultSet:
1432 FuncDeclList.append(Result)
1433
1434 UndeclFuncList = []
1435 for FuncDef in FuncDefList:
1436 FuncName = FuncDef[2].strip()
1437 FuncModifier = FuncDef[0]
1438 FuncDefHeader = FuncDef[1]
1439 for FuncDecl in FuncDeclList:
1440 LBPos = FuncDecl[1].find('(')
1441 DeclName = FuncDecl[1][0:LBPos].strip()
1442 DeclModifier = FuncDecl[0]
1443 if DeclName == FuncName:
1444 if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName):
1445 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3])
1446 ParamListOfDef = GetParamList(FuncDefHeader)
1447 ParamListOfDecl = GetParamList(FuncDecl[1])
1448 if len(ParamListOfDef) != len(ParamListOfDecl) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, FuncName):
1449 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, 'Parameter number different in function [%s].' % FuncName, 'Function', FuncDef[3])
1450 break
1451
1452 Index = 0
1453 while Index < len(ParamListOfDef):
1454 if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, FuncName):
1455 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])
1456 Index += 1
1457 break
1458 else:
1459 UndeclFuncList.append(FuncDef)
1460
1461 IncludeFileList = GetAllIncludeFiles(FullFileName)
1462 FuncDeclList = []
1463 for F in IncludeFileList:
1464 FileID = GetTableID(F, ErrorMsgList)
1465 if FileID < 0:
1466 continue
1467
1468 FileTable = 'Identifier' + str(FileID)
1469 SqlStatement = """ select Modifier, Name, ID
1470 from %s
1471 where Model = %d
1472 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1473 ResultSet = Db.TblFile.Exec(SqlStatement)
1474
1475 for Result in ResultSet:
1476 FuncDeclList.append(Result)
1477
1478 for FuncDef in UndeclFuncList:
1479 FuncName = FuncDef[2].strip()
1480 FuncModifier = FuncDef[0]
1481 FuncDefHeader = FuncDef[1]
1482 for FuncDecl in FuncDeclList:
1483 LBPos = FuncDecl[1].find('(')
1484 DeclName = FuncDecl[1][0:LBPos].strip()
1485 DeclModifier = FuncDecl[0]
1486 if DeclName == FuncName:
1487 if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName):
1488 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3])
1489 ParamListOfDef = GetParamList(FuncDefHeader)
1490 ParamListOfDecl = GetParamList(FuncDecl[1])
1491 if len(ParamListOfDef) != len(ParamListOfDecl) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, FuncName):
1492 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, 'Parameter number different in function [%s].' % FuncName, 'Function', FuncDef[3])
1493 break
1494
1495 Index = 0
1496 while Index < len(ParamListOfDef):
1497 if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, FuncName):
1498 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])
1499 Index += 1
1500 break
1501
1502 def CheckFuncLayoutBody(FullFileName):
1503 ErrorMsgList = []
1504
1505 FileID = GetTableID(FullFileName, ErrorMsgList)
1506 if FileID < 0:
1507 return ErrorMsgList
1508
1509 FileTable = 'Identifier' + str(FileID)
1510 Db = GetDB()
1511 SqlStatement = """ select BodyStartColumn, EndColumn, ID, Name
1512 from Function
1513 where BelongsToFile = %d
1514 """ % (FileID)
1515 ResultSet = Db.TblFile.Exec(SqlStatement)
1516 if len(ResultSet) == 0:
1517 return ErrorMsgList
1518 for Result in ResultSet:
1519 if Result[0] != 0:
1520 if not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, Result[3]):
1521 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY,
1522 'The open brace should be at the very beginning of a line for the function [%s].' % Result[3],
1523 'Function', Result[2])
1524 if Result[1] != 0:
1525 if not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, Result[3]):
1526 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY,
1527 'The close brace should be at the very beginning of a line for the function [%s].' % Result[3],
1528 'Function', Result[2])
1529
1530 def CheckFuncLayoutLocalVariable(FullFileName):
1531 ErrorMsgList = []
1532
1533 FileID = GetTableID(FullFileName, ErrorMsgList)
1534 if FileID < 0:
1535 return ErrorMsgList
1536
1537 Db = GetDB()
1538 FileTable = 'Identifier' + str(FileID)
1539 SqlStatement = """ select ID
1540 from Function
1541 where BelongsToFile = %d
1542 """ % (FileID)
1543 ResultSet = Db.TblFile.Exec(SqlStatement)
1544 if len(ResultSet) == 0:
1545 return ErrorMsgList
1546 FL = []
1547 for Result in ResultSet:
1548 FL.append(Result)
1549
1550 for F in FL:
1551 SqlStatement = """ select Name, Value, ID, Modifier
1552 from %s
1553 where Model = %d and BelongsToFunction = %d
1554 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, F[0])
1555 ResultSet = Db.TblFile.Exec(SqlStatement)
1556 if len(ResultSet) == 0:
1557 continue
1558
1559 for Result in ResultSet:
1560 if len(Result[1]) > 0 and 'CONST' not in Result[3]:
1561 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE, 'Variable Name: %s' % Result[0], FileTable, Result[2])
1562
1563 def CheckMemberVariableFormat(Name, Value, FileTable, TdId, ModelId):
1564 ErrMsgList = []
1565 # Member variable format pattern.
1566 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
1567
1568 LBPos = Value.find('{')
1569 RBPos = Value.rfind('}')
1570 if LBPos == -1 or RBPos == -1:
1571 return ErrMsgList
1572
1573 Fields = Value[LBPos + 1 : RBPos]
1574 Fields = StripComments(Fields).strip()
1575 NestPos = Fields.find ('struct')
1576 if NestPos != -1 and (NestPos + len('struct') < len(Fields)) and ModelId != DataClass.MODEL_IDENTIFIER_UNION:
1577 if not Fields[NestPos + len('struct') + 1].isalnum():
1578 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1579 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested struct in [%s].' % (Name), FileTable, TdId)
1580 return ErrMsgList
1581 NestPos = Fields.find ('union')
1582 if NestPos != -1 and (NestPos + len('union') < len(Fields)):
1583 if not Fields[NestPos + len('union') + 1].isalnum():
1584 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1585 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested union in [%s].' % (Name), FileTable, TdId)
1586 return ErrMsgList
1587 NestPos = Fields.find ('enum')
1588 if NestPos != -1 and (NestPos + len('enum') < len(Fields)):
1589 if not Fields[NestPos + len('enum') + 1].isalnum():
1590 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1591 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested enum in [%s].' % (Name), FileTable, TdId)
1592 return ErrMsgList
1593
1594 if ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:
1595 FieldsList = Fields.split(',')
1596 # deal with enum is pre-assigned a value by function call ( , , , ...)
1597 QuoteCount = 0
1598 Index = 0
1599 RemoveCurrentElement = False
1600 while Index < len(FieldsList):
1601 Field = FieldsList[Index]
1602
1603 if Field.find('(') != -1:
1604 QuoteCount += 1
1605 RemoveCurrentElement = True
1606 Index += 1
1607 continue
1608
1609 if Field.find(')') != -1 and QuoteCount > 0:
1610 QuoteCount -= 1
1611
1612 if RemoveCurrentElement:
1613 FieldsList.remove(Field)
1614 if QuoteCount == 0:
1615 RemoveCurrentElement = False
1616 continue
1617
1618 if QuoteCount == 0:
1619 RemoveCurrentElement = False
1620
1621 Index += 1
1622 else:
1623 FieldsList = Fields.split(';')
1624
1625 for Field in FieldsList:
1626 Field = Field.strip()
1627 if Field == '':
1628 continue
1629 # For the condition that the field in struct is an array with [] suffixes...
1630 if Field[-1] == ']':
1631 LBPos = Field.find('[')
1632 Field = Field[0:LBPos]
1633 # For the condition that bit field ": Number"
1634 if Field.find(':') != -1:
1635 ColonPos = Field.find(':')
1636 Field = Field[0:ColonPos]
1637
1638 Field = Field.strip()
1639 if Field == '':
1640 continue
1641 if Field.startswith("#"):
1642 continue
1643 # Enum could directly assign value to variable
1644 Field = Field.split('=')[0].strip()
1645 TokenList = Field.split()
1646 # Remove pointers before variable
1647 Token = TokenList[-1]
1648 if Token in ['OPTIONAL']:
1649 Token = TokenList[-2]
1650 if not Pattern.match(Token.lstrip('*')):
1651 ErrMsgList.append(Token.lstrip('*'))
1652
1653 return ErrMsgList
1654
1655 def CheckDeclTypedefFormat(FullFileName, ModelId):
1656 ErrorMsgList = []
1657
1658 FileID = GetTableID(FullFileName, ErrorMsgList)
1659 if FileID < 0:
1660 return ErrorMsgList
1661
1662 Db = GetDB()
1663 FileTable = 'Identifier' + str(FileID)
1664 SqlStatement = """ select Name, StartLine, EndLine, ID, Value
1665 from %s
1666 where Model = %d
1667 """ % (FileTable, ModelId)
1668 ResultSet = Db.TblFile.Exec(SqlStatement)
1669 ResultList = []
1670 for Result in ResultSet:
1671 ResultList.append(Result)
1672
1673 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1674 if ModelId == DataClass.MODEL_IDENTIFIER_STRUCTURE:
1675 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1676 elif ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:
1677 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1678 elif ModelId == DataClass.MODEL_IDENTIFIER_UNION:
1679 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1680
1681 SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID
1682 from %s
1683 where Model = %d
1684 """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
1685 TdSet = Db.TblFile.Exec(SqlStatement)
1686 TdList = []
1687 for Td in TdSet:
1688 TdList.append(Td)
1689 # Check member variable name format that from typedefs of ONLY this file.
1690 for Td in TdList:
1691 Name = Td[1].strip()
1692 Value = Td[2].strip()
1693 if Value.startswith('enum'):
1694 ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE
1695 elif Value.startswith('struct'):
1696 ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE
1697 elif Value.startswith('union'):
1698 ValueModelId = DataClass.MODEL_IDENTIFIER_UNION
1699 else:
1700 continue
1701
1702 if ValueModelId != ModelId:
1703 continue
1704 # Check member variable format.
1705 ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Td[5], ModelId)
1706 for ErrMsg in ErrMsgList:
1707 if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Name + '.' + ErrMsg):
1708 continue
1709 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Name + '.' + ErrMsg), FileTable, Td[5])
1710
1711 # First check in current file to see whether struct/union/enum is typedef-ed.
1712 UntypedefedList = []
1713 for Result in ResultList:
1714 # Check member variable format.
1715 Name = Result[0].strip()
1716 Value = Result[4].strip()
1717 if Value.startswith('enum'):
1718 ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE
1719 elif Value.startswith('struct'):
1720 ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE
1721 elif Value.startswith('union'):
1722 ValueModelId = DataClass.MODEL_IDENTIFIER_UNION
1723 else:
1724 continue
1725
1726 if ValueModelId != ModelId:
1727 continue
1728 ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Result[3], ModelId)
1729 for ErrMsg in ErrMsgList:
1730 if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Result[0] + '.' + ErrMsg):
1731 continue
1732 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Result[0] + '.' + ErrMsg), FileTable, Result[3])
1733 # Check whether it is typedefed.
1734 Found = False
1735 for Td in TdList:
1736 # skip function pointer
1737 if len(Td[0]) > 0:
1738 continue
1739 if Result[1] >= Td[3] and Td[4] >= Result[2]:
1740 Found = True
1741 if not Td[1].isupper():
1742 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1743 if Result[0] in Td[2].split():
1744 Found = True
1745 if not Td[1].isupper():
1746 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1747 if Found:
1748 break
1749
1750 if not Found:
1751 UntypedefedList.append(Result)
1752 continue
1753
1754 if len(UntypedefedList) == 0:
1755 return
1756
1757 IncludeFileList = GetAllIncludeFiles(FullFileName)
1758 TdList = []
1759 for F in IncludeFileList:
1760 FileID = GetTableID(F, ErrorMsgList)
1761 if FileID < 0:
1762 continue
1763
1764 IncludeFileTable = 'Identifier' + str(FileID)
1765 SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID
1766 from %s
1767 where Model = %d
1768 """ % (IncludeFileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
1769 ResultSet = Db.TblFile.Exec(SqlStatement)
1770 TdList.extend(ResultSet)
1771
1772 for Result in UntypedefedList:
1773
1774 # Check whether it is typedefed.
1775 Found = False
1776 for Td in TdList:
1777
1778 if len(Td[0]) > 0:
1779 continue
1780 if Result[1] >= Td[3] and Td[4] >= Result[2]:
1781 Found = True
1782 if not Td[1].isupper():
1783 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1784 if Result[0] in Td[2].split():
1785 Found = True
1786 if not Td[1].isupper():
1787 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1788 if Found:
1789 break
1790
1791 if not Found:
1792 PrintErrorMsg(ErrorType, 'No Typedef for %s' % Result[0], FileTable, Result[3])
1793 continue
1794
1795 def CheckDeclStructTypedef(FullFileName):
1796 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_STRUCTURE)
1797
1798 def CheckDeclEnumTypedef(FullFileName):
1799 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_ENUMERATE)
1800
1801 def CheckDeclUnionTypedef(FullFileName):
1802 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_UNION)
1803
1804 def CheckDeclArgModifier(FullFileName):
1805 ErrorMsgList = []
1806
1807 FileID = GetTableID(FullFileName, ErrorMsgList)
1808 if FileID < 0:
1809 return ErrorMsgList
1810
1811 Db = GetDB()
1812 FileTable = 'Identifier' + str(FileID)
1813 SqlStatement = """ select Modifier, Name, ID
1814 from %s
1815 where Model = %d
1816 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
1817 ResultSet = Db.TblFile.Exec(SqlStatement)
1818 ModifierTuple = ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1819 MAX_MODIFIER_LENGTH = 100
1820 for Result in ResultSet:
1821 for Modifier in ModifierTuple:
1822 if PatternInModifier(Result[0], Modifier) and len(Result[0]) < MAX_MODIFIER_LENGTH:
1823 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Variable Modifier %s' % Result[0], FileTable, Result[2])
1824 break
1825
1826 SqlStatement = """ select Modifier, Name, ID
1827 from %s
1828 where Model = %d
1829 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1830 ResultSet = Db.TblFile.Exec(SqlStatement)
1831 for Result in ResultSet:
1832 for Modifier in ModifierTuple:
1833 if PatternInModifier(Result[0], Modifier):
1834 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])
1835 break
1836
1837 SqlStatement = """ select Modifier, Header, ID
1838 from Function
1839 where BelongsToFile = %d
1840 """ % (FileID)
1841 ResultSet = Db.TblFile.Exec(SqlStatement)
1842 for Result in ResultSet:
1843 for Modifier in ModifierTuple:
1844 if PatternInModifier(Result[0], Modifier):
1845 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])
1846 break
1847
1848 def CheckDeclNoUseCType(FullFileName):
1849 ErrorMsgList = []
1850
1851 FileID = GetTableID(FullFileName, ErrorMsgList)
1852 if FileID < 0:
1853 return ErrorMsgList
1854
1855 Db = GetDB()
1856 FileTable = 'Identifier' + str(FileID)
1857 SqlStatement = """ select Modifier, Name, ID
1858 from %s
1859 where Model = %d
1860 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
1861 ResultSet = Db.TblFile.Exec(SqlStatement)
1862 CTypeTuple = ('int', 'unsigned', 'char', 'void', 'static', 'long')
1863 for Result in ResultSet:
1864 for Type in CTypeTuple:
1865 if PatternInModifier(Result[0], Type):
1866 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE,
1867 Result[0] + ' ' + Result[1]):
1868 continue
1869 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE,
1870 'Invalid variable type (%s) in definition [%s]' % (Type, Result[0] + ' ' + Result[1]),
1871 FileTable,
1872 Result[2])
1873 break
1874
1875 SqlStatement = """ select Modifier, Name, ID, Value
1876 from %s
1877 where Model = %d
1878 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1879 ResultSet = Db.TblFile.Exec(SqlStatement)
1880 for Result in ResultSet:
1881 ParamList = GetParamList(Result[1])
1882 FuncName = Result[3]
1883 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):
1884 continue
1885 for Type in CTypeTuple:
1886 if PatternInModifier(Result[0], Type):
1887 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '%s Return type %s' % (FuncName, Result[0]), FileTable, Result[2])
1888
1889 for Param in ParamList:
1890 if PatternInModifier(Param.Modifier, Type):
1891 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])
1892
1893 SqlStatement = """ select Modifier, Header, ID, Name
1894 from Function
1895 where BelongsToFile = %d
1896 """ % (FileID)
1897 ResultSet = Db.TblFile.Exec(SqlStatement)
1898 for Result in ResultSet:
1899 ParamList = GetParamList(Result[1])
1900 FuncName = Result[3]
1901 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):
1902 continue
1903 for Type in CTypeTuple:
1904 if PatternInModifier(Result[0], Type):
1905 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '[%s] Return type %s' % (FuncName, Result[0]), FileTable, Result[2])
1906
1907 for Param in ParamList:
1908 if PatternInModifier(Param.Modifier, Type):
1909 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])
1910
1911
1912 def CheckPointerNullComparison(FullFileName):
1913 ErrorMsgList = []
1914
1915 FileID = GetTableID(FullFileName, ErrorMsgList)
1916 if FileID < 0:
1917 return ErrorMsgList
1918
1919 # cache the found function return type to accelerate later checking in this file.
1920 FuncReturnTypeDict = {}
1921
1922 Db = GetDB()
1923 FileTable = 'Identifier' + str(FileID)
1924 SqlStatement = """ select Value, StartLine, ID
1925 from %s
1926 where Model = %d
1927 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
1928 ResultSet = Db.TblFile.Exec(SqlStatement)
1929 if len(ResultSet) == 0:
1930 return
1931 PSL = []
1932 for Result in ResultSet:
1933 PSL.append([Result[0], Result[1], Result[2]])
1934
1935 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
1936 from Function
1937 where BelongsToFile = %d
1938 """ % (FileID)
1939 ResultSet = Db.TblFile.Exec(SqlStatement)
1940 FL = []
1941 for Result in ResultSet:
1942 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
1943
1944 p = GetFuncDeclPattern()
1945 for Str in PSL:
1946 FuncRecord = GetFuncContainsPE(Str[1], FL)
1947 if FuncRecord is None:
1948 continue
1949
1950 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
1951 PredInfo = SplitPredicateStr(Exp)
1952 if PredInfo[1] is None:
1953 PredVarStr = PredInfo[0][0].strip()
1954 IsFuncCall = False
1955 SearchInCache = False
1956 # PredVarStr may contain '.' or '->'
1957 TmpStr = PredVarStr.replace('.', '').replace('->', '')
1958 if p.match(TmpStr):
1959 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
1960 SearchInCache = True
1961 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1962 if TmpStr.startswith(PredVarStr):
1963 IsFuncCall = True
1964
1965 if PredVarStr.strip() in IgnoredKeywordList:
1966 continue
1967 StarList = []
1968 PredVarList = GetCNameList(PredVarStr, StarList)
1969 # No variable found, maybe value first? like (0 == VarName)
1970 if len(PredVarList) == 0:
1971 continue
1972 if SearchInCache:
1973 Type = FuncReturnTypeDict.get(PredVarStr)
1974 if Type is not None:
1975 if Type.find('*') != -1 and Type != 'BOOLEAN*':
1976 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
1977 continue
1978
1979 if PredVarStr in FuncReturnTypeDict:
1980 continue
1981
1982 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, None, StarList)
1983 if SearchInCache:
1984 FuncReturnTypeDict[PredVarStr] = Type
1985 if Type is None:
1986 continue
1987 Type = GetTypeFromArray(Type, PredVarStr)
1988 if Type.find('*') != -1 and Type != 'BOOLEAN*':
1989 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
1990
1991 def CheckNonBooleanValueComparison(FullFileName):
1992 ErrorMsgList = []
1993
1994 FileID = GetTableID(FullFileName, ErrorMsgList)
1995 if FileID < 0:
1996 return ErrorMsgList
1997
1998 # cache the found function return type to accelerate later checking in this file.
1999 FuncReturnTypeDict = {}
2000
2001 Db = GetDB()
2002 FileTable = 'Identifier' + str(FileID)
2003 SqlStatement = """ select Value, StartLine, ID
2004 from %s
2005 where Model = %d
2006 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
2007 ResultSet = Db.TblFile.Exec(SqlStatement)
2008 if len(ResultSet) == 0:
2009 return
2010 PSL = []
2011 for Result in ResultSet:
2012 PSL.append([Result[0], Result[1], Result[2]])
2013
2014 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
2015 from Function
2016 where BelongsToFile = %d
2017 """ % (FileID)
2018 ResultSet = Db.TblFile.Exec(SqlStatement)
2019 FL = []
2020 for Result in ResultSet:
2021 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
2022
2023 p = GetFuncDeclPattern()
2024 for Str in PSL:
2025 FuncRecord = GetFuncContainsPE(Str[1], FL)
2026 if FuncRecord is None:
2027 continue
2028
2029 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
2030 PredInfo = SplitPredicateStr(Exp)
2031 if PredInfo[1] is None:
2032 PredVarStr = PredInfo[0][0].strip()
2033 IsFuncCall = False
2034 SearchInCache = False
2035 # PredVarStr may contain '.' or '->'
2036 TmpStr = PredVarStr.replace('.', '').replace('->', '')
2037 if p.match(TmpStr):
2038 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
2039 SearchInCache = True
2040 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2041 if TmpStr.startswith(PredVarStr):
2042 IsFuncCall = True
2043
2044 if PredVarStr.strip() in IgnoredKeywordList:
2045 continue
2046 StarList = []
2047 PredVarList = GetCNameList(PredVarStr, StarList)
2048 # No variable found, maybe value first? like (0 == VarName)
2049 if len(PredVarList) == 0:
2050 continue
2051
2052 if SearchInCache:
2053 Type = FuncReturnTypeDict.get(PredVarStr)
2054 if Type is not None:
2055 if Type.find('BOOLEAN') == -1:
2056 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2057 continue
2058
2059 if PredVarStr in FuncReturnTypeDict:
2060 continue
2061 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)
2062 if SearchInCache:
2063 FuncReturnTypeDict[PredVarStr] = Type
2064 if Type is None:
2065 continue
2066 if Type.find('BOOLEAN') == -1:
2067 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2068
2069
2070 def CheckBooleanValueComparison(FullFileName):
2071 ErrorMsgList = []
2072
2073 FileID = GetTableID(FullFileName, ErrorMsgList)
2074 if FileID < 0:
2075 return ErrorMsgList
2076
2077 # cache the found function return type to accelerate later checking in this file.
2078 FuncReturnTypeDict = {}
2079
2080 Db = GetDB()
2081 FileTable = 'Identifier' + str(FileID)
2082 SqlStatement = """ select Value, StartLine, ID
2083 from %s
2084 where Model = %d
2085 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
2086 ResultSet = Db.TblFile.Exec(SqlStatement)
2087 if len(ResultSet) == 0:
2088 return
2089 PSL = []
2090 for Result in ResultSet:
2091 PSL.append([Result[0], Result[1], Result[2]])
2092
2093 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
2094 from Function
2095 where BelongsToFile = %d
2096 """ % (FileID)
2097 ResultSet = Db.TblFile.Exec(SqlStatement)
2098 FL = []
2099 for Result in ResultSet:
2100 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
2101
2102 p = GetFuncDeclPattern()
2103 for Str in PSL:
2104 FuncRecord = GetFuncContainsPE(Str[1], FL)
2105 if FuncRecord is None:
2106 continue
2107
2108 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
2109 PredInfo = SplitPredicateStr(Exp)
2110 if PredInfo[1] in ('==', '!=') and PredInfo[0][1] in ('TRUE', 'FALSE'):
2111 PredVarStr = PredInfo[0][0].strip()
2112 IsFuncCall = False
2113 SearchInCache = False
2114 # PredVarStr may contain '.' or '->'
2115 TmpStr = PredVarStr.replace('.', '').replace('->', '')
2116 if p.match(TmpStr):
2117 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
2118 SearchInCache = True
2119 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2120 if TmpStr.startswith(PredVarStr):
2121 IsFuncCall = True
2122
2123 if PredVarStr.strip() in IgnoredKeywordList:
2124 continue
2125 StarList = []
2126 PredVarList = GetCNameList(PredVarStr, StarList)
2127 # No variable found, maybe value first? like (0 == VarName)
2128 if len(PredVarList) == 0:
2129 continue
2130
2131 if SearchInCache:
2132 Type = FuncReturnTypeDict.get(PredVarStr)
2133 if Type is not None:
2134 if Type.find('BOOLEAN') != -1:
2135 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2136 continue
2137
2138 if PredVarStr in FuncReturnTypeDict:
2139 continue
2140
2141 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)
2142 if SearchInCache:
2143 FuncReturnTypeDict[PredVarStr] = Type
2144 if Type is None:
2145 continue
2146 if Type.find('BOOLEAN') != -1:
2147 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2148
2149
2150 def CheckHeaderFileData(FullFileName, AllTypedefFun=[]):
2151 ErrorMsgList = []
2152
2153 FileID = GetTableID(FullFileName, ErrorMsgList)
2154 if FileID < 0:
2155 return ErrorMsgList
2156
2157 Db = GetDB()
2158 FileTable = 'Identifier' + str(FileID)
2159 SqlStatement = """ select ID, Modifier
2160 from %s
2161 where Model = %d
2162 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
2163 ResultSet = Db.TblFile.Exec(SqlStatement)
2164 for Result in ResultSet:
2165 if not Result[1].startswith('extern'):
2166 for Item in AllTypedefFun:
2167 if '(%s)' % Result[1] in Item:
2168 break
2169 else:
2170 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Variable definition appears in header file', FileTable, Result[0])
2171
2172 SqlStatement = """ select ID
2173 from Function
2174 where BelongsToFile = %d
2175 """ % FileID
2176 ResultSet = Db.TblFile.Exec(SqlStatement)
2177 for Result in ResultSet:
2178 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Function definition appears in header file', 'Function', Result[0])
2179
2180 return ErrorMsgList
2181
2182 def CheckHeaderFileIfndef(FullFileName):
2183 ErrorMsgList = []
2184
2185 FileID = GetTableID(FullFileName, ErrorMsgList)
2186 if FileID < 0:
2187 return ErrorMsgList
2188
2189 Db = GetDB()
2190 FileTable = 'Identifier' + str(FileID)
2191 SqlStatement = """ select Value, StartLine
2192 from %s
2193 where Model = %d order by StartLine
2194 """ % (FileTable, DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF)
2195 ResultSet = Db.TblFile.Exec(SqlStatement)
2196 if len(ResultSet) == 0:
2197 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1, '', 'File', FileID)
2198 return ErrorMsgList
2199 for Result in ResultSet:
2200 SqlStatement = """ select Value, EndLine
2201 from %s
2202 where EndLine < %d
2203 """ % (FileTable, Result[1])
2204 ResultSet = Db.TblFile.Exec(SqlStatement)
2205 for Result in ResultSet:
2206 if not Result[0].startswith('/*') and not Result[0].startswith('//'):
2207 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2, '', 'File', FileID)
2208 break
2209
2210 SqlStatement = """ select Value
2211 from %s
2212 where StartLine > (select max(EndLine) from %s where Model = %d)
2213 """ % (FileTable, FileTable, DataClass.MODEL_IDENTIFIER_MACRO_ENDIF)
2214 ResultSet = Db.TblFile.Exec(SqlStatement)
2215 for Result in ResultSet:
2216 if not Result[0].startswith('/*') and not Result[0].startswith('//'):
2217 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3, '', 'File', FileID)
2218 return ErrorMsgList
2219
2220 def CheckDoxygenCommand(FullFileName):
2221 ErrorMsgList = []
2222
2223 FileID = GetTableID(FullFileName, ErrorMsgList)
2224 if FileID < 0:
2225 return ErrorMsgList
2226
2227 Db = GetDB()
2228 FileTable = 'Identifier' + str(FileID)
2229 SqlStatement = """ select Value, ID
2230 from %s
2231 where Model = %d or Model = %d
2232 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)
2233 ResultSet = Db.TblFile.Exec(SqlStatement)
2234 DoxygenCommandList = ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval',
2235 'return', 'sa', 'since', 'test', 'note', 'par', 'endcode', 'code']
2236 for Result in ResultSet:
2237 CommentStr = Result[0]
2238 CommentPartList = CommentStr.split()
2239 for Part in CommentPartList:
2240 if Part.upper() == 'BUGBUG':
2241 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Bug should be marked with doxygen tag @bug', FileTable, Result[1])
2242 if Part.upper() == 'TODO':
2243 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'ToDo should be marked with doxygen tag @todo', FileTable, Result[1])
2244 if Part.startswith('@'):
2245 if EccGlobalData.gException.IsException(ERROR_DOXYGEN_CHECK_COMMAND, Part):
2246 continue
2247 if not Part.replace('@', '').strip():
2248 continue
2249 if Part.lstrip('@') in ['{', '}']:
2250 continue
2251 if Part.lstrip('@').isalpha():
2252 if Part.lstrip('@') not in DoxygenCommandList:
2253 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2254 else:
2255 Index = Part.find('[')
2256 if Index == -1:
2257 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2258 RealCmd = Part[1:Index]
2259 if RealCmd not in DoxygenCommandList:
2260 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2261
2262
2263 def CheckDoxygenTripleForwardSlash(FullFileName):
2264 ErrorMsgList = []
2265
2266 FileID = GetTableID(FullFileName, ErrorMsgList)
2267 if FileID < 0:
2268 return ErrorMsgList
2269
2270 Db = GetDB()
2271
2272 SqlStatement = """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2273 from Function
2274 where BelongsToFile = %d
2275 """ % (FileID)
2276 ResultSet = Db.TblFile.Exec(SqlStatement)
2277 if len(ResultSet) == 0:
2278 return
2279
2280 FuncDefSet = []
2281 for Result in ResultSet:
2282 FuncDefSet.append(Result)
2283
2284
2285 FileTable = 'Identifier' + str(FileID)
2286 SqlStatement = """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2287 from %s
2288 where Model = %d
2289
2290 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2291 ResultSet = Db.TblFile.Exec(SqlStatement)
2292 CommentSet = []
2293 try:
2294 for Result in ResultSet:
2295 CommentSet.append(Result)
2296 except:
2297 print('Unrecognized chars in comment of file %s', FullFileName)
2298
2299
2300 for Result in CommentSet:
2301 CommentStr = Result[0]
2302 StartLine = Result[2]
2303 StartColumn = Result[3]
2304 EndLine = Result[4]
2305 EndColumn = Result[5]
2306 if not CommentStr.startswith('///<'):
2307 continue
2308
2309 Found = False
2310 for FuncDef in FuncDefSet:
2311 if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:
2312 Found = True
2313 break
2314 if StartLine > FuncDef[1] and EndLine < FuncDef[3]:
2315 Found = True
2316 break
2317 if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine < FuncDef[3]:
2318 Found = True
2319 break
2320 if StartLine > FuncDef[1] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:
2321 Found = True
2322 break
2323 if Found:
2324 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT, '', FileTable, Result[1])
2325
2326
2327 def CheckFileHeaderDoxygenComments(FullFileName):
2328 ErrorMsgList = []
2329
2330 FileID = GetTableID(FullFileName, ErrorMsgList)
2331 if FileID < 0:
2332 return ErrorMsgList
2333
2334 Db = GetDB()
2335 FileTable = 'Identifier' + str(FileID)
2336 SqlStatement = """ select Value, ID
2337 from %s
2338 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2339 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2340 ResultSet = Db.TblFile.Exec(SqlStatement)
2341 if len(ResultSet) == 0:
2342 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'No File License header appear at the very beginning of file.', 'File', FileID)
2343 return ErrorMsgList
2344
2345 NoHeaderCommentStartFlag = True
2346 NoHeaderCommentEndFlag = True
2347 NoHeaderCommentPeriodFlag = True
2348 NoCopyrightFlag = True
2349 NoLicenseFlag = True
2350 NoRevReferFlag = True
2351 NextLineIndex = 0
2352 for Result in ResultSet:
2353 FileStartFlag = False
2354 CommentStrList = []
2355 CommentStr = Result[0].strip()
2356 CommentStrListTemp = CommentStr.split('\n')
2357 if (len(CommentStrListTemp) <= 1):
2358 # For Mac
2359 CommentStrListTemp = CommentStr.split('\r')
2360 # Skip the content before the file header
2361 for CommentLine in CommentStrListTemp:
2362 if CommentLine.strip().startswith('/** @file'):
2363 FileStartFlag = True
2364 if FileStartFlag == True:
2365 CommentStrList.append(CommentLine)
2366
2367 ID = Result[1]
2368 Index = 0
2369 if CommentStrList and CommentStrList[0].strip().startswith('/** @file'):
2370 NoHeaderCommentStartFlag = False
2371 else:
2372 continue
2373 if CommentStrList and CommentStrList[-1].strip().endswith('**/'):
2374 NoHeaderCommentEndFlag = False
2375 else:
2376 continue
2377
2378 for CommentLine in CommentStrList:
2379 Index = Index + 1
2380 NextLineIndex = Index
2381 if CommentLine.startswith('/** @file'):
2382 continue
2383 if CommentLine.startswith('**/'):
2384 break
2385 # Check whether C File header Comment content start with two spaces.
2386 if EccGlobalData.gConfig.HeaderCheckCFileCommentStartSpacesNum == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
2387 if CommentLine.startswith('/** @file') == False and CommentLine.startswith('**/') == False and CommentLine.strip() and CommentLine.startswith(' ') == False:
2388 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment content should start with two spaces at each line', FileTable, ID)
2389
2390 CommentLine = CommentLine.strip()
2391 if CommentLine.startswith('Copyright') or ('Copyright' in CommentLine and CommentLine.lower().startswith('(c)')):
2392 NoCopyrightFlag = False
2393 if CommentLine.find('All rights reserved') == -1:
2394 for Copyright in EccGlobalData.gConfig.Copyright:
2395 if CommentLine.find(Copyright) > -1:
2396 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable, ID)
2397 break
2398 if CommentLine.endswith('<BR>') == -1:
2399 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'The ""<BR>"" at the end of the Copyright line is required', FileTable, ID)
2400 if NextLineIndex < len(CommentStrList) and CommentStrList[NextLineIndex].strip().startswith('Copyright') == False and CommentStrList[NextLineIndex].strip():
2401 NoLicenseFlag = False
2402 if CommentLine.startswith('@par Revision Reference:'):
2403 NoRevReferFlag = False
2404 RefListFlag = False
2405 for RefLine in CommentStrList[NextLineIndex:]:
2406 if RefLine.strip() and (NextLineIndex + 1) < len(CommentStrList) and CommentStrList[NextLineIndex+1].strip() and CommentStrList[NextLineIndex+1].strip().startswith('**/') == False:
2407 RefListFlag = True
2408 if RefLine.strip() == False or RefLine.strip().startswith('**/'):
2409 RefListFlag = False
2410 break
2411 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2412 if EccGlobalData.gConfig.HeaderCheckCFileCommentReferenceFormat == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
2413 if RefListFlag == True:
2414 if RefLine.strip() and RefLine.strip().startswith('**/') == False and RefLine.startswith(' -') == False:
2415 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable, ID)
2416
2417 if NoHeaderCommentStartFlag:
2418 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER, 'File header comment should begin with ""/** @file""', FileTable, ID)
2419 return
2420 if NoHeaderCommentEndFlag:
2421 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should end with ""**/""', FileTable, ID)
2422 return
2423 if NoCopyrightFlag:
2424 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment missing the ""Copyright""', FileTable, ID)
2425 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2426 if EccGlobalData.gConfig.HeaderCheckCFileCommentLicenseFormat == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
2427 if NoLicenseFlag:
2428 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable, ID)
2429
2430 def CheckFuncHeaderDoxygenComments(FullFileName):
2431 ErrorMsgList = []
2432
2433 FileID = GetTableID(FullFileName, ErrorMsgList)
2434 if FileID < 0:
2435 return ErrorMsgList
2436
2437 Db = GetDB()
2438 FileTable = 'Identifier' + str(FileID)
2439 SqlStatement = """ select Value, StartLine, EndLine, ID
2440 from %s
2441 where Model = %d
2442 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2443
2444 ResultSet = Db.TblFile.Exec(SqlStatement)
2445 CommentSet = []
2446 try:
2447 for Result in ResultSet:
2448 CommentSet.append(Result)
2449 except:
2450 print('Unrecognized chars in comment of file %s', FullFileName)
2451
2452 # Func Decl check
2453 SqlStatement = """ select Modifier, Name, StartLine, ID, Value
2454 from %s
2455 where Model = %d
2456 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
2457 ResultSet = Db.TblFile.Exec(SqlStatement)
2458 for Result in ResultSet:
2459 FuncName = Result[4]
2460 FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)
2461 if FunctionHeaderComment:
2462 CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)
2463 else:
2464 if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):
2465 continue
2466 ErrorMsgList.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result[2], Result[1]))
2467 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), FileTable, Result[3])
2468
2469 # Func Def check
2470 SqlStatement = """ select Value, StartLine, EndLine, ID
2471 from %s
2472 where Model = %d
2473 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)
2474
2475 ResultSet = Db.TblFile.Exec(SqlStatement)
2476 CommentSet = []
2477 try:
2478 for Result in ResultSet:
2479 CommentSet.append(Result)
2480 except:
2481 print('Unrecognized chars in comment of file %s', FullFileName)
2482
2483 SqlStatement = """ select Modifier, Header, StartLine, ID, Name
2484 from Function
2485 where BelongsToFile = %d
2486 """ % (FileID)
2487 ResultSet = Db.TblFile.Exec(SqlStatement)
2488 for Result in ResultSet:
2489 FuncName = Result[4]
2490 FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)
2491 if FunctionHeaderComment:
2492 CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)
2493 else:
2494 if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):
2495 continue
2496 ErrorMsgList.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result[2], Result[1]))
2497 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), 'Function', Result[3])
2498 return ErrorMsgList
2499
2500 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName, FuncStartLine, CommentSet):
2501
2502 for Comment in CommentSet:
2503 if Comment[2] == FuncStartLine - 1:
2504 return Comment
2505 return None
2506
2507 def GetDoxygenStrFromComment(Str):
2508 DoxygenStrList = []
2509 ParamTagList = Str.split('@param')
2510 if len(ParamTagList) > 1:
2511 i = 1
2512 while i < len(ParamTagList):
2513 DoxygenStrList.append('@param' + ParamTagList[i])
2514 i += 1
2515
2516 Str = ParamTagList[0]
2517
2518 RetvalTagList = ParamTagList[-1].split('@retval')
2519 if len(RetvalTagList) > 1:
2520 if len(ParamTagList) > 1:
2521 DoxygenStrList[-1] = '@param' + RetvalTagList[0]
2522 i = 1
2523 while i < len(RetvalTagList):
2524 DoxygenStrList.append('@retval' + RetvalTagList[i])
2525 i += 1
2526
2527 ReturnTagList = RetvalTagList[-1].split('@return')
2528 if len(ReturnTagList) > 1:
2529 if len(RetvalTagList) > 1:
2530 DoxygenStrList[-1] = '@retval' + ReturnTagList[0]
2531 elif len(ParamTagList) > 1:
2532 DoxygenStrList[-1] = '@param' + ReturnTagList[0]
2533 i = 1
2534 while i < len(ReturnTagList):
2535 DoxygenStrList.append('@return' + ReturnTagList[i])
2536 i += 1
2537
2538 if len(DoxygenStrList) > 0:
2539 DoxygenStrList[-1] = DoxygenStrList[-1].rstrip('--*/')
2540
2541 return DoxygenStrList
2542
2543 def CheckGeneralDoxygenCommentLayout(Str, StartLine, ErrorMsgList, CommentId= -1, TableName=''):
2544 #/** --*/ @retval after @param
2545 if not Str.startswith('/**'):
2546 ErrorMsgList.append('Line %d : Comment does NOT have prefix /** ' % StartLine)
2547 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have prefix /** ', TableName, CommentId)
2548 if not Str.endswith('**/'):
2549 ErrorMsgList.append('Line %d : Comment does NOT have tail **/ ' % StartLine)
2550 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have tail **/ ', TableName, CommentId)
2551 FirstRetvalIndex = Str.find('@retval')
2552 LastParamIndex = Str.rfind('@param')
2553 if (FirstRetvalIndex > 0) and (LastParamIndex > 0) and (FirstRetvalIndex < LastParamIndex):
2554 ErrorMsgList.append('Line %d : @retval appear before @param ' % StartLine)
2555 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, @retval appear before @param ', TableName, CommentId)
2556
2557 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier, FuncHeader, FuncStartLine, CommentStr, CommentStartLine, ErrorMsgList, CommentId= -1, TableName=''):
2558
2559 ParamList = GetParamList(FuncHeader)
2560 CheckGeneralDoxygenCommentLayout(CommentStr, CommentStartLine, ErrorMsgList, CommentId, TableName)
2561 DescriptionStr = CommentStr
2562 DoxygenStrList = GetDoxygenStrFromComment(DescriptionStr)
2563 if DescriptionStr.find('.') == -1:
2564 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period \'.\'', TableName, CommentId)
2565 DoxygenTagNumber = len(DoxygenStrList)
2566 ParamNumber = len(ParamList)
2567 for Param in ParamList:
2568 if Param.Name.upper() == 'VOID' and ParamNumber == 1:
2569 ParamNumber -= 1
2570 Index = 0
2571 if ParamNumber > 0 and DoxygenTagNumber > 0:
2572 while Index < ParamNumber and Index < DoxygenTagNumber:
2573 ParamModifier = ParamList[Index].Modifier
2574 ParamName = ParamList[Index].Name.strip()
2575 Tag = DoxygenStrList[Index].strip(' ')
2576 if (not Tag[-1] == ('\n')) and (not Tag[-1] == ('\r')):
2577 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))
2578 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'in Comment, <%s> does NOT end with new line ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)
2579 TagPartList = Tag.split()
2580 if len(TagPartList) < 2:
2581 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))
2582 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)
2583 Index += 1
2584 continue
2585 LBPos = Tag.find('[')
2586 RBPos = Tag.find(']')
2587 ParamToLBContent = Tag[len('@param'):LBPos].strip()
2588 if LBPos > 0 and len(ParamToLBContent) == 0 and RBPos > LBPos:
2589 InOutStr = ''
2590 ModifierPartList = ParamModifier.split()
2591 for Part in ModifierPartList:
2592 if Part.strip() == 'IN':
2593 InOutStr += 'in'
2594 if Part.strip() == 'OUT':
2595 if InOutStr != '':
2596 InOutStr += ', out'
2597 else:
2598 InOutStr = 'out'
2599
2600 if InOutStr != '':
2601 if Tag.find('[' + InOutStr + ']') == -1:
2602 if InOutStr != 'in, out':
2603 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'))
2604 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT have %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'), TableName, CommentId)
2605 else:
2606 if Tag.find('[in,out]') == -1:
2607 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'))
2608 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT have %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'), TableName, CommentId)
2609
2610
2611 if Tag.find(ParamName) == -1 and ParamName != 'VOID' and ParamName != 'void':
2612 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), ParamName))
2613 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)
2614 Index += 1
2615
2616 if Index < ParamNumber:
2617 ErrorMsgList.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine)
2618 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of doxygen tags in comment less than number of function parameters ', TableName, CommentId)
2619 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2620 if (FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1:
2621
2622 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2623 if Index < DoxygenTagNumber - 1 or (Index < DoxygenTagNumber and DoxygenStrList[Index].startswith('@retval')):
2624 ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)
2625 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need no doxygen tags in comment ', TableName, CommentId)
2626 else:
2627 if Index < DoxygenTagNumber and not DoxygenStrList[Index].startswith('@retval') and not DoxygenStrList[Index].startswith('@return'):
2628 ErrorMsgList.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine)
2629 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName, CommentId)
2630 else:
2631 if ParamNumber == 0 and DoxygenTagNumber != 0 and ((FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1):
2632 ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)
2633 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need NO doxygen tags in comment ', TableName, CommentId)
2634 if ParamNumber != 0 and DoxygenTagNumber == 0:
2635 ErrorMsgList.append('Line %d : No doxygen tags in comment' % CommentStartLine)
2636 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'No doxygen tags in comment ', TableName, CommentId)
2637
2638 if __name__ == '__main__':
2639
2640 # EdkLogger.Initialize()
2641 # EdkLogger.SetLevel(EdkLogger.QUIET)
2642 # CollectSourceCodeDataIntoDB(sys.argv[1])
2643 try:
2644 test_file = sys.argv[1]
2645 except IndexError as v:
2646 print("Usage: %s filename" % sys.argv[0])
2647 sys.exit(1)
2648 MsgList = CheckFuncHeaderDoxygenComments(test_file)
2649 for Msg in MsgList:
2650 print(Msg)
2651 print('Done!')