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