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