BaseTools: Use absolute import in Ecc
[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 - 2018, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 from __future__ import print_function
15 from __future__ import absolute_import
16 import sys
17 import Common.LongFilePathOs as os
18 import re
19 import string
20 from . import CodeFragmentCollector
21 from . import FileProfile
22 from CommonDataClass import DataClass
23 from . import Database
24 from Common import EdkLogger
25 from .EccToolError import *
26 from . import EccGlobalData
27 from . import MetaDataParser
28
29 IncludeFileListDict = {}
30 AllIncludeFileListDict = {}
31 IncludePathListDict = {}
32 ComplexTypeDict = {}
33 SUDict = {}
34 IgnoredKeywordList = ['EFI_ERROR']
35
36 def GetIgnoredDirListPattern():
37 skipList = list(EccGlobalData.gConfig.SkipDirList) + ['.svn']
38 DirString = string.join(skipList, '|')
39 p = re.compile(r'.*[\\/](?:%s)[\\/]?.*' % DirString)
40 return p
41
42 def GetFuncDeclPattern():
43 p = re.compile(r'(?:EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re.DOTALL)
44 return p
45
46 def GetArrayPattern():
47 p = re.compile(r'[_\w]*\s*[\[.*\]]+')
48 return p
49
50 def GetTypedefFuncPointerPattern():
51 p = re.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re.DOTALL)
52 return p
53
54 def GetDB():
55 return EccGlobalData.gDb
56
57 def GetConfig():
58 return EccGlobalData.gConfig
59
60 def PrintErrorMsg(ErrorType, Msg, TableName, ItemId):
61 Msg = Msg.replace('\n', '').replace('\r', '')
62 MsgPartList = Msg.split()
63 Msg = ''
64 for Part in MsgPartList:
65 Msg += Part
66 Msg += ' '
67 GetDB().TblReport.Insert(ErrorType, OtherMsg=Msg, BelongsToTable=TableName, BelongsToItem=ItemId)
68
69 def GetIdType(Str):
70 Type = DataClass.MODEL_UNKNOWN
71 Str = Str.replace('#', '# ')
72 List = Str.split()
73 if List[1] == 'include':
74 Type = DataClass.MODEL_IDENTIFIER_INCLUDE
75 elif List[1] == 'define':
76 Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE
77 elif List[1] == 'ifdef':
78 Type = DataClass.MODEL_IDENTIFIER_MACRO_IFDEF
79 elif List[1] == 'ifndef':
80 Type = DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF
81 elif List[1] == 'endif':
82 Type = DataClass.MODEL_IDENTIFIER_MACRO_ENDIF
83 elif List[1] == 'pragma':
84 Type = DataClass.MODEL_IDENTIFIER_MACRO_PROGMA
85 else:
86 Type = DataClass.MODEL_UNKNOWN
87 return Type
88
89 def SuOccurInTypedef (Su, TdList):
90 for Td in TdList:
91 if Su.StartPos[0] == Td.StartPos[0] and Su.EndPos[0] == Td.EndPos[0]:
92 return True
93 return False
94
95 def GetIdentifierList():
96 IdList = []
97 for comment in FileProfile.CommentList:
98 IdComment = DataClass.IdentifierClass(-1, '', '', '', comment.Content, DataClass.MODEL_IDENTIFIER_COMMENT, -1, -1, comment.StartPos[0], comment.StartPos[1], comment.EndPos[0], comment.EndPos[1])
99 IdList.append(IdComment)
100
101 for pp in FileProfile.PPDirectiveList:
102 Type = GetIdType(pp.Content)
103 IdPP = DataClass.IdentifierClass(-1, '', '', '', pp.Content, Type, -1, -1, pp.StartPos[0], pp.StartPos[1], pp.EndPos[0], pp.EndPos[1])
104 IdList.append(IdPP)
105
106 for pe in FileProfile.PredicateExpressionList:
107 IdPE = DataClass.IdentifierClass(-1, '', '', '', pe.Content, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION, -1, -1, pe.StartPos[0], pe.StartPos[1], pe.EndPos[0], pe.EndPos[1])
108 IdList.append(IdPE)
109
110 FuncDeclPattern = GetFuncDeclPattern()
111 ArrayPattern = GetArrayPattern()
112 for var in FileProfile.VariableDeclarationList:
113 DeclText = var.Declarator.lstrip()
114 FuncPointerPattern = GetTypedefFuncPointerPattern()
115 if FuncPointerPattern.match(DeclText):
116 continue
117 VarNameStartLine = var.NameStartPos[0]
118 VarNameStartColumn = var.NameStartPos[1]
119 FirstChar = DeclText[0]
120 while not FirstChar.isalpha() and FirstChar != '_':
121 if FirstChar == '*':
122 var.Modifier += '*'
123 VarNameStartColumn += 1
124 DeclText = DeclText.lstrip('*')
125 elif FirstChar == '\r':
126 DeclText = DeclText.lstrip('\r\n').lstrip('\r')
127 VarNameStartLine += 1
128 VarNameStartColumn = 0
129 elif FirstChar == '\n':
130 DeclText = DeclText.lstrip('\n')
131 VarNameStartLine += 1
132 VarNameStartColumn = 0
133 elif FirstChar == ' ':
134 DeclText = DeclText.lstrip(' ')
135 VarNameStartColumn += 1
136 elif FirstChar == '\t':
137 DeclText = DeclText.lstrip('\t')
138 VarNameStartColumn += 8
139 else:
140 DeclText = DeclText[1:]
141 VarNameStartColumn += 1
142 FirstChar = DeclText[0]
143
144 var.Declarator = DeclText
145 if FuncDeclPattern.match(var.Declarator):
146 DeclSplitList = var.Declarator.split('(')
147 FuncName = DeclSplitList[0].strip()
148 FuncNamePartList = FuncName.split()
149 if len(FuncNamePartList) > 1:
150 FuncName = FuncNamePartList[-1].strip()
151 NameStart = DeclSplitList[0].rfind(FuncName)
152 var.Declarator = var.Declarator[NameStart:]
153 if NameStart > 0:
154 var.Modifier += ' ' + DeclSplitList[0][0:NameStart]
155 Index = 0
156 PreChar = ''
157 while Index < NameStart:
158 FirstChar = DeclSplitList[0][Index]
159 if DeclSplitList[0][Index:].startswith('EFIAPI'):
160 Index += 6
161 VarNameStartColumn += 6
162 PreChar = ''
163 continue
164 elif FirstChar == '\r':
165 Index += 1
166 VarNameStartLine += 1
167 VarNameStartColumn = 0
168 elif FirstChar == '\n':
169 Index += 1
170 if PreChar != '\r':
171 VarNameStartLine += 1
172 VarNameStartColumn = 0
173 elif FirstChar == ' ':
174 Index += 1
175 VarNameStartColumn += 1
176 elif FirstChar == '\t':
177 Index += 1
178 VarNameStartColumn += 8
179 else:
180 Index += 1
181 VarNameStartColumn += 1
182 PreChar = FirstChar
183 IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', var.Declarator, FuncName, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, -1, -1, var.StartPos[0], var.StartPos[1], VarNameStartLine, VarNameStartColumn)
184 IdList.append(IdVar)
185 continue
186
187 if var.Declarator.find('{') == -1:
188 for decl in var.Declarator.split(','):
189 DeclList = decl.split('=')
190 Name = DeclList[0].strip()
191 if ArrayPattern.match(Name):
192 LSBPos = var.Declarator.find('[')
193 var.Modifier += ' ' + Name[LSBPos:]
194 Name = Name[0:LSBPos]
195
196 IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', Name, (len(DeclList) > 1 and [DeclList[1]]or [''])[0], DataClass.MODEL_IDENTIFIER_VARIABLE, -1, -1, var.StartPos[0], var.StartPos[1], VarNameStartLine, VarNameStartColumn)
197 IdList.append(IdVar)
198 else:
199 DeclList = var.Declarator.split('=')
200 Name = DeclList[0].strip()
201 if ArrayPattern.match(Name):
202 LSBPos = var.Declarator.find('[')
203 var.Modifier += ' ' + Name[LSBPos:]
204 Name = Name[0:LSBPos]
205 IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', Name, (len(DeclList) > 1 and [DeclList[1]]or [''])[0], DataClass.MODEL_IDENTIFIER_VARIABLE, -1, -1, var.StartPos[0], var.StartPos[1], VarNameStartLine, VarNameStartColumn)
206 IdList.append(IdVar)
207
208 for enum in FileProfile.EnumerationDefinitionList:
209 LBPos = enum.Content.find('{')
210 RBPos = enum.Content.find('}')
211 Name = enum.Content[4:LBPos].strip()
212 Value = enum.Content[LBPos + 1:RBPos]
213 IdEnum = DataClass.IdentifierClass(-1, '', '', Name, Value, DataClass.MODEL_IDENTIFIER_ENUMERATE, -1, -1, enum.StartPos[0], enum.StartPos[1], enum.EndPos[0], enum.EndPos[1])
214 IdList.append(IdEnum)
215
216 for su in FileProfile.StructUnionDefinitionList:
217 if SuOccurInTypedef(su, FileProfile.TypedefDefinitionList):
218 continue
219 Type = DataClass.MODEL_IDENTIFIER_STRUCTURE
220 SkipLen = 6
221 if su.Content.startswith('union'):
222 Type = DataClass.MODEL_IDENTIFIER_UNION
223 SkipLen = 5
224 LBPos = su.Content.find('{')
225 RBPos = su.Content.find('}')
226 if LBPos == -1 or RBPos == -1:
227 Name = su.Content[SkipLen:].strip()
228 Value = ''
229 else:
230 Name = su.Content[SkipLen:LBPos].strip()
231 Value = su.Content[LBPos:RBPos + 1]
232 IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0], su.StartPos[1], su.EndPos[0], su.EndPos[1])
233 IdList.append(IdPE)
234
235 TdFuncPointerPattern = GetTypedefFuncPointerPattern()
236 for td in FileProfile.TypedefDefinitionList:
237 Modifier = ''
238 Name = td.ToType
239 Value = td.FromType
240 if TdFuncPointerPattern.match(td.ToType):
241 Modifier = td.FromType
242 LBPos = td.ToType.find('(')
243 TmpStr = td.ToType[LBPos + 1:].strip()
244 StarPos = TmpStr.find('*')
245 if StarPos != -1:
246 Modifier += ' ' + TmpStr[0:StarPos]
247 while TmpStr[StarPos] == '*':
248 # Modifier += ' ' + '*'
249 StarPos += 1
250 TmpStr = TmpStr[StarPos:].strip()
251 RBPos = TmpStr.find(')')
252 Name = TmpStr[0:RBPos]
253 Value = 'FP' + TmpStr[RBPos + 1:]
254 else:
255 while Name.startswith('*'):
256 Value += ' ' + '*'
257 Name = Name.lstrip('*').strip()
258
259 if Name.find('[') != -1:
260 LBPos = Name.find('[')
261 RBPos = Name.rfind(']')
262 Value += Name[LBPos : RBPos + 1]
263 Name = Name[0 : LBPos]
264
265 IdTd = DataClass.IdentifierClass(-1, Modifier, '', Name, Value, DataClass.MODEL_IDENTIFIER_TYPEDEF, -1, -1, td.StartPos[0], td.StartPos[1], td.EndPos[0], td.EndPos[1])
266 IdList.append(IdTd)
267
268 for funcCall in FileProfile.FunctionCallingList:
269 IdFC = DataClass.IdentifierClass(-1, '', '', funcCall.FuncName, funcCall.ParamList, DataClass.MODEL_IDENTIFIER_FUNCTION_CALLING, -1, -1, funcCall.StartPos[0], funcCall.StartPos[1], funcCall.EndPos[0], funcCall.EndPos[1])
270 IdList.append(IdFC)
271 return IdList
272
273 def StripNonAlnumChars(Str):
274 StrippedStr = ''
275 for Char in Str:
276 if Char.isalnum() or Char == '_':
277 StrippedStr += Char
278 return StrippedStr
279
280 def GetParamList(FuncDeclarator, FuncNameLine=0, FuncNameOffset=0):
281 FuncDeclarator = StripComments(FuncDeclarator)
282 ParamIdList = []
283 #DeclSplitList = FuncDeclarator.split('(')
284 LBPos = FuncDeclarator.find('(')
285 #if len(DeclSplitList) < 2:
286 if LBPos == -1:
287 return ParamIdList
288 #FuncName = DeclSplitList[0]
289 FuncName = FuncDeclarator[0:LBPos]
290 #ParamStr = DeclSplitList[1].rstrip(')')
291 ParamStr = FuncDeclarator[LBPos + 1:].rstrip(')')
292 LineSkipped = 0
293 OffsetSkipped = 0
294 TailChar = FuncName[-1]
295 while not TailChar.isalpha() and TailChar != '_':
296
297 if TailChar == '\n':
298 FuncName = FuncName.rstrip('\r\n').rstrip('\n')
299 LineSkipped += 1
300 OffsetSkipped = 0
301 elif TailChar == '\r':
302 FuncName = FuncName.rstrip('\r')
303 LineSkipped += 1
304 OffsetSkipped = 0
305 elif TailChar == ' ':
306 FuncName = FuncName.rstrip(' ')
307 OffsetSkipped += 1
308 elif TailChar == '\t':
309 FuncName = FuncName.rstrip('\t')
310 OffsetSkipped += 8
311 else:
312 FuncName = FuncName[:-1]
313 TailChar = FuncName[-1]
314
315 OffsetSkipped += 1 #skip '('
316
317 for p in ParamStr.split(','):
318 ListP = p.split()
319 if len(ListP) == 0:
320 continue
321 ParamName = ListP[-1]
322 DeclText = ParamName.strip()
323 RightSpacePos = p.rfind(ParamName)
324 ParamModifier = p[0:RightSpacePos]
325 if ParamName == 'OPTIONAL':
326 if ParamModifier == '':
327 ParamModifier += ' ' + 'OPTIONAL'
328 DeclText = ''
329 else:
330 ParamName = ListP[-2]
331 DeclText = ParamName.strip()
332 RightSpacePos = p.rfind(ParamName)
333 ParamModifier = p[0:RightSpacePos]
334 ParamModifier += 'OPTIONAL'
335 while DeclText.startswith('*'):
336 ParamModifier += ' ' + '*'
337 DeclText = DeclText.lstrip('*').strip()
338 ParamName = DeclText
339 # ignore array length if exists.
340 LBIndex = ParamName.find('[')
341 if LBIndex != -1:
342 ParamName = ParamName[0:LBIndex]
343
344 Start = RightSpacePos
345 Index = 0
346 PreChar = ''
347 while Index < Start:
348 FirstChar = p[Index]
349
350 if FirstChar == '\r':
351 Index += 1
352 LineSkipped += 1
353 OffsetSkipped = 0
354 elif FirstChar == '\n':
355 Index += 1
356 if PreChar != '\r':
357 LineSkipped += 1
358 OffsetSkipped = 0
359 elif FirstChar == ' ':
360 Index += 1
361 OffsetSkipped += 1
362 elif FirstChar == '\t':
363 Index += 1
364 OffsetSkipped += 8
365 else:
366 Index += 1
367 OffsetSkipped += 1
368 PreChar = FirstChar
369
370 ParamBeginLine = FuncNameLine + LineSkipped
371 ParamBeginOffset = FuncNameOffset + OffsetSkipped
372
373 Index = Start + len(ParamName)
374 PreChar = ''
375 while Index < len(p):
376 FirstChar = p[Index]
377
378 if FirstChar == '\r':
379 Index += 1
380 LineSkipped += 1
381 OffsetSkipped = 0
382 elif FirstChar == '\n':
383 Index += 1
384 if PreChar != '\r':
385 LineSkipped += 1
386 OffsetSkipped = 0
387 elif FirstChar == ' ':
388 Index += 1
389 OffsetSkipped += 1
390 elif FirstChar == '\t':
391 Index += 1
392 OffsetSkipped += 8
393 else:
394 Index += 1
395 OffsetSkipped += 1
396 PreChar = FirstChar
397
398 ParamEndLine = FuncNameLine + LineSkipped
399 ParamEndOffset = FuncNameOffset + OffsetSkipped
400 if ParamName != '...':
401 ParamName = StripNonAlnumChars(ParamName)
402 IdParam = DataClass.IdentifierClass(-1, ParamModifier, '', ParamName, '', DataClass.MODEL_IDENTIFIER_PARAMETER, -1, -1, ParamBeginLine, ParamBeginOffset, ParamEndLine, ParamEndOffset)
403 ParamIdList.append(IdParam)
404
405 OffsetSkipped += 1 #skip ','
406
407 return ParamIdList
408
409 def GetFunctionList():
410 FuncObjList = []
411 for FuncDef in FileProfile.FunctionDefinitionList:
412 ParamIdList = []
413 DeclText = FuncDef.Declarator.lstrip()
414 FuncNameStartLine = FuncDef.NamePos[0]
415 FuncNameStartColumn = FuncDef.NamePos[1]
416 FirstChar = DeclText[0]
417 while not FirstChar.isalpha() and FirstChar != '_':
418 if FirstChar == '*':
419 FuncDef.Modifier += '*'
420 FuncNameStartColumn += 1
421 DeclText = DeclText.lstrip('*')
422 elif FirstChar == '\r':
423 DeclText = DeclText.lstrip('\r\n').lstrip('\r')
424 FuncNameStartLine += 1
425 FuncNameStartColumn = 0
426 elif FirstChar == '\n':
427 DeclText = DeclText.lstrip('\n')
428 FuncNameStartLine += 1
429 FuncNameStartColumn = 0
430 elif FirstChar == ' ':
431 DeclText = DeclText.lstrip(' ')
432 FuncNameStartColumn += 1
433 elif FirstChar == '\t':
434 DeclText = DeclText.lstrip('\t')
435 FuncNameStartColumn += 8
436 else:
437 DeclText = DeclText[1:]
438 FuncNameStartColumn += 1
439 FirstChar = DeclText[0]
440
441 FuncDef.Declarator = DeclText
442 DeclSplitList = FuncDef.Declarator.split('(')
443 if len(DeclSplitList) < 2:
444 continue
445
446 FuncName = DeclSplitList[0]
447 FuncNamePartList = FuncName.split()
448 if len(FuncNamePartList) > 1:
449 FuncName = FuncNamePartList[-1]
450 NameStart = DeclSplitList[0].rfind(FuncName)
451 if NameStart > 0:
452 FuncDef.Modifier += ' ' + DeclSplitList[0][0:NameStart]
453 Index = 0
454 PreChar = ''
455 while Index < NameStart:
456 FirstChar = DeclSplitList[0][Index]
457 if DeclSplitList[0][Index:].startswith('EFIAPI'):
458 Index += 6
459 FuncNameStartColumn += 6
460 PreChar = ''
461 continue
462 elif FirstChar == '\r':
463 Index += 1
464 FuncNameStartLine += 1
465 FuncNameStartColumn = 0
466 elif FirstChar == '\n':
467 Index += 1
468 if PreChar != '\r':
469 FuncNameStartLine += 1
470 FuncNameStartColumn = 0
471 elif FirstChar == ' ':
472 Index += 1
473 FuncNameStartColumn += 1
474 elif FirstChar == '\t':
475 Index += 1
476 FuncNameStartColumn += 8
477 else:
478 Index += 1
479 FuncNameStartColumn += 1
480 PreChar = FirstChar
481
482 FuncObj = DataClass.FunctionClass(-1, FuncDef.Declarator, FuncDef.Modifier, FuncName.strip(), '', FuncDef.StartPos[0], FuncDef.StartPos[1], FuncDef.EndPos[0], FuncDef.EndPos[1], FuncDef.LeftBracePos[0], FuncDef.LeftBracePos[1], -1, ParamIdList, [], FuncNameStartLine, FuncNameStartColumn)
483 FuncObjList.append(FuncObj)
484
485 return FuncObjList
486
487 def GetFileModificationTimeFromDB(FullFileName):
488 TimeValue = 0.0
489 Db = GetDB()
490 SqlStatement = """ select TimeStamp
491 from File
492 where FullPath = \'%s\'
493 """ % (FullFileName)
494 ResultSet = Db.TblFile.Exec(SqlStatement)
495 for Result in ResultSet:
496 TimeValue = Result[0]
497 return TimeValue
498
499 def CollectSourceCodeDataIntoDB(RootDir):
500 FileObjList = []
501 tuple = os.walk(RootDir)
502 IgnoredPattern = GetIgnoredDirListPattern()
503 ParseErrorFileList = []
504
505 for dirpath, dirnames, filenames in tuple:
506 if IgnoredPattern.match(dirpath.upper()):
507 continue
508
509 for Dir in dirnames:
510 Dirname = os.path.join(dirpath, Dir)
511 if os.path.islink(Dirname):
512 Dirname = os.path.realpath(Dirname)
513 if os.path.isdir(Dirname):
514 # symlinks to directories are treated as directories
515 dirnames.remove(Dir)
516 dirnames.append(Dirname)
517
518 for f in filenames:
519 if f.lower() in EccGlobalData.gConfig.SkipFileList:
520 continue
521 collector = None
522 FullName = os.path.normpath(os.path.join(dirpath, f))
523 model = DataClass.MODEL_FILE_OTHERS
524 if os.path.splitext(f)[1] in ('.h', '.c'):
525 EdkLogger.info("Parsing " + FullName)
526 model = f.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H
527 collector = CodeFragmentCollector.CodeFragmentCollector(FullName)
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 begining, 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 sufix
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] == '/' and ListFromStr[Index + 2] != '\n':
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 [] sufixes...
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(ReturnType)
1301 if Index != 0 or Result[3] != 0:
1302 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, 'Function', Result[1])
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
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 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'open brace should be at the very beginning of a line.', 'Function', Result[2])
1524 if Result[1] != 0:
1525 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'close brace should be at the very beginning of a line.', 'Function', Result[2])
1526
1527 def CheckFuncLayoutLocalVariable(FullFileName):
1528 ErrorMsgList = []
1529
1530 FileID = GetTableID(FullFileName, ErrorMsgList)
1531 if FileID < 0:
1532 return ErrorMsgList
1533
1534 Db = GetDB()
1535 FileTable = 'Identifier' + str(FileID)
1536 SqlStatement = """ select ID
1537 from Function
1538 where BelongsToFile = %d
1539 """ % (FileID)
1540 ResultSet = Db.TblFile.Exec(SqlStatement)
1541 if len(ResultSet) == 0:
1542 return ErrorMsgList
1543 FL = []
1544 for Result in ResultSet:
1545 FL.append(Result)
1546
1547 for F in FL:
1548 SqlStatement = """ select Name, Value, ID, Modifier
1549 from %s
1550 where Model = %d and BelongsToFunction = %d
1551 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, F[0])
1552 ResultSet = Db.TblFile.Exec(SqlStatement)
1553 if len(ResultSet) == 0:
1554 continue
1555
1556 for Result in ResultSet:
1557 if len(Result[1]) > 0 and 'CONST' not in Result[3]:
1558 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE, 'Variable Name: %s' % Result[0], FileTable, Result[2])
1559
1560 def CheckMemberVariableFormat(Name, Value, FileTable, TdId, ModelId):
1561 ErrMsgList = []
1562 # Member variable format pattern.
1563 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
1564
1565 LBPos = Value.find('{')
1566 RBPos = Value.rfind('}')
1567 if LBPos == -1 or RBPos == -1:
1568 return ErrMsgList
1569
1570 Fields = Value[LBPos + 1 : RBPos]
1571 Fields = StripComments(Fields).strip()
1572 NestPos = Fields.find ('struct')
1573 if NestPos != -1 and (NestPos + len('struct') < len(Fields)) and ModelId != DataClass.MODEL_IDENTIFIER_UNION:
1574 if not Fields[NestPos + len('struct') + 1].isalnum():
1575 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1576 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested struct in [%s].' % (Name), FileTable, TdId)
1577 return ErrMsgList
1578 NestPos = Fields.find ('union')
1579 if NestPos != -1 and (NestPos + len('union') < len(Fields)):
1580 if not Fields[NestPos + len('union') + 1].isalnum():
1581 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1582 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested union in [%s].' % (Name), FileTable, TdId)
1583 return ErrMsgList
1584 NestPos = Fields.find ('enum')
1585 if NestPos != -1 and (NestPos + len('enum') < len(Fields)):
1586 if not Fields[NestPos + len('enum') + 1].isalnum():
1587 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1588 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested enum in [%s].' % (Name), FileTable, TdId)
1589 return ErrMsgList
1590
1591 if ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:
1592 FieldsList = Fields.split(',')
1593 # deal with enum is pre-assigned a value by function call ( , , , ...)
1594 QuoteCount = 0
1595 Index = 0
1596 RemoveCurrentElement = False
1597 while Index < len(FieldsList):
1598 Field = FieldsList[Index]
1599
1600 if Field.find('(') != -1:
1601 QuoteCount += 1
1602 RemoveCurrentElement = True
1603 Index += 1
1604 continue
1605
1606 if Field.find(')') != -1 and QuoteCount > 0:
1607 QuoteCount -= 1
1608
1609 if RemoveCurrentElement:
1610 FieldsList.remove(Field)
1611 if QuoteCount == 0:
1612 RemoveCurrentElement = False
1613 continue
1614
1615 if QuoteCount == 0:
1616 RemoveCurrentElement = False
1617
1618 Index += 1
1619 else:
1620 FieldsList = Fields.split(';')
1621
1622 for Field in FieldsList:
1623 Field = Field.strip()
1624 if Field == '':
1625 continue
1626 # For the condition that the field in struct is an array with [] sufixes...
1627 if Field[-1] == ']':
1628 LBPos = Field.find('[')
1629 Field = Field[0:LBPos]
1630 # For the condition that bit field ": Number"
1631 if Field.find(':') != -1:
1632 ColonPos = Field.find(':')
1633 Field = Field[0:ColonPos]
1634
1635 Field = Field.strip()
1636 if Field == '':
1637 continue
1638 if Field.startswith("#"):
1639 continue
1640 # Enum could directly assign value to variable
1641 Field = Field.split('=')[0].strip()
1642 TokenList = Field.split()
1643 # Remove pointers before variable
1644 Token = TokenList[-1]
1645 if Token in ['OPTIONAL']:
1646 Token = TokenList[-2]
1647 if not Pattern.match(Token.lstrip('*')):
1648 ErrMsgList.append(Token.lstrip('*'))
1649
1650 return ErrMsgList
1651
1652 def CheckDeclTypedefFormat(FullFileName, ModelId):
1653 ErrorMsgList = []
1654
1655 FileID = GetTableID(FullFileName, ErrorMsgList)
1656 if FileID < 0:
1657 return ErrorMsgList
1658
1659 Db = GetDB()
1660 FileTable = 'Identifier' + str(FileID)
1661 SqlStatement = """ select Name, StartLine, EndLine, ID, Value
1662 from %s
1663 where Model = %d
1664 """ % (FileTable, ModelId)
1665 ResultSet = Db.TblFile.Exec(SqlStatement)
1666 ResultList = []
1667 for Result in ResultSet:
1668 ResultList.append(Result)
1669
1670 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1671 if ModelId == DataClass.MODEL_IDENTIFIER_STRUCTURE:
1672 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1673 elif ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:
1674 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1675 elif ModelId == DataClass.MODEL_IDENTIFIER_UNION:
1676 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1677
1678 SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID
1679 from %s
1680 where Model = %d
1681 """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
1682 TdSet = Db.TblFile.Exec(SqlStatement)
1683 TdList = []
1684 for Td in TdSet:
1685 TdList.append(Td)
1686 # Check member variable name format that from typedefs of ONLY this file.
1687 for Td in TdList:
1688 Name = Td[1].strip()
1689 Value = Td[2].strip()
1690 if Value.startswith('enum'):
1691 ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE
1692 elif Value.startswith('struct'):
1693 ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE
1694 elif Value.startswith('union'):
1695 ValueModelId = DataClass.MODEL_IDENTIFIER_UNION
1696 else:
1697 continue
1698
1699 if ValueModelId != ModelId:
1700 continue
1701 # Check member variable format.
1702 ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Td[5], ModelId)
1703 for ErrMsg in ErrMsgList:
1704 if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Name + '.' + ErrMsg):
1705 continue
1706 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Name + '.' + ErrMsg), FileTable, Td[5])
1707
1708 # First check in current file to see whether struct/union/enum is typedef-ed.
1709 UntypedefedList = []
1710 for Result in ResultList:
1711 # Check member variable format.
1712 Name = Result[0].strip()
1713 Value = Result[4].strip()
1714 if Value.startswith('enum'):
1715 ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE
1716 elif Value.startswith('struct'):
1717 ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE
1718 elif Value.startswith('union'):
1719 ValueModelId = DataClass.MODEL_IDENTIFIER_UNION
1720 else:
1721 continue
1722
1723 if ValueModelId != ModelId:
1724 continue
1725 ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Result[3], ModelId)
1726 for ErrMsg in ErrMsgList:
1727 if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Result[0] + '.' + ErrMsg):
1728 continue
1729 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Result[0] + '.' + ErrMsg), FileTable, Result[3])
1730 # Check whether it is typedefed.
1731 Found = False
1732 for Td in TdList:
1733 # skip function pointer
1734 if len(Td[0]) > 0:
1735 continue
1736 if Result[1] >= Td[3] and Td[4] >= Result[2]:
1737 Found = True
1738 if not Td[1].isupper():
1739 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1740 if Result[0] in Td[2].split():
1741 Found = True
1742 if not Td[1].isupper():
1743 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1744 if Found:
1745 break
1746
1747 if not Found:
1748 UntypedefedList.append(Result)
1749 continue
1750
1751 if len(UntypedefedList) == 0:
1752 return
1753
1754 IncludeFileList = GetAllIncludeFiles(FullFileName)
1755 TdList = []
1756 for F in IncludeFileList:
1757 FileID = GetTableID(F, ErrorMsgList)
1758 if FileID < 0:
1759 continue
1760
1761 IncludeFileTable = 'Identifier' + str(FileID)
1762 SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID
1763 from %s
1764 where Model = %d
1765 """ % (IncludeFileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
1766 ResultSet = Db.TblFile.Exec(SqlStatement)
1767 TdList.extend(ResultSet)
1768
1769 for Result in UntypedefedList:
1770
1771 # Check whether it is typedefed.
1772 Found = False
1773 for Td in TdList:
1774
1775 if len(Td[0]) > 0:
1776 continue
1777 if Result[1] >= Td[3] and Td[4] >= Result[2]:
1778 Found = True
1779 if not Td[1].isupper():
1780 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1781 if Result[0] in Td[2].split():
1782 Found = True
1783 if not Td[1].isupper():
1784 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1785 if Found:
1786 break
1787
1788 if not Found:
1789 PrintErrorMsg(ErrorType, 'No Typedef for %s' % Result[0], FileTable, Result[3])
1790 continue
1791
1792 def CheckDeclStructTypedef(FullFileName):
1793 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_STRUCTURE)
1794
1795 def CheckDeclEnumTypedef(FullFileName):
1796 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_ENUMERATE)
1797
1798 def CheckDeclUnionTypedef(FullFileName):
1799 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_UNION)
1800
1801 def CheckDeclArgModifier(FullFileName):
1802 ErrorMsgList = []
1803
1804 FileID = GetTableID(FullFileName, ErrorMsgList)
1805 if FileID < 0:
1806 return ErrorMsgList
1807
1808 Db = GetDB()
1809 FileTable = 'Identifier' + str(FileID)
1810 SqlStatement = """ select Modifier, Name, ID
1811 from %s
1812 where Model = %d
1813 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
1814 ResultSet = Db.TblFile.Exec(SqlStatement)
1815 ModifierTuple = ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1816 MAX_MODIFIER_LENGTH = 100
1817 for Result in ResultSet:
1818 for Modifier in ModifierTuple:
1819 if PatternInModifier(Result[0], Modifier) and len(Result[0]) < MAX_MODIFIER_LENGTH:
1820 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Variable Modifier %s' % Result[0], FileTable, Result[2])
1821 break
1822
1823 SqlStatement = """ select Modifier, Name, ID
1824 from %s
1825 where Model = %d
1826 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1827 ResultSet = Db.TblFile.Exec(SqlStatement)
1828 for Result in ResultSet:
1829 for Modifier in ModifierTuple:
1830 if PatternInModifier(Result[0], Modifier):
1831 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])
1832 break
1833
1834 SqlStatement = """ select Modifier, Header, ID
1835 from Function
1836 where BelongsToFile = %d
1837 """ % (FileID)
1838 ResultSet = Db.TblFile.Exec(SqlStatement)
1839 for Result in ResultSet:
1840 for Modifier in ModifierTuple:
1841 if PatternInModifier(Result[0], Modifier):
1842 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])
1843 break
1844
1845 def CheckDeclNoUseCType(FullFileName):
1846 ErrorMsgList = []
1847
1848 FileID = GetTableID(FullFileName, ErrorMsgList)
1849 if FileID < 0:
1850 return ErrorMsgList
1851
1852 Db = GetDB()
1853 FileTable = 'Identifier' + str(FileID)
1854 SqlStatement = """ select Modifier, Name, ID
1855 from %s
1856 where Model = %d
1857 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
1858 ResultSet = Db.TblFile.Exec(SqlStatement)
1859 CTypeTuple = ('int', 'unsigned', 'char', 'void', 'static', 'long')
1860 for Result in ResultSet:
1861 for Type in CTypeTuple:
1862 if PatternInModifier(Result[0], Type):
1863 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE,
1864 Result[0] + ' ' + Result[1]):
1865 continue
1866 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE,
1867 'Invalid variable type (%s) in definition [%s]' % (Type, Result[0] + ' ' + Result[1]),
1868 FileTable,
1869 Result[2])
1870 break
1871
1872 SqlStatement = """ select Modifier, Name, ID, Value
1873 from %s
1874 where Model = %d
1875 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1876 ResultSet = Db.TblFile.Exec(SqlStatement)
1877 for Result in ResultSet:
1878 ParamList = GetParamList(Result[1])
1879 FuncName = Result[3]
1880 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):
1881 continue
1882 for Type in CTypeTuple:
1883 if PatternInModifier(Result[0], Type):
1884 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '%s Return type %s' % (FuncName, Result[0]), FileTable, Result[2])
1885
1886 for Param in ParamList:
1887 if PatternInModifier(Param.Modifier, Type):
1888 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])
1889
1890 SqlStatement = """ select Modifier, Header, ID, Name
1891 from Function
1892 where BelongsToFile = %d
1893 """ % (FileID)
1894 ResultSet = Db.TblFile.Exec(SqlStatement)
1895 for Result in ResultSet:
1896 ParamList = GetParamList(Result[1])
1897 FuncName = Result[3]
1898 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):
1899 continue
1900 for Type in CTypeTuple:
1901 if PatternInModifier(Result[0], Type):
1902 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '[%s] Return type %s' % (FuncName, Result[0]), FileTable, Result[2])
1903
1904 for Param in ParamList:
1905 if PatternInModifier(Param.Modifier, Type):
1906 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])
1907
1908
1909 def CheckPointerNullComparison(FullFileName):
1910 ErrorMsgList = []
1911
1912 FileID = GetTableID(FullFileName, ErrorMsgList)
1913 if FileID < 0:
1914 return ErrorMsgList
1915
1916 # cache the found function return type to accelerate later checking in this file.
1917 FuncReturnTypeDict = {}
1918
1919 Db = GetDB()
1920 FileTable = 'Identifier' + str(FileID)
1921 SqlStatement = """ select Value, StartLine, ID
1922 from %s
1923 where Model = %d
1924 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
1925 ResultSet = Db.TblFile.Exec(SqlStatement)
1926 if len(ResultSet) == 0:
1927 return
1928 PSL = []
1929 for Result in ResultSet:
1930 PSL.append([Result[0], Result[1], Result[2]])
1931
1932 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
1933 from Function
1934 where BelongsToFile = %d
1935 """ % (FileID)
1936 ResultSet = Db.TblFile.Exec(SqlStatement)
1937 FL = []
1938 for Result in ResultSet:
1939 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
1940
1941 p = GetFuncDeclPattern()
1942 for Str in PSL:
1943 FuncRecord = GetFuncContainsPE(Str[1], FL)
1944 if FuncRecord is None:
1945 continue
1946
1947 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
1948 PredInfo = SplitPredicateStr(Exp)
1949 if PredInfo[1] is None:
1950 PredVarStr = PredInfo[0][0].strip()
1951 IsFuncCall = False
1952 SearchInCache = False
1953 # PredVarStr may contain '.' or '->'
1954 TmpStr = PredVarStr.replace('.', '').replace('->', '')
1955 if p.match(TmpStr):
1956 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
1957 SearchInCache = True
1958 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1959 if TmpStr.startswith(PredVarStr):
1960 IsFuncCall = True
1961
1962 if PredVarStr.strip() in IgnoredKeywordList:
1963 continue
1964 StarList = []
1965 PredVarList = GetCNameList(PredVarStr, StarList)
1966 # No variable found, maybe value first? like (0 == VarName)
1967 if len(PredVarList) == 0:
1968 continue
1969 if SearchInCache:
1970 Type = FuncReturnTypeDict.get(PredVarStr)
1971 if Type is not None:
1972 if Type.find('*') != -1 and Type != 'BOOLEAN*':
1973 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
1974 continue
1975
1976 if PredVarStr in FuncReturnTypeDict:
1977 continue
1978
1979 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, None, StarList)
1980 if SearchInCache:
1981 FuncReturnTypeDict[PredVarStr] = Type
1982 if Type is None:
1983 continue
1984 Type = GetTypeFromArray(Type, PredVarStr)
1985 if Type.find('*') != -1 and Type != 'BOOLEAN*':
1986 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
1987
1988 def CheckNonBooleanValueComparison(FullFileName):
1989 ErrorMsgList = []
1990
1991 FileID = GetTableID(FullFileName, ErrorMsgList)
1992 if FileID < 0:
1993 return ErrorMsgList
1994
1995 # cache the found function return type to accelerate later checking in this file.
1996 FuncReturnTypeDict = {}
1997
1998 Db = GetDB()
1999 FileTable = 'Identifier' + str(FileID)
2000 SqlStatement = """ select Value, StartLine, ID
2001 from %s
2002 where Model = %d
2003 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
2004 ResultSet = Db.TblFile.Exec(SqlStatement)
2005 if len(ResultSet) == 0:
2006 return
2007 PSL = []
2008 for Result in ResultSet:
2009 PSL.append([Result[0], Result[1], Result[2]])
2010
2011 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
2012 from Function
2013 where BelongsToFile = %d
2014 """ % (FileID)
2015 ResultSet = Db.TblFile.Exec(SqlStatement)
2016 FL = []
2017 for Result in ResultSet:
2018 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
2019
2020 p = GetFuncDeclPattern()
2021 for Str in PSL:
2022 FuncRecord = GetFuncContainsPE(Str[1], FL)
2023 if FuncRecord is None:
2024 continue
2025
2026 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
2027 PredInfo = SplitPredicateStr(Exp)
2028 if PredInfo[1] is None:
2029 PredVarStr = PredInfo[0][0].strip()
2030 IsFuncCall = False
2031 SearchInCache = False
2032 # PredVarStr may contain '.' or '->'
2033 TmpStr = PredVarStr.replace('.', '').replace('->', '')
2034 if p.match(TmpStr):
2035 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
2036 SearchInCache = True
2037 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2038 if TmpStr.startswith(PredVarStr):
2039 IsFuncCall = True
2040
2041 if PredVarStr.strip() in IgnoredKeywordList:
2042 continue
2043 StarList = []
2044 PredVarList = GetCNameList(PredVarStr, StarList)
2045 # No variable found, maybe value first? like (0 == VarName)
2046 if len(PredVarList) == 0:
2047 continue
2048
2049 if SearchInCache:
2050 Type = FuncReturnTypeDict.get(PredVarStr)
2051 if Type is not None:
2052 if Type.find('BOOLEAN') == -1:
2053 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2054 continue
2055
2056 if PredVarStr in FuncReturnTypeDict:
2057 continue
2058 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)
2059 if SearchInCache:
2060 FuncReturnTypeDict[PredVarStr] = Type
2061 if Type is None:
2062 continue
2063 if Type.find('BOOLEAN') == -1:
2064 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2065
2066
2067 def CheckBooleanValueComparison(FullFileName):
2068 ErrorMsgList = []
2069
2070 FileID = GetTableID(FullFileName, ErrorMsgList)
2071 if FileID < 0:
2072 return ErrorMsgList
2073
2074 # cache the found function return type to accelerate later checking in this file.
2075 FuncReturnTypeDict = {}
2076
2077 Db = GetDB()
2078 FileTable = 'Identifier' + str(FileID)
2079 SqlStatement = """ select Value, StartLine, ID
2080 from %s
2081 where Model = %d
2082 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
2083 ResultSet = Db.TblFile.Exec(SqlStatement)
2084 if len(ResultSet) == 0:
2085 return
2086 PSL = []
2087 for Result in ResultSet:
2088 PSL.append([Result[0], Result[1], Result[2]])
2089
2090 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
2091 from Function
2092 where BelongsToFile = %d
2093 """ % (FileID)
2094 ResultSet = Db.TblFile.Exec(SqlStatement)
2095 FL = []
2096 for Result in ResultSet:
2097 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
2098
2099 p = GetFuncDeclPattern()
2100 for Str in PSL:
2101 FuncRecord = GetFuncContainsPE(Str[1], FL)
2102 if FuncRecord is None:
2103 continue
2104
2105 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
2106 PredInfo = SplitPredicateStr(Exp)
2107 if PredInfo[1] in ('==', '!=') and PredInfo[0][1] in ('TRUE', 'FALSE'):
2108 PredVarStr = PredInfo[0][0].strip()
2109 IsFuncCall = False
2110 SearchInCache = False
2111 # PredVarStr may contain '.' or '->'
2112 TmpStr = PredVarStr.replace('.', '').replace('->', '')
2113 if p.match(TmpStr):
2114 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
2115 SearchInCache = True
2116 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2117 if TmpStr.startswith(PredVarStr):
2118 IsFuncCall = True
2119
2120 if PredVarStr.strip() in IgnoredKeywordList:
2121 continue
2122 StarList = []
2123 PredVarList = GetCNameList(PredVarStr, StarList)
2124 # No variable found, maybe value first? like (0 == VarName)
2125 if len(PredVarList) == 0:
2126 continue
2127
2128 if SearchInCache:
2129 Type = FuncReturnTypeDict.get(PredVarStr)
2130 if Type is not None:
2131 if Type.find('BOOLEAN') != -1:
2132 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2133 continue
2134
2135 if PredVarStr in FuncReturnTypeDict:
2136 continue
2137
2138 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)
2139 if SearchInCache:
2140 FuncReturnTypeDict[PredVarStr] = Type
2141 if Type is None:
2142 continue
2143 if Type.find('BOOLEAN') != -1:
2144 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2145
2146
2147 def CheckHeaderFileData(FullFileName):
2148 ErrorMsgList = []
2149
2150 FileID = GetTableID(FullFileName, ErrorMsgList)
2151 if FileID < 0:
2152 return ErrorMsgList
2153
2154 Db = GetDB()
2155 FileTable = 'Identifier' + str(FileID)
2156 SqlStatement = """ select ID, Modifier
2157 from %s
2158 where Model = %d
2159 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
2160 ResultSet = Db.TblFile.Exec(SqlStatement)
2161 for Result in ResultSet:
2162 if not Result[1].startswith('extern'):
2163 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Variable definition appears in header file', FileTable, Result[0])
2164
2165 SqlStatement = """ select ID
2166 from Function
2167 where BelongsToFile = %d
2168 """ % FileID
2169 ResultSet = Db.TblFile.Exec(SqlStatement)
2170 for Result in ResultSet:
2171 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Function definition appears in header file', 'Function', Result[0])
2172
2173 return ErrorMsgList
2174
2175 def CheckHeaderFileIfndef(FullFileName):
2176 ErrorMsgList = []
2177
2178 FileID = GetTableID(FullFileName, ErrorMsgList)
2179 if FileID < 0:
2180 return ErrorMsgList
2181
2182 Db = GetDB()
2183 FileTable = 'Identifier' + str(FileID)
2184 SqlStatement = """ select Value, StartLine
2185 from %s
2186 where Model = %d order by StartLine
2187 """ % (FileTable, DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF)
2188 ResultSet = Db.TblFile.Exec(SqlStatement)
2189 if len(ResultSet) == 0:
2190 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1, '', 'File', FileID)
2191 return ErrorMsgList
2192 for Result in ResultSet:
2193 SqlStatement = """ select Value, EndLine
2194 from %s
2195 where EndLine < %d
2196 """ % (FileTable, Result[1])
2197 ResultSet = Db.TblFile.Exec(SqlStatement)
2198 for Result in ResultSet:
2199 if not Result[0].startswith('/*') and not Result[0].startswith('//'):
2200 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2, '', 'File', FileID)
2201 break
2202
2203 SqlStatement = """ select Value
2204 from %s
2205 where StartLine > (select max(EndLine) from %s where Model = %d)
2206 """ % (FileTable, FileTable, DataClass.MODEL_IDENTIFIER_MACRO_ENDIF)
2207 ResultSet = Db.TblFile.Exec(SqlStatement)
2208 for Result in ResultSet:
2209 if not Result[0].startswith('/*') and not Result[0].startswith('//'):
2210 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3, '', 'File', FileID)
2211 return ErrorMsgList
2212
2213 def CheckDoxygenCommand(FullFileName):
2214 ErrorMsgList = []
2215
2216 FileID = GetTableID(FullFileName, ErrorMsgList)
2217 if FileID < 0:
2218 return ErrorMsgList
2219
2220 Db = GetDB()
2221 FileTable = 'Identifier' + str(FileID)
2222 SqlStatement = """ select Value, ID
2223 from %s
2224 where Model = %d or Model = %d
2225 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)
2226 ResultSet = Db.TblFile.Exec(SqlStatement)
2227 DoxygenCommandList = ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval',
2228 'return', 'sa', 'since', 'test', 'note', 'par', 'endcode', 'code']
2229 for Result in ResultSet:
2230 CommentStr = Result[0]
2231 CommentPartList = CommentStr.split()
2232 for Part in CommentPartList:
2233 if Part.upper() == 'BUGBUG':
2234 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Bug should be marked with doxygen tag @bug', FileTable, Result[1])
2235 if Part.upper() == 'TODO':
2236 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'ToDo should be marked with doxygen tag @todo', FileTable, Result[1])
2237 if Part.startswith('@'):
2238 if EccGlobalData.gException.IsException(ERROR_DOXYGEN_CHECK_COMMAND, Part):
2239 continue
2240 if not Part.replace('@', '').strip():
2241 continue
2242 if Part.lstrip('@') in ['{', '}']:
2243 continue
2244 if Part.lstrip('@').isalpha():
2245 if Part.lstrip('@') not in DoxygenCommandList:
2246 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2247 else:
2248 Index = Part.find('[')
2249 if Index == -1:
2250 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2251 RealCmd = Part[1:Index]
2252 if RealCmd not in DoxygenCommandList:
2253 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2254
2255
2256 def CheckDoxygenTripleForwardSlash(FullFileName):
2257 ErrorMsgList = []
2258
2259 FileID = GetTableID(FullFileName, ErrorMsgList)
2260 if FileID < 0:
2261 return ErrorMsgList
2262
2263 Db = GetDB()
2264
2265 SqlStatement = """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2266 from Function
2267 where BelongsToFile = %d
2268 """ % (FileID)
2269 ResultSet = Db.TblFile.Exec(SqlStatement)
2270 if len(ResultSet) == 0:
2271 return
2272
2273 FuncDefSet = []
2274 for Result in ResultSet:
2275 FuncDefSet.append(Result)
2276
2277
2278 FileTable = 'Identifier' + str(FileID)
2279 SqlStatement = """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2280 from %s
2281 where Model = %d
2282
2283 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2284 ResultSet = Db.TblFile.Exec(SqlStatement)
2285 CommentSet = []
2286 try:
2287 for Result in ResultSet:
2288 CommentSet.append(Result)
2289 except:
2290 print('Unrecognized chars in comment of file %s', FullFileName)
2291
2292
2293 for Result in CommentSet:
2294 CommentStr = Result[0]
2295 StartLine = Result[2]
2296 StartColumn = Result[3]
2297 EndLine = Result[4]
2298 EndColumn = Result[5]
2299 if not CommentStr.startswith('///<'):
2300 continue
2301
2302 Found = False
2303 for FuncDef in FuncDefSet:
2304 if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:
2305 Found = True
2306 break
2307 if StartLine > FuncDef[1] and EndLine < FuncDef[3]:
2308 Found = True
2309 break
2310 if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine < FuncDef[3]:
2311 Found = True
2312 break
2313 if StartLine > FuncDef[1] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:
2314 Found = True
2315 break
2316 if Found:
2317 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT, '', FileTable, Result[1])
2318
2319
2320 def CheckFileHeaderDoxygenComments(FullFileName):
2321 ErrorMsgList = []
2322
2323 FileID = GetTableID(FullFileName, ErrorMsgList)
2324 if FileID < 0:
2325 return ErrorMsgList
2326
2327 Db = GetDB()
2328 FileTable = 'Identifier' + str(FileID)
2329 SqlStatement = """ select Value, ID
2330 from %s
2331 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2332 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2333 ResultSet = Db.TblFile.Exec(SqlStatement)
2334 if len(ResultSet) == 0:
2335 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'No File License header appear at the very beginning of file.', 'File', FileID)
2336 return ErrorMsgList
2337
2338 NoHeaderCommentStartFlag = True
2339 NoHeaderCommentEndFlag = True
2340 NoHeaderCommentPeriodFlag = True
2341 NoCopyrightFlag = True
2342 NoLicenseFlag = True
2343 NoRevReferFlag = True
2344 NextLineIndex = 0
2345 for Result in ResultSet:
2346 FileStartFlag = False
2347 CommentStrList = []
2348 CommentStr = Result[0].strip()
2349 CommentStrListTemp = CommentStr.split('\n')
2350 if (len(CommentStrListTemp) <= 1):
2351 # For Mac
2352 CommentStrListTemp = CommentStr.split('\r')
2353 # Skip the content before the file header
2354 for CommentLine in CommentStrListTemp:
2355 if CommentLine.strip().startswith('/** @file'):
2356 FileStartFlag = True
2357 if FileStartFlag == True:
2358 CommentStrList.append(CommentLine)
2359
2360 ID = Result[1]
2361 Index = 0
2362 if CommentStrList and CommentStrList[0].strip().startswith('/** @file'):
2363 NoHeaderCommentStartFlag = False
2364 else:
2365 continue
2366 if CommentStrList and CommentStrList[-1].strip().endswith('**/'):
2367 NoHeaderCommentEndFlag = False
2368 else:
2369 continue
2370
2371 for CommentLine in CommentStrList:
2372 Index = Index + 1
2373 NextLineIndex = Index
2374 if CommentLine.startswith('/** @file'):
2375 continue
2376 if CommentLine.startswith('**/'):
2377 break
2378 # Check whether C File header Comment content start with two spaces.
2379 if EccGlobalData.gConfig.HeaderCheckCFileCommentStartSpacesNum == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
2380 if CommentLine.startswith('/** @file') == False and CommentLine.startswith('**/') == False and CommentLine.strip() and CommentLine.startswith(' ') == False:
2381 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment content should start with two spaces at each line', FileTable, ID)
2382
2383 CommentLine = CommentLine.strip()
2384 if CommentLine.startswith('Copyright'):
2385 NoCopyrightFlag = False
2386 if CommentLine.find('All rights reserved') == -1:
2387 for Copyright in EccGlobalData.gConfig.Copyright:
2388 if CommentLine.find(Copyright) > -1:
2389 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable, ID)
2390 break
2391 if CommentLine.endswith('<BR>') == -1:
2392 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'The ""<BR>"" at the end of the Copyright line is required', FileTable, ID)
2393 if NextLineIndex < len(CommentStrList) and CommentStrList[NextLineIndex].strip().startswith('Copyright') == False and CommentStrList[NextLineIndex].strip():
2394 NoLicenseFlag = False
2395 if CommentLine.startswith('@par Revision Reference:'):
2396 NoRevReferFlag = False
2397 RefListFlag = False
2398 for RefLine in CommentStrList[NextLineIndex:]:
2399 if RefLine.strip() and (NextLineIndex + 1) < len(CommentStrList) and CommentStrList[NextLineIndex+1].strip() and CommentStrList[NextLineIndex+1].strip().startswith('**/') == False:
2400 RefListFlag = True
2401 if RefLine.strip() == False or RefLine.strip().startswith('**/'):
2402 RefListFlag = False
2403 break
2404 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2405 if EccGlobalData.gConfig.HeaderCheckCFileCommentReferenceFormat == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
2406 if RefListFlag == True:
2407 if RefLine.strip() and RefLine.strip().startswith('**/') == False and RefLine.startswith(' -') == False:
2408 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable, ID)
2409
2410 if NoHeaderCommentStartFlag:
2411 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER, 'File header comment should begin with ""/** @file""', FileTable, ID)
2412 return
2413 if NoHeaderCommentEndFlag:
2414 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should end with ""**/""', FileTable, ID)
2415 return
2416 if NoCopyrightFlag:
2417 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment missing the ""Copyright""', FileTable, ID)
2418 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2419 if EccGlobalData.gConfig.HeaderCheckCFileCommentLicenseFormat == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
2420 if NoLicenseFlag:
2421 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable, ID)
2422
2423 def CheckFuncHeaderDoxygenComments(FullFileName):
2424 ErrorMsgList = []
2425
2426 FileID = GetTableID(FullFileName, ErrorMsgList)
2427 if FileID < 0:
2428 return ErrorMsgList
2429
2430 Db = GetDB()
2431 FileTable = 'Identifier' + str(FileID)
2432 SqlStatement = """ select Value, StartLine, EndLine, ID
2433 from %s
2434 where Model = %d
2435 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2436
2437 ResultSet = Db.TblFile.Exec(SqlStatement)
2438 CommentSet = []
2439 try:
2440 for Result in ResultSet:
2441 CommentSet.append(Result)
2442 except:
2443 print('Unrecognized chars in comment of file %s', FullFileName)
2444
2445 # Func Decl check
2446 SqlStatement = """ select Modifier, Name, StartLine, ID, Value
2447 from %s
2448 where Model = %d
2449 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
2450 ResultSet = Db.TblFile.Exec(SqlStatement)
2451 for Result in ResultSet:
2452 FuncName = Result[4]
2453 FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)
2454 if FunctionHeaderComment:
2455 CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)
2456 else:
2457 if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):
2458 continue
2459 ErrorMsgList.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result[2], Result[1]))
2460 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), FileTable, Result[3])
2461
2462 # Func Def check
2463 SqlStatement = """ select Value, StartLine, EndLine, ID
2464 from %s
2465 where Model = %d
2466 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)
2467
2468 ResultSet = Db.TblFile.Exec(SqlStatement)
2469 CommentSet = []
2470 try:
2471 for Result in ResultSet:
2472 CommentSet.append(Result)
2473 except:
2474 print('Unrecognized chars in comment of file %s', FullFileName)
2475
2476 SqlStatement = """ select Modifier, Header, StartLine, ID, Name
2477 from Function
2478 where BelongsToFile = %d
2479 """ % (FileID)
2480 ResultSet = Db.TblFile.Exec(SqlStatement)
2481 for Result in ResultSet:
2482 FuncName = Result[4]
2483 FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)
2484 if FunctionHeaderComment:
2485 CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)
2486 else:
2487 if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):
2488 continue
2489 ErrorMsgList.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result[2], Result[1]))
2490 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), 'Function', Result[3])
2491 return ErrorMsgList
2492
2493 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName, FuncStartLine, CommentSet):
2494
2495 for Comment in CommentSet:
2496 if Comment[2] == FuncStartLine - 1:
2497 return Comment
2498 return None
2499
2500 def GetDoxygenStrFromComment(Str):
2501 DoxygenStrList = []
2502 ParamTagList = Str.split('@param')
2503 if len(ParamTagList) > 1:
2504 i = 1
2505 while i < len(ParamTagList):
2506 DoxygenStrList.append('@param' + ParamTagList[i])
2507 i += 1
2508
2509 Str = ParamTagList[0]
2510
2511 RetvalTagList = ParamTagList[-1].split('@retval')
2512 if len(RetvalTagList) > 1:
2513 if len(ParamTagList) > 1:
2514 DoxygenStrList[-1] = '@param' + RetvalTagList[0]
2515 i = 1
2516 while i < len(RetvalTagList):
2517 DoxygenStrList.append('@retval' + RetvalTagList[i])
2518 i += 1
2519
2520 ReturnTagList = RetvalTagList[-1].split('@return')
2521 if len(ReturnTagList) > 1:
2522 if len(RetvalTagList) > 1:
2523 DoxygenStrList[-1] = '@retval' + ReturnTagList[0]
2524 elif len(ParamTagList) > 1:
2525 DoxygenStrList[-1] = '@param' + ReturnTagList[0]
2526 i = 1
2527 while i < len(ReturnTagList):
2528 DoxygenStrList.append('@return' + ReturnTagList[i])
2529 i += 1
2530
2531 if len(DoxygenStrList) > 0:
2532 DoxygenStrList[-1] = DoxygenStrList[-1].rstrip('--*/')
2533
2534 return DoxygenStrList
2535
2536 def CheckGeneralDoxygenCommentLayout(Str, StartLine, ErrorMsgList, CommentId= -1, TableName=''):
2537 #/** --*/ @retval after @param
2538 if not Str.startswith('/**'):
2539 ErrorMsgList.append('Line %d : Comment does NOT have prefix /** ' % StartLine)
2540 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have prefix /** ', TableName, CommentId)
2541 if not Str.endswith('**/'):
2542 ErrorMsgList.append('Line %d : Comment does NOT have tail **/ ' % StartLine)
2543 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have tail **/ ', TableName, CommentId)
2544 FirstRetvalIndex = Str.find('@retval')
2545 LastParamIndex = Str.rfind('@param')
2546 if (FirstRetvalIndex > 0) and (LastParamIndex > 0) and (FirstRetvalIndex < LastParamIndex):
2547 ErrorMsgList.append('Line %d : @retval appear before @param ' % StartLine)
2548 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, @retval appear before @param ', TableName, CommentId)
2549
2550 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier, FuncHeader, FuncStartLine, CommentStr, CommentStartLine, ErrorMsgList, CommentId= -1, TableName=''):
2551
2552 ParamList = GetParamList(FuncHeader)
2553 CheckGeneralDoxygenCommentLayout(CommentStr, CommentStartLine, ErrorMsgList, CommentId, TableName)
2554 DescriptionStr = CommentStr
2555 DoxygenStrList = GetDoxygenStrFromComment(DescriptionStr)
2556 if DescriptionStr.find('.') == -1:
2557 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period \'.\'', TableName, CommentId)
2558 DoxygenTagNumber = len(DoxygenStrList)
2559 ParamNumber = len(ParamList)
2560 for Param in ParamList:
2561 if Param.Name.upper() == 'VOID' and ParamNumber == 1:
2562 ParamNumber -= 1
2563 Index = 0
2564 if ParamNumber > 0 and DoxygenTagNumber > 0:
2565 while Index < ParamNumber and Index < DoxygenTagNumber:
2566 ParamModifier = ParamList[Index].Modifier
2567 ParamName = ParamList[Index].Name.strip()
2568 Tag = DoxygenStrList[Index].strip(' ')
2569 if (not Tag[-1] == ('\n')) and (not Tag[-1] == ('\r')):
2570 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))
2571 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'in Comment, <%s> does NOT end with new line ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)
2572 TagPartList = Tag.split()
2573 if len(TagPartList) < 2:
2574 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))
2575 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)
2576 Index += 1
2577 continue
2578 LBPos = Tag.find('[')
2579 RBPos = Tag.find(']')
2580 ParamToLBContent = Tag[len('@param'):LBPos].strip()
2581 if LBPos > 0 and len(ParamToLBContent) == 0 and RBPos > LBPos:
2582 InOutStr = ''
2583 ModifierPartList = ParamModifier.split()
2584 for Part in ModifierPartList:
2585 if Part.strip() == 'IN':
2586 InOutStr += 'in'
2587 if Part.strip() == 'OUT':
2588 if InOutStr != '':
2589 InOutStr += ', out'
2590 else:
2591 InOutStr = 'out'
2592
2593 if InOutStr != '':
2594 if Tag.find('[' + InOutStr + ']') == -1:
2595 if InOutStr != 'in, out':
2596 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'))
2597 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT have %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'), TableName, CommentId)
2598 else:
2599 if Tag.find('[in,out]') == -1:
2600 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'))
2601 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT have %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'), TableName, CommentId)
2602
2603
2604 if Tag.find(ParamName) == -1 and ParamName != 'VOID' and ParamName != 'void':
2605 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), ParamName))
2606 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT consistent with parameter name %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), ParamName), TableName, CommentId)
2607 Index += 1
2608
2609 if Index < ParamNumber:
2610 ErrorMsgList.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine)
2611 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of doxygen tags in comment less than number of function parameters ', TableName, CommentId)
2612 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2613 if (FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1:
2614
2615 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2616 if Index < DoxygenTagNumber - 1 or (Index < DoxygenTagNumber and DoxygenStrList[Index].startswith('@retval')):
2617 ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)
2618 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need no doxygen tags in comment ', TableName, CommentId)
2619 else:
2620 if Index < DoxygenTagNumber and not DoxygenStrList[Index].startswith('@retval') and not DoxygenStrList[Index].startswith('@return'):
2621 ErrorMsgList.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine)
2622 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName, CommentId)
2623 else:
2624 if ParamNumber == 0 and DoxygenTagNumber != 0 and ((FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1):
2625 ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)
2626 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need NO doxygen tags in comment ', TableName, CommentId)
2627 if ParamNumber != 0 and DoxygenTagNumber == 0:
2628 ErrorMsgList.append('Line %d : No doxygen tags in comment' % CommentStartLine)
2629 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'No doxygen tags in comment ', TableName, CommentId)
2630
2631 if __name__ == '__main__':
2632
2633 # EdkLogger.Initialize()
2634 # EdkLogger.SetLevel(EdkLogger.QUIET)
2635 # CollectSourceCodeDataIntoDB(sys.argv[1])
2636 try:
2637 test_file = sys.argv[1]
2638 except IndexError as v:
2639 print("Usage: %s filename" % sys.argv[0])
2640 sys.exit(1)
2641 MsgList = CheckFuncHeaderDoxygenComments(test_file)
2642 for Msg in MsgList:
2643 print(Msg)
2644 print('Done!')