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