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