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