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