Sync BaseTools Branch (version r2362) to EDKII main trunk.
[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 - 2010, 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 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 collector = None
518 FullName = os.path.normpath(os.path.join(dirpath, f))
519 model = DataClass.MODEL_FILE_OTHERS
520 if os.path.splitext(f)[1] in ('.h', '.c'):
521 EdkLogger.info("Parsing " + FullName)
522 model = f.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H
523 collector = CodeFragmentCollector.CodeFragmentCollector(FullName)
524 try:
525 collector.ParseFile()
526 except UnicodeError:
527 ParseErrorFileList.append(FullName)
528 collector.CleanFileProfileBuffer()
529 collector.ParseFileWithClearedPPDirective()
530 # collector.PrintFragments()
531 BaseName = os.path.basename(f)
532 DirName = os.path.dirname(FullName)
533 Ext = os.path.splitext(f)[1].lstrip('.')
534 ModifiedTime = os.path.getmtime(FullName)
535 FileObj = DataClass.FileClass(-1, BaseName, Ext, DirName, FullName, model, ModifiedTime, GetFunctionList(), GetIdentifierList(), [])
536 FileObjList.append(FileObj)
537 if collector:
538 collector.CleanFileProfileBuffer()
539
540 if len(ParseErrorFileList) > 0:
541 EdkLogger.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList))
542
543 Db = GetDB()
544 for file in FileObjList:
545 if file.ExtName.upper() not in ['INF', 'DEC', 'DSC', 'FDF']:
546 Db.InsertOneFile(file)
547
548 Db.UpdateIdentifierBelongsToFunction()
549
550 def GetTableID(FullFileName, ErrorMsgList=None):
551 if ErrorMsgList == None:
552 ErrorMsgList = []
553
554 Db = GetDB()
555 SqlStatement = """ select ID
556 from File
557 where FullPath like '%s'
558 """ % FullFileName
559 ResultSet = Db.TblFile.Exec(SqlStatement)
560
561 FileID = -1
562 for Result in ResultSet:
563 if FileID != -1:
564 ErrorMsgList.append('Duplicate file ID found in DB for file %s' % FullFileName)
565 return - 2
566 FileID = Result[0]
567 if FileID == -1:
568 ErrorMsgList.append('NO file ID found in DB for file %s' % FullFileName)
569 return - 1
570 return FileID
571
572 def GetIncludeFileList(FullFileName):
573 if os.path.splitext(FullFileName)[1].upper() not in ('.H'):
574 return []
575 IFList = IncludeFileListDict.get(FullFileName)
576 if IFList != None:
577 return IFList
578
579 FileID = GetTableID(FullFileName)
580 if FileID < 0:
581 return []
582
583 Db = GetDB()
584 FileTable = 'Identifier' + str(FileID)
585 SqlStatement = """ select Value
586 from %s
587 where Model = %d
588 """ % (FileTable, DataClass.MODEL_IDENTIFIER_INCLUDE)
589 ResultSet = Db.TblFile.Exec(SqlStatement)
590 IncludeFileListDict[FullFileName] = ResultSet
591 return ResultSet
592
593 def GetFullPathOfIncludeFile(Str, IncludePathList):
594 for IncludePath in IncludePathList:
595 FullPath = os.path.join(IncludePath, Str)
596 FullPath = os.path.normpath(FullPath)
597 if os.path.exists(FullPath):
598 return FullPath
599 return None
600
601 def GetAllIncludeFiles(FullFileName):
602 if AllIncludeFileListDict.get(FullFileName) != None:
603 return AllIncludeFileListDict.get(FullFileName)
604
605 FileDirName = os.path.dirname(FullFileName)
606 IncludePathList = IncludePathListDict.get(FileDirName)
607 if IncludePathList == None:
608 IncludePathList = MetaDataParser.GetIncludeListOfFile(EccGlobalData.gWorkspace, FullFileName, GetDB())
609 if FileDirName not in IncludePathList:
610 IncludePathList.insert(0, FileDirName)
611 IncludePathListDict[FileDirName] = IncludePathList
612 IncludeFileQueue = []
613 for IncludeFile in GetIncludeFileList(FullFileName):
614 FileName = IncludeFile[0].lstrip('#').strip()
615 FileName = FileName.lstrip('include').strip()
616 FileName = FileName.strip('\"')
617 FileName = FileName.lstrip('<').rstrip('>').strip()
618 FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList)
619 if FullPath != None:
620 IncludeFileQueue.append(FullPath)
621
622 i = 0
623 while i < len(IncludeFileQueue):
624 for IncludeFile in GetIncludeFileList(IncludeFileQueue[i]):
625 FileName = IncludeFile[0].lstrip('#').strip()
626 FileName = FileName.lstrip('include').strip()
627 FileName = FileName.strip('\"')
628 FileName = FileName.lstrip('<').rstrip('>').strip()
629 FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList)
630 if FullPath != None and FullPath not in IncludeFileQueue:
631 IncludeFileQueue.insert(i + 1, FullPath)
632 i += 1
633
634 AllIncludeFileListDict[FullFileName] = IncludeFileQueue
635 return IncludeFileQueue
636
637 def GetPredicateListFromPredicateExpStr(PES):
638
639 PredicateList = []
640 i = 0
641 PredicateBegin = 0
642 #PredicateEnd = 0
643 LogicOpPos = -1
644 p = GetFuncDeclPattern()
645 while i < len(PES) - 1:
646 if (PES[i].isalnum() or PES[i] == '_' or PES[i] == '*') and LogicOpPos > PredicateBegin:
647 PredicateBegin = i
648 if (PES[i] == '&' and PES[i + 1] == '&') or (PES[i] == '|' and PES[i + 1] == '|'):
649 LogicOpPos = i
650 Exp = PES[PredicateBegin:i].strip()
651 # Exp may contain '.' or '->'
652 TmpExp = Exp.replace('.', '').replace('->', '')
653 if p.match(TmpExp):
654 PredicateList.append(Exp)
655 else:
656 PredicateList.append(Exp.rstrip(';').rstrip(')').strip())
657 i += 1
658
659 if PredicateBegin > LogicOpPos:
660 while PredicateBegin < len(PES):
661 if PES[PredicateBegin].isalnum() or PES[PredicateBegin] == '_' or PES[PredicateBegin] == '*':
662 break
663 PredicateBegin += 1
664 Exp = PES[PredicateBegin:len(PES)].strip()
665 # Exp may contain '.' or '->'
666 TmpExp = Exp.replace('.', '').replace('->', '')
667 if p.match(TmpExp):
668 PredicateList.append(Exp)
669 else:
670 PredicateList.append(Exp.rstrip(';').rstrip(')').strip())
671 return PredicateList
672
673 def GetCNameList(Lvalue, StarList=[]):
674 Lvalue += ' '
675 i = 0
676 SearchBegin = 0
677 VarStart = -1
678 VarEnd = -1
679 VarList = []
680
681 while SearchBegin < len(Lvalue):
682 while i < len(Lvalue):
683 if Lvalue[i].isalnum() or Lvalue[i] == '_':
684 if VarStart == -1:
685 VarStart = i
686 VarEnd = i
687 i += 1
688 elif VarEnd != -1:
689 VarList.append(Lvalue[VarStart:VarEnd + 1])
690 i += 1
691 break
692 else:
693 if VarStart == -1 and Lvalue[i] == '*':
694 StarList.append('*')
695 i += 1
696 if VarEnd == -1:
697 break
698
699
700 DotIndex = Lvalue[VarEnd:].find('.')
701 ArrowIndex = Lvalue[VarEnd:].find('->')
702 if DotIndex == -1 and ArrowIndex == -1:
703 break
704 elif DotIndex == -1 and ArrowIndex != -1:
705 SearchBegin = VarEnd + ArrowIndex
706 elif ArrowIndex == -1 and DotIndex != -1:
707 SearchBegin = VarEnd + DotIndex
708 else:
709 SearchBegin = VarEnd + ((DotIndex < ArrowIndex) and DotIndex or ArrowIndex)
710
711 i = SearchBegin
712 VarStart = -1
713 VarEnd = -1
714
715 return VarList
716
717 def SplitPredicateByOp(Str, Op, IsFuncCalling=False):
718
719 Name = Str.strip()
720 Value = None
721
722 if IsFuncCalling:
723 Index = 0
724 LBFound = False
725 UnmatchedLBCount = 0
726 while Index < len(Str):
727 while not LBFound and Str[Index] != '_' and not Str[Index].isalnum():
728 Index += 1
729
730 while not LBFound and (Str[Index].isalnum() or Str[Index] == '_'):
731 Index += 1
732 # maybe type-cast at the begining, skip it.
733 RemainingStr = Str[Index:].lstrip()
734 if RemainingStr.startswith(')') and not LBFound:
735 Index += 1
736 continue
737
738 if RemainingStr.startswith('(') and not LBFound:
739 LBFound = True
740
741 if Str[Index] == '(':
742 UnmatchedLBCount += 1
743 Index += 1
744 continue
745
746 if Str[Index] == ')':
747 UnmatchedLBCount -= 1
748 Index += 1
749 if UnmatchedLBCount == 0:
750 break
751 continue
752
753 Index += 1
754
755 if UnmatchedLBCount > 0:
756 return [Name]
757
758 IndexInRemainingStr = Str[Index:].find(Op)
759 if IndexInRemainingStr == -1:
760 return [Name]
761
762 Name = Str[0:Index + IndexInRemainingStr].strip()
763 Value = Str[Index + IndexInRemainingStr + len(Op):].strip().strip(')')
764 return [Name, Value]
765
766 TmpStr = Str.rstrip(';').rstrip(')')
767 while True:
768 Index = TmpStr.rfind(Op)
769 if Index == -1:
770 return [Name]
771
772 if Str[Index - 1].isalnum() or Str[Index - 1].isspace() or Str[Index - 1] == ')' or Str[Index - 1] == ']':
773 Name = Str[0:Index].strip()
774 Value = Str[Index + len(Op):].strip()
775 return [Name, Value]
776
777 TmpStr = Str[0:Index - 1]
778
779 def SplitPredicateStr(Str):
780
781 Str = Str.lstrip('(')
782 IsFuncCalling = False
783 p = GetFuncDeclPattern()
784 TmpStr = Str.replace('.', '').replace('->', '')
785 if p.match(TmpStr):
786 IsFuncCalling = True
787
788 PredPartList = SplitPredicateByOp(Str, '==', IsFuncCalling)
789 if len(PredPartList) > 1:
790 return [PredPartList, '==']
791
792 PredPartList = SplitPredicateByOp(Str, '!=', IsFuncCalling)
793 if len(PredPartList) > 1:
794 return [PredPartList, '!=']
795
796 PredPartList = SplitPredicateByOp(Str, '>=', IsFuncCalling)
797 if len(PredPartList) > 1:
798 return [PredPartList, '>=']
799
800 PredPartList = SplitPredicateByOp(Str, '<=', IsFuncCalling)
801 if len(PredPartList) > 1:
802 return [PredPartList, '<=']
803
804 PredPartList = SplitPredicateByOp(Str, '>', IsFuncCalling)
805 if len(PredPartList) > 1:
806 return [PredPartList, '>']
807
808 PredPartList = SplitPredicateByOp(Str, '<', IsFuncCalling)
809 if len(PredPartList) > 1:
810 return [PredPartList, '<']
811
812 return [[Str, None], None]
813
814 def GetFuncContainsPE(ExpLine, ResultSet):
815 for Result in ResultSet:
816 if Result[0] < ExpLine and Result[1] > ExpLine:
817 return Result
818 return None
819
820 def PatternInModifier(Modifier, SubStr):
821 PartList = Modifier.split()
822 for Part in PartList:
823 if Part == SubStr:
824 return True
825 return False
826
827 def GetDataTypeFromModifier(ModifierStr):
828 MList = ModifierStr.split()
829 ReturnType = ''
830 for M in MList:
831 if M in EccGlobalData.gConfig.ModifierList:
832 continue
833 # remove array sufix
834 if M.startswith('[') or M.endswith(']'):
835 continue
836 ReturnType += M + ' '
837
838 ReturnType = ReturnType.strip()
839 if len(ReturnType) == 0:
840 ReturnType = 'VOID'
841 return ReturnType
842
843 def DiffModifier(Str1, Str2):
844 PartList1 = Str1.split()
845 PartList2 = Str2.split()
846 if PartList1 == PartList2:
847 return False
848 else:
849 return True
850
851 def GetTypedefDict(FullFileName):
852
853 Dict = ComplexTypeDict.get(FullFileName)
854 if Dict != None:
855 return Dict
856
857 FileID = GetTableID(FullFileName)
858 FileTable = 'Identifier' + str(FileID)
859 Db = GetDB()
860 SqlStatement = """ select Modifier, Name, Value, ID
861 from %s
862 where Model = %d
863 """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
864 ResultSet = Db.TblFile.Exec(SqlStatement)
865
866 Dict = {}
867 for Result in ResultSet:
868 if len(Result[0]) == 0:
869 Dict[Result[1]] = Result[2]
870
871 IncludeFileList = GetAllIncludeFiles(FullFileName)
872 for F in IncludeFileList:
873 FileID = GetTableID(F)
874 if FileID < 0:
875 continue
876
877 FileTable = 'Identifier' + str(FileID)
878 SqlStatement = """ select Modifier, Name, Value, ID
879 from %s
880 where Model = %d
881 """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
882 ResultSet = Db.TblFile.Exec(SqlStatement)
883
884 for Result in ResultSet:
885 if not Result[2].startswith('FP ('):
886 Dict[Result[1]] = Result[2]
887 else:
888 if len(Result[0]) == 0:
889 Dict[Result[1]] = 'VOID'
890 else:
891 Dict[Result[1]] = GetDataTypeFromModifier(Result[0])
892
893 ComplexTypeDict[FullFileName] = Dict
894 return Dict
895
896 def GetSUDict(FullFileName):
897
898 Dict = SUDict.get(FullFileName)
899 if Dict != None:
900 return Dict
901
902 FileID = GetTableID(FullFileName)
903 FileTable = 'Identifier' + str(FileID)
904 Db = GetDB()
905 SqlStatement = """ select Name, Value, ID
906 from %s
907 where Model = %d or Model = %d
908 """ % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION)
909 ResultSet = Db.TblFile.Exec(SqlStatement)
910
911 Dict = {}
912 for Result in ResultSet:
913 if len(Result[1]) > 0:
914 Dict[Result[0]] = Result[1]
915
916 IncludeFileList = GetAllIncludeFiles(FullFileName)
917 for F in IncludeFileList:
918 FileID = GetTableID(F)
919 if FileID < 0:
920 continue
921
922 FileTable = 'Identifier' + str(FileID)
923 SqlStatement = """ select Name, Value, ID
924 from %s
925 where Model = %d or Model = %d
926 """ % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION)
927 ResultSet = Db.TblFile.Exec(SqlStatement)
928
929 for Result in ResultSet:
930 if len(Result[1]) > 0:
931 Dict[Result[0]] = Result[1]
932
933 SUDict[FullFileName] = Dict
934 return Dict
935
936 def StripComments(Str):
937 Str += ' '
938 ListFromStr = list(Str)
939
940 InComment = False
941 DoubleSlashComment = False
942 Index = 0
943 while Index < len(ListFromStr):
944 # meet new line, then no longer in a comment for //
945 if ListFromStr[Index] == '\n':
946 if InComment and DoubleSlashComment:
947 InComment = False
948 DoubleSlashComment = False
949 Index += 1
950 # check for */ comment end
951 elif InComment and not DoubleSlashComment and ListFromStr[Index] == '*' and ListFromStr[Index + 1] == '/':
952 ListFromStr[Index] = ' '
953 Index += 1
954 ListFromStr[Index] = ' '
955 Index += 1
956 InComment = False
957 # set comments to spaces
958 elif InComment:
959 ListFromStr[Index] = ' '
960 Index += 1
961 # check for // comment
962 elif ListFromStr[Index] == '/' and ListFromStr[Index + 1] == '/' and ListFromStr[Index + 2] != '\n':
963 InComment = True
964 DoubleSlashComment = True
965
966 # check for /* comment start
967 elif ListFromStr[Index] == '/' and ListFromStr[Index + 1] == '*':
968 ListFromStr[Index] = ' '
969 Index += 1
970 ListFromStr[Index] = ' '
971 Index += 1
972 InComment = True
973 else:
974 Index += 1
975
976 # restore from List to String
977 Str = "".join(ListFromStr)
978 Str = Str.rstrip(' ')
979
980 return Str
981
982 def GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict):
983 Value = TypedefDict.get(Type)
984 if Value == None:
985 Value = SUDict.get(Type)
986 if Value == None:
987 return None
988
989 LBPos = Value.find('{')
990 while LBPos == -1:
991 FTList = Value.split()
992 for FT in FTList:
993 if FT not in ('struct', 'union'):
994 Value = TypedefDict.get(FT)
995 if Value == None:
996 Value = SUDict.get(FT)
997 break
998
999 if Value == None:
1000 return None
1001
1002 LBPos = Value.find('{')
1003
1004 # RBPos = Value.find('}')
1005 Fields = Value[LBPos + 1:]
1006 Fields = StripComments(Fields)
1007 FieldsList = Fields.split(';')
1008 for Field in FieldsList:
1009 Field = Field.strip()
1010 Index = Field.rfind(FieldName)
1011 if Index < 1:
1012 continue
1013 if not Field[Index - 1].isalnum():
1014 if Index + len(FieldName) == len(Field):
1015 Type = GetDataTypeFromModifier(Field[0:Index])
1016 return Type.strip()
1017 else:
1018 # For the condition that the field in struct is an array with [] sufixes...
1019 if not Field[Index + len(FieldName)].isalnum():
1020 Type = GetDataTypeFromModifier(Field[0:Index])
1021 return Type.strip()
1022
1023 return None
1024
1025 def GetRealType(Type, TypedefDict, TargetType=None):
1026 if TargetType != None and Type == TargetType:
1027 return Type
1028 while TypedefDict.get(Type):
1029 Type = TypedefDict.get(Type)
1030 if TargetType != None and Type == TargetType:
1031 return Type
1032 return Type
1033
1034 def GetTypeInfo(RefList, Modifier, FullFileName, TargetType=None):
1035 TypedefDict = GetTypedefDict(FullFileName)
1036 SUDict = GetSUDict(FullFileName)
1037 Type = GetDataTypeFromModifier(Modifier).replace('*', '').strip()
1038
1039 Type = Type.split()[-1]
1040 Index = 0
1041 while Index < len(RefList):
1042 FieldName = RefList[Index]
1043 FromType = GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict)
1044 if FromType == None:
1045 return None
1046 # we want to determine the exact type.
1047 if TargetType != None:
1048 Type = FromType.split()[0]
1049 # we only want to check if it is a pointer
1050 else:
1051 Type = FromType
1052 if Type.find('*') != -1 and Index == len(RefList) - 1:
1053 return Type
1054 Type = FromType.split()[0]
1055
1056 Index += 1
1057
1058 Type = GetRealType(Type, TypedefDict, TargetType)
1059
1060 return Type
1061
1062 def GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall=False, TargetType=None, StarList=None):
1063
1064 PredVar = PredVarList[0]
1065 FileID = GetTableID(FullFileName)
1066
1067 Db = GetDB()
1068 FileTable = 'Identifier' + str(FileID)
1069 # search variable in include files
1070
1071 # it is a function call, search function declarations and definitions
1072 if IsFuncCall:
1073 SqlStatement = """ select Modifier, ID
1074 from %s
1075 where Model = %d and Value = \'%s\'
1076 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar)
1077 ResultSet = Db.TblFile.Exec(SqlStatement)
1078
1079 for Result in ResultSet:
1080 Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1081 TypedefDict = GetTypedefDict(FullFileName)
1082 Type = GetRealType(Type, TypedefDict, TargetType)
1083 return Type
1084
1085 IncludeFileList = GetAllIncludeFiles(FullFileName)
1086 for F in IncludeFileList:
1087 FileID = GetTableID(F)
1088 if FileID < 0:
1089 continue
1090
1091 FileTable = 'Identifier' + str(FileID)
1092 SqlStatement = """ select Modifier, ID
1093 from %s
1094 where Model = %d and Value = \'%s\'
1095 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar)
1096 ResultSet = Db.TblFile.Exec(SqlStatement)
1097
1098 for Result in ResultSet:
1099 Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1100 TypedefDict = GetTypedefDict(FullFileName)
1101 Type = GetRealType(Type, TypedefDict, TargetType)
1102 return Type
1103
1104 FileID = GetTableID(FullFileName)
1105 SqlStatement = """ select Modifier, ID
1106 from Function
1107 where BelongsToFile = %d and Name = \'%s\'
1108 """ % (FileID, PredVar)
1109 ResultSet = Db.TblFile.Exec(SqlStatement)
1110
1111 for Result in ResultSet:
1112 Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1113 TypedefDict = GetTypedefDict(FullFileName)
1114 Type = GetRealType(Type, TypedefDict, TargetType)
1115 return Type
1116
1117 for F in IncludeFileList:
1118 FileID = GetTableID(F)
1119 if FileID < 0:
1120 continue
1121
1122 FileTable = 'Identifier' + str(FileID)
1123 SqlStatement = """ select Modifier, ID
1124 from Function
1125 where BelongsToFile = %d and Name = \'%s\'
1126 """ % (FileID, PredVar)
1127 ResultSet = Db.TblFile.Exec(SqlStatement)
1128
1129 for Result in ResultSet:
1130 Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1131 TypedefDict = GetTypedefDict(FullFileName)
1132 Type = GetRealType(Type, TypedefDict, TargetType)
1133 return Type
1134
1135 return None
1136
1137 # really variable, search local variable first
1138 SqlStatement = """ select Modifier, ID
1139 from %s
1140 where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d
1141 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar, FuncRecord[0], FuncRecord[1])
1142 ResultSet = Db.TblFile.Exec(SqlStatement)
1143 VarFound = False
1144 for Result in ResultSet:
1145 if len(PredVarList) > 1:
1146 Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)
1147 return Type
1148 else:
1149 # Type = GetDataTypeFromModifier(Result[0]).split()[-1]
1150 TypeList = GetDataTypeFromModifier(Result[0]).split()
1151 Type = TypeList[-1]
1152 if len(TypeList) > 1 and StarList != None:
1153 for Star in StarList:
1154 Type = Type.strip()
1155 Type = Type.rstrip(Star)
1156 # Get real type after de-reference pointers.
1157 if len(Type.strip()) == 0:
1158 Type = TypeList[-2]
1159 TypedefDict = GetTypedefDict(FullFileName)
1160 Type = GetRealType(Type, TypedefDict, TargetType)
1161 return Type
1162
1163 # search function parameters second
1164 ParamList = GetParamList(FuncRecord[2])
1165 for Param in ParamList:
1166 if Param.Name.strip() == PredVar:
1167 if len(PredVarList) > 1:
1168 Type = GetTypeInfo(PredVarList[1:], Param.Modifier, FullFileName, TargetType)
1169 return Type
1170 else:
1171 TypeList = GetDataTypeFromModifier(Param.Modifier).split()
1172 Type = TypeList[-1]
1173 if len(TypeList) > 1 and StarList != None:
1174 for Star in StarList:
1175 Type = Type.strip()
1176 Type = Type.rstrip(Star)
1177 # Get real type after de-reference pointers.
1178 if len(Type.strip()) == 0:
1179 Type = TypeList[-2]
1180 TypedefDict = GetTypedefDict(FullFileName)
1181 Type = GetRealType(Type, TypedefDict, TargetType)
1182 return Type
1183
1184 # search global variable next
1185 SqlStatement = """ select Modifier, ID
1186 from %s
1187 where Model = %d and Name = \'%s\' and BelongsToFunction = -1
1188 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar)
1189 ResultSet = Db.TblFile.Exec(SqlStatement)
1190
1191 for Result in ResultSet:
1192 if len(PredVarList) > 1:
1193 Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)
1194 return Type
1195 else:
1196 TypeList = GetDataTypeFromModifier(Result[0]).split()
1197 Type = TypeList[-1]
1198 if len(TypeList) > 1 and StarList != None:
1199 for Star in StarList:
1200 Type = Type.strip()
1201 Type = Type.rstrip(Star)
1202 # Get real type after de-reference pointers.
1203 if len(Type.strip()) == 0:
1204 Type = TypeList[-2]
1205 TypedefDict = GetTypedefDict(FullFileName)
1206 Type = GetRealType(Type, TypedefDict, TargetType)
1207 return Type
1208
1209 IncludeFileList = GetAllIncludeFiles(FullFileName)
1210 for F in IncludeFileList:
1211 FileID = GetTableID(F)
1212 if FileID < 0:
1213 continue
1214
1215 FileTable = 'Identifier' + str(FileID)
1216 SqlStatement = """ select Modifier, ID
1217 from %s
1218 where Model = %d and BelongsToFunction = -1 and Name = \'%s\'
1219 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar)
1220 ResultSet = Db.TblFile.Exec(SqlStatement)
1221
1222 for Result in ResultSet:
1223 if len(PredVarList) > 1:
1224 Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)
1225 return Type
1226 else:
1227 TypeList = GetDataTypeFromModifier(Result[0]).split()
1228 Type = TypeList[-1]
1229 if len(TypeList) > 1 and StarList != None:
1230 for Star in StarList:
1231 Type = Type.strip()
1232 Type = Type.rstrip(Star)
1233 # Get real type after de-reference pointers.
1234 if len(Type.strip()) == 0:
1235 Type = TypeList[-2]
1236 TypedefDict = GetTypedefDict(FullFileName)
1237 Type = GetRealType(Type, TypedefDict, TargetType)
1238 return Type
1239
1240 def GetTypeFromArray(Type, Var):
1241 Count = Var.count('[')
1242
1243 while Count > 0:
1244 Type = Type.strip()
1245 Type = Type.rstrip('*')
1246 Count = Count - 1
1247
1248 return Type
1249
1250 def CheckFuncLayoutReturnType(FullFileName):
1251 ErrorMsgList = []
1252
1253 FileID = GetTableID(FullFileName, ErrorMsgList)
1254 if FileID < 0:
1255 return ErrorMsgList
1256
1257 Db = GetDB()
1258 FileTable = 'Identifier' + str(FileID)
1259 SqlStatement = """ select Modifier, ID, StartLine, StartColumn, EndLine, Value
1260 from %s
1261 where Model = %d
1262 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1263 ResultSet = Db.TblFile.Exec(SqlStatement)
1264 for Result in ResultSet:
1265 ReturnType = GetDataTypeFromModifier(Result[0])
1266 TypeStart = ReturnType.split()[0]
1267 FuncName = Result[5]
1268 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, FuncName):
1269 continue
1270 Index = Result[0].find(TypeStart)
1271 if Index != 0 or Result[3] != 0:
1272 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, FileTable, Result[1])
1273
1274 if Result[2] == Result[4]:
1275 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear on its own line' % FuncName, FileTable, Result[1])
1276
1277 SqlStatement = """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine, Name
1278 from Function
1279 where BelongsToFile = %d
1280 """ % (FileID)
1281 ResultSet = Db.TblFile.Exec(SqlStatement)
1282 for Result in ResultSet:
1283 ReturnType = GetDataTypeFromModifier(Result[0])
1284 TypeStart = ReturnType.split()[0]
1285 FuncName = Result[5]
1286 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, FuncName):
1287 continue
1288 Index = Result[0].find(ReturnType)
1289 if Index != 0 or Result[3] != 0:
1290 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear at the start of line' % FuncName, 'Function', Result[1])
1291
1292 if Result[2] == Result[4]:
1293 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, '[%s] Return Type should appear on its own line' % FuncName, 'Function', Result[1])
1294
1295 def CheckFuncLayoutModifier(FullFileName):
1296 ErrorMsgList = []
1297
1298 FileID = GetTableID(FullFileName, ErrorMsgList)
1299 if FileID < 0:
1300 return ErrorMsgList
1301
1302 Db = GetDB()
1303 FileTable = 'Identifier' + str(FileID)
1304 SqlStatement = """ select Modifier, ID
1305 from %s
1306 where Model = %d
1307 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1308 ResultSet = Db.TblFile.Exec(SqlStatement)
1309 for Result in ResultSet:
1310 ReturnType = GetDataTypeFromModifier(Result[0])
1311 TypeStart = ReturnType.split()[0]
1312 # if len(ReturnType) == 0:
1313 # continue
1314 Index = Result[0].find(TypeStart)
1315 if Index != 0:
1316 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', FileTable, Result[1])
1317
1318 SqlStatement = """ select Modifier, ID
1319 from Function
1320 where BelongsToFile = %d
1321 """ % (FileID)
1322 ResultSet = Db.TblFile.Exec(SqlStatement)
1323 for Result in ResultSet:
1324 ReturnType = GetDataTypeFromModifier(Result[0])
1325 TypeStart = ReturnType.split()[0]
1326 # if len(ReturnType) == 0:
1327 # continue
1328 Index = Result[0].find(TypeStart)
1329 if Index != 0:
1330 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', 'Function', Result[1])
1331
1332 def CheckFuncLayoutName(FullFileName):
1333 ErrorMsgList = []
1334 # Parameter variable format pattern.
1335 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
1336 ParamIgnoreList = ('VOID', '...')
1337 FileID = GetTableID(FullFileName, ErrorMsgList)
1338 if FileID < 0:
1339 return ErrorMsgList
1340
1341 Db = GetDB()
1342 FileTable = 'Identifier' + str(FileID)
1343 SqlStatement = """ select Name, ID, EndColumn, Value
1344 from %s
1345 where Model = %d
1346 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1347 ResultSet = Db.TblFile.Exec(SqlStatement)
1348 for Result in ResultSet:
1349 FuncName = Result[3]
1350 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName):
1351 continue
1352 if Result[2] != 0:
1353 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, FileTable, Result[1])
1354 ParamList = GetParamList(Result[0])
1355 if len(ParamList) == 0:
1356 continue
1357 StartLine = 0
1358 for Param in ParamList:
1359 if Param.StartLine <= StartLine:
1360 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, FileTable, Result[1])
1361 if Param.StartLine - StartLine > 1:
1362 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, FileTable, Result[1])
1363 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):
1364 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1])
1365 StartLine = Param.StartLine
1366
1367 if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'):
1368 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', FileTable, Result[1])
1369
1370 SqlStatement = """ select Modifier, ID, FunNameStartColumn, Name
1371 from Function
1372 where BelongsToFile = %d
1373 """ % (FileID)
1374 ResultSet = Db.TblFile.Exec(SqlStatement)
1375 for Result in ResultSet:
1376 FuncName = Result[3]
1377 if EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, FuncName):
1378 continue
1379 if Result[2] != 0:
1380 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name [%s] should appear at the start of a line' % FuncName, 'Function', Result[1])
1381 ParamList = GetParamList(Result[0])
1382 if len(ParamList) == 0:
1383 continue
1384 StartLine = 0
1385 for Param in ParamList:
1386 if Param.StartLine <= StartLine:
1387 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, 'Function', Result[1])
1388 if Param.StartLine - StartLine > 1:
1389 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Empty line appears before Parameter %s.' % Param.Name, 'Function', Result[1])
1390 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):
1391 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Parameter [%s] NOT follow naming convention.' % Param.Name, FileTable, Result[1])
1392 StartLine = Param.StartLine
1393 if not Result[0].endswith('\n )') and not Result[0].endswith('\r )'):
1394 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', 'Function', Result[1])
1395
1396 def CheckFuncLayoutPrototype(FullFileName):
1397 ErrorMsgList = []
1398
1399 FileID = GetTableID(FullFileName, ErrorMsgList)
1400 if FileID < 0:
1401 return ErrorMsgList
1402
1403 FileTable = 'Identifier' + str(FileID)
1404 Db = GetDB()
1405 SqlStatement = """ select Modifier, Header, Name, ID
1406 from Function
1407 where BelongsToFile = %d
1408 """ % (FileID)
1409 ResultSet = Db.TblFile.Exec(SqlStatement)
1410 if len(ResultSet) == 0:
1411 return ErrorMsgList
1412
1413 FuncDefList = []
1414 for Result in ResultSet:
1415 FuncDefList.append(Result)
1416
1417 SqlStatement = """ select Modifier, Name, ID
1418 from %s
1419 where Model = %d
1420 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1421 ResultSet = Db.TblFile.Exec(SqlStatement)
1422 FuncDeclList = []
1423 for Result in ResultSet:
1424 FuncDeclList.append(Result)
1425
1426 UndeclFuncList = []
1427 for FuncDef in FuncDefList:
1428 FuncName = FuncDef[2].strip()
1429 FuncModifier = FuncDef[0]
1430 FuncDefHeader = FuncDef[1]
1431 for FuncDecl in FuncDeclList:
1432 LBPos = FuncDecl[1].find('(')
1433 DeclName = FuncDecl[1][0:LBPos].strip()
1434 DeclModifier = FuncDecl[0]
1435 if DeclName == FuncName:
1436 if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName):
1437 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3])
1438 ParamListOfDef = GetParamList(FuncDefHeader)
1439 ParamListOfDecl = GetParamList(FuncDecl[1])
1440 if len(ParamListOfDef) != len(ParamListOfDecl) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, FuncName):
1441 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, 'Parameter number different in function [%s].' % FuncName, 'Function', FuncDef[3])
1442 break
1443
1444 Index = 0
1445 while Index < len(ParamListOfDef):
1446 if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, FuncName):
1447 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])
1448 Index += 1
1449 break
1450 else:
1451 UndeclFuncList.append(FuncDef)
1452
1453 IncludeFileList = GetAllIncludeFiles(FullFileName)
1454 FuncDeclList = []
1455 for F in IncludeFileList:
1456 FileID = GetTableID(F, ErrorMsgList)
1457 if FileID < 0:
1458 continue
1459
1460 FileTable = 'Identifier' + str(FileID)
1461 SqlStatement = """ select Modifier, Name, ID
1462 from %s
1463 where Model = %d
1464 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1465 ResultSet = Db.TblFile.Exec(SqlStatement)
1466
1467 for Result in ResultSet:
1468 FuncDeclList.append(Result)
1469
1470 for FuncDef in UndeclFuncList:
1471 FuncName = FuncDef[2].strip()
1472 FuncModifier = FuncDef[0]
1473 FuncDefHeader = FuncDef[1]
1474 for FuncDecl in FuncDeclList:
1475 LBPos = FuncDecl[1].find('(')
1476 DeclName = FuncDecl[1][0:LBPos].strip()
1477 DeclModifier = FuncDecl[0]
1478 if DeclName == FuncName:
1479 if DiffModifier(FuncModifier, DeclModifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, FuncName):
1480 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function [%s] modifier different with prototype.' % FuncName, 'Function', FuncDef[3])
1481 ParamListOfDef = GetParamList(FuncDefHeader)
1482 ParamListOfDecl = GetParamList(FuncDecl[1])
1483 if len(ParamListOfDef) != len(ParamListOfDecl) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, FuncName):
1484 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_2, 'Parameter number different in function [%s].' % FuncName, 'Function', FuncDef[3])
1485 break
1486
1487 Index = 0
1488 while Index < len(ParamListOfDef):
1489 if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier) and not EccGlobalData.gException.IsException(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE_3, FuncName):
1490 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])
1491 Index += 1
1492 break
1493
1494 def CheckFuncLayoutBody(FullFileName):
1495 ErrorMsgList = []
1496
1497 FileID = GetTableID(FullFileName, ErrorMsgList)
1498 if FileID < 0:
1499 return ErrorMsgList
1500
1501 FileTable = 'Identifier' + str(FileID)
1502 Db = GetDB()
1503 SqlStatement = """ select BodyStartColumn, EndColumn, ID
1504 from Function
1505 where BelongsToFile = %d
1506 """ % (FileID)
1507 ResultSet = Db.TblFile.Exec(SqlStatement)
1508 if len(ResultSet) == 0:
1509 return ErrorMsgList
1510 for Result in ResultSet:
1511 if Result[0] != 0:
1512 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'open brace should be at the very beginning of a line.', 'Function', Result[2])
1513 if Result[1] != 0:
1514 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'close brace should be at the very beginning of a line.', 'Function', Result[2])
1515
1516 def CheckFuncLayoutLocalVariable(FullFileName):
1517 ErrorMsgList = []
1518
1519 FileID = GetTableID(FullFileName, ErrorMsgList)
1520 if FileID < 0:
1521 return ErrorMsgList
1522
1523 Db = GetDB()
1524 FileTable = 'Identifier' + str(FileID)
1525 SqlStatement = """ select ID
1526 from Function
1527 where BelongsToFile = %d
1528 """ % (FileID)
1529 ResultSet = Db.TblFile.Exec(SqlStatement)
1530 if len(ResultSet) == 0:
1531 return ErrorMsgList
1532 FL = []
1533 for Result in ResultSet:
1534 FL.append(Result)
1535
1536 for F in FL:
1537 SqlStatement = """ select Name, Value, ID, Modifier
1538 from %s
1539 where Model = %d and BelongsToFunction = %d
1540 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, F[0])
1541 ResultSet = Db.TblFile.Exec(SqlStatement)
1542 if len(ResultSet) == 0:
1543 continue
1544
1545 for Result in ResultSet:
1546 if len(Result[1]) > 0 and 'CONST' not in Result[3]:
1547 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE, 'Variable Name: %s' % Result[0], FileTable, Result[2])
1548
1549 def CheckMemberVariableFormat(Name, Value, FileTable, TdId, ModelId):
1550 ErrMsgList = []
1551 # Member variable format pattern.
1552 Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
1553
1554 LBPos = Value.find('{')
1555 RBPos = Value.rfind('}')
1556 if LBPos == -1 or RBPos == -1:
1557 return ErrMsgList
1558
1559 Fields = Value[LBPos + 1 : RBPos]
1560 Fields = StripComments(Fields).strip()
1561 NestPos = Fields.find ('struct')
1562 if NestPos != -1 and (NestPos + len('struct') < len(Fields)):
1563 if not Fields[NestPos + len('struct') + 1].isalnum():
1564 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1565 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested struct in [%s].' % (Name), FileTable, TdId)
1566 return ErrMsgList
1567 NestPos = Fields.find ('union')
1568 if NestPos != -1 and (NestPos + len('union') < len(Fields)):
1569 if not Fields[NestPos + len('union') + 1].isalnum():
1570 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1571 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested union in [%s].' % (Name), FileTable, TdId)
1572 return ErrMsgList
1573 NestPos = Fields.find ('enum')
1574 if NestPos != -1 and (NestPos + len('enum') < len(Fields)):
1575 if not Fields[NestPos + len('enum') + 1].isalnum():
1576 if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, Name):
1577 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NESTED_STRUCTURE, 'Nested enum in [%s].' % (Name), FileTable, TdId)
1578 return ErrMsgList
1579
1580 if ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:
1581 FieldsList = Fields.split(',')
1582 # deal with enum is pre-assigned a value by function call ( , , , ...)
1583 QuoteCount = 0
1584 Index = 0
1585 RemoveCurrentElement = False
1586 while Index < len(FieldsList):
1587 Field = FieldsList[Index]
1588
1589 if Field.find('(') != -1:
1590 QuoteCount += 1
1591 RemoveCurrentElement = True
1592 Index += 1
1593 continue
1594
1595 if Field.find(')') != -1 and QuoteCount > 0:
1596 QuoteCount -= 1
1597
1598 if RemoveCurrentElement:
1599 FieldsList.remove(Field)
1600 if QuoteCount == 0:
1601 RemoveCurrentElement = False
1602 continue
1603
1604 if QuoteCount == 0:
1605 RemoveCurrentElement = False
1606
1607 Index += 1
1608 else:
1609 FieldsList = Fields.split(';')
1610
1611 for Field in FieldsList:
1612 Field = Field.strip()
1613 if Field == '':
1614 continue
1615 # For the condition that the field in struct is an array with [] sufixes...
1616 if Field[-1] == ']':
1617 LBPos = Field.find('[')
1618 Field = Field[0:LBPos]
1619 # For the condition that bit field ": Number"
1620 if Field.find(':') != -1:
1621 ColonPos = Field.find(':')
1622 Field = Field[0:ColonPos]
1623
1624 Field = Field.strip()
1625 if Field == '':
1626 continue
1627 # Enum could directly assign value to variable
1628 Field = Field.split('=')[0].strip()
1629 TokenList = Field.split()
1630 # Remove pointers before variable
1631 if not Pattern.match(TokenList[-1].lstrip('*')):
1632 ErrMsgList.append(TokenList[-1].lstrip('*'))
1633
1634 return ErrMsgList
1635
1636 def CheckDeclTypedefFormat(FullFileName, ModelId):
1637 ErrorMsgList = []
1638
1639 FileID = GetTableID(FullFileName, ErrorMsgList)
1640 if FileID < 0:
1641 return ErrorMsgList
1642
1643 Db = GetDB()
1644 FileTable = 'Identifier' + str(FileID)
1645 SqlStatement = """ select Name, StartLine, EndLine, ID, Value
1646 from %s
1647 where Model = %d
1648 """ % (FileTable, ModelId)
1649 ResultSet = Db.TblFile.Exec(SqlStatement)
1650 ResultList = []
1651 for Result in ResultSet:
1652 ResultList.append(Result)
1653
1654 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ALL
1655 if ModelId == DataClass.MODEL_IDENTIFIER_STRUCTURE:
1656 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION
1657 elif ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:
1658 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE
1659 elif ModelId == DataClass.MODEL_IDENTIFIER_UNION:
1660 ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE
1661
1662 SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID
1663 from %s
1664 where Model = %d
1665 """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
1666 TdSet = Db.TblFile.Exec(SqlStatement)
1667 TdList = []
1668 for Td in TdSet:
1669 TdList.append(Td)
1670 # Check member variable name format that from typedefs of ONLY this file.
1671 for Td in TdList:
1672 Name = Td[1].strip()
1673 Value = Td[2].strip()
1674 if Value.startswith('enum'):
1675 ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE
1676 elif Value.startswith('struct'):
1677 ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE
1678 elif Value.startswith('union'):
1679 ValueModelId = DataClass.MODEL_IDENTIFIER_UNION
1680 else:
1681 continue
1682
1683 if ValueModelId != ModelId:
1684 continue
1685 # Check member variable format.
1686 ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Td[5], ModelId)
1687 for ErrMsg in ErrMsgList:
1688 if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Name + '.' + ErrMsg):
1689 continue
1690 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Name + '.' + ErrMsg), FileTable, Td[5])
1691
1692 # First check in current file to see whether struct/union/enum is typedef-ed.
1693 UntypedefedList = []
1694 for Result in ResultList:
1695 # Check member variable format.
1696 Name = Result[0].strip()
1697 Value = Result[4].strip()
1698 if Value.startswith('enum'):
1699 ValueModelId = DataClass.MODEL_IDENTIFIER_ENUMERATE
1700 elif Value.startswith('struct'):
1701 ValueModelId = DataClass.MODEL_IDENTIFIER_STRUCTURE
1702 elif Value.startswith('union'):
1703 ValueModelId = DataClass.MODEL_IDENTIFIER_UNION
1704 else:
1705 continue
1706
1707 if ValueModelId != ModelId:
1708 continue
1709 ErrMsgList = CheckMemberVariableFormat(Name, Value, FileTable, Result[3], ModelId)
1710 for ErrMsg in ErrMsgList:
1711 if EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Result[0] + '.' + ErrMsg):
1712 continue
1713 PrintErrorMsg(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, 'Member variable [%s] NOT follow naming convention.' % (Result[0] + '.' + ErrMsg), FileTable, Result[3])
1714 # Check whether it is typedefed.
1715 Found = False
1716 for Td in TdList:
1717 # skip function pointer
1718 if len(Td[0]) > 0:
1719 continue
1720 if Result[1] >= Td[3] and Td[4] >= Result[2]:
1721 Found = True
1722 if not Td[1].isupper():
1723 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1724 if Result[0] in Td[2].split():
1725 Found = True
1726 if not Td[1].isupper():
1727 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1728 if Found:
1729 break
1730
1731 if not Found:
1732 UntypedefedList.append(Result)
1733 continue
1734
1735 if len(UntypedefedList) == 0:
1736 return
1737
1738 IncludeFileList = GetAllIncludeFiles(FullFileName)
1739 TdList = []
1740 for F in IncludeFileList:
1741 FileID = GetTableID(F, ErrorMsgList)
1742 if FileID < 0:
1743 continue
1744
1745 IncludeFileTable = 'Identifier' + str(FileID)
1746 SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID
1747 from %s
1748 where Model = %d
1749 """ % (IncludeFileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)
1750 ResultSet = Db.TblFile.Exec(SqlStatement)
1751 TdList.extend(ResultSet)
1752
1753 for Result in UntypedefedList:
1754
1755 # Check whether it is typedefed.
1756 Found = False
1757 for Td in TdList:
1758
1759 if len(Td[0]) > 0:
1760 continue
1761 if Result[1] >= Td[3] and Td[4] >= Result[2]:
1762 Found = True
1763 if not Td[1].isupper():
1764 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1765 if Result[0] in Td[2].split():
1766 Found = True
1767 if not Td[1].isupper():
1768 PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])
1769 if Found:
1770 break
1771
1772 if not Found:
1773 PrintErrorMsg(ErrorType, 'No Typedef for %s' % Result[0], FileTable, Result[3])
1774 continue
1775
1776 def CheckDeclStructTypedef(FullFileName):
1777 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_STRUCTURE)
1778
1779 def CheckDeclEnumTypedef(FullFileName):
1780 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_ENUMERATE)
1781
1782 def CheckDeclUnionTypedef(FullFileName):
1783 CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_UNION)
1784
1785 def CheckDeclArgModifier(FullFileName):
1786 ErrorMsgList = []
1787
1788 FileID = GetTableID(FullFileName, ErrorMsgList)
1789 if FileID < 0:
1790 return ErrorMsgList
1791
1792 Db = GetDB()
1793 FileTable = 'Identifier' + str(FileID)
1794 SqlStatement = """ select Modifier, Name, ID
1795 from %s
1796 where Model = %d
1797 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
1798 ResultSet = Db.TblFile.Exec(SqlStatement)
1799 ModifierTuple = ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')
1800 MAX_MODIFIER_LENGTH = 100
1801 for Result in ResultSet:
1802 for Modifier in ModifierTuple:
1803 if PatternInModifier(Result[0], Modifier) and len(Result[0]) < MAX_MODIFIER_LENGTH:
1804 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Variable Modifier %s' % Result[0], FileTable, Result[2])
1805 break
1806
1807 SqlStatement = """ select Modifier, Name, ID
1808 from %s
1809 where Model = %d
1810 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1811 ResultSet = Db.TblFile.Exec(SqlStatement)
1812 for Result in ResultSet:
1813 for Modifier in ModifierTuple:
1814 if PatternInModifier(Result[0], Modifier):
1815 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])
1816 break
1817
1818 SqlStatement = """ select Modifier, Header, ID
1819 from Function
1820 where BelongsToFile = %d
1821 """ % (FileID)
1822 ResultSet = Db.TblFile.Exec(SqlStatement)
1823 for Result in ResultSet:
1824 for Modifier in ModifierTuple:
1825 if PatternInModifier(Result[0], Modifier):
1826 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])
1827 break
1828
1829 def CheckDeclNoUseCType(FullFileName):
1830 ErrorMsgList = []
1831
1832 FileID = GetTableID(FullFileName, ErrorMsgList)
1833 if FileID < 0:
1834 return ErrorMsgList
1835
1836 Db = GetDB()
1837 FileTable = 'Identifier' + str(FileID)
1838 SqlStatement = """ select Modifier, Name, ID
1839 from %s
1840 where Model = %d
1841 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
1842 ResultSet = Db.TblFile.Exec(SqlStatement)
1843 CTypeTuple = ('int', 'unsigned', 'char', 'void', 'static', 'long')
1844 for Result in ResultSet:
1845 for Type in CTypeTuple:
1846 if PatternInModifier(Result[0], Type):
1847 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Variable type %s' % Type, FileTable, Result[2])
1848 break
1849
1850 SqlStatement = """ select Modifier, Name, ID, Value
1851 from %s
1852 where Model = %d
1853 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
1854 ResultSet = Db.TblFile.Exec(SqlStatement)
1855 for Result in ResultSet:
1856 ParamList = GetParamList(Result[1])
1857 FuncName = Result[3]
1858 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):
1859 continue
1860 for Type in CTypeTuple:
1861 if PatternInModifier(Result[0], Type):
1862 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '%s Return type %s' % (FuncName, Result[0]), FileTable, Result[2])
1863
1864 for Param in ParamList:
1865 if PatternInModifier(Param.Modifier, Type):
1866 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])
1867
1868 SqlStatement = """ select Modifier, Header, ID, Name
1869 from Function
1870 where BelongsToFile = %d
1871 """ % (FileID)
1872 ResultSet = Db.TblFile.Exec(SqlStatement)
1873 for Result in ResultSet:
1874 ParamList = GetParamList(Result[1])
1875 FuncName = Result[3]
1876 if EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, FuncName):
1877 continue
1878 for Type in CTypeTuple:
1879 if PatternInModifier(Result[0], Type):
1880 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, '[%s] Return type %s' % (FuncName, Result[0]), FileTable, Result[2])
1881
1882 for Param in ParamList:
1883 if PatternInModifier(Param.Modifier, Type):
1884 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])
1885
1886
1887 def CheckPointerNullComparison(FullFileName):
1888 ErrorMsgList = []
1889
1890 FileID = GetTableID(FullFileName, ErrorMsgList)
1891 if FileID < 0:
1892 return ErrorMsgList
1893
1894 # cache the found function return type to accelerate later checking in this file.
1895 FuncReturnTypeDict = {}
1896
1897 Db = GetDB()
1898 FileTable = 'Identifier' + str(FileID)
1899 SqlStatement = """ select Value, StartLine, ID
1900 from %s
1901 where Model = %d
1902 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
1903 ResultSet = Db.TblFile.Exec(SqlStatement)
1904 if len(ResultSet) == 0:
1905 return
1906 PSL = []
1907 for Result in ResultSet:
1908 PSL.append([Result[0], Result[1], Result[2]])
1909
1910 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
1911 from Function
1912 where BelongsToFile = %d
1913 """ % (FileID)
1914 ResultSet = Db.TblFile.Exec(SqlStatement)
1915 FL = []
1916 for Result in ResultSet:
1917 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
1918
1919 p = GetFuncDeclPattern()
1920 for Str in PSL:
1921 FuncRecord = GetFuncContainsPE(Str[1], FL)
1922 if FuncRecord == None:
1923 continue
1924
1925 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
1926 PredInfo = SplitPredicateStr(Exp)
1927 if PredInfo[1] == None:
1928 PredVarStr = PredInfo[0][0].strip()
1929 IsFuncCall = False
1930 SearchInCache = False
1931 # PredVarStr may contain '.' or '->'
1932 TmpStr = PredVarStr.replace('.', '').replace('->', '')
1933 if p.match(TmpStr):
1934 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
1935 SearchInCache = True
1936 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
1937 if TmpStr.startswith(PredVarStr):
1938 IsFuncCall = True
1939
1940 if PredVarStr.strip() in IgnoredKeywordList:
1941 continue
1942 StarList = []
1943 PredVarList = GetCNameList(PredVarStr, StarList)
1944 # No variable found, maybe value first? like (0 == VarName)
1945 if len(PredVarList) == 0:
1946 continue
1947 if SearchInCache:
1948 Type = FuncReturnTypeDict.get(PredVarStr)
1949 if Type != None:
1950 if Type.find('*') != -1 and Type != 'BOOLEAN*':
1951 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
1952 continue
1953
1954 if PredVarStr in FuncReturnTypeDict:
1955 continue
1956
1957 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, None, StarList)
1958 if SearchInCache:
1959 FuncReturnTypeDict[PredVarStr] = Type
1960 if Type == None:
1961 continue
1962 Type = GetTypeFromArray(Type, PredVarStr)
1963 if Type.find('*') != -1 and Type != 'BOOLEAN*':
1964 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
1965
1966 def CheckNonBooleanValueComparison(FullFileName):
1967 ErrorMsgList = []
1968
1969 FileID = GetTableID(FullFileName, ErrorMsgList)
1970 if FileID < 0:
1971 return ErrorMsgList
1972
1973 # cache the found function return type to accelerate later checking in this file.
1974 FuncReturnTypeDict = {}
1975
1976 Db = GetDB()
1977 FileTable = 'Identifier' + str(FileID)
1978 SqlStatement = """ select Value, StartLine, ID
1979 from %s
1980 where Model = %d
1981 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
1982 ResultSet = Db.TblFile.Exec(SqlStatement)
1983 if len(ResultSet) == 0:
1984 return
1985 PSL = []
1986 for Result in ResultSet:
1987 PSL.append([Result[0], Result[1], Result[2]])
1988
1989 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
1990 from Function
1991 where BelongsToFile = %d
1992 """ % (FileID)
1993 ResultSet = Db.TblFile.Exec(SqlStatement)
1994 FL = []
1995 for Result in ResultSet:
1996 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
1997
1998 p = GetFuncDeclPattern()
1999 for Str in PSL:
2000 FuncRecord = GetFuncContainsPE(Str[1], FL)
2001 if FuncRecord == None:
2002 continue
2003
2004 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
2005 PredInfo = SplitPredicateStr(Exp)
2006 if PredInfo[1] == None:
2007 PredVarStr = PredInfo[0][0].strip()
2008 IsFuncCall = False
2009 SearchInCache = False
2010 # PredVarStr may contain '.' or '->'
2011 TmpStr = PredVarStr.replace('.', '').replace('->', '')
2012 if p.match(TmpStr):
2013 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
2014 SearchInCache = True
2015 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2016 if TmpStr.startswith(PredVarStr):
2017 IsFuncCall = True
2018
2019 if PredVarStr.strip() in IgnoredKeywordList:
2020 continue
2021 StarList = []
2022 PredVarList = GetCNameList(PredVarStr, StarList)
2023 # No variable found, maybe value first? like (0 == VarName)
2024 if len(PredVarList) == 0:
2025 continue
2026
2027 if SearchInCache:
2028 Type = FuncReturnTypeDict.get(PredVarStr)
2029 if Type != None:
2030 if Type.find('BOOLEAN') == -1:
2031 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2032 continue
2033
2034 if PredVarStr in FuncReturnTypeDict:
2035 continue
2036 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)
2037 if SearchInCache:
2038 FuncReturnTypeDict[PredVarStr] = Type
2039 if Type == None:
2040 continue
2041 if Type.find('BOOLEAN') == -1:
2042 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2043
2044
2045 def CheckBooleanValueComparison(FullFileName):
2046 ErrorMsgList = []
2047
2048 FileID = GetTableID(FullFileName, ErrorMsgList)
2049 if FileID < 0:
2050 return ErrorMsgList
2051
2052 # cache the found function return type to accelerate later checking in this file.
2053 FuncReturnTypeDict = {}
2054
2055 Db = GetDB()
2056 FileTable = 'Identifier' + str(FileID)
2057 SqlStatement = """ select Value, StartLine, ID
2058 from %s
2059 where Model = %d
2060 """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)
2061 ResultSet = Db.TblFile.Exec(SqlStatement)
2062 if len(ResultSet) == 0:
2063 return
2064 PSL = []
2065 for Result in ResultSet:
2066 PSL.append([Result[0], Result[1], Result[2]])
2067
2068 SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID
2069 from Function
2070 where BelongsToFile = %d
2071 """ % (FileID)
2072 ResultSet = Db.TblFile.Exec(SqlStatement)
2073 FL = []
2074 for Result in ResultSet:
2075 FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])
2076
2077 p = GetFuncDeclPattern()
2078 for Str in PSL:
2079 FuncRecord = GetFuncContainsPE(Str[1], FL)
2080 if FuncRecord == None:
2081 continue
2082
2083 for Exp in GetPredicateListFromPredicateExpStr(Str[0]):
2084 PredInfo = SplitPredicateStr(Exp)
2085 if PredInfo[1] in ('==', '!=') and PredInfo[0][1] in ('TRUE', 'FALSE'):
2086 PredVarStr = PredInfo[0][0].strip()
2087 IsFuncCall = False
2088 SearchInCache = False
2089 # PredVarStr may contain '.' or '->'
2090 TmpStr = PredVarStr.replace('.', '').replace('->', '')
2091 if p.match(TmpStr):
2092 PredVarStr = PredVarStr[0:PredVarStr.find('(')]
2093 SearchInCache = True
2094 # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.
2095 if TmpStr.startswith(PredVarStr):
2096 IsFuncCall = True
2097
2098 if PredVarStr.strip() in IgnoredKeywordList:
2099 continue
2100 StarList = []
2101 PredVarList = GetCNameList(PredVarStr, StarList)
2102 # No variable found, maybe value first? like (0 == VarName)
2103 if len(PredVarList) == 0:
2104 continue
2105
2106 if SearchInCache:
2107 Type = FuncReturnTypeDict.get(PredVarStr)
2108 if Type != None:
2109 if Type.find('BOOLEAN') != -1:
2110 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2111 continue
2112
2113 if PredVarStr in FuncReturnTypeDict:
2114 continue
2115
2116 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN', StarList)
2117 if SearchInCache:
2118 FuncReturnTypeDict[PredVarStr] = Type
2119 if Type == None:
2120 continue
2121 if Type.find('BOOLEAN') != -1:
2122 PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_BOOLEAN_VALUE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])
2123
2124
2125 def CheckHeaderFileData(FullFileName):
2126 ErrorMsgList = []
2127
2128 FileID = GetTableID(FullFileName, ErrorMsgList)
2129 if FileID < 0:
2130 return ErrorMsgList
2131
2132 Db = GetDB()
2133 FileTable = 'Identifier' + str(FileID)
2134 SqlStatement = """ select ID, Modifier
2135 from %s
2136 where Model = %d
2137 """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)
2138 ResultSet = Db.TblFile.Exec(SqlStatement)
2139 for Result in ResultSet:
2140 if not Result[1].startswith('extern'):
2141 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Variable definition appears in header file', FileTable, Result[0])
2142
2143 SqlStatement = """ select ID
2144 from Function
2145 where BelongsToFile = %d
2146 """ % FileID
2147 ResultSet = Db.TblFile.Exec(SqlStatement)
2148 for Result in ResultSet:
2149 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Function definition appears in header file', 'Function', Result[0])
2150
2151 return ErrorMsgList
2152
2153 def CheckHeaderFileIfndef(FullFileName):
2154 ErrorMsgList = []
2155
2156 FileID = GetTableID(FullFileName, ErrorMsgList)
2157 if FileID < 0:
2158 return ErrorMsgList
2159
2160 Db = GetDB()
2161 FileTable = 'Identifier' + str(FileID)
2162 SqlStatement = """ select Value, StartLine
2163 from %s
2164 where Model = %d order by StartLine
2165 """ % (FileTable, DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF)
2166 ResultSet = Db.TblFile.Exec(SqlStatement)
2167 if len(ResultSet) == 0:
2168 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1, '', 'File', FileID)
2169 return ErrorMsgList
2170 for Result in ResultSet:
2171 SqlStatement = """ select Value, EndLine
2172 from %s
2173 where EndLine < %d
2174 """ % (FileTable, Result[1])
2175 ResultSet = Db.TblFile.Exec(SqlStatement)
2176 for Result in ResultSet:
2177 if not Result[0].startswith('/*') and not Result[0].startswith('//'):
2178 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2, '', 'File', FileID)
2179 break
2180
2181 SqlStatement = """ select Value
2182 from %s
2183 where StartLine > (select max(EndLine) from %s where Model = %d)
2184 """ % (FileTable, FileTable, DataClass.MODEL_IDENTIFIER_MACRO_ENDIF)
2185 ResultSet = Db.TblFile.Exec(SqlStatement)
2186 for Result in ResultSet:
2187 if not Result[0].startswith('/*') and not Result[0].startswith('//'):
2188 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3, '', 'File', FileID)
2189 return ErrorMsgList
2190
2191 def CheckDoxygenCommand(FullFileName):
2192 ErrorMsgList = []
2193
2194 FileID = GetTableID(FullFileName, ErrorMsgList)
2195 if FileID < 0:
2196 return ErrorMsgList
2197
2198 Db = GetDB()
2199 FileTable = 'Identifier' + str(FileID)
2200 SqlStatement = """ select Value, ID
2201 from %s
2202 where Model = %d or Model = %d
2203 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)
2204 ResultSet = Db.TblFile.Exec(SqlStatement)
2205 DoxygenCommandList = ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval', 'return', 'sa', 'since', 'test', 'note', 'par']
2206 for Result in ResultSet:
2207 CommentStr = Result[0]
2208 CommentPartList = CommentStr.split()
2209 for Part in CommentPartList:
2210 if Part.upper() == 'BUGBUG':
2211 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Bug should be marked with doxygen tag @bug', FileTable, Result[1])
2212 if Part.upper() == 'TODO':
2213 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'ToDo should be marked with doxygen tag @todo', FileTable, Result[1])
2214 if Part.startswith('@'):
2215 if EccGlobalData.gException.IsException(ERROR_DOXYGEN_CHECK_COMMAND, Part):
2216 continue
2217 if Part.lstrip('@').isalpha():
2218 if Part.lstrip('@') not in DoxygenCommandList:
2219 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2220 else:
2221 Index = Part.find('[')
2222 if Index == -1:
2223 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2224 RealCmd = Part[1:Index]
2225 if RealCmd not in DoxygenCommandList:
2226 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])
2227
2228
2229 def CheckDoxygenTripleForwardSlash(FullFileName):
2230 ErrorMsgList = []
2231
2232 FileID = GetTableID(FullFileName, ErrorMsgList)
2233 if FileID < 0:
2234 return ErrorMsgList
2235
2236 Db = GetDB()
2237
2238 SqlStatement = """ select ID, BodyStartLine, BodyStartColumn, EndLine, EndColumn
2239 from Function
2240 where BelongsToFile = %d
2241 """ % (FileID)
2242 ResultSet = Db.TblFile.Exec(SqlStatement)
2243 if len(ResultSet) == 0:
2244 return
2245
2246 FuncDefSet = []
2247 for Result in ResultSet:
2248 FuncDefSet.append(Result)
2249
2250
2251 FileTable = 'Identifier' + str(FileID)
2252 SqlStatement = """ select Value, ID, StartLine, StartColumn, EndLine, EndColumn
2253 from %s
2254 where Model = %d
2255
2256 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2257 ResultSet = Db.TblFile.Exec(SqlStatement)
2258 CommentSet = []
2259 try:
2260 for Result in ResultSet:
2261 CommentSet.append(Result)
2262 except:
2263 print 'Unrecognized chars in comment of file %s', FullFileName
2264
2265
2266 for Result in CommentSet:
2267 CommentStr = Result[0]
2268 StartLine = Result[2]
2269 StartColumn = Result[3]
2270 EndLine = Result[4]
2271 EndColumn = Result[5]
2272 if not CommentStr.startswith('///<'):
2273 continue
2274
2275 Found = False
2276 for FuncDef in FuncDefSet:
2277 if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:
2278 Found = True
2279 break
2280 if StartLine > FuncDef[1] and EndLine < FuncDef[3]:
2281 Found = True
2282 break
2283 if StartLine == FuncDef[1] and StartColumn > FuncDef[2] and EndLine < FuncDef[3]:
2284 Found = True
2285 break
2286 if StartLine > FuncDef[1] and EndLine == FuncDef[3] and EndColumn < FuncDef[4]:
2287 Found = True
2288 break
2289 if Found:
2290 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT, '', FileTable, Result[1])
2291
2292
2293 def CheckFileHeaderDoxygenComments(FullFileName):
2294 ErrorMsgList = []
2295
2296 FileID = GetTableID(FullFileName, ErrorMsgList)
2297 if FileID < 0:
2298 return ErrorMsgList
2299
2300 Db = GetDB()
2301 FileTable = 'Identifier' + str(FileID)
2302 SqlStatement = """ select Value, ID
2303 from %s
2304 where Model = %d and (StartLine = 1 or StartLine = 7 or StartLine = 8) and StartColumn = 0
2305 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2306 ResultSet = Db.TblFile.Exec(SqlStatement)
2307 if len(ResultSet) == 0:
2308 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'No Comment appear at the very beginning of file.', 'File', FileID)
2309 return ErrorMsgList
2310
2311 IsFoundError1 = True
2312 IsFoundError2 = True
2313 IsFoundError3 = True
2314 for Result in ResultSet:
2315 CommentStr = Result[0].strip()
2316 ID = Result[1]
2317 if CommentStr.startswith('/** @file'):
2318 IsFoundError1 = False
2319 if CommentStr.endswith('**/'):
2320 IsFoundError2 = False
2321 if CommentStr.find('.') != -1:
2322 IsFoundError3 = False
2323
2324 if IsFoundError1:
2325 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER, 'File header comment should begin with ""/** @file""', FileTable, ID)
2326 if IsFoundError2:
2327 PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should end with ""**/""', FileTable, ID)
2328 if IsFoundError3:
2329 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period "".""', FileTable, ID)
2330
2331 def CheckFuncHeaderDoxygenComments(FullFileName):
2332 ErrorMsgList = []
2333
2334 FileID = GetTableID(FullFileName, ErrorMsgList)
2335 if FileID < 0:
2336 return ErrorMsgList
2337
2338 Db = GetDB()
2339 FileTable = 'Identifier' + str(FileID)
2340 SqlStatement = """ select Value, StartLine, EndLine, ID
2341 from %s
2342 where Model = %d
2343 """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)
2344
2345 ResultSet = Db.TblFile.Exec(SqlStatement)
2346 CommentSet = []
2347 try:
2348 for Result in ResultSet:
2349 CommentSet.append(Result)
2350 except:
2351 print 'Unrecognized chars in comment of file %s', FullFileName
2352
2353 # Func Decl check
2354 SqlStatement = """ select Modifier, Name, StartLine, ID, Value
2355 from %s
2356 where Model = %d
2357 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)
2358 ResultSet = Db.TblFile.Exec(SqlStatement)
2359 for Result in ResultSet:
2360 FuncName = Result[4]
2361 FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)
2362 if FunctionHeaderComment:
2363 CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)
2364 else:
2365 if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):
2366 continue
2367 ErrorMsgList.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result[2], Result[1]))
2368 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), FileTable, Result[3])
2369
2370 # Func Def check
2371 SqlStatement = """ select Value, StartLine, EndLine, ID
2372 from %s
2373 where Model = %d
2374 """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)
2375
2376 ResultSet = Db.TblFile.Exec(SqlStatement)
2377 CommentSet = []
2378 try:
2379 for Result in ResultSet:
2380 CommentSet.append(Result)
2381 except:
2382 print 'Unrecognized chars in comment of file %s', FullFileName
2383
2384 SqlStatement = """ select Modifier, Header, StartLine, ID, Name
2385 from Function
2386 where BelongsToFile = %d
2387 """ % (FileID)
2388 ResultSet = Db.TblFile.Exec(SqlStatement)
2389 for Result in ResultSet:
2390 FuncName = Result[4]
2391 FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)
2392 if FunctionHeaderComment:
2393 CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)
2394 else:
2395 if EccGlobalData.gException.IsException(ERROR_HEADER_CHECK_FUNCTION, FuncName):
2396 continue
2397 ErrorMsgList.append('Line %d :Function [%s] has NO comment immediately preceding it.' % (Result[2], Result[1]))
2398 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function [%s] has NO comment immediately preceding it.' % (FuncName), 'Function', Result[3])
2399 return ErrorMsgList
2400
2401 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName, FuncStartLine, CommentSet):
2402
2403 for Comment in CommentSet:
2404 if Comment[2] == FuncStartLine - 1:
2405 return Comment
2406 return None
2407
2408 def GetDoxygenStrFromComment(Str):
2409 DoxygenStrList = []
2410 ParamTagList = Str.split('@param')
2411 if len(ParamTagList) > 1:
2412 i = 1
2413 while i < len(ParamTagList):
2414 DoxygenStrList.append('@param' + ParamTagList[i])
2415 i += 1
2416
2417 Str = ParamTagList[0]
2418
2419 RetvalTagList = ParamTagList[-1].split('@retval')
2420 if len(RetvalTagList) > 1:
2421 if len(ParamTagList) > 1:
2422 DoxygenStrList[-1] = '@param' + RetvalTagList[0]
2423 i = 1
2424 while i < len(RetvalTagList):
2425 DoxygenStrList.append('@retval' + RetvalTagList[i])
2426 i += 1
2427
2428 ReturnTagList = RetvalTagList[-1].split('@return')
2429 if len(ReturnTagList) > 1:
2430 if len(RetvalTagList) > 1:
2431 DoxygenStrList[-1] = '@retval' + ReturnTagList[0]
2432 elif len(ParamTagList) > 1:
2433 DoxygenStrList[-1] = '@param' + ReturnTagList[0]
2434 i = 1
2435 while i < len(ReturnTagList):
2436 DoxygenStrList.append('@return' + ReturnTagList[i])
2437 i += 1
2438
2439 if len(DoxygenStrList) > 0:
2440 DoxygenStrList[-1] = DoxygenStrList[-1].rstrip('--*/')
2441
2442 return DoxygenStrList
2443
2444 def CheckGeneralDoxygenCommentLayout(Str, StartLine, ErrorMsgList, CommentId= -1, TableName=''):
2445 #/** --*/ @retval after @param
2446 if not Str.startswith('/**'):
2447 ErrorMsgList.append('Line %d : Comment does NOT have prefix /** ' % StartLine)
2448 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have prefix /** ', TableName, CommentId)
2449 if not Str.endswith('**/'):
2450 ErrorMsgList.append('Line %d : Comment does NOT have tail **/ ' % StartLine)
2451 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have tail **/ ', TableName, CommentId)
2452 FirstRetvalIndex = Str.find('@retval')
2453 LastParamIndex = Str.rfind('@param')
2454 if (FirstRetvalIndex > 0) and (LastParamIndex > 0) and (FirstRetvalIndex < LastParamIndex):
2455 ErrorMsgList.append('Line %d : @retval appear before @param ' % StartLine)
2456 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, @retval appear before @param ', TableName, CommentId)
2457
2458 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier, FuncHeader, FuncStartLine, CommentStr, CommentStartLine, ErrorMsgList, CommentId= -1, TableName=''):
2459
2460 ParamList = GetParamList(FuncHeader)
2461 CheckGeneralDoxygenCommentLayout(CommentStr, CommentStartLine, ErrorMsgList, CommentId, TableName)
2462 DescriptionStr = CommentStr
2463 DoxygenStrList = GetDoxygenStrFromComment(DescriptionStr)
2464 if DescriptionStr.find('.') == -1:
2465 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period \'.\'', TableName, CommentId)
2466 DoxygenTagNumber = len(DoxygenStrList)
2467 ParamNumber = len(ParamList)
2468 for Param in ParamList:
2469 if Param.Name.upper() == 'VOID' and ParamNumber == 1:
2470 ParamNumber -= 1
2471 Index = 0
2472 if ParamNumber > 0 and DoxygenTagNumber > 0:
2473 while Index < ParamNumber and Index < DoxygenTagNumber:
2474 ParamModifier = ParamList[Index].Modifier
2475 ParamName = ParamList[Index].Name.strip()
2476 Tag = DoxygenStrList[Index].strip(' ')
2477 if (not Tag[-1] == ('\n')) and (not Tag[-1] == ('\r')):
2478 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT end with new line ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))
2479 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'in Comment, <%s> does NOT end with new line ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)
2480 TagPartList = Tag.split()
2481 if len(TagPartList) < 2:
2482 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT contain doxygen contents ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))
2483 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT contain doxygen contents ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)
2484 Index += 1
2485 continue
2486 LBPos = Tag.find('[')
2487 RBPos = Tag.find(']')
2488 ParamToLBContent = Tag[len('@param'):LBPos].strip()
2489 if LBPos > 0 and len(ParamToLBContent) == 0 and RBPos > LBPos:
2490 InOutStr = ''
2491 ModifierPartList = ParamModifier.split()
2492 for Part in ModifierPartList:
2493 if Part.strip() == 'IN':
2494 InOutStr += 'in'
2495 if Part.strip() == 'OUT':
2496 if InOutStr != '':
2497 InOutStr += ', out'
2498 else:
2499 InOutStr = 'out'
2500
2501 if InOutStr != '':
2502 if Tag.find('[' + InOutStr + ']') == -1:
2503 if InOutStr != 'in, out':
2504 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'))
2505 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT have %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'), TableName, CommentId)
2506 else:
2507 if Tag.find('[in,out]') == -1:
2508 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'))
2509 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, <%s> does NOT have %s ' % ((TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), '[' + InOutStr + ']'), TableName, CommentId)
2510
2511
2512 if Tag.find(ParamName) == -1 and ParamName != 'VOID' and ParamName != 'void':
2513 ErrorMsgList.append('Line %d : in Comment, <%s> does NOT consistent with parameter name %s ' % (CommentStartLine, (TagPartList[0] + ' ' + TagPartList[1]).replace('\n', '').replace('\r', ''), ParamName))
2514 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)
2515 Index += 1
2516
2517 if Index < ParamNumber:
2518 ErrorMsgList.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine)
2519 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of doxygen tags in comment less than number of function parameters ', TableName, CommentId)
2520 # VOID return type, NOT VOID*. VOID* should be matched with a doxygen tag.
2521 if (FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1:
2522
2523 # assume we allow a return description tag for void func. return. that's why 'DoxygenTagNumber - 1' is used instead of 'DoxygenTagNumber'
2524 if Index < DoxygenTagNumber - 1 or (Index < DoxygenTagNumber and DoxygenStrList[Index].startswith('@retval')):
2525 ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)
2526 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need no doxygen tags in comment ', TableName, CommentId)
2527 else:
2528 if Index < DoxygenTagNumber and not DoxygenStrList[Index].startswith('@retval') and not DoxygenStrList[Index].startswith('@return'):
2529 ErrorMsgList.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine)
2530 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName, CommentId)
2531 else:
2532 if ParamNumber == 0 and DoxygenTagNumber != 0 and ((FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1) and FuncModifier.find('*') == -1):
2533 ErrorMsgList.append('Line %d : VOID return type need NO doxygen tags in comment' % CommentStartLine)
2534 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'VOID return type need NO doxygen tags in comment ', TableName, CommentId)
2535 if ParamNumber != 0 and DoxygenTagNumber == 0:
2536 ErrorMsgList.append('Line %d : No doxygen tags in comment' % CommentStartLine)
2537 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'No doxygen tags in comment ', TableName, CommentId)
2538
2539 if __name__ == '__main__':
2540
2541 # EdkLogger.Initialize()
2542 # EdkLogger.SetLevel(EdkLogger.QUIET)
2543 # CollectSourceCodeDataIntoDB(sys.argv[1])
2544 try:
2545 test_file = sys.argv[1]
2546 except IndexError, v:
2547 print "Usage: %s filename" % sys.argv[0]
2548 sys.exit(1)
2549 MsgList = CheckFuncHeaderDoxygenComments(test_file)
2550 for Msg in MsgList:
2551 print Msg
2552 print 'Done!'