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