a5cf1446825f3ed691bc8cbd3217ed22db5f58d8
[people/mcb30/basetools.git] / Source / Python / Ecc / c.py
1 import sys\r
2 import os\r
3 import re\r
4 import CodeFragmentCollector\r
5 import FileProfile\r
6 from CommonDataClass import DataClass\r
7 import Database\r
8 from Common import EdkLogger\r
9 from EccToolError import *\r
10 import EccGlobalData\r
11 import MetaDataParser\r
12 \r
13 IncludeFileListDict = {}\r
14 IncludePathListDict = {}\r
15 ComplexTypeDict = {}\r
16 SUDict = {}\r
17 \r
18 def GetIgnoredDirListPattern():\r
19     p = re.compile(r'.*[\\/](?:BUILD|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG|PCCTS)[\\/].*')\r
20     return p\r
21 \r
22 def GetFuncDeclPattern():\r
23     p = re.compile(r'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re.DOTALL)\r
24     return p\r
25 \r
26 def GetArrayPattern():\r
27     p = re.compile(r'[_\w]*\s*[\[.*\]]+')\r
28     return p\r
29 \r
30 def GetTypedefFuncPointerPattern():\r
31     p = re.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re.DOTALL)\r
32     return p\r
33 \r
34 def GetDB():\r
35     return EccGlobalData.gDb\r
36 \r
37 def GetConfig():\r
38     return EccGlobalData.gConfig\r
39 \r
40 def PrintErrorMsg(ErrorType, Msg, TableName, ItemId):\r
41     Msg = Msg.replace('\n', '').replace('\r', '')\r
42     MsgPartList = Msg.split()\r
43     Msg = ''\r
44     for Part in MsgPartList:\r
45         Msg += Part\r
46         Msg += ' '\r
47     GetDB().TblReport.Insert(ErrorType, OtherMsg = Msg, BelongsToTable = TableName, BelongsToItem = ItemId)\r
48 \r
49 def GetIdType(Str):\r
50     Type = DataClass.MODEL_UNKNOWN\r
51     Str = Str.replace('#', '# ')\r
52     List = Str.split()\r
53     if List[1] == 'include':\r
54         Type = DataClass.MODEL_IDENTIFIER_INCLUDE\r
55     elif List[1] == 'define':\r
56         Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE\r
57     elif List[1] == 'ifdef':\r
58         Type = DataClass.MODEL_IDENTIFIER_MACRO_IFDEF\r
59     elif List[1] == 'ifndef':\r
60         Type = DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF\r
61     elif List[1] == 'endif':\r
62         Type = DataClass.MODEL_IDENTIFIER_MACRO_ENDIF\r
63     elif List[1] == 'pragma':\r
64         Type = DataClass.MODEL_IDENTIFIER_MACRO_PROGMA\r
65     else:\r
66         Type = DataClass.MODEL_UNKNOWN\r
67     return Type\r
68 \r
69 def GetIdentifierList():\r
70     IdList = []\r
71     for comment in FileProfile.CommentList:\r
72         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
73         IdList.append(IdComment)\r
74         \r
75     for pp in FileProfile.PPDirectiveList:\r
76         Type = GetIdType(pp.Content)\r
77         IdPP = DataClass.IdentifierClass(-1, '', '', '', pp.Content, Type, -1, -1, pp.StartPos[0],pp.StartPos[1],pp.EndPos[0],pp.EndPos[1])\r
78         IdList.append(IdPP)\r
79         \r
80     for pe in FileProfile.PredicateExpressionList:\r
81         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
82         IdList.append(IdPE)\r
83         \r
84     FuncDeclPattern = GetFuncDeclPattern()\r
85     ArrayPattern = GetArrayPattern()\r
86     for var in FileProfile.VariableDeclarationList:\r
87         DeclText = var.Declarator.lstrip()\r
88         FuncPointerPattern = GetTypedefFuncPointerPattern()\r
89         if FuncPointerPattern.match(DeclText):\r
90             continue\r
91         VarNameStartLine = var.NameStartPos[0]\r
92         VarNameStartColumn = var.NameStartPos[1]\r
93         FirstChar = DeclText[0]\r
94         while not FirstChar.isalpha() and FirstChar != '_':\r
95             if FirstChar == '*':\r
96                 var.Modifier += '*'\r
97                 VarNameStartColumn += 1\r
98                 DeclText = DeclText.lstrip('*')\r
99             elif FirstChar == '\r':\r
100                 DeclText = DeclText.lstrip('\r\n').lstrip('\r')\r
101                 VarNameStartLine += 1\r
102                 VarNameStartColumn = 0\r
103             elif FirstChar == '\n':\r
104                 DeclText = DeclText.lstrip('\n')\r
105                 VarNameStartLine += 1\r
106                 VarNameStartColumn = 0\r
107             elif FirstChar == ' ':\r
108                 DeclText = DeclText.lstrip(' ')\r
109                 VarNameStartColumn += 1\r
110             elif FirstChar == '\t':\r
111                 DeclText = DeclText.lstrip('\t')\r
112                 VarNameStartColumn += 8\r
113             else:\r
114                 DeclText = DeclText[1:]\r
115             FirstChar = DeclText[0]\r
116             \r
117         var.Declarator = DeclText\r
118         if FuncDeclPattern.match(var.Declarator):\r
119             DeclSplitList = var.Declarator.split('(')     \r
120             FuncName = DeclSplitList[0]\r
121             FuncNamePartList = FuncName.split()\r
122             if len(FuncNamePartList) > 1:\r
123                 FuncName = FuncNamePartList[-1]\r
124                 NameStart = DeclSplitList[0].rfind(FuncName)\r
125                 var.Declarator = var.Declarator[NameStart:]\r
126                 if NameStart > 0:\r
127                     var.Modifier += ' ' + DeclSplitList[0][0:NameStart]\r
128                     Index = 0\r
129                     PreChar = ''\r
130                     while Index < NameStart:\r
131                         FirstChar = DeclSplitList[0][Index]\r
132                         if DeclSplitList[0][Index:].startswith('EFIAPI'):\r
133                             Index += 6\r
134                             VarNameStartColumn += 6\r
135                             PreChar = ''\r
136                             continue\r
137                         elif FirstChar == '\r':\r
138                             Index += 1\r
139                             VarNameStartLine += 1\r
140                             VarNameStartColumn = 0\r
141                         elif FirstChar == '\n':\r
142                             Index += 1\r
143                             if PreChar != '\r':\r
144                                 VarNameStartLine += 1\r
145                                 VarNameStartColumn = 0\r
146                         elif FirstChar == ' ':\r
147                             Index += 1\r
148                             VarNameStartColumn += 1\r
149                         elif FirstChar == '\t':\r
150                             Index += 1\r
151                             VarNameStartColumn += 8\r
152                         else:\r
153                             Index += 1\r
154                         PreChar = FirstChar\r
155             IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', var.Declarator, '', DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, -1, -1, var.StartPos[0], var.StartPos[1], VarNameStartLine, VarNameStartColumn)\r
156             IdList.append(IdVar)\r
157             continue\r
158         \r
159         if var.Declarator.find('{') == -1:      \r
160             for decl in var.Declarator.split(','):\r
161                 DeclList = decl.split('=')\r
162                 Name = DeclList[0].strip()\r
163                 if ArrayPattern.match(Name):\r
164                     LSBPos = var.Declarator.find('[')\r
165                     var.Modifier += ' ' + Name[LSBPos:]\r
166                     Name = Name[0:LSBPos]\r
167             \r
168                 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
169                 IdList.append(IdVar)\r
170         else:\r
171             DeclList = var.Declarator.split('=')\r
172             Name = DeclList[0].strip()\r
173             if ArrayPattern.match(Name):\r
174                 LSBPos = var.Declarator.find('[')\r
175                 var.Modifier += ' ' + Name[LSBPos:]\r
176                 Name = Name[0:LSBPos]\r
177             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
178             IdList.append(IdVar)\r
179             \r
180     for enum in FileProfile.EnumerationDefinitionList:\r
181         LBPos = enum.Content.find('{')\r
182         RBPos = enum.Content.find('}')\r
183         Name = enum.Content[4:LBPos].strip()\r
184         Value = enum.Content[LBPos+1:RBPos]\r
185         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
186         IdList.append(IdEnum)\r
187         \r
188     for su in FileProfile.StructUnionDefinitionList:\r
189         Type = DataClass.MODEL_IDENTIFIER_STRUCTURE\r
190         SkipLen = 6\r
191         if su.Content.startswith('union'):\r
192             Type = DataClass.MODEL_IDENTIFIER_UNION\r
193             SkipLen = 5\r
194         LBPos = su.Content.find('{')\r
195         RBPos = su.Content.find('}')\r
196         if LBPos == -1 or RBPos == -1:\r
197             Name = su.Content[SkipLen:].strip()\r
198             Value = ''\r
199         else:\r
200             Name = su.Content[SkipLen:LBPos].strip()\r
201             Value = su.Content[LBPos+1:RBPos]\r
202         IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0],su.StartPos[1],su.EndPos[0],su.EndPos[1])\r
203         IdList.append(IdPE)\r
204     \r
205     TdFuncPointerPattern = GetTypedefFuncPointerPattern()    \r
206     for td in FileProfile.TypedefDefinitionList:\r
207         Modifier = ''\r
208         Name = td.ToType\r
209         Value = td.FromType\r
210         if TdFuncPointerPattern.match(td.ToType):\r
211             Modifier = td.FromType\r
212             LBPos = td.ToType.find('(')\r
213             TmpStr = td.ToType[LBPos+1:].strip()\r
214             StarPos = TmpStr.find('*')\r
215             if StarPos != -1:\r
216                 Modifier += ' ' + TmpStr[0:StarPos]\r
217             while TmpStr[StarPos] == '*':\r
218                 Modifier += ' ' + '*'\r
219                 StarPos += 1\r
220             TmpStr = TmpStr[StarPos:].strip()\r
221             RBPos = TmpStr.find(')')\r
222             Name = TmpStr[0:RBPos]\r
223             Value = 'FP' + TmpStr[RBPos + 1:]\r
224             \r
225         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
226         IdList.append(IdTd)\r
227         \r
228     for funcCall in FileProfile.FunctionCallingList:\r
229         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
230         IdList.append(IdFC)\r
231     return IdList\r
232 \r
233 def GetParamList(FuncDeclarator, FuncNameLine = 0, FuncNameOffset = 0):\r
234     ParamIdList = []\r
235     DeclSplitList = FuncDeclarator.split('(')\r
236     if len(DeclSplitList) < 2:\r
237         return ParamIdList\r
238     FuncName = DeclSplitList[0]\r
239     ParamStr = DeclSplitList[1].rstrip(')')\r
240     LineSkipped = 0\r
241     OffsetSkipped = 0\r
242     Start = 0\r
243     while FuncName.find('\n', Start) != -1:\r
244         LineSkipped += 1\r
245         OffsetSkipped = 0\r
246         Start += FuncName.find('\n', Start)\r
247         Start += 1       \r
248     OffsetSkipped += len(FuncName[Start:])\r
249     OffsetSkipped += 1 #skip '('\r
250     ParamBeginLine = FuncNameLine + LineSkipped\r
251     ParamBeginOffset = OffsetSkipped\r
252     for p in ParamStr.split(','):\r
253         ListP = p.split()\r
254         if len(ListP) == 0:\r
255             continue\r
256         ParamName = ListP[-1]\r
257         DeclText = ParamName.strip()\r
258         RightSpacePos = p.rfind(ParamName)\r
259         ParamModifier = p[0:RightSpacePos]\r
260         if ParamName == 'OPTIONAL':\r
261             if ParamModifier == '':\r
262                 ParamModifier += ' ' + 'OPTIONAL'\r
263                 DeclText = ''\r
264             else:\r
265                 ParamName = ListP[-2]\r
266                 DeclText = ParamName.strip()\r
267                 RightSpacePos = p.rfind(ParamName)\r
268                 ParamModifier = p[0:RightSpacePos]\r
269                 ParamModifier += 'OPTIONAL'\r
270         while DeclText.startswith('*'):\r
271             ParamModifier += ' ' + '*'\r
272             DeclText = DeclText.lstrip('*').strip()\r
273         ParamName = DeclText\r
274         \r
275         Start = 0\r
276         while p.find('\n', Start) != -1:\r
277             LineSkipped += 1\r
278             OffsetSkipped = 0\r
279             Start += p.find('\n', Start)\r
280             Start += 1\r
281         OffsetSkipped += len(p[Start:])\r
282         \r
283         ParamEndLine = ParamBeginLine + LineSkipped\r
284         ParamEndOffset = OffsetSkipped\r
285         IdParam = DataClass.IdentifierClass(-1, ParamModifier, '', ParamName, '', DataClass.MODEL_IDENTIFIER_PARAMETER, -1, -1, ParamBeginLine, ParamBeginOffset, ParamEndLine, ParamEndOffset)\r
286         ParamIdList.append(IdParam)\r
287         ParamBeginLine = ParamEndLine\r
288         ParamBeginOffset = OffsetSkipped + 1 #skip ','\r
289     \r
290     return ParamIdList\r
291     \r
292 def GetFunctionList():\r
293     FuncObjList = []\r
294     for FuncDef in FileProfile.FunctionDefinitionList:\r
295         ParamIdList = []\r
296         DeclText = FuncDef.Declarator.lstrip()\r
297         FuncNameStartLine = FuncDef.NamePos[0]\r
298         FuncNameStartColumn = FuncDef.NamePos[1]\r
299         FirstChar = DeclText[0]\r
300         while not FirstChar.isalpha() and FirstChar != '_':\r
301             if FirstChar == '*':\r
302                 FuncDef.Modifier += '*'\r
303                 FuncNameStartColumn += 1\r
304                 DeclText = DeclText.lstrip('*')\r
305             elif FirstChar == '\r':\r
306                 DeclText = DeclText.lstrip('\r\n').lstrip('\r')\r
307                 FuncNameStartLine += 1\r
308                 FuncNameStartColumn = 0\r
309             elif FirstChar == '\n':\r
310                 DeclText = DeclText.lstrip('\n')\r
311                 FuncNameStartLine += 1\r
312                 FuncNameStartColumn = 0\r
313             elif FirstChar == ' ':\r
314                 DeclText = DeclText.lstrip(' ')\r
315                 FuncNameStartColumn += 1\r
316             elif FirstChar == '\t':\r
317                 DeclText = DeclText.lstrip('\t')\r
318                 FuncNameStartColumn += 8\r
319             else:\r
320                 DeclText = DeclText[1:]\r
321             FirstChar = DeclText[0]\r
322         \r
323         FuncDef.Declarator = DeclText\r
324         DeclSplitList = FuncDef.Declarator.split('(')\r
325         if len(DeclSplitList) < 2:\r
326             continue\r
327         \r
328         FuncName = DeclSplitList[0]\r
329         FuncNamePartList = FuncName.split()\r
330         if len(FuncNamePartList) > 1:\r
331             FuncName = FuncNamePartList[-1]\r
332             NameStart = DeclSplitList[0].rfind(FuncName)\r
333             if NameStart > 0:\r
334                 FuncDef.Modifier += ' ' + DeclSplitList[0][0:NameStart]\r
335                 Index = 0\r
336                 PreChar = ''\r
337                 while Index < NameStart:\r
338                     FirstChar = DeclSplitList[0][Index]\r
339                     if DeclSplitList[0][Index:].startswith('EFIAPI'):\r
340                         Index += 6\r
341                         FuncNameStartColumn += 6\r
342                         PreChar = ''\r
343                         continue\r
344                     elif FirstChar == '\r':\r
345                         Index += 1\r
346                         FuncNameStartLine += 1\r
347                         FuncNameStartColumn = 0\r
348                     elif FirstChar == '\n':\r
349                         Index += 1\r
350                         if PreChar != '\r':\r
351                             FuncNameStartLine += 1\r
352                             FuncNameStartColumn = 0\r
353                     elif FirstChar == ' ':\r
354                         Index += 1\r
355                         FuncNameStartColumn += 1\r
356                     elif FirstChar == '\t':\r
357                         Index += 1\r
358                         FuncNameStartColumn += 8\r
359                     else:\r
360                         Index += 1\r
361                     PreChar = FirstChar\r
362                 \r
363         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
364         FuncObjList.append(FuncObj)\r
365         \r
366     return FuncObjList\r
367 \r
368 def GetFileModificationTimeFromDB(FullFileName):\r
369     TimeValue = 0.0\r
370     Db = GetDB()\r
371     SqlStatement = """ select TimeStamp\r
372                        from File\r
373                        where FullPath = \'%s\'\r
374                    """ % (FullFileName)\r
375     ResultSet = Db.TblFile.Exec(SqlStatement)\r
376     for Result in ResultSet:\r
377         TimeValue = Result[0]\r
378     return TimeValue\r
379 \r
380 def CollectSourceCodeDataIntoDB(RootDir):\r
381     FileObjList = []\r
382     tuple = os.walk(RootDir)\r
383     IgnoredPattern = GetIgnoredDirListPattern()\r
384     ParseErrorFileList = []\r
385 \r
386     for dirpath, dirnames, filenames in tuple:\r
387         if IgnoredPattern.match(dirpath.upper()):\r
388             continue\r
389         for f in filenames:\r
390             FullName = os.path.join(dirpath, f)\r
391             if os.path.splitext(f)[1] in ('.h', '.c'):\r
392                 EdkLogger.info("Parsing " + FullName)\r
393                 model = f.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H\r
394                 collector = CodeFragmentCollector.CodeFragmentCollector(FullName)\r
395                 try:\r
396                     collector.ParseFile()\r
397                 except UnicodeError:\r
398                     ParseErrorFileList.append(FullName)\r
399                     collector.CleanFileProfileBuffer()\r
400                     collector.ParseFileWithClearedPPDirective()\r
401 #                collector.PrintFragments()\r
402                 BaseName = os.path.basename(f)\r
403                 DirName = os.path.dirname(FullName)\r
404                 Ext = os.path.splitext(f)[1].lstrip('.')\r
405                 ModifiedTime = os.path.getmtime(FullName)\r
406                 FileObj = DataClass.FileClass(-1, BaseName, Ext, DirName, FullName, model, ModifiedTime, GetFunctionList(), GetIdentifierList(), [])\r
407                 FileObjList.append(FileObj)\r
408                 collector.CleanFileProfileBuffer()   \r
409     \r
410     if len(ParseErrorFileList) > 0:\r
411         EdkLogger.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList))\r
412     \r
413     Db = GetDB()    \r
414     for file in FileObjList:    \r
415         Db.InsertOneFile(file)\r
416 \r
417     Db.UpdateIdentifierBelongsToFunction()\r
418 \r
419 def GetTableID(FullFileName, ErrorMsgList = None):\r
420     if ErrorMsgList == None:\r
421         ErrorMsgList = []\r
422         \r
423     Db = GetDB()\r
424     SqlStatement = """ select ID\r
425                        from File\r
426                        where FullPath = '%s'\r
427                    """ % FullFileName\r
428     \r
429     ResultSet = Db.TblFile.Exec(SqlStatement)\r
430 \r
431     FileID = -1\r
432     for Result in ResultSet:\r
433         if FileID != -1:\r
434             ErrorMsgList.append('Duplicate file ID found in DB for file %s' % FullFileName)\r
435             return -2\r
436         FileID = Result[0]\r
437     if FileID == -1:\r
438         ErrorMsgList.append('NO file ID found in DB for file %s' % FullFileName)\r
439         return -1\r
440     return FileID\r
441 \r
442 def GetIncludeFileList(FullFileName):\r
443     IFList = IncludeFileListDict.get(FullFileName)\r
444     if IFList != None:\r
445         return IFList\r
446     \r
447     ErrorMsgList = []\r
448     \r
449     FileID = GetTableID(FullFileName, ErrorMsgList)\r
450     if FileID < 0:\r
451         return []\r
452     \r
453     Db = GetDB()\r
454     FileTable = 'Identifier' + str(FileID)\r
455     SqlStatement = """ select Value\r
456                        from %s\r
457                        where Model = %d\r
458                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_INCLUDE)\r
459     ResultSet = Db.TblFile.Exec(SqlStatement)\r
460     IncludeFileListDict[FullFileName] = ResultSet\r
461     return ResultSet\r
462 \r
463 def GetFullPathOfIncludeFile(Str, IncludePathList):\r
464     for IncludePath in IncludePathList:\r
465         FullPath = os.path.join(IncludePath, Str)\r
466         if os.path.exists(FullPath):\r
467             return FullPath\r
468     return None\r
469 \r
470 def GetAllIncludeFiles(FullFileName):\r
471     IncludePathList = IncludePathListDict.get(os.path.dirname(FullFileName))\r
472     if IncludePathList == None:\r
473         IncludePathList = MetaDataParser.GetIncludeListOfFile(EccGlobalData.gWorkspace, FullFileName, GetDB())\r
474         IncludePathList.insert(0, os.path.dirname(FullFileName))\r
475         IncludePathListDict[os.path.dirname(FullFileName)] = IncludePathList\r
476     IncludeFileQueue = []\r
477     for IncludeFile in GetIncludeFileList(FullFileName):\r
478         FileName = IncludeFile[0].lstrip('#').strip()\r
479         FileName = FileName.lstrip('include').strip()\r
480         FileName = FileName.strip('\"')\r
481         FileName = FileName.lstrip('<').rstrip('>').strip()\r
482         FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList)\r
483         if FullPath != None:\r
484             IncludeFileQueue.append(FullPath)\r
485         \r
486     i = 0\r
487     while i < len(IncludeFileQueue):\r
488         for IncludeFile in GetIncludeFileList(IncludeFileQueue[i]):\r
489             FileName = IncludeFile[0].lstrip('#').strip()\r
490             FileName = FileName.lstrip('include').strip()\r
491             FileName = FileName.strip('\"')\r
492             FileName = FileName.lstrip('<').rstrip('>').strip()\r
493             FullPath = GetFullPathOfIncludeFile(FileName, IncludePathList)\r
494             if FullPath != None and FullPath not in IncludeFileQueue:\r
495                 IncludeFileQueue.insert(i + 1, FullPath)\r
496         i += 1\r
497     return IncludeFileQueue\r
498 \r
499 def GetPredicateListFromPredicateExpStr(PES):\r
500 \r
501     PredicateList = []\r
502     i = 0\r
503     PredicateBegin = 0\r
504     #PredicateEnd = 0\r
505     LogicOpPos = -1\r
506     p = GetFuncDeclPattern()\r
507     while i < len(PES) - 1:\r
508         if (PES[i].isalnum() or PES[i] == '_') and LogicOpPos > PredicateBegin:\r
509             PredicateBegin = i\r
510         if (PES[i] == '&' and PES[i+1] == '&') or (PES[i] == '|' and PES[i+1] == '|'):\r
511             LogicOpPos = i\r
512             Exp = PES[PredicateBegin:i].strip()\r
513             if p.match(Exp):\r
514                 PredicateList.append(Exp)\r
515             else:\r
516                 PredicateList.append(Exp.rstrip(';').rstrip(')').strip())\r
517         i += 1\r
518     \r
519     if PredicateBegin > LogicOpPos:\r
520         while PredicateBegin < len(PES):\r
521             if PES[PredicateBegin].isalnum() or PES[PredicateBegin] == '_':\r
522                 break\r
523             PredicateBegin += 1\r
524         Exp = PES[PredicateBegin:len(PES)].strip()\r
525         if p.match(Exp):\r
526             PredicateList.append(Exp)\r
527         else:\r
528             PredicateList.append(Exp.rstrip(';').rstrip(')').strip())\r
529     return PredicateList\r
530     \r
531 def GetCNameList(Lvalue):\r
532     Lvalue += ' '\r
533     i = 0\r
534     SearchBegin = 0\r
535     VarStart = -1\r
536     VarEnd = -1\r
537     VarList = []\r
538     while SearchBegin < len(Lvalue):\r
539         while i < len(Lvalue):\r
540             if Lvalue[i].isalnum() or Lvalue[i] == '_':\r
541                 if VarStart == -1:\r
542                     VarStart = i\r
543                 VarEnd = i\r
544                 i += 1\r
545             elif VarEnd != -1:\r
546                 VarList.append(Lvalue[VarStart:VarEnd+1])\r
547                 i += 1\r
548                 break\r
549             else:\r
550                 i += 1\r
551         if VarEnd == -1:\r
552             break\r
553         \r
554         \r
555         Index = Lvalue[VarEnd:].find('.')\r
556         if Index > 0:\r
557             SearchBegin += VarEnd + Index\r
558         else:\r
559             Index = Lvalue[VarEnd:].find('->')\r
560             if Index > 0:\r
561                 SearchBegin += VarEnd + Index\r
562             else:\r
563                 break\r
564         i = SearchBegin\r
565         VarStart = -1\r
566         VarEnd = -1\r
567     \r
568     return VarList    \r
569 \r
570 def SplitPredicateByOp(Str, Op):\r
571 \r
572     Name = Str.strip()\r
573     Value = None\r
574     \r
575     TmpStr = Str.rstrip(';').rstrip(')')\r
576     while True:\r
577         Index = TmpStr.rfind(Op)\r
578         if Index == -1:\r
579             return [Name]\r
580         \r
581         if Str[Index - 1].isalnum() or Str[Index - 1].isspace() or Str[Index - 1] == ')':\r
582             Name = Str[0:Index].strip()\r
583             Value = Str[Index + len(Op):].strip()\r
584             return [Name, Value]   \r
585     \r
586         TmpStr = Str[0:Index - 1]\r
587 \r
588 def SplitPredicateStr(Str):\r
589     PredPartList = SplitPredicateByOp(Str, '==')\r
590     if len(PredPartList) > 1:\r
591         return [PredPartList, '==']\r
592     \r
593     PredPartList = SplitPredicateByOp(Str, '!=')\r
594     if len(PredPartList) > 1:\r
595         return [PredPartList, '!=']\r
596     \r
597     PredPartList = SplitPredicateByOp(Str, '>=')\r
598     if len(PredPartList) > 1:\r
599         return [PredPartList, '>=']\r
600         \r
601     PredPartList = SplitPredicateByOp(Str, '<=')\r
602     if len(PredPartList) > 1:\r
603         return [PredPartList, '<=']\r
604         \r
605     PredPartList = SplitPredicateByOp(Str, '>')\r
606     if len(PredPartList) > 1:\r
607         return [PredPartList, '>']\r
608         \r
609     PredPartList = SplitPredicateByOp(Str, '<')\r
610     if len(PredPartList) > 1:\r
611         return [PredPartList, '<']\r
612         \r
613     return [[Str, None], None]\r
614 \r
615 def GetFuncContainsPE(ExpLine, ResultSet):\r
616     for Result in ResultSet:\r
617         if Result[0] < ExpLine and Result[1] > ExpLine:\r
618             return Result\r
619     return None\r
620 \r
621 def PatternInModifier(Modifier, SubStr):\r
622     PartList = Modifier.split()\r
623     for Part in PartList:\r
624         if Part == SubStr:\r
625             return True\r
626     return False\r
627 \r
628 def GetDataTypeFromModifier(ModifierStr):\r
629     MList = ModifierStr.split()\r
630     for M in MList:\r
631         if M in EccGlobalData.gConfig.ModifierList:\r
632             MList.remove(M)\r
633             \r
634     ReturnType = ''\r
635     for M in MList:\r
636         ReturnType += M + ' '\r
637     return ReturnType.strip()    \r
638 \r
639 def DiffModifier(Str1, Str2):\r
640     PartList1 = Str1.split()\r
641     PartList2 = Str2.split()\r
642     if PartList1 == PartList2:\r
643         return False\r
644     else:\r
645         return True\r
646     \r
647 def GetTypedefDict(FullFileName):\r
648     \r
649     Dict = ComplexTypeDict.get(FullFileName)\r
650     if Dict != None:\r
651         return Dict\r
652     \r
653     FileID = GetTableID(FullFileName)\r
654     FileTable = 'Identifier' + str(FileID)\r
655     Db = GetDB()\r
656     SqlStatement = """ select Modifier, Name, Value, ID\r
657                        from %s\r
658                        where Model = %d\r
659                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)\r
660     ResultSet = Db.TblFile.Exec(SqlStatement)\r
661     \r
662     Dict = {}\r
663     for Result in ResultSet:\r
664         if len(Result[0]) == 0:\r
665             Dict[Result[1]] = Result[2]\r
666         \r
667     IncludeFileList = GetAllIncludeFiles(FullFileName)\r
668     for F in IncludeFileList:\r
669         FileID = GetTableID(F)\r
670         if FileID < 0:\r
671             continue\r
672     \r
673         FileTable = 'Identifier' + str(FileID)\r
674         SqlStatement = """ select Modifier, Name, Value, ID\r
675                        from %s\r
676                        where Model = %d\r
677                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)\r
678         ResultSet = Db.TblFile.Exec(SqlStatement)\r
679     \r
680         for Result in ResultSet:\r
681             if len(Result[0]) == 0:\r
682                 Dict[Result[1]] = Result[2]\r
683                 \r
684     ComplexTypeDict[FullFileName] = Dict\r
685     return Dict\r
686 \r
687 def GetSUDict(FullFileName):\r
688     \r
689     Dict = SUDict.get(FullFileName)\r
690     if Dict != None:\r
691         return Dict\r
692     \r
693     FileID = GetTableID(FullFileName)\r
694     FileTable = 'Identifier' + str(FileID)\r
695     Db = GetDB()\r
696     SqlStatement = """ select Name, Value, ID\r
697                        from %s\r
698                        where Model = %d or Model = %d\r
699                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION)\r
700     ResultSet = Db.TblFile.Exec(SqlStatement)\r
701     \r
702     Dict = {}\r
703     for Result in ResultSet:\r
704         if len(Result[1]) > 0:\r
705             Dict[Result[0]] = Result[1]\r
706         \r
707     IncludeFileList = GetAllIncludeFiles(FullFileName)\r
708     for F in IncludeFileList:\r
709         FileID = GetTableID(F)\r
710         if FileID < 0:\r
711             continue\r
712     \r
713         FileTable = 'Identifier' + str(FileID)\r
714         SqlStatement = """ select Name, Value, ID\r
715                        from %s\r
716                        where Model = %d or Model = %d\r
717                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_UNION)\r
718         ResultSet = Db.TblFile.Exec(SqlStatement)\r
719     \r
720         for Result in ResultSet:\r
721             if len(Result[1]) > 0:\r
722                 Dict[Result[0]] = Result[1]\r
723                 \r
724     SUDict[FullFileName] = Dict\r
725     return Dict\r
726 \r
727 def GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict):\r
728     Value = TypedefDict.get(Type)\r
729     if Value == None:\r
730         Value = SUDict.get(Type)\r
731     if Value == None:\r
732         return None\r
733     \r
734     LBPos = Value.find('{')\r
735     while LBPos == -1:\r
736         FTList = Value.split()\r
737         for FT in FTList:\r
738             if FT not in ('struct', 'union'):\r
739                 Value = TypedefDict.get(FT)\r
740                 if Value == None:\r
741                     Value = SUDict.get(FT)\r
742                 break\r
743         \r
744         if Value == None:\r
745             return None\r
746      \r
747         LBPos = Value.find('{')\r
748      \r
749 #    RBPos = Value.find('}')\r
750     Fields = Value[LBPos + 1:]\r
751     FieldsList = Fields.split(';')\r
752     for Field in FieldsList:\r
753         Field = Field.strip()\r
754         Index = Field.find(FieldName)\r
755         if Index < 1:\r
756             continue\r
757         if not Field[Index - 1].isalnum():\r
758             if Index + len(FieldName) == len(Field):\r
759                 Type = GetCNameList(Field[0:Index])\r
760                 if len(Type) == 0:\r
761                     return Field[0:Index]\r
762                 return Type[0]\r
763             else:\r
764                 if not Field[Index + len(FieldName) + 1].isalnum():\r
765                     Type = GetCNameList(Field[0:Index])\r
766                     if len(Type) == 0:\r
767                         return Field[0:Index]\r
768                     return Type[0]\r
769     return None\r
770     \r
771 \r
772 def GetTypeInfo(RefList, Modifier, FullFileName):\r
773     TypedefDict = GetTypedefDict(FullFileName)\r
774     SUDict = GetSUDict(FullFileName)\r
775     Type = GetDataTypeFromModifier(Modifier).rstrip('*').strip()\r
776     Index = 0\r
777     while Index < len(RefList):\r
778         FieldName = RefList[Index]\r
779         FromType = GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict)\r
780         if FromType == None:\r
781             return None\r
782         Type = FromType\r
783         Index += 1\r
784 \r
785     return Type\r
786 \r
787 def GetVarInfo(PredVarList, FuncRecord, FullFileName):\r
788     \r
789     PredVar = PredVarList[0]\r
790     FileID = GetTableID(FullFileName)\r
791     \r
792     Db = GetDB()\r
793     FileTable = 'Identifier' + str(FileID)\r
794     # really variable, search local variable first\r
795     SqlStatement = """ select Modifier, ID\r
796                        from %s\r
797                        where Model = %d and Name = \'%s\' and StartLine >= %d and StartLine <= %d\r
798                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar, FuncRecord[0], FuncRecord[1])\r
799     ResultSet = Db.TblFile.Exec(SqlStatement)\r
800     VarFound = False\r
801     for Result in ResultSet:\r
802         if len(PredVarList) > 1:\r
803             Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName)\r
804             return Type\r
805         else:\r
806             Type = GetDataTypeFromModifier(Result[0])\r
807             return Type\r
808                 \r
809     # search function parameters second\r
810     ParamList = GetParamList(FuncRecord[2])\r
811     for Param in ParamList:\r
812         if Param.Name.strip() == PredVar:\r
813             if len(PredVarList) > 1:\r
814                 Type = GetTypeInfo(PredVarList[1:], Param.Modifier, FullFileName)\r
815                 return Type\r
816             else:\r
817                 Type = GetDataTypeFromModifier(Param.Modifier)\r
818                 return Type\r
819           \r
820     # search global variable next\r
821     SqlStatement = """ select Modifier, ID\r
822            from %s\r
823            where Model = %d and Name = \'%s\' and BelongsToFunction = -1\r
824        """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar)\r
825     ResultSet = Db.TblFile.Exec(SqlStatement)\r
826 \r
827     for Result in ResultSet:\r
828         if len(PredVarList) > 1:\r
829             Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName)\r
830             return Type\r
831         else:\r
832             Type = GetDataTypeFromModifier(Result[0])\r
833             return Type\r
834     \r
835     # search variable in include files\r
836     IncludeFileList = GetAllIncludeFiles(FullFileName)\r
837     for F in IncludeFileList:\r
838         FileID = GetTableID(F)\r
839         if FileID < 0:\r
840             continue\r
841     \r
842         FileTable = 'Identifier' + str(FileID)\r
843         SqlStatement = """ select Modifier, ID\r
844                        from %s\r
845                        where Model = %d and BelongsToFunction = -1 and Name = \'%s\'\r
846                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, PredVar)\r
847         ResultSet = Db.TblFile.Exec(SqlStatement)\r
848 \r
849         for Result in ResultSet:\r
850             if len(PredVarList) > 1:\r
851                 Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName)\r
852                 return Type\r
853             else:\r
854                 Type = GetDataTypeFromModifier(Result[0])\r
855                 return Type\r
856 \r
857 def CheckFuncLayoutReturnType(FullFileName):\r
858     ErrorMsgList = []\r
859     \r
860     FileID = GetTableID(FullFileName, ErrorMsgList)\r
861     if FileID < 0:\r
862         return ErrorMsgList\r
863     \r
864     Db = GetDB()\r
865     FileTable = 'Identifier' + str(FileID)\r
866     SqlStatement = """ select Modifier, ID, StartLine, StartColumn, EndLine \r
867                        from %s\r
868                        where Model = %d\r
869                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
870     ResultSet = Db.TblFile.Exec(SqlStatement)\r
871     for Result in ResultSet:\r
872         ReturnType = GetDataTypeFromModifier(Result[0])\r
873         if len(ReturnType) == 0:\r
874             PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, 'Function has No Return Type', FileTable, Result[1])\r
875             continue\r
876         Index = Result[0].find(ReturnType)\r
877         if Index != 0 or Result[3] != 0:\r
878             PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, 'Return Type should appear at the start of line', FileTable, Result[1])\r
879             \r
880         if Result[2] == Result[4]:\r
881             PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, 'Return Type should appear on its own line', FileTable, Result[1])\r
882             \r
883     SqlStatement = """ select Modifier, ID, StartLine, StartColumn, FunNameStartLine\r
884                        from Function\r
885                        where BelongsToFile = %d\r
886                    """ % (FileID)\r
887     ResultSet = Db.TblFile.Exec(SqlStatement)\r
888     for Result in ResultSet:\r
889         ReturnType = GetDataTypeFromModifier(Result[0])\r
890         if len(ReturnType) == 0:\r
891             PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, 'Function has No Return Type', 'Function', Result[1])\r
892             continue\r
893         Index = Result[0].find(ReturnType)\r
894         if Index != 0 or Result[3] != 0:\r
895             PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, 'Return Type should appear at the start of line', 'Function', Result[1])\r
896             \r
897         if Result[2] == Result[4]:\r
898             PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_RETURN_TYPE, 'Return Type should appear on its own line', 'Function', Result[1])\r
899     \r
900 def CheckFuncLayoutModifier(FullFileName):\r
901     ErrorMsgList = []\r
902     \r
903     FileID = GetTableID(FullFileName, ErrorMsgList)\r
904     if FileID < 0:\r
905         return ErrorMsgList\r
906     \r
907     Db = GetDB()\r
908     FileTable = 'Identifier' + str(FileID)\r
909     SqlStatement = """ select Modifier, ID\r
910                        from %s\r
911                        where Model = %d\r
912                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
913     ResultSet = Db.TblFile.Exec(SqlStatement)\r
914     for Result in ResultSet:\r
915         ReturnType = GetDataTypeFromModifier(Result[0])\r
916         if len(ReturnType) == 0:\r
917             continue\r
918         Index = Result[0].find(ReturnType)\r
919         if Index != 0:\r
920             PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', FileTable, Result[1])\r
921             \r
922     SqlStatement = """ select Modifier, ID\r
923                        from Function\r
924                        where BelongsToFile = %d\r
925                    """ % (FileID)\r
926     ResultSet = Db.TblFile.Exec(SqlStatement)\r
927     for Result in ResultSet:\r
928         ReturnType = GetDataTypeFromModifier(Result[0])\r
929         if len(ReturnType) == 0:\r
930             continue\r
931         Index = Result[0].find(ReturnType)\r
932         if Index != 0:\r
933             PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_OPTIONAL_FUNCTIONAL_MODIFIER, '', FileTable, Result[1])\r
934 \r
935 def CheckFuncLayoutName(FullFileName):\r
936     ErrorMsgList = []\r
937     \r
938     FileID = GetTableID(FullFileName, ErrorMsgList)\r
939     if FileID < 0:\r
940         return ErrorMsgList\r
941     \r
942     Db = GetDB()\r
943     FileTable = 'Identifier' + str(FileID)\r
944     SqlStatement = """ select Name, ID, EndColumn\r
945                        from %s\r
946                        where Model = %d\r
947                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
948     ResultSet = Db.TblFile.Exec(SqlStatement)\r
949     for Result in ResultSet:\r
950         if Result[2] != 0:\r
951                 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name should appear at the start of a line', FileTable, Result[1])\r
952         ParamList = GetParamList(Result[0])\r
953         if len(ParamList) == 0:\r
954             continue\r
955         StartLine = 0\r
956         for Param in ParamList:\r
957             if Param.StartLine <= StartLine:\r
958                 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, FileTable, Result[1])\r
959             StartLine = Param.StartLine\r
960             if not Result[0].endswith('\n  )') and not Result[0].endswith('\r  )'):\r
961                 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', FileTable, Result[1])\r
962             \r
963     SqlStatement = """ select Modifier, ID, FunNameStartColumn\r
964                        from Function\r
965                        where BelongsToFile = %d\r
966                    """ % (FileID)\r
967     ResultSet = Db.TblFile.Exec(SqlStatement)\r
968     for Result in ResultSet:\r
969         if Result[2] != 0:\r
970                 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Function name should appear at the start of a line', FileTable, Result[1])\r
971         ParamList = GetParamList(Result[0])\r
972         if len(ParamList) == 0:\r
973             continue\r
974         StartLine = 0\r
975         for Param in ParamList:\r
976             if Param.StartLine <= StartLine:\r
977                 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, 'Parameter %s should be in its own line.' % Param.Name, 'Function', Result[1])\r
978             StartLine = Param.StartLine\r
979             if not Result[0].endswith('\n  )') and not Result[0].endswith('\r  )'):\r
980                 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_NAME, '\')\' should be on a new line and indented two spaces', 'Function', Result[1])\r
981 \r
982 def CheckFuncLayoutPrototype(FullFileName):\r
983     ErrorMsgList = []\r
984     \r
985     FileID = GetTableID(FullFileName, ErrorMsgList)\r
986     if FileID < 0:\r
987         return ErrorMsgList\r
988     \r
989     FileTable = 'Identifier' + str(FileID)\r
990     Db = GetDB()\r
991     SqlStatement = """ select Modifier, Header, Name, ID\r
992                        from Function\r
993                        where BelongsToFile = %d\r
994                    """ % (FileID)\r
995     ResultSet = Db.TblFile.Exec(SqlStatement)\r
996     if len(ResultSet) == 0:\r
997         return ErrorMsgList\r
998     \r
999     FuncDefList = []\r
1000     for Result in ResultSet:\r
1001         FuncDefList.append(Result)\r
1002         \r
1003     SqlStatement = """ select Modifier, Name, ID\r
1004                        from %s\r
1005                        where Model = %d\r
1006                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1007     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1008     FuncDeclList = []\r
1009     for Result in ResultSet:\r
1010         FuncDeclList.append(Result)\r
1011     \r
1012     IncludeFileList = GetAllIncludeFiles(FullFileName)\r
1013     for F in IncludeFileList:\r
1014         FileID = GetTableID(F, ErrorMsgList)\r
1015         if FileID < 0:\r
1016             continue\r
1017     \r
1018         FileTable = 'Identifier' + str(FileID)\r
1019         SqlStatement = """ select Modifier, Name, ID\r
1020                        from %s\r
1021                        where Model = %d\r
1022                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1023         ResultSet = Db.TblFile.Exec(SqlStatement)\r
1024 \r
1025         for Result in ResultSet:\r
1026             FuncDeclList.append(Result)\r
1027     \r
1028     for FuncDef in FuncDefList:\r
1029         FuncName = FuncDef[2].strip()\r
1030         FuncModifier = FuncDef[0]\r
1031         FuncDefHeader = FuncDef[1]\r
1032         for FuncDecl in FuncDeclList:\r
1033             LBPos = FuncDecl[1].find('(')\r
1034             DeclName = FuncDecl[1][0:LBPos].strip()\r
1035             DeclModifier = FuncDecl[0]\r
1036             if DeclName == FuncName:\r
1037                 if DiffModifier(FuncModifier, DeclModifier):\r
1038                     PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Function modifier different with prototype.', 'Function', FuncDef[3])\r
1039                 ParamListOfDef = GetParamList(FuncDefHeader)\r
1040                 ParamListOfDecl = GetParamList(FuncDecl[1])\r
1041                 if len(ParamListOfDef) != len(ParamListOfDecl):\r
1042                     PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Parameter number different.', 'Function', FuncDef[3])\r
1043                     break\r
1044 \r
1045                 Index = 0\r
1046                 while Index < len(ParamListOfDef):\r
1047                     if DiffModifier(ParamListOfDef[Index].Modifier, ParamListOfDecl[Index].Modifier):\r
1048                         PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_PROTO_TYPE, 'Parameter %s has different modifier with prototype.' % ParamListOfDef[Index].Name, 'Function', FuncDef[3])\r
1049                     Index += 1\r
1050                 break\r
1051     \r
1052 def CheckFuncLayoutBody(FullFileName):\r
1053     ErrorMsgList = []\r
1054     \r
1055     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1056     if FileID < 0:\r
1057         return ErrorMsgList\r
1058     \r
1059     FileTable = 'Identifier' + str(FileID)\r
1060     Db = GetDB()\r
1061     SqlStatement = """ select BodyStartColumn, EndColumn, ID\r
1062                        from Function\r
1063                        where BelongsToFile = %d\r
1064                    """ % (FileID)\r
1065     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1066     if len(ResultSet) == 0:\r
1067         return ErrorMsgList\r
1068     for Result in ResultSet:\r
1069         if Result[0] != 0:\r
1070             PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'open brace should be at the very beginning of a line.', 'Function', Result[2])\r
1071         if Result[1] != 0:\r
1072             PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_FUNCTION_BODY, 'close brace should be at the very beginning of a line.', 'Function', Result[2])\r
1073 \r
1074 def CheckFuncLayoutLocalVariable(FullFileName):\r
1075     ErrorMsgList = []\r
1076     \r
1077     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1078     if FileID < 0:\r
1079         return ErrorMsgList\r
1080     \r
1081     Db = GetDB()\r
1082     FileTable = 'Identifier' + str(FileID)\r
1083     SqlStatement = """ select ID\r
1084                        from Function\r
1085                        where BelongsToFile = %d\r
1086                    """ % (FileID)\r
1087     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1088     if len(ResultSet) == 0:\r
1089         return ErrorMsgList\r
1090     FL = []\r
1091     for Result in ResultSet:\r
1092         FL.append(Result)\r
1093         \r
1094     for F in FL:\r
1095         SqlStatement = """ select Name, Value, ID\r
1096                        from %s\r
1097                        where Model = %d and BelongsToFunction = %d\r
1098                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE, F[0])\r
1099         ResultSet = Db.TblFile.Exec(SqlStatement)\r
1100         if len(ResultSet) == 0:\r
1101             continue\r
1102         \r
1103         for Result in ResultSet:\r
1104             if len(Result[1]) > 0:\r
1105                 PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE, 'Variable Name: %s' % Result[0], FileTable, Result[2])\r
1106         \r
1107 \r
1108 def CheckDeclTypedefFormat(FullFileName, ModelId):\r
1109     ErrorMsgList = []\r
1110     \r
1111     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1112     if FileID < 0:\r
1113         return ErrorMsgList\r
1114     \r
1115     Db = GetDB()\r
1116     FileTable = 'Identifier' + str(FileID)\r
1117     SqlStatement = """ select Name, StartLine, EndLine, ID\r
1118                        from %s\r
1119                        where Model = %d\r
1120                    """ % (FileTable, ModelId)\r
1121     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1122     ResultList = []\r
1123     for Result in ResultSet:\r
1124         ResultList.append(Result)\r
1125     \r
1126     ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ALL\r
1127     if ModelId == DataClass.MODEL_IDENTIFIER_STRUCTURE:\r
1128         ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_STRUCTURE_DECLARATION\r
1129     if ModelId == DataClass.MODEL_IDENTIFIER_ENUMERATE:\r
1130         ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_ENUMERATED_TYPE\r
1131     if ModelId == DataClass.MODEL_IDENTIFIER_UNION:\r
1132         ErrorType = ERROR_DECLARATION_DATA_TYPE_CHECK_UNION_TYPE\r
1133     \r
1134     SqlStatement = """ select Modifier, Name, Value, StartLine, EndLine, ID\r
1135                        from %s\r
1136                        where Model = %d\r
1137                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_TYPEDEF)\r
1138     TdSet = Db.TblFile.Exec(SqlStatement)\r
1139     \r
1140     for Result in ResultList:\r
1141         Found = False\r
1142         for Td in TdSet:\r
1143             if len(Td[0]) > 0:\r
1144                 continue\r
1145             if Result[1] >= Td[3] and Td[4] >= Result[2]:\r
1146                 Found = True\r
1147                 if not Td[1].isupper():\r
1148                     PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])\r
1149             if Result[0] in Td[2].split():\r
1150                 Found = True\r
1151                 if not Td[1].isupper():\r
1152                     PrintErrorMsg(ErrorType, 'Typedef should be UPPER case', FileTable, Td[5])\r
1153         \r
1154         if not Found:\r
1155             PrintErrorMsg(ErrorType, 'No Typedef for %s' % Result[0], FileTable, Result[3])\r
1156             continue\r
1157                 \r
1158 def CheckDeclStructTypedef(FullFileName):\r
1159     CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_STRUCTURE)\r
1160 \r
1161 def CheckDeclEnumTypedef(FullFileName):\r
1162     CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_ENUMERATE)\r
1163     \r
1164 def CheckDeclUnionTypedef(FullFileName):\r
1165     CheckDeclTypedefFormat(FullFileName, DataClass.MODEL_IDENTIFIER_UNION)\r
1166 \r
1167 def CheckDeclArgModifier(FullFileName):\r
1168     ErrorMsgList = []\r
1169     \r
1170     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1171     if FileID < 0:\r
1172         return ErrorMsgList\r
1173     \r
1174     Db = GetDB()\r
1175     FileTable = 'Identifier' + str(FileID)\r
1176     SqlStatement = """ select Modifier, Name, ID\r
1177                        from %s\r
1178                        where Model = %d\r
1179                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)\r
1180     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1181     ModifierTuple = ('IN', 'OUT', 'OPTIONAL', 'UNALIGNED')\r
1182     MAX_MODIFIER_LENGTH = 100\r
1183     for Result in ResultSet:\r
1184         for Modifier in ModifierTuple:\r
1185             if PatternInModifier(Result[0], Modifier) and len(Result[0]) < MAX_MODIFIER_LENGTH:\r
1186                 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Variable Modifier %s' % Result[0], FileTable, Result[2])\r
1187                 break\r
1188     \r
1189     SqlStatement = """ select Modifier, Name, ID\r
1190                        from %s\r
1191                        where Model = %d\r
1192                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1193     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1194     for Result in ResultSet:\r
1195         for Modifier in ModifierTuple:\r
1196             if PatternInModifier(Result[0], Modifier):\r
1197                 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])\r
1198                 break\r
1199                     \r
1200     SqlStatement = """ select Modifier, Header, ID\r
1201                        from Function\r
1202                        where BelongsToFile = %d\r
1203                    """ % (FileID)\r
1204     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1205     for Result in ResultSet:\r
1206         for Modifier in ModifierTuple:\r
1207             if PatternInModifier(Result[0], Modifier):\r
1208                 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_IN_OUT_MODIFIER, 'Return Type Modifier %s' % Result[0], FileTable, Result[2])\r
1209                 break\r
1210 \r
1211 def CheckDeclNoUseCType(FullFileName):\r
1212     ErrorMsgList = []\r
1213     \r
1214     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1215     if FileID < 0:\r
1216         return ErrorMsgList\r
1217     \r
1218     Db = GetDB()\r
1219     FileTable = 'Identifier' + str(FileID)\r
1220     SqlStatement = """ select Modifier, Name, ID\r
1221                        from %s\r
1222                        where Model = %d\r
1223                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)\r
1224     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1225     CTypeTuple = ('int', 'unsigned', 'char', 'void', 'static', 'long')\r
1226     for Result in ResultSet:\r
1227         for Type in CTypeTuple:\r
1228             if PatternInModifier(Result[0], Type):\r
1229                 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Variable type %s' % Type, FileTable, Result[2])\r
1230                 break\r
1231     \r
1232     SqlStatement = """ select Modifier, Name, ID\r
1233                        from %s\r
1234                        where Model = %d\r
1235                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1236     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1237     for Result in ResultSet:\r
1238         ParamList = GetParamList(Result[1])\r
1239         for Type in CTypeTuple:\r
1240             if PatternInModifier(Result[0], Type):\r
1241                 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Return type %s' % Result[0], FileTable, Result[2])\r
1242             \r
1243             for Param in ParamList:\r
1244                 if PatternInModifier(Param.Modifier, Type):\r
1245                     PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])\r
1246                     \r
1247     SqlStatement = """ select Modifier, Header, ID\r
1248                        from Function\r
1249                        where BelongsToFile = %d\r
1250                    """ % (FileID)\r
1251     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1252     for Result in ResultSet:\r
1253         ParamList = GetParamList(Result[1])\r
1254         for Type in CTypeTuple:\r
1255             if PatternInModifier(Result[0], Type):\r
1256                 PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Return type %s' % Result[0], FileTable, Result[2])\r
1257             \r
1258             for Param in ParamList:\r
1259                 if PatternInModifier(Param.Modifier, Type):\r
1260                     PrintErrorMsg(ERROR_DECLARATION_DATA_TYPE_CHECK_NO_USE_C_TYPE, 'Parameter %s' % Param.Name, FileTable, Result[2])\r
1261             \r
1262 \r
1263 def CheckPointerNullComparison(FullFileName):\r
1264     ErrorMsgList = []\r
1265     \r
1266     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1267     if FileID < 0:\r
1268         return ErrorMsgList\r
1269     \r
1270     Db = GetDB()\r
1271     FileTable = 'Identifier' + str(FileID)\r
1272     SqlStatement = """ select Value, StartLine, ID\r
1273                        from %s\r
1274                        where Model = %d\r
1275                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)\r
1276     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1277     if len(ResultSet) == 0:\r
1278         return\r
1279     PSL = []\r
1280     for Result in ResultSet:\r
1281         PSL.append([Result[0], Result[1], Result[2]])\r
1282     \r
1283     SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID\r
1284                        from Function\r
1285                        where BelongsToFile = %d\r
1286                    """ % (FileID)\r
1287     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1288     FL = []\r
1289     for Result in ResultSet:\r
1290         FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])\r
1291     \r
1292     p = GetFuncDeclPattern()\r
1293     for Str in PSL:\r
1294         FuncRecord = GetFuncContainsPE(Str[1], FL)\r
1295         if FuncRecord == None:\r
1296             continue\r
1297         \r
1298         for Exp in GetPredicateListFromPredicateExpStr(Str[0]):\r
1299             PredInfo = SplitPredicateStr(Exp)\r
1300             if PredInfo[1] == None:\r
1301                 PredVarList = GetCNameList(PredInfo[0][0])\r
1302                 # No variable found, maybe value first? like (0 == VarName)\r
1303                 if len(PredVarList) == 0:\r
1304                     continue\r
1305                 # in the form of function call\r
1306                 if p.match(PredInfo[0][0]):\r
1307                     continue\r
1308                 \r
1309                 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName)\r
1310                 if Type == None:\r
1311                     continue\r
1312                 if Type.find('*') != -1:\r
1313                     PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_COMPARISON_NULL_TYPE, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
1314 \r
1315 def CheckNonBooleanValueComparison(FullFileName):\r
1316     ErrorMsgList = []\r
1317     \r
1318     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1319     if FileID < 0:\r
1320         return ErrorMsgList\r
1321     \r
1322     Db = GetDB()\r
1323     FileTable = 'Identifier' + str(FileID)\r
1324     SqlStatement = """ select Value, StartLine, ID\r
1325                        from %s\r
1326                        where Model = %d\r
1327                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)\r
1328     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1329     if len(ResultSet) == 0:\r
1330         return\r
1331     PSL = []\r
1332     for Result in ResultSet:\r
1333         PSL.append([Result[0], Result[1], Result[2]])\r
1334     \r
1335     SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID\r
1336                        from Function\r
1337                        where BelongsToFile = %d\r
1338                    """ % (FileID)\r
1339     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1340     FL = []\r
1341     for Result in ResultSet:\r
1342         FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])\r
1343     \r
1344     p = GetFuncDeclPattern()\r
1345     for Str in PSL:\r
1346         FuncRecord = GetFuncContainsPE(Str[1], FL)\r
1347         if FuncRecord == None:\r
1348             continue\r
1349         \r
1350         for Exp in GetPredicateListFromPredicateExpStr(Str[0]):\r
1351             if p.match(Exp):\r
1352                 continue\r
1353             PredInfo = SplitPredicateStr(Exp)\r
1354             if PredInfo[1] == None:\r
1355                 PredVarList = GetCNameList(PredInfo[0][0])\r
1356                 # No variable found, maybe value first? like (0 == VarName)\r
1357                 if len(PredVarList) == 0:\r
1358                     continue\r
1359                 # in the form of function call\r
1360                 if p.match(PredInfo[0][0]):\r
1361                     continue\r
1362                 \r
1363                 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName)\r
1364                 if Type == None:\r
1365                     continue\r
1366                 if Type.find('BOOLEAN') == -1:\r
1367                     PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
1368 \r
1369 def CheckBooleanValueComparison(FullFileName):\r
1370     ErrorMsgList = []\r
1371     \r
1372     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1373     if FileID < 0:\r
1374         return ErrorMsgList\r
1375     \r
1376     Db = GetDB()\r
1377     FileTable = 'Identifier' + str(FileID)\r
1378     SqlStatement = """ select Value, StartLine, ID\r
1379                        from %s\r
1380                        where Model = %d\r
1381                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_PREDICATE_EXPRESSION)\r
1382     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1383     if len(ResultSet) == 0:\r
1384         return\r
1385     PSL = []\r
1386     for Result in ResultSet:\r
1387         PSL.append([Result[0], Result[1], Result[2]])\r
1388     \r
1389     SqlStatement = """ select BodyStartLine, EndLine, Header, Modifier, ID\r
1390                        from Function\r
1391                        where BelongsToFile = %d\r
1392                    """ % (FileID)\r
1393     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1394     FL = []\r
1395     for Result in ResultSet:\r
1396         FL.append([Result[0], Result[1], Result[2], Result[3], Result[4]])\r
1397     \r
1398     p = GetFuncDeclPattern()\r
1399     for Str in PSL:\r
1400         FuncRecord = GetFuncContainsPE(Str[1], FL)\r
1401         if FuncRecord == None:\r
1402             continue\r
1403         \r
1404         for Exp in GetPredicateListFromPredicateExpStr(Str[0]):\r
1405             PredInfo = SplitPredicateStr(Exp)\r
1406             if PredInfo[1] in ('==', '!=') and PredInfo[0][1] in ('TRUE', 'FALSE'):\r
1407                 PredVarList = GetCNameList(PredInfo[0][0])\r
1408                 # No variable found, maybe value first? like (0 == VarName)\r
1409                 if len(PredVarList) == 0:\r
1410                     continue\r
1411                 # in the form of function call\r
1412                 if p.match(PredInfo[0][0]):\r
1413                     continue\r
1414                 \r
1415                 Type = GetVarInfo(PredVarList, FuncRecord, FullFileName)\r
1416                 if Type == None:\r
1417                     continue\r
1418                 if Type.find('BOOLEAN') != -1:\r
1419                     PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
1420                 \r
1421 \r
1422 def CheckHeaderFileData(FullFileName):\r
1423     ErrorMsgList = []\r
1424     \r
1425     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1426     if FileID < 0:\r
1427         return ErrorMsgList\r
1428     \r
1429     Db = GetDB()\r
1430     FileTable = 'Identifier' + str(FileID)\r
1431     SqlStatement = """ select ID, Modifier\r
1432                        from %s\r
1433                        where Model = %d\r
1434                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_VARIABLE)\r
1435     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1436     for Result in ResultSet:\r
1437         if not Result[1].startswith('extern'):\r
1438             PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Variable definition appears in header file', FileTable, Result[0])\r
1439         \r
1440     SqlStatement = """ select ID\r
1441                        from Function\r
1442                        where BelongsToFile = %d\r
1443                    """ % FileID\r
1444     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1445     for Result in ResultSet:\r
1446         PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_DATA, 'Function definition appears in header file', 'Function', Result[0])\r
1447 \r
1448     return ErrorMsgList\r
1449 \r
1450 def CheckHeaderFileIfndef(FullFileName):\r
1451     ErrorMsgList = []\r
1452     \r
1453     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1454     if FileID < 0:\r
1455         return ErrorMsgList\r
1456     \r
1457     Db = GetDB()\r
1458     FileTable = 'Identifier' + str(FileID)\r
1459     SqlStatement = """ select Value, StartLine\r
1460                        from %s\r
1461                        where Model = %d order by StartLine\r
1462                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF)\r
1463     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1464     if len(ResultSet) == 0:\r
1465         PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_1, '', 'File', FileID)\r
1466         return ErrorMsgList\r
1467     for Result in ResultSet:\r
1468         SqlStatement = """ select Value, EndLine\r
1469                        from %s\r
1470                        where EndLine < %d\r
1471                    """ % (FileTable, Result[1])\r
1472         ResultSet = Db.TblFile.Exec(SqlStatement)\r
1473         for Result in ResultSet:\r
1474             if not Result[0].startswith('/*') and not Result[0].startswith('//'):\r
1475                 PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_2, '', 'File', FileID)\r
1476         break\r
1477     \r
1478     SqlStatement = """ select Value\r
1479                        from %s\r
1480                        where StartLine > (select max(EndLine) from %s where Model = %d)\r
1481                    """ % (FileTable, FileTable, DataClass.MODEL_IDENTIFIER_MACRO_ENDIF)\r
1482     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1483     for Result in ResultSet:\r
1484         if not Result[0].startswith('/*') and not Result[0].startswith('//'):\r
1485             PrintErrorMsg(ERROR_INCLUDE_FILE_CHECK_IFNDEF_STATEMENT_3, '', 'File', FileID)\r
1486     return ErrorMsgList\r
1487 \r
1488 def CheckDoxygenCommand(FullFileName):\r
1489     ErrorMsgList = []\r
1490     \r
1491     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1492     if FileID < 0:\r
1493         return ErrorMsgList\r
1494     \r
1495     Db = GetDB()\r
1496     FileTable = 'Identifier' + str(FileID)\r
1497     SqlStatement = """ select Value, ID\r
1498                        from %s\r
1499                        where Model = %d or Model = %d\r
1500                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)\r
1501     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1502     DoxygenCommandList = ['bug', 'todo', 'example', 'file', 'attention', 'param', 'post', 'pre', 'retval', 'return', 'sa', 'since', 'test', 'note', 'par']\r
1503     for Result in ResultSet:\r
1504         CommentStr = Result[0]\r
1505         CommentPartList = CommentStr.split()\r
1506         for Part in CommentPartList:\r
1507             if Part.upper() == 'BUGBUG':\r
1508                 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Bug should be marked with doxygen tag @bug', FileTable, Result[1])\r
1509             if Part.upper() == 'TODO':\r
1510                 PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'ToDo should be marked with doxygen tag @todo', FileTable, Result[1])\r
1511             if Part.startswith('@'):\r
1512                 if Part.lstrip('@').isalpha():\r
1513                     if Part.lstrip('@') not in DoxygenCommandList:\r
1514                         PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])\r
1515                 else:\r
1516                     Index = Part.find('[')\r
1517                     if Index == -1:\r
1518                         PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])\r
1519                     RealCmd = Part[1:Index]\r
1520                     if RealCmd not in DoxygenCommandList:\r
1521                         PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMAND, 'Unknown doxygen command %s' % Part, FileTable, Result[1])\r
1522         \r
1523     \r
1524 def CheckDoxygenTripleForwardSlash(FullFileName):\r
1525     ErrorMsgList = []\r
1526     \r
1527     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1528     if FileID < 0:\r
1529         return ErrorMsgList\r
1530     \r
1531     Db = GetDB()\r
1532     FileTable = 'Identifier' + str(FileID)\r
1533     SqlStatement = """ select Value, ID, StartLine\r
1534                        from %s\r
1535                        where Model = %d or Model = %d\r
1536                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)\r
1537     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1538     CommentSet = []\r
1539     try:\r
1540         for Result in ResultSet:\r
1541             CommentSet.append(Result)\r
1542     except:\r
1543         print 'Unrecognized chars in comment of file %s', FullFileName\r
1544     \r
1545     SqlStatement = """ select ID, StartLine, EndLine\r
1546                        from %s\r
1547                        where Model = %d or Model = %d or Model = %d\r
1548                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_STRUCTURE, DataClass.MODEL_IDENTIFIER_ENUMERATE, DataClass.MODEL_IDENTIFIER_UNION)\r
1549     SUEResultSet = Db.TblFile.Exec(SqlStatement)\r
1550     \r
1551     for Result in CommentSet:\r
1552         CommentStr = Result[0]\r
1553         StartLine = Result[2]\r
1554         if not CommentStr.startswith('///<'):\r
1555             continue\r
1556         if len(ResultSet) == 0:\r
1557             PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT, '', FileTable, Result[1])\r
1558             continue\r
1559         Found = False\r
1560         for SUE in SUEResultSet:\r
1561             if StartLine > SUE[1] and StartLine < SUE[2]:\r
1562                 Found = True\r
1563                 break\r
1564         if not Found:\r
1565             PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_FORMAT, '', FileTable, Result[1])\r
1566 \r
1567 \r
1568 def CheckFileHeaderDoxygenComments(FullFileName):\r
1569     ErrorMsgList = []\r
1570     \r
1571     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1572     if FileID < 0:\r
1573         return ErrorMsgList\r
1574     \r
1575     Db = GetDB()\r
1576     FileTable = 'Identifier' + str(FileID)\r
1577     SqlStatement = """ select Value, ID\r
1578                        from %s\r
1579                        where Model = %d and StartLine = 1 and StartColumn = 0\r
1580                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)\r
1581     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1582     if len(ResultSet) == 0:\r
1583         PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'No Comment appear at the very beginning of file.', 'File', FileID)\r
1584         return ErrorMsgList\r
1585     \r
1586     for Result in ResultSet:\r
1587         CommentStr = Result[0]\r
1588         if not CommentStr.startswith('/** @file'):\r
1589             PrintErrorMsg(ERROR_DOXYGEN_CHECK_FILE_HEADER, 'File header comment should begin with ""/** @file""', FileTable, Result[1])\r
1590         if not CommentStr.endswith('**/'):\r
1591             PrintErrorMsg(ERROR_HEADER_CHECK_FILE, 'File header comment should end with **/', FileTable, Result[1])\r
1592         if CommentStr.find('.') == -1:\r
1593             PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period \'.\'', FileTable, Result[1])\r
1594 \r
1595 def CheckFuncHeaderDoxygenComments(FullFileName):\r
1596     ErrorMsgList = []\r
1597     \r
1598     FileID = GetTableID(FullFileName, ErrorMsgList)\r
1599     if FileID < 0:\r
1600         return ErrorMsgList\r
1601     \r
1602     Db = GetDB()\r
1603     FileTable = 'Identifier' + str(FileID)\r
1604     SqlStatement = """ select Value, StartLine, EndLine, ID\r
1605                        from %s\r
1606                        where Model = %d\r
1607                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_COMMENT)\r
1608     \r
1609     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1610     CommentSet = []\r
1611     try:\r
1612         for Result in ResultSet:\r
1613             CommentSet.append(Result)\r
1614     except:\r
1615         print 'Unrecognized chars in comment of file %s', FullFileName\r
1616     \r
1617     # Func Decl check\r
1618     SqlStatement = """ select Modifier, Name, StartLine, ID\r
1619                        from %s\r
1620                        where Model = %d\r
1621                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION)\r
1622     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1623     for Result in ResultSet:\r
1624         FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)\r
1625         if FunctionHeaderComment:\r
1626             CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)\r
1627         else:\r
1628             ErrorMsgList.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result[2], Result[1]))\r
1629             PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function %s has NO comment immediately preceding it.' % (Result[1]), FileTable, Result[3])\r
1630     \r
1631     # Func Def check\r
1632     SqlStatement = """ select Value, StartLine, EndLine, ID\r
1633                        from %s\r
1634                        where Model = %d\r
1635                    """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_HEADER)\r
1636     \r
1637     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1638     CommentSet = []\r
1639     try:\r
1640         for Result in ResultSet:\r
1641             CommentSet.append(Result)\r
1642     except:\r
1643         print 'Unrecognized chars in comment of file %s', FullFileName\r
1644     \r
1645     SqlStatement = """ select Modifier, Header, StartLine, ID\r
1646                        from Function\r
1647                        where BelongsToFile = %d\r
1648                    """ % (FileID)\r
1649     ResultSet = Db.TblFile.Exec(SqlStatement)\r
1650     for Result in ResultSet:\r
1651         FunctionHeaderComment = CheckCommentImmediatelyPrecedeFunctionHeader(Result[1], Result[2], CommentSet)\r
1652         if FunctionHeaderComment:\r
1653             CheckFunctionHeaderConsistentWithDoxygenComment(Result[0], Result[1], Result[2], FunctionHeaderComment[0], FunctionHeaderComment[1], ErrorMsgList, FunctionHeaderComment[3], FileTable)\r
1654         else:\r
1655             ErrorMsgList.append('Line %d :Function %s has NO comment immediately preceding it.' % (Result[2], Result[1]))\r
1656             PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'Function %s has NO comment immediately preceding it.' % (Result[1]), 'Function', Result[3])\r
1657     return ErrorMsgList\r
1658 \r
1659 def CheckCommentImmediatelyPrecedeFunctionHeader(FuncName, FuncStartLine, CommentSet):\r
1660 \r
1661     for Comment in CommentSet:\r
1662         if Comment[2] == FuncStartLine - 1:\r
1663             return Comment\r
1664     return None\r
1665 \r
1666 def GetDoxygenStrFromComment(Str):\r
1667     DoxygenStrList = []\r
1668     ParamTagList = Str.split('@param')\r
1669     if len(ParamTagList) > 1:\r
1670         i = 1\r
1671         while i < len(ParamTagList):\r
1672             DoxygenStrList.append('@param' + ParamTagList[i])\r
1673             i += 1\r
1674     \r
1675     Str = ParamTagList[0]\r
1676             \r
1677     RetvalTagList = ParamTagList[-1].split('@retval')\r
1678     if len(RetvalTagList) > 1:\r
1679         if len(ParamTagList) > 1:\r
1680             DoxygenStrList[-1] = '@param' + RetvalTagList[0]\r
1681         i = 1\r
1682         while i < len(RetvalTagList):\r
1683             DoxygenStrList.append('@retval' + RetvalTagList[i])\r
1684             i += 1\r
1685     \r
1686     if len(DoxygenStrList) > 0:\r
1687         DoxygenStrList[-1] = DoxygenStrList[-1].rstrip('--*/')\r
1688     \r
1689     return DoxygenStrList\r
1690     \r
1691 def CheckGeneralDoxygenCommentLayout(Str, StartLine, ErrorMsgList, CommentId = -1, TableName = ''):\r
1692     #/** --*/ @retval after @param\r
1693     if not Str.startswith('/**'):\r
1694         ErrorMsgList.append('Line %d : Comment does NOT have prefix /** ' % StartLine)\r
1695         PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have prefix /** ', TableName, CommentId)\r
1696     if not Str.endswith('**/'):\r
1697         ErrorMsgList.append('Line %d : Comment does NOT have tail **/ ' % StartLine)\r
1698         PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Comment does NOT have tail **/ ', TableName, CommentId)\r
1699     FirstRetvalIndex = Str.find('@retval')\r
1700     LastParamIndex = Str.rfind('@param')\r
1701     if (FirstRetvalIndex > 0) and (LastParamIndex > 0) and (FirstRetvalIndex < LastParamIndex):\r
1702         ErrorMsgList.append('Line %d : @retval appear before @param ' % StartLine)\r
1703         PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, @retval appear before @param  ', TableName, CommentId)\r
1704     \r
1705 def CheckFunctionHeaderConsistentWithDoxygenComment(FuncModifier, FuncHeader, FuncStartLine, CommentStr, CommentStartLine, ErrorMsgList, CommentId = -1, TableName = ''):\r
1706     \r
1707     ParamList = GetParamList(FuncHeader) \r
1708     CheckGeneralDoxygenCommentLayout(CommentStr, CommentStartLine, ErrorMsgList, CommentId, TableName)\r
1709     DescriptionStr = CommentStr\r
1710     DoxygenStrList = GetDoxygenStrFromComment(DescriptionStr)\r
1711     if DescriptionStr.find('.') == -1:\r
1712         PrintErrorMsg(ERROR_DOXYGEN_CHECK_COMMENT_DESCRIPTION, 'Comment description should end with period \'.\'', TableName, CommentId)\r
1713     DoxygenTagNumber = len(DoxygenStrList)\r
1714     ParamNumber = len(ParamList)\r
1715     for Param in ParamList:\r
1716         if Param.Name.upper() == 'VOID':\r
1717             ParamNumber -= 1\r
1718     Index = 0\r
1719     if ParamNumber > 0 and DoxygenTagNumber > 0:\r
1720         while Index < ParamNumber and Index < DoxygenTagNumber:\r
1721             ParamModifier = ParamList[Index].Modifier\r
1722             ParamName = ParamList[Index].Name.strip()\r
1723             Tag = DoxygenStrList[Index].strip(' ')\r
1724             if (not Tag[-1] == ('\n')) and (not Tag[-1] == ('\r')):\r
1725                 ErrorMsgList.append('Line %d : in Comment, \"%s\" does NOT end with new line ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))\r
1726                 PrintErrorMsg(ERROR_HEADER_CHECK_FUNCTION, 'in Comment, \"%s\" does NOT end with new line ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)\r
1727             TagPartList = Tag.split()\r
1728             if len(TagPartList) < 2:\r
1729                 ErrorMsgList.append('Line %d : in Comment, \"%s\" does NOT contain doxygen contents ' % (CommentStartLine, Tag.replace('\n', '').replace('\r', '')))\r
1730                 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'in Comment, \"%s\" does NOT contain doxygen contents ' % (Tag.replace('\n', '').replace('\r', '')), TableName, CommentId)\r
1731                 Index += 1\r
1732                 continue\r
1733             if Tag.find('[') > 0:\r
1734                 InOutStr = ''\r
1735                 ModifierPartList = ParamModifier.split()\r
1736                 for Part in ModifierPartList:\r
1737                     if Part.strip() == 'IN':\r
1738                         InOutStr += 'in'\r
1739                     if Part.strip() == 'OUT':\r
1740                         if InOutStr != '':    \r
1741                             InOutStr += ', out'\r
1742                         else:\r
1743                             InOutStr = 'out'\r
1744                 \r
1745                 if InOutStr != '':\r
1746                     if Tag.find('['+InOutStr+']') == -1:\r
1747                         ErrorMsgList.append('Line %d : in Comment, \"%s\" does NOT have %s ' % (CommentStartLine, (TagPartList[0] + ' ' +TagPartList[1]).replace('\n', '').replace('\r', ''), '['+InOutStr+']'))    \r
1748                         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
1749             if Tag.find(ParamName) == -1 and ParamName != 'VOID' and ParamName != 'void':\r
1750                 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
1751                 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
1752             Index += 1\r
1753         \r
1754         if Index < ParamNumber:\r
1755             ErrorMsgList.append('Line %d : Number of doxygen tags in comment less than number of function parameters' % CommentStartLine)\r
1756             PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of doxygen tags in comment less than number of function parameters ', TableName, CommentId)\r
1757         if FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1:\r
1758             if Index < DoxygenTagNumber - 1:\r
1759                 ErrorMsgList.append('Line %d : Excessive doxygen tags in comment' % CommentStartLine)\r
1760                 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Excessive doxygen tags in comment ', TableName, CommentId)\r
1761         else:\r
1762             if Index < DoxygenTagNumber and not DoxygenStrList[Index].startswith('@retval'): \r
1763                 ErrorMsgList.append('Line %d : Number of @param doxygen tags in comment does NOT match number of function parameters' % CommentStartLine)\r
1764                 PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Number of @param doxygen tags in comment does NOT match number of function parameters ', TableName, CommentId)\r
1765     else:\r
1766         if ParamNumber == 0 and DoxygenTagNumber != 0 and (FuncModifier.find('VOID') != -1 or FuncModifier.find('void') != -1):\r
1767             ErrorMsgList.append('Line %d : Excessive doxygen tags in comment' % CommentStartLine)\r
1768             PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'Excessive doxygen tags in comment ', TableName, CommentId)\r
1769         if ParamNumber != 0 and DoxygenTagNumber == 0:\r
1770             ErrorMsgList.append('Line %d : No doxygen tags in comment' % CommentStartLine)\r
1771             PrintErrorMsg(ERROR_DOXYGEN_CHECK_FUNCTION_HEADER, 'No doxygen tags in comment ', TableName, CommentId)\r
1772 \r
1773 if __name__ == '__main__':\r
1774 \r
1775 #    EdkLogger.Initialize()\r
1776 #    EdkLogger.SetLevel(EdkLogger.QUIET)\r
1777 #    CollectSourceCodeDataIntoDB(sys.argv[1])       \r
1778     MsgList = CheckFuncHeaderDoxygenComments('C:\\Combo\\R9\\LakeportX64Dev\\FlashDevicePkg\\Library\\SpiFlashChipM25P64\\SpiFlashChipM25P64.c')\r
1779     for Msg in MsgList:\r
1780         print Msg\r
1781     print 'Done!'\r