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