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