]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Ecc/c.py
997e631c97c195357eab18d4622ce9d0575732a3
[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 - 2015, 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 Index = Result[0].find(TypeStart)
1275 if Index != 0 or Result[3] != 0:
1276 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, FileTable, Result[1])
1277
1278 if Result[2] == Result[4]:
1279 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear on its own line' % FuncName, FileTable, Result[1])
1280
1281 SqlStatement = """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1282 from Function
1283 where BelongsToFile = %d
1284 """ % (FileID)
1285 ResultSet = Db.TblFile.Exec(SqlStatement)
1286 for Result in ResultSet:
1287 ReturnType = GetDataTypeFromModifier(Result[0])
1288 TypeStart = ReturnType.split()[0]
1289 FuncName = Result[5]
1290 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, FuncName):
1291 continue
1292 Index = Result[0].find(ReturnType)
1293 if Index != 0 or Result[3] != 0:
1294 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, 'Function', Result[1])
1295
1296 if Result[2] == Result[4]:
1297 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear on its own line' % FuncName, 'Function', Result[1])
1298
1299 def CheckFuncLayoutModifier(FullFileName):
1300 ErrorMsgList = []
1301
1302 FileID = GetTableID(FullFileName, ErrorMsgList)
1303 if FileID < 0:
1304 return ErrorMsgList
1305
1306 Db = GetDB()
1307 FileTable = 'Identifier' + str(FileID)
1308 SqlStatement = """ select Modifier, ID
1309 from %s
1310 where Model = %d
1311 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1312 ResultSet = Db.TblFile.Exec(SqlStatement)
1313 for Result in ResultSet:
1314 ReturnType = GetDataTypeFromModifier(Result[0])
1315 TypeStart = ReturnType.split()[0]
1316 # if len(ReturnType) == 0:
1317 # continue
1318 Index = Result[0].find(TypeStart)
1319 if Index != 0:
1320 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', FileTable, Result[1])
1321
1322 SqlStatement = """ select Modifier, ID
1323 from Function
1324 where BelongsToFile = %d
1325 """ % (FileID)
1326 ResultSet = Db.TblFile.Exec(SqlStatement)
1327 for Result in ResultSet:
1328 ReturnType = GetDataTypeFromModifier(Result[0])
1329 TypeStart = ReturnType.split()[0]
1330 # if len(ReturnType) == 0:
1331 # continue
1332 Index = Result[0].find(TypeStart)
1333 if Index != 0:
1334 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', 'Function', Result[1])
1335
1336 def CheckFuncLayoutName(FullFileName):
1337 ErrorMsgList = []
1338 # Parameter variable format pattern.
1339 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
1340 ParamIgnoreList = ('VOID', '...')
1341 FileID = GetTableID(FullFileName, ErrorMsgList)
1342 if FileID < 0:
1343 return ErrorMsgList
1344
1345 Db = GetDB()
1346 FileTable = 'Identifier' + str(FileID)
1347 SqlStatement = """ select Name, ID, EndColumn, Value
1348 from %s
1349 where Model = %d
1350 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1351 ResultSet = Db.TblFile.Exec(SqlStatement)
1352 for Result in ResultSet:
1353 FuncName = Result[3]
1354 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName):
1355 continue
1356 if Result[2] != 0:
1357 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, FileTable, Result[1])
1358 ParamList = GetParamList(Result[0])
1359 if len(ParamList) == 0:
1360 continue
1361 StartLine = 0
1362 for Param in ParamList:
1363 if Param.StartLine <= StartLine:
1364 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, FileTable, Result[1])
1365 if Param.StartLine - StartLine > 1:
1366 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, FileTable, Result[1])
1367 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):
1368 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1])
1369 StartLine = Param.StartLine
1370
1371 if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'):
1372 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', FileTable, Result[1])
1373
1374 SqlStatement = """ select Modifier, ID, FunNameStartColumn, Name
1375 from Function
1376 where BelongsToFile = %d
1377 """ % (FileID)
1378 ResultSet = Db.TblFile.Exec(SqlStatement)
1379 for Result in ResultSet:
1380 FuncName = Result[3]
1381 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName):
1382 continue
1383 if Result[2] != 0:
1384 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, 'Function', Result[1])
1385 ParamList = GetParamList(Result[0])
1386 if len(ParamList) == 0:
1387 continue
1388 StartLine = 0
1389 for Param in ParamList:
1390 if Param.StartLine <= StartLine:
1391 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, 'Function', Result[1])
1392 if Param.StartLine - StartLine > 1:
1393 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, 'Function', Result[1])
1394 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):
1395 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1])
1396 StartLine = Param.StartLine
1397 if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'):
1398 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', 'Function', Result[1])
1399
1400 def CheckFuncLayoutPrototype(FullFileName):
1401 ErrorMsgList = []
1402
1403 FileID = GetTableID(FullFileName, ErrorMsgList)
1404 if FileID < 0:
1405 return ErrorMsgList
1406
1407 FileTable = 'Identifier' + str(FileID)
1408 Db = GetDB()
1409 SqlStatement = """ select Modifier, Header, Name, ID
1410 from Function
1411 where BelongsToFile = %d
1412 """ % (FileID)
1413 ResultSet = Db.TblFile.Exec(SqlStatement)
1414 if len(ResultSet) == 0:
1415 return ErrorMsgList
1416
1417 FuncDefList = []
1418 for Result in ResultSet:
1419 FuncDefList.append(Result)
1420
1421 SqlStatement = """ select Modifier, Name, ID
1422 from %s
1423 where Model = %d
1424 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1425 ResultSet = Db.TblFile.Exec(SqlStatement)
1426 FuncDeclList = []
1427 for Result in ResultSet:
1428 FuncDeclList.append(Result)
1429
1430 UndeclFuncList = []
1431 for FuncDef in FuncDefList:
1432 FuncName = FuncDef[2].strip()
1433 FuncModifier = FuncDef[0]
1434 FuncDefHeader = FuncDef[1]
1435 for FuncDecl in FuncDeclList:
1436 LBPos = FuncDecl[1].find('(')
1437 DeclName = FuncDecl[1][0:LBPos].strip()
1438 DeclModifier = FuncDecl[0]
1439 if DeclName == FuncName:
1440 if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName):
1441 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3])
1442 ParamListOfDef = GetParamList(FuncDefHeader)
1443 ParamListOfDecl = GetParamList(FuncDecl[1])
1444 if len(ParamListOfDef) != len(ParamListOfDecl) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, FuncName):
1445 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, 'Parameter number different in function [%s].' % FuncName, 'Function', FuncDef[3])
1446 break
1447
1448 Index = 0
1449 while Index < len(ParamListOfDef):
1450 if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, FuncName):
1451 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])
1452 Index += 1
1453 break
1454 else:
1455 UndeclFuncList.append(FuncDef)
1456
1457 IncludeFileList = GetAllIncludeFiles(FullFileName)
1458 FuncDeclList = []
1459 for F in IncludeFileList:
1460 FileID = GetTableID(F, ErrorMsgList)
1461 if FileID < 0:
1462 continue
1463
1464 FileTable = 'Identifier' + str(FileID)
1465 SqlStatement = """ select Modifier, Name, ID
1466 from %s
1467 where Model = %d
1468 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1469 ResultSet = Db.TblFile.Exec(SqlStatement)
1470
1471 for Result in ResultSet:
1472 FuncDeclList.append(Result)
1473
1474 for FuncDef in UndeclFuncList:
1475 FuncName = FuncDef[2].strip()
1476 FuncModifier = FuncDef[0]
1477 FuncDefHeader = FuncDef[1]
1478 for FuncDecl in FuncDeclList:
1479 LBPos = FuncDecl[1].find('(')
1480 DeclName = FuncDecl[1][0:LBPos].strip()
1481 DeclModifier = FuncDecl[0]
1482 if DeclName == FuncName:
1483 if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName):
1484 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3])
1485 ParamListOfDef = GetParamList(FuncDefHeader)
1486 ParamListOfDecl = GetParamList(FuncDecl[1])
1487 if len(ParamListOfDef) != len(ParamListOfDecl) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, FuncName):
1488 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, 'Parameter number different in function [%s].' % FuncName, 'Function', FuncDef[3])
1489 break
1490
1491 Index = 0
1492 while Index < len(ParamListOfDef):
1493 if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, FuncName):
1494 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])
1495 Index += 1
1496 break
1497
1498 def CheckFuncLayoutBody(FullFileName):
1499 ErrorMsgList = []
1500
1501 FileID = GetTableID(FullFileName, ErrorMsgList)
1502 if FileID < 0:
1503 return ErrorMsgList
1504
1505 FileTable = 'Identifier' + str(FileID)
1506 Db = GetDB()
1507 SqlStatement = """ select BodyStartColumn, EndColumn, ID
1508 from Function
1509 where BelongsToFile = %d
1510 """ % (FileID)
1511 ResultSet = Db.TblFile.Exec(SqlStatement)
1512 if len(ResultSet) == 0:
1513 return ErrorMsgList
1514 for Result in ResultSet:
1515 if Result[0] != 0:
1516 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'open brace should be at the very beginning of a line.', 'Function', Result[2])
1517 if Result[1] != 0:
1518 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'close brace should be at the very beginning of a line.', 'Function', Result[2])
1519
1520 def CheckFuncLayoutLocalVariable(FullFileName):
1521 ErrorMsgList = []
1522
1523 FileID = GetTableID(FullFileName, ErrorMsgList)
1524 if FileID < 0:
1525 return ErrorMsgList
1526
1527 Db = GetDB()
1528 FileTable = 'Identifier' + str(FileID)
1529 SqlStatement = """ select ID
1530 from Function
1531 where BelongsToFile = %d
1532 """ % (FileID)
1533 ResultSet = Db.TblFile.Exec(SqlStatement)
1534 if len(ResultSet) == 0:
1535 return ErrorMsgList
1536 FL = []
1537 for Result in ResultSet:
1538 FL.append(Result)
1539
1540 for F in FL:
1541 SqlStatement = """ select Name, Value, ID, Modifier
1542 from %s
1543 where Model = %d and BelongsToFunction = %d
1544 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, F[0])
1545 ResultSet = Db.TblFile.Exec(SqlStatement)
1546 if len(ResultSet) == 0:
1547 continue
1548
1549 for Result in ResultSet:
1550 if len(Result[1]) > 0 and 'CONST' not in Result[3]:
1551 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE, 'Variable Name: %s' % Result[0], FileTable, Result[2])
1552
1553 def CheckMemberVariableFormat(Name, Value, FileTable, TdId, ModelId):
1554 ErrMsgList = []
1555 # Member variable format pattern.
1556 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
1557
1558 LBPos = Value.find('{')
1559 RBPos = Value.rfind('}')
1560 if LBPos == -1 or RBPos == -1:
1561 return ErrMsgList
1562
1563 Fields = Value[LBPos + 1 : RBPos]
1564 Fields = StripComments(Fields).strip()
1565 NestPos = Fields.find ('struct')
1566 if NestPos != -1 and (NestPos + len('struct') < len(Fields)):
1567 if not Fields[NestPos + len('struct') + 1].isalnum():
1568 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1569 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested struct in [%s].' % (Name), FileTable, TdId)
1570 return ErrMsgList
1571 NestPos = Fields.find ('union')
1572 if NestPos != -1 and (NestPos + len('union') < len(Fields)):
1573 if not Fields[NestPos + len('union') + 1].isalnum():
1574 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1575 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested union in [%s].' % (Name), FileTable, TdId)
1576 return ErrMsgList
1577 NestPos = Fields.find ('enum')
1578 if NestPos != -1 and (NestPos + len('enum') < len(Fields)):
1579 if not Fields[NestPos + len('enum') + 1].isalnum():
1580 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1581 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested enum in [%s].' % (Name), FileTable, TdId)
1582 return ErrMsgList
1583
1584 if ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:
1585 FieldsList = Fields.split(',')
1586 # deal with enum is pre-assigned a value by function call ( , , , ...)
1587 QuoteCount = 0
1588 Index = 0
1589 RemoveCurrentElement = False
1590 while Index < len(FieldsList):
1591 Field = FieldsList[Index]
1592
1593 if Field.find('(') != -1:
1594 QuoteCount += 1
1595 RemoveCurrentElement = True
1596 Index += 1
1597 continue
1598
1599 if Field.find(')') != -1 and QuoteCount > 0:
1600 QuoteCount -= 1
1601
1602 if RemoveCurrentElement:
1603 FieldsList.remove(Field)
1604 if QuoteCount == 0:
1605 RemoveCurrentElement = False
1606 continue
1607
1608 if QuoteCount == 0:
1609 RemoveCurrentElement = False
1610
1611 Index += 1
1612 else:
1613 FieldsList = Fields.split(';')
1614
1615 for Field in FieldsList:
1616 Field = Field.strip()
1617 if Field == '':
1618 continue
1619 # For the condition that the field in struct is an array with [] sufixes...
1620 if Field[-1] == ']':
1621 LBPos = Field.find('[')
1622 Field = Field[0:LBPos]
1623 # For the condition that bit field ": Number"
1624 if Field.find(':') != -1:
1625 ColonPos = Field.find(':')
1626 Field = Field[0:ColonPos]
1627
1628 Field = Field.strip()
1629 if Field == '':
1630 continue
1631 # Enum could directly assign value to variable
1632 Field = Field.split('=')[0].strip()
1633 TokenList = Field.split()
1634 # Remove pointers before variable
1635 if not Pattern.match(TokenList[-1].lstrip('*')):
1636 ErrMsgList.append(TokenList[-1].lstrip('*'))
1637
1638 return ErrMsgList
1639
1640 def CheckDeclTypedefFormat(FullFileName, ModelId):
1641 ErrorMsgList = []
1642
1643 FileID = GetTableID(FullFileName, ErrorMsgList)
1644 if FileID < 0:
1645 return ErrorMsgList
1646
1647 Db = GetDB()
1648 FileTable = 'Identifier' + str(FileID)
1649 SqlStatement = """ select Name, StartLine, EndLine, ID, Value
1650 from %s
1651 where Model = %d
1652 """ % (FileTable, ModelId)
1653 ResultSet = Db.TblFile.Exec(SqlStatement)
1654 ResultList = []
1655 for Result in ResultSet:
1656 ResultList.append(Result)
1657
1658 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1659 if ModelId == DataClass.MODEL_IDENTIFIER_STRUCTURE:
1660 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1661 elif ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:
1662 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1663 elif ModelId == DataClass.MODEL_IDENTIFIER_UNION:
1664 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1665
1666 SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID
1667 from %s
1668 where Model = %d
1669 """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
1670 TdSet = Db.TblFile.Exec(SqlStatement)
1671 TdList = []
1672 for Td in TdSet:
1673 TdList.append(Td)
1674 # Check member variable name format that from typedefs of ONLY this file.
1675 for Td in TdList:
1676 Name = Td[1].strip()
1677 Value = Td[2].strip()
1678 if Value.startswith('enum'):
1679 ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE
1680 elif Value.startswith('struct'):
1681 ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE
1682 elif Value.startswith('union'):
1683 ValueModelId = DataClass.MODEL_IDENTIFIER_UNION
1684 else:
1685 continue
1686
1687 if ValueModelId != ModelId:
1688 continue
1689 # Check member variable format.
1690 ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Td[5], ModelId)
1691 for ErrMsg in ErrMsgList:
1692 if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Name + '.' + ErrMsg):
1693 continue
1694 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Name + '.' + ErrMsg), FileTable, Td[5])
1695
1696 # First check in current file to see whether struct/union/enum is typedef-ed.
1697 UntypedefedList = []
1698 for Result in ResultList:
1699 # Check member variable format.
1700 Name = Result[0].strip()
1701 Value = Result[4].strip()
1702 if Value.startswith('enum'):
1703 ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE
1704 elif Value.startswith('struct'):
1705 ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE
1706 elif Value.startswith('union'):
1707 ValueModelId = DataClass.MODEL_IDENTIFIER_UNION
1708 else:
1709 continue
1710
1711 if ValueModelId != ModelId:
1712 continue
1713 ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Result[3], ModelId)
1714 for ErrMsg in ErrMsgList:
1715 if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Result[0] + '.' + ErrMsg):
1716 continue
1717 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Result[0] + '.' + ErrMsg), FileTable, Result[3])
1718 # Check whether it is typedefed.
1719 Found = False
1720 for Td in TdList:
1721 # skip function pointer
1722 if len(Td[0]) > 0:
1723 continue
1724 if Result[1] >= Td[3] and Td[4] >= Result[2]:
1725 Found = True
1726 if not Td[1].isupper():
1727 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1728 if Result[0] in Td[2].split():
1729 Found = True
1730 if not Td[1].isupper():
1731 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1732 if Found:
1733 break
1734
1735 if not Found:
1736 UntypedefedList.append(Result)
1737 continue
1738
1739 if len(UntypedefedList) == 0:
1740 return
1741
1742 IncludeFileList = GetAllIncludeFiles(FullFileName)
1743 TdList = []
1744 for F in IncludeFileList:
1745 FileID = GetTableID(F, ErrorMsgList)
1746 if FileID < 0:
1747 continue
1748
1749 IncludeFileTable = 'Identifier' + str(FileID)
1750 SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID
1751 from %s
1752 where Model = %d
1753 """ % (IncludeFileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
1754 ResultSet = Db.TblFile.Exec(SqlStatement)
1755 TdList.extend(ResultSet)
1756
1757 for Result in UntypedefedList:
1758
1759 # Check whether it is typedefed.
1760 Found = False
1761 for Td in TdList:
1762
1763 if len(Td[0]) > 0:
1764 continue
1765 if Result[1] >= Td[3] and Td[4] >= Result[2]:
1766 Found = True
1767 if not Td[1].isupper():
1768 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1769 if Result[0] in Td[2].split():
1770 Found = True
1771 if not Td[1].isupper():
1772 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1773 if Found:
1774 break
1775
1776 if not Found:
1777 PrintErrorMsg(ErrorType, 'No Typedef for %s' % Result[0], FileTable, Result[3])
1778 continue
1779
1780 def CheckDeclStructTypedef(FullFileName):
1781 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_STRUCTURE)
1782
1783 def CheckDeclEnumTypedef(FullFileName):
1784 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_ENUMERATE)
1785
1786 def CheckDeclUnionTypedef(FullFileName):
1787 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_UNION)
1788
1789 def CheckDeclArgModifier(FullFileName):
1790 ErrorMsgList = []
1791
1792 FileID = GetTableID(FullFileName, ErrorMsgList)
1793 if FileID < 0:
1794 return ErrorMsgList
1795
1796 Db = GetDB()
1797 FileTable = 'Identifier' + str(FileID)
1798 SqlStatement = """ select Modifier, Name, ID
1799 from %s
1800 where Model = %d
1801 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
1802 ResultSet = Db.TblFile.Exec(SqlStatement)
1803 ModifierTuple = ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1804 MAX_MODIFIER_LENGTH = 100
1805 for Result in ResultSet:
1806 for Modifier in ModifierTuple:
1807 if PatternInModifier(Result[0], Modifier) and len(Result[0]) < MAX_MODIFIER_LENGTH:
1808 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Variable Modifier %s' % Result[0], FileTable, Result[2])
1809 break
1810
1811 SqlStatement = """ select Modifier, Name, ID
1812 from %s
1813 where Model = %d
1814 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1815 ResultSet = Db.TblFile.Exec(SqlStatement)
1816 for Result in ResultSet:
1817 for Modifier in ModifierTuple:
1818 if PatternInModifier(Result[0], Modifier):
1819 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])
1820 break
1821
1822 SqlStatement = """ select Modifier, Header, ID
1823 from Function
1824 where BelongsToFile = %d
1825 """ % (FileID)
1826 ResultSet = Db.TblFile.Exec(SqlStatement)
1827 for Result in ResultSet:
1828 for Modifier in ModifierTuple:
1829 if PatternInModifier(Result[0], Modifier):
1830 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])
1831 break
1832
1833 def CheckDeclNoUseCType(FullFileName):
1834 ErrorMsgList = []
1835
1836 FileID = GetTableID(FullFileName, ErrorMsgList)
1837 if FileID < 0:
1838 return ErrorMsgList
1839
1840 Db = GetDB()
1841 FileTable = 'Identifier' + str(FileID)
1842 SqlStatement = """ select Modifier, Name, ID
1843 from %s
1844 where Model = %d
1845 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
1846 ResultSet = Db.TblFile.Exec(SqlStatement)
1847 CTypeTuple = ('int', 'unsigned', 'char', 'void', 'static', 'long')
1848 for Result in ResultSet:
1849 for Type in CTypeTuple:
1850 if PatternInModifier(Result[0], Type):
1851 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Variable type %s' % Type, FileTable, Result[2])
1852 break
1853
1854 SqlStatement = """ select Modifier, Name, ID, Value
1855 from %s
1856 where Model = %d
1857 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1858 ResultSet = Db.TblFile.Exec(SqlStatement)
1859 for Result in ResultSet:
1860 ParamList = GetParamList(Result[1])
1861 FuncName = Result[3]
1862 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):
1863 continue
1864 for Type in CTypeTuple:
1865 if PatternInModifier(Result[0], Type):
1866 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '%s Return type %s' % (FuncName, Result[0]), FileTable, Result[2])
1867
1868 for Param in ParamList:
1869 if PatternInModifier(Param.Modifier, Type):
1870 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])
1871
1872 SqlStatement = """ select Modifier, Header, ID, Name
1873 from Function
1874 where BelongsToFile = %d
1875 """ % (FileID)
1876 ResultSet = Db.TblFile.Exec(SqlStatement)
1877 for Result in ResultSet:
1878 ParamList = GetParamList(Result[1])
1879 FuncName = Result[3]
1880 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):
1881 continue
1882 for Type in CTypeTuple:
1883 if PatternInModifier(Result[0], Type):
1884 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '[%s] Return type %s' % (FuncName, Result[0]), FileTable, Result[2])
1885
1886 for Param in ParamList:
1887 if PatternInModifier(Param.Modifier, Type):
1888 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])
1889
1890
1891 def CheckPointerNullComparison(FullFileName):
1892 ErrorMsgList = []
1893
1894 FileID = GetTableID(FullFileName, ErrorMsgList)
1895 if FileID < 0:
1896 return ErrorMsgList
1897
1898 # cache the found function return type to accelerate later checking in this file.
1899 FuncReturnTypeDict = {}
1900
1901 Db = GetDB()
1902 FileTable = 'Identifier' + str(FileID)
1903 SqlStatement = """ select Value, StartLine, ID
1904 from %s
1905 where Model = %d
1906 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
1907 ResultSet = Db.TblFile.Exec(SqlStatement)
1908 if len(ResultSet) == 0:
1909 return
1910 PSL = []
1911 for Result in ResultSet:
1912 PSL.append([Result[0], Result[1], Result[2]])
1913
1914 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
1915 from Function
1916 where BelongsToFile = %d
1917 """ % (FileID)
1918 ResultSet = Db.TblFile.Exec(SqlStatement)
1919 FL = []
1920 for Result in ResultSet:
1921 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
1922
1923 p = GetFuncDeclPattern()
1924 for Str in PSL:
1925 FuncRecord = GetFuncContainsPE(Str[1], FL)
1926 if FuncRecord == None:
1927 continue
1928
1929 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
1930 PredInfo = SplitPredicateStr(Exp)
1931 if PredInfo[1] == None:
1932 PredVarStr = PredInfo[0][0].strip()
1933 IsFuncCall = False
1934 SearchInCache = False
1935 # PredVarStr may contain '.' or '->'
1936 TmpStr = PredVarStr.replace('.', '').replace('->', '')
1937 if p.match(TmpStr):
1938 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
1939 SearchInCache = True
1940 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1941 if TmpStr.startswith(PredVarStr):
1942 IsFuncCall = True
1943
1944 if PredVarStr.strip() in IgnoredKeywordList:
1945 continue
1946 StarList = []
1947 PredVarList = GetCNameList(PredVarStr, StarList)
1948 # No variable found, maybe value first? like (0 == VarName)
1949 if len(PredVarList) == 0:
1950 continue
1951 if SearchInCache:
1952 Type = FuncReturnTypeDict.get(PredVarStr)
1953 if Type != None:
1954 if Type.find('*') != -1 and Type != 'BOOLEAN*':
1955 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
1956 continue
1957
1958 if PredVarStr in FuncReturnTypeDict:
1959 continue
1960
1961 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, None, StarList)
1962 if SearchInCache:
1963 FuncReturnTypeDict[PredVarStr] = Type
1964 if Type == None:
1965 continue
1966 Type = GetTypeFromArray(Type, PredVarStr)
1967 if Type.find('*') != -1 and Type != 'BOOLEAN*':
1968 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
1969
1970 def CheckNonBooleanValueComparison(FullFileName):
1971 ErrorMsgList = []
1972
1973 FileID = GetTableID(FullFileName, ErrorMsgList)
1974 if FileID < 0:
1975 return ErrorMsgList
1976
1977 # cache the found function return type to accelerate later checking in this file.
1978 FuncReturnTypeDict = {}
1979
1980 Db = GetDB()
1981 FileTable = 'Identifier' + str(FileID)
1982 SqlStatement = """ select Value, StartLine, ID
1983 from %s
1984 where Model = %d
1985 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
1986 ResultSet = Db.TblFile.Exec(SqlStatement)
1987 if len(ResultSet) == 0:
1988 return
1989 PSL = []
1990 for Result in ResultSet:
1991 PSL.append([Result[0], Result[1], Result[2]])
1992
1993 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
1994 from Function
1995 where BelongsToFile = %d
1996 """ % (FileID)
1997 ResultSet = Db.TblFile.Exec(SqlStatement)
1998 FL = []
1999 for Result in ResultSet:
2000 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
2001
2002 p = GetFuncDeclPattern()
2003 for Str in PSL:
2004 FuncRecord = GetFuncContainsPE(Str[1], FL)
2005 if FuncRecord == None:
2006 continue
2007
2008 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
2009 PredInfo = SplitPredicateStr(Exp)
2010 if PredInfo[1] == None:
2011 PredVarStr = PredInfo[0][0].strip()
2012 IsFuncCall = False
2013 SearchInCache = False
2014 # PredVarStr may contain '.' or '->'
2015 TmpStr = PredVarStr.replace('.', '').replace('->', '')
2016 if p.match(TmpStr):
2017 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
2018 SearchInCache = True
2019 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2020 if TmpStr.startswith(PredVarStr):
2021 IsFuncCall = True
2022
2023 if PredVarStr.strip() in IgnoredKeywordList:
2024 continue
2025 StarList = []
2026 PredVarList = GetCNameList(PredVarStr, StarList)
2027 # No variable found, maybe value first? like (0 == VarName)
2028 if len(PredVarList) == 0:
2029 continue
2030
2031 if SearchInCache:
2032 Type = FuncReturnTypeDict.get(PredVarStr)
2033 if Type != None:
2034 if Type.find('BOOLEAN') == -1:
2035 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2036 continue
2037
2038 if PredVarStr in FuncReturnTypeDict:
2039 continue
2040 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)
2041 if SearchInCache:
2042 FuncReturnTypeDict[PredVarStr] = Type
2043 if Type == None:
2044 continue
2045 if Type.find('BOOLEAN') == -1:
2046 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2047
2048
2049 def CheckBooleanValueComparison(FullFileName):
2050 ErrorMsgList = []
2051
2052 FileID = GetTableID(FullFileName, ErrorMsgList)
2053 if FileID < 0:
2054 return ErrorMsgList
2055
2056 # cache the found function return type to accelerate later checking in this file.
2057 FuncReturnTypeDict = {}
2058
2059 Db = GetDB()
2060 FileTable = 'Identifier' + str(FileID)
2061 SqlStatement = """ select Value, StartLine, ID
2062 from %s
2063 where Model = %d
2064 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
2065 ResultSet = Db.TblFile.Exec(SqlStatement)
2066 if len(ResultSet) == 0:
2067 return
2068 PSL = []
2069 for Result in ResultSet:
2070 PSL.append([Result[0], Result[1], Result[2]])
2071
2072 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
2073 from Function
2074 where BelongsToFile = %d
2075 """ % (FileID)
2076 ResultSet = Db.TblFile.Exec(SqlStatement)
2077 FL = []
2078 for Result in ResultSet:
2079 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
2080
2081 p = GetFuncDeclPattern()
2082 for Str in PSL:
2083 FuncRecord = GetFuncContainsPE(Str[1], FL)
2084 if FuncRecord == None:
2085 continue
2086
2087 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
2088 PredInfo = SplitPredicateStr(Exp)
2089 if PredInfo[1] in ('==', '!=') and PredInfo[0][1] in ('TRUE', 'FALSE'):
2090 PredVarStr = PredInfo[0][0].strip()
2091 IsFuncCall = False
2092 SearchInCache = False
2093 # PredVarStr may contain '.' or '->'
2094 TmpStr = PredVarStr.replace('.', '').replace('->', '')
2095 if p.match(TmpStr):
2096 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
2097 SearchInCache = True
2098 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2099 if TmpStr.startswith(PredVarStr):
2100 IsFuncCall = True
2101
2102 if PredVarStr.strip() in IgnoredKeywordList:
2103 continue
2104 StarList = []
2105 PredVarList = GetCNameList(PredVarStr, StarList)
2106 # No variable found, maybe value first? like (0 == VarName)
2107 if len(PredVarList) == 0:
2108 continue
2109
2110 if SearchInCache:
2111 Type = FuncReturnTypeDict.get(PredVarStr)
2112 if Type != None:
2113 if Type.find('BOOLEAN') != -1:
2114 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2115 continue
2116
2117 if PredVarStr in FuncReturnTypeDict:
2118 continue
2119
2120 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)
2121 if SearchInCache:
2122 FuncReturnTypeDict[PredVarStr] = Type
2123 if Type == None:
2124 continue
2125 if Type.find('BOOLEAN') != -1:
2126 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2127
2128
2129 def CheckHeaderFileData(FullFileName):
2130 ErrorMsgList = []
2131
2132 FileID = GetTableID(FullFileName, ErrorMsgList)
2133 if FileID < 0:
2134 return ErrorMsgList
2135
2136 Db = GetDB()
2137 FileTable = 'Identifier' + str(FileID)
2138 SqlStatement = """ select ID, Modifier
2139 from %s
2140 where Model = %d
2141 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
2142 ResultSet = Db.TblFile.Exec(SqlStatement)
2143 for Result in ResultSet:
2144 if not Result[1].startswith('extern'):
2145 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Variable definition appears in header file', FileTable, Result[0])
2146
2147 SqlStatement = """ select ID
2148 from Function
2149 where BelongsToFile = %d
2150 """ % FileID
2151 ResultSet = Db.TblFile.Exec(SqlStatement)
2152 for Result in ResultSet:
2153 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Function definition appears in header file', 'Function', Result[0])
2154
2155 return ErrorMsgList
2156
2157 def CheckHeaderFileIfndef(FullFileName):
2158 ErrorMsgList = []
2159
2160 FileID = GetTableID(FullFileName, ErrorMsgList)
2161 if FileID < 0:
2162 return ErrorMsgList
2163
2164 Db = GetDB()
2165 FileTable = 'Identifier' + str(FileID)
2166 SqlStatement = """ select Value, StartLine
2167 from %s
2168 where Model = %d order by StartLine
2169 """ % (FileTable, DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF)
2170 ResultSet = Db.TblFile.Exec(SqlStatement)
2171 if len(ResultSet) == 0:
2172 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1, '', 'File', FileID)
2173 return ErrorMsgList
2174 for Result in ResultSet:
2175 SqlStatement = """ select Value, EndLine
2176 from %s
2177 where EndLine < %d
2178 """ % (FileTable, Result[1])
2179 ResultSet = Db.TblFile.Exec(SqlStatement)
2180 for Result in ResultSet:
2181 if not Result[0].startswith('/*') and not Result[0].startswith('//'):
2182 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2, '', 'File', FileID)
2183 break
2184
2185 SqlStatement = """ select Value
2186 from %s
2187 where StartLine > (select max(EndLine) from %s where Model = %d)
2188 """ % (FileTable, FileTable, DataClass.MODEL_IDENTIFIER_MACRO_ENDIF)
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_3, '', 'File', FileID)
2193 return ErrorMsgList
2194
2195 def CheckDoxygenCommand(FullFileName):
2196 ErrorMsgList = []
2197
2198 FileID = GetTableID(FullFileName, ErrorMsgList)
2199 if FileID < 0:
2200 return ErrorMsgList
2201
2202 Db = GetDB()
2203 FileTable = 'Identifier' + str(FileID)
2204 SqlStatement = """ select Value, ID
2205 from %s
2206 where Model = %d or Model = %d
2207 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)
2208 ResultSet = Db.TblFile.Exec(SqlStatement)
2209 DoxygenCommandList = ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval', 'return', 'sa', 'since', 'test', 'note', 'par']
2210 for Result in ResultSet:
2211 CommentStr = Result[0]
2212 CommentPartList = CommentStr.split()
2213 for Part in CommentPartList:
2214 if Part.upper() == 'BUGBUG':
2215 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Bug should be marked with doxygen tag @bug', FileTable, Result[1])
2216 if Part.upper() == 'TODO':
2217 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'ToDo should be marked with doxygen tag @todo', FileTable, Result[1])
2218 if Part.startswith('@'):
2219 if EccGlobalData.gException.IsException(ERROR_DOXYGEN_CHECK_COMMAND, Part):
2220 continue
2221 if Part.lstrip('@').isalpha():
2222 if Part.lstrip('@') not in DoxygenCommandList:
2223 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2224 else:
2225 Index = Part.find('[')
2226 if Index == -1:
2227 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2228 RealCmd = Part[1:Index]
2229 if RealCmd not in DoxygenCommandList:
2230 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2231
2232
2233 def CheckDoxygenTripleForwardSlash(FullFileName):
2234 ErrorMsgList = []
2235
2236 FileID = GetTableID(FullFileName, ErrorMsgList)
2237 if FileID < 0:
2238 return ErrorMsgList
2239
2240 Db = GetDB()
2241
2242 SqlStatement = """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2243 from Function
2244 where BelongsToFile = %d
2245 """ % (FileID)
2246 ResultSet = Db.TblFile.Exec(SqlStatement)
2247 if len(ResultSet) == 0:
2248 return
2249
2250 FuncDefSet = []
2251 for Result in ResultSet:
2252 FuncDefSet.append(Result)
2253
2254
2255 FileTable = 'Identifier' + str(FileID)
2256 SqlStatement = """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2257 from %s
2258 where Model = %d
2259
2260 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2261 ResultSet = Db.TblFile.Exec(SqlStatement)
2262 CommentSet = []
2263 try:
2264 for Result in ResultSet:
2265 CommentSet.append(Result)
2266 except:
2267 print 'Unrecognized chars in comment of file %s', FullFileName
2268
2269
2270 for Result in CommentSet:
2271 CommentStr = Result[0]
2272 StartLine = Result[2]
2273 StartColumn = Result[3]
2274 EndLine = Result[4]
2275 EndColumn = Result[5]
2276 if not CommentStr.startswith('///<'):
2277 continue
2278
2279 Found = False
2280 for FuncDef in FuncDefSet:
2281 if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:
2282 Found = True
2283 break
2284 if StartLine > FuncDef[1] and EndLine < FuncDef[3]:
2285 Found = True
2286 break
2287 if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine < FuncDef[3]:
2288 Found = True
2289 break
2290 if StartLine > FuncDef[1] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:
2291 Found = True
2292 break
2293 if Found:
2294 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT, '', FileTable, Result[1])
2295
2296
2297 def CheckFileHeaderDoxygenComments(FullFileName):
2298 ErrorMsgList = []
2299
2300 FileID = GetTableID(FullFileName, ErrorMsgList)
2301 if FileID < 0:
2302 return ErrorMsgList
2303
2304 Db = GetDB()
2305 FileTable = 'Identifier' + str(FileID)
2306 SqlStatement = """ select Value, ID
2307 from %s
2308 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2309 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2310 ResultSet = Db.TblFile.Exec(SqlStatement)
2311 if len(ResultSet) == 0:
2312 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'No File License header appear at the very beginning of file.', 'File', FileID)
2313 return ErrorMsgList
2314
2315 NoHeaderCommentStartFlag = True
2316 NoHeaderCommentEndFlag = True
2317 NoHeaderCommentPeriodFlag = True
2318 NoCopyrightFlag = True
2319 NoLicenseFlag = True
2320 NoRevReferFlag = True
2321 NextLineIndex = 0
2322 for Result in ResultSet:
2323 FileStartFlag = False
2324 CommentStrList = []
2325 CommentStr = Result[0].strip()
2326 CommentStrListTemp = CommentStr.split('\n')
2327 if (len(CommentStrListTemp) <= 1):
2328 # For Mac
2329 CommentStrListTemp = CommentStr.split('\r')
2330 # Skip the content before the file header
2331 for CommentLine in CommentStrListTemp:
2332 if CommentLine.strip().startswith('/** @file'):
2333 FileStartFlag = True
2334 if FileStartFlag == True:
2335 CommentStrList.append(CommentLine)
2336
2337 ID = Result[1]
2338 Index = 0
2339 if CommentStrList and CommentStrList[0].strip().startswith('/** @file'):
2340 NoHeaderCommentStartFlag = False
2341 else:
2342 continue
2343 if CommentStrList and CommentStrList[-1].strip().endswith('**/'):
2344 NoHeaderCommentEndFlag = False
2345 else:
2346 continue
2347
2348 for CommentLine in CommentStrList:
2349 Index = Index + 1
2350 NextLineIndex = Index
2351 if CommentLine.startswith('/** @file'):
2352 continue
2353 if CommentLine.startswith('**/'):
2354 break
2355 # Check whether C File header Comment content start with two spaces.
2356 if EccGlobalData.gConfig.HeaderCheckCFileCommentStartSpacesNum == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
2357 if CommentLine.startswith('/** @file') == False and CommentLine.startswith('**/') == False and CommentLine.strip() and CommentLine.startswith(' ') == False:
2358 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment content should start with two spaces at each line', FileTable, ID)
2359
2360 CommentLine = CommentLine.strip()
2361 if CommentLine.startswith('Copyright'):
2362 NoCopyrightFlag = False
2363 if CommentLine.find('All rights reserved') == -1:
2364 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, '""All rights reserved"" announcement should be following the ""Copyright"" at the same line', FileTable, ID)
2365 if CommentLine.endswith('<BR>') == -1:
2366 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'The ""<BR>"" at the end of the Copyright line is required', FileTable, ID)
2367 if NextLineIndex < len(CommentStrList) and CommentStrList[NextLineIndex].strip().startswith('Copyright') == False and CommentStrList[NextLineIndex].strip():
2368 NoLicenseFlag = False
2369 if CommentLine.startswith('@par Revision Reference:'):
2370 NoRevReferFlag = False
2371 RefListFlag = False
2372 for RefLine in CommentStrList[NextLineIndex:]:
2373 if RefLine.strip() and (NextLineIndex + 1) < len(CommentStrList) and CommentStrList[NextLineIndex+1].strip() and CommentStrList[NextLineIndex+1].strip().startswith('**/') == False:
2374 RefListFlag = True
2375 if RefLine.strip() == False or RefLine.strip().startswith('**/'):
2376 RefListFlag = False
2377 break
2378 # Check whether C File header Comment's each reference at list should begin with a bullet character.
2379 if EccGlobalData.gConfig.HeaderCheckCFileCommentReferenceFormat == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
2380 if RefListFlag == True:
2381 if RefLine.strip() and RefLine.strip().startswith('**/') == False and RefLine.startswith(' -') == False:
2382 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'Each reference on a separate line should begin with a bullet character ""-"" ', FileTable, ID)
2383
2384 if NoHeaderCommentStartFlag:
2385 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER, 'File header comment should begin with ""/** @file""', FileTable, ID)
2386 return
2387 if NoHeaderCommentEndFlag:
2388 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should end with ""**/""', FileTable, ID)
2389 return
2390 if NoCopyrightFlag:
2391 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment missing the ""Copyright""', FileTable, ID)
2392 #Check whether C File header Comment have the License immediately after the ""Copyright"" line.
2393 if EccGlobalData.gConfig.HeaderCheckCFileCommentLicenseFormat == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
2394 if NoLicenseFlag:
2395 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should have the License immediately after the ""Copyright"" line', FileTable, ID)
2396
2397 def CheckFuncHeaderDoxygenComments(FullFileName):
2398 ErrorMsgList = []
2399
2400 FileID = GetTableID(FullFileName, ErrorMsgList)
2401 if FileID < 0:
2402 return ErrorMsgList
2403
2404 Db = GetDB()
2405 FileTable = 'Identifier' + str(FileID)
2406 SqlStatement = """ select Value, StartLine, EndLine, ID
2407 from %s
2408 where Model = %d
2409 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2410
2411 ResultSet = Db.TblFile.Exec(SqlStatement)
2412 CommentSet = []
2413 try:
2414 for Result in ResultSet:
2415 CommentSet.append(Result)
2416 except:
2417 print 'Unrecognized chars in comment of file %s', FullFileName
2418
2419 # Func Decl check
2420 SqlStatement = """ select Modifier, Name, StartLine, ID, Value
2421 from %s
2422 where Model = %d
2423 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
2424 ResultSet = Db.TblFile.Exec(SqlStatement)
2425 for Result in ResultSet:
2426 FuncName = Result[4]
2427 FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)
2428 if FunctionHeaderComment:
2429 CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)
2430 else:
2431 if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):
2432 continue
2433 ErrorMsgList.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result[2], Result[1]))
2434 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), FileTable, Result[3])
2435
2436 # Func Def check
2437 SqlStatement = """ select Value, StartLine, EndLine, ID
2438 from %s
2439 where Model = %d
2440 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)
2441
2442 ResultSet = Db.TblFile.Exec(SqlStatement)
2443 CommentSet = []
2444 try:
2445 for Result in ResultSet:
2446 CommentSet.append(Result)
2447 except:
2448 print 'Unrecognized chars in comment of file %s', FullFileName
2449
2450 SqlStatement = """ select Modifier, Header, StartLine, ID, Name
2451 from Function
2452 where BelongsToFile = %d
2453 """ % (FileID)
2454 ResultSet = Db.TblFile.Exec(SqlStatement)
2455 for Result in ResultSet:
2456 FuncName = Result[4]
2457 FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)
2458 if FunctionHeaderComment:
2459 CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)
2460 else:
2461 if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):
2462 continue
2463 ErrorMsgList.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result[2], Result[1]))
2464 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), 'Function', Result[3])
2465 return ErrorMsgList
2466
2467 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName, FuncStartLine, CommentSet):
2468
2469 for Comment in CommentSet:
2470 if Comment[2] == FuncStartLine - 1:
2471 return Comment
2472 return None
2473
2474 def GetDoxygenStrFromComment(Str):
2475 DoxygenStrList = []
2476 ParamTagList = Str.split('@param')
2477 if len(ParamTagList) > 1:
2478 i = 1
2479 while i < len(ParamTagList):
2480 DoxygenStrList.append('@param' + ParamTagList[i])
2481 i += 1
2482
2483 Str = ParamTagList[0]
2484
2485 RetvalTagList = ParamTagList[-1].split('@retval')
2486 if len(RetvalTagList) > 1:
2487 if len(ParamTagList) > 1:
2488 DoxygenStrList[-1] = '@param' + RetvalTagList[0]
2489 i = 1
2490 while i < len(RetvalTagList):
2491 DoxygenStrList.append('@retval' + RetvalTagList[i])
2492 i += 1
2493
2494 ReturnTagList = RetvalTagList[-1].split('@return')
2495 if len(ReturnTagList) > 1:
2496 if len(RetvalTagList) > 1:
2497 DoxygenStrList[-1] = '@retval' + ReturnTagList[0]
2498 elif len(ParamTagList) > 1:
2499 DoxygenStrList[-1] = '@param' + ReturnTagList[0]
2500 i = 1
2501 while i < len(ReturnTagList):
2502 DoxygenStrList.append('@return' + ReturnTagList[i])
2503 i += 1
2504
2505 if len(DoxygenStrList) > 0:
2506 DoxygenStrList[-1] = DoxygenStrList[-1].rstrip('--*/')
2507
2508 return DoxygenStrList
2509
2510 def CheckGeneralDoxygenCommentLayout(Str, StartLine, ErrorMsgList, CommentId= -1, TableName=''):
2511 #/** --*/ @retval after @param
2512 if not Str.startswith('/**'):
2513 ErrorMsgList.append('Line %d : Comment does NOT have prefix /** ' % StartLine)
2514 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have prefix /** ', TableName, CommentId)
2515 if not Str.endswith('**/'):
2516 ErrorMsgList.append('Line %d : Comment does NOT have tail **/ ' % StartLine)
2517 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have tail **/ ', TableName, CommentId)
2518 FirstRetvalIndex = Str.find('@retval')
2519 LastParamIndex = Str.rfind('@param')
2520 if (FirstRetvalIndex > 0) and (LastParamIndex > 0) and (FirstRetvalIndex < LastParamIndex):
2521 ErrorMsgList.append('Line %d : @retval appear before @param ' % StartLine)
2522 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, @retval appear before @param ', TableName, CommentId)
2523
2524 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier, FuncHeader, FuncStartLine, CommentStr, CommentStartLine, ErrorMsgList, CommentId= -1, TableName=''):
2525
2526 ParamList = GetParamList(FuncHeader)
2527 CheckGeneralDoxygenCommentLayout(CommentStr, CommentStartLine, ErrorMsgList, CommentId, TableName)
2528 DescriptionStr = CommentStr
2529 DoxygenStrList = GetDoxygenStrFromComment(DescriptionStr)
2530 if DescriptionStr.find('.') == -1:
2531 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period \'.\'', TableName, CommentId)
2532 DoxygenTagNumber = len(DoxygenStrList)
2533 ParamNumber = len(ParamList)
2534 for Param in ParamList:
2535 if Param.Name.upper() == 'VOID' and ParamNumber == 1:
2536 ParamNumber -= 1
2537 Index = 0
2538 if ParamNumber > 0 and DoxygenTagNumber > 0:
2539 while Index < ParamNumber and Index < DoxygenTagNumber:
2540 ParamModifier = ParamList[Index].Modifier
2541 ParamName = ParamList[Index].Name.strip()
2542 Tag = DoxygenStrList[Index].strip(' ')
2543 if (not Tag[-1] == ('\n')) and (not Tag[-1] == ('\r')):
2544 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))
2545 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'in Comment, <%s> does NOT end with new line ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)
2546 TagPartList = Tag.split()
2547 if len(TagPartList) < 2:
2548 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))
2549 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)
2550 Index += 1
2551 continue
2552 LBPos = Tag.find('[')
2553 RBPos = Tag.find(']')
2554 ParamToLBContent = Tag[len('@param'):LBPos].strip()
2555 if LBPos > 0 and len(ParamToLBContent) == 0 and RBPos > LBPos:
2556 InOutStr = ''
2557 ModifierPartList = ParamModifier.split()
2558 for Part in ModifierPartList:
2559 if Part.strip() == 'IN':
2560 InOutStr += 'in'
2561 if Part.strip() == 'OUT':
2562 if InOutStr != '':
2563 InOutStr += ', out'
2564 else:
2565 InOutStr = 'out'
2566
2567 if InOutStr != '':
2568 if Tag.find('[' + InOutStr + ']') == -1:
2569 if InOutStr != 'in, out':
2570 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'))
2571 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT have %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'), TableName, CommentId)
2572 else:
2573 if Tag.find('[in,out]') == -1:
2574 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'))
2575 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT have %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'), TableName, CommentId)
2576
2577
2578 if Tag.find(ParamName) == -1 and ParamName != 'VOID' and ParamName != 'void':
2579 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), ParamName))
2580 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)
2581 Index += 1
2582
2583 if Index < ParamNumber:
2584 ErrorMsgList.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine)
2585 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of doxygen tags in comment less than number of function parameters ', TableName, CommentId)
2586 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2587 if (FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1:
2588
2589 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2590 if Index < DoxygenTagNumber - 1 or (Index < DoxygenTagNumber and DoxygenStrList[Index].startswith('@retval')):
2591 ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)
2592 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need no doxygen tags in comment ', TableName, CommentId)
2593 else:
2594 if Index < DoxygenTagNumber and not DoxygenStrList[Index].startswith('@retval') and not DoxygenStrList[Index].startswith('@return'):
2595 ErrorMsgList.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine)
2596 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName, CommentId)
2597 else:
2598 if ParamNumber == 0 and DoxygenTagNumber != 0 and ((FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1):
2599 ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)
2600 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need NO doxygen tags in comment ', TableName, CommentId)
2601 if ParamNumber != 0 and DoxygenTagNumber == 0:
2602 ErrorMsgList.append('Line %d : No doxygen tags in comment' % CommentStartLine)
2603 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'No doxygen tags in comment ', TableName, CommentId)
2604
2605 if __name__ == '__main__':
2606
2607 # EdkLogger.Initialize()
2608 # EdkLogger.SetLevel(EdkLogger.QUIET)
2609 # CollectSourceCodeDataIntoDB(sys.argv[1])
2610 try:
2611 test_file = sys.argv[1]
2612 except IndexError, v:
2613 print "Usage: %s filename" % sys.argv[0]
2614 sys.exit(1)
2615 MsgList = CheckFuncHeaderDoxygenComments(test_file)
2616 for Msg in MsgList:
2617 print Msg
2618 print 'Done!'