]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/UPT/Library/CommentParsing.py
BaseTools/UPT:merge UPT Tool use Python2 and Python3
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Library / CommentParsing.py
CommitLineData
4234283c
LG
1## @file\r
2# This file is used to define comment parsing interface\r
3#\r
64285f15 4# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
4234283c 5#\r
f7496d71
LG
6# This program and the accompanying materials are licensed and made available\r
7# under the terms and conditions of the BSD License which accompanies this\r
8# distribution. The full text of the license may be found at\r
4234283c
LG
9# http://opensource.org/licenses/bsd-license.php\r
10#\r
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13#\r
14\r
15'''\r
16CommentParsing\r
17'''\r
18\r
19##\r
20# Import Modules\r
21#\r
22import re\r
23\r
64285f15
YZ
24from Library.StringUtils import GetSplitValueList\r
25from Library.StringUtils import CleanString2\r
4234283c
LG
26from Library.DataType import HEADER_COMMENT_NOT_STARTED\r
27from Library.DataType import TAB_COMMENT_SPLIT\r
28from Library.DataType import HEADER_COMMENT_LICENSE\r
29from Library.DataType import HEADER_COMMENT_ABSTRACT\r
30from Library.DataType import HEADER_COMMENT_COPYRIGHT\r
31from Library.DataType import HEADER_COMMENT_DESCRIPTION\r
32from Library.DataType import TAB_SPACE_SPLIT\r
33from Library.DataType import TAB_COMMA_SPLIT\r
34from Library.DataType import SUP_MODULE_LIST\r
421ccda3
HC
35from Library.DataType import TAB_VALUE_SPLIT\r
36from Library.DataType import TAB_PCD_VALIDRANGE\r
37from Library.DataType import TAB_PCD_VALIDLIST\r
38from Library.DataType import TAB_PCD_EXPRESSION\r
39from Library.DataType import TAB_PCD_PROMPT\r
40from Library.DataType import TAB_CAPHEX_START\r
41from Library.DataType import TAB_HEX_START\r
42from Library.DataType import PCD_ERR_CODE_MAX_SIZE\r
43from Library.ExpressionValidate import IsValidRangeExpr\r
44from Library.ExpressionValidate import IsValidListExpr\r
45from Library.ExpressionValidate import IsValidLogicalExpr\r
4234283c
LG
46from Object.POM.CommonObject import TextObject\r
47from Object.POM.CommonObject import PcdErrorObject\r
48import Logger.Log as Logger\r
49from Logger.ToolError import FORMAT_INVALID\r
50from Logger.ToolError import FORMAT_NOT_SUPPORTED\r
51from Logger import StringTable as ST\r
52\r
53## ParseHeaderCommentSection\r
54#\r
55# Parse Header comment section lines, extract Abstract, Description, Copyright\r
56# , License lines\r
57#\r
58# @param CommentList: List of (Comment, LineNumber)\r
59# @param FileName: FileName of the comment\r
60#\r
421ccda3 61def ParseHeaderCommentSection(CommentList, FileName = None, IsBinaryHeader = False):\r
4234283c
LG
62 Abstract = ''\r
63 Description = ''\r
64 Copyright = ''\r
65 License = ''\r
66 EndOfLine = "\n"\r
421ccda3
HC
67 if IsBinaryHeader:\r
68 STR_HEADER_COMMENT_START = "@BinaryHeader"\r
69 else:\r
70 STR_HEADER_COMMENT_START = "@file"\r
4234283c 71 HeaderCommentStage = HEADER_COMMENT_NOT_STARTED\r
f7496d71 72\r
4234283c
LG
73 #\r
74 # first find the last copyright line\r
75 #\r
76 Last = 0\r
174a9d3c 77 for Index in range(len(CommentList)-1, 0, -1):\r
4234283c
LG
78 Line = CommentList[Index][0]\r
79 if _IsCopyrightLine(Line):\r
80 Last = Index\r
81 break\r
f7496d71 82\r
4234283c
LG
83 for Item in CommentList:\r
84 Line = Item[0]\r
85 LineNo = Item[1]\r
f7496d71 86\r
4234283c
LG
87 if not Line.startswith(TAB_COMMENT_SPLIT) and Line:\r
88 Logger.Error("\nUPT", FORMAT_INVALID, ST.ERR_INVALID_COMMENT_FORMAT, FileName, Item[1])\r
89 Comment = CleanString2(Line)[1]\r
90 Comment = Comment.strip()\r
91 #\r
f7496d71 92 # if there are blank lines between License or Description, keep them as they would be\r
4234283c
LG
93 # indication of different block; or in the position that Abstract should be, also keep it\r
94 # as it indicates that no abstract\r
95 #\r
96 if not Comment and HeaderCommentStage not in [HEADER_COMMENT_LICENSE, \\r
97 HEADER_COMMENT_DESCRIPTION, HEADER_COMMENT_ABSTRACT]:\r
98 continue\r
f7496d71 99\r
4234283c
LG
100 if HeaderCommentStage == HEADER_COMMENT_NOT_STARTED:\r
101 if Comment.startswith(STR_HEADER_COMMENT_START):\r
102 HeaderCommentStage = HEADER_COMMENT_ABSTRACT\r
103 else:\r
104 License += Comment + EndOfLine\r
105 else:\r
106 if HeaderCommentStage == HEADER_COMMENT_ABSTRACT:\r
107 #\r
108 # in case there is no abstract and description\r
109 #\r
110 if not Comment:\r
4234283c
LG
111 HeaderCommentStage = HEADER_COMMENT_DESCRIPTION\r
112 elif _IsCopyrightLine(Comment):\r
113 Result, ErrMsg = _ValidateCopyright(Comment)\r
114 ValidateCopyright(Result, ST.WRN_INVALID_COPYRIGHT, FileName, LineNo, ErrMsg)\r
115 Copyright += Comment + EndOfLine\r
116 HeaderCommentStage = HEADER_COMMENT_COPYRIGHT\r
f7496d71 117 else:\r
4234283c
LG
118 Abstract += Comment + EndOfLine\r
119 HeaderCommentStage = HEADER_COMMENT_DESCRIPTION\r
120 elif HeaderCommentStage == HEADER_COMMENT_DESCRIPTION:\r
121 #\r
122 # in case there is no description\r
f7496d71 123 #\r
4234283c
LG
124 if _IsCopyrightLine(Comment):\r
125 Result, ErrMsg = _ValidateCopyright(Comment)\r
126 ValidateCopyright(Result, ST.WRN_INVALID_COPYRIGHT, FileName, LineNo, ErrMsg)\r
127 Copyright += Comment + EndOfLine\r
128 HeaderCommentStage = HEADER_COMMENT_COPYRIGHT\r
129 else:\r
f7496d71 130 Description += Comment + EndOfLine\r
4234283c
LG
131 elif HeaderCommentStage == HEADER_COMMENT_COPYRIGHT:\r
132 if _IsCopyrightLine(Comment):\r
133 Result, ErrMsg = _ValidateCopyright(Comment)\r
134 ValidateCopyright(Result, ST.WRN_INVALID_COPYRIGHT, FileName, LineNo, ErrMsg)\r
135 Copyright += Comment + EndOfLine\r
136 else:\r
137 #\r
138 # Contents after copyright line are license, those non-copyright lines in between\r
f7496d71 139 # copyright line will be discarded\r
4234283c
LG
140 #\r
141 if LineNo > Last:\r
142 if License:\r
143 License += EndOfLine\r
144 License += Comment + EndOfLine\r
f7496d71 145 HeaderCommentStage = HEADER_COMMENT_LICENSE\r
4234283c
LG
146 else:\r
147 if not Comment and not License:\r
148 continue\r
149 License += Comment + EndOfLine\r
f7496d71 150\r
4234283c
LG
151 return Abstract.strip(), Description.strip(), Copyright.strip(), License.strip()\r
152\r
153## _IsCopyrightLine\r
f7496d71
LG
154# check whether current line is copyright line, the criteria is whether there is case insensitive keyword "Copyright"\r
155# followed by zero or more white space characters followed by a "(" character\r
4234283c
LG
156#\r
157# @param LineContent: the line need to be checked\r
158# @return: True if current line is copyright line, False else\r
159#\r
160def _IsCopyrightLine (LineContent):\r
161 LineContent = LineContent.upper()\r
162 Result = False\r
f7496d71 163\r
4234283c
LG
164 ReIsCopyrightRe = re.compile(r"""(^|\s)COPYRIGHT *\(""", re.DOTALL)\r
165 if ReIsCopyrightRe.search(LineContent):\r
166 Result = True\r
421ccda3 167\r
4234283c
LG
168 return Result\r
169\r
170## ParseGenericComment\r
171#\r
f7496d71 172# @param GenericComment: Generic comment list, element of\r
4234283c
LG
173# (CommentLine, LineNum)\r
174# @param ContainerFile: Input value for filename of Dec file\r
f7496d71 175#\r
4234283c
LG
176def ParseGenericComment (GenericComment, ContainerFile=None, SkipTag=None):\r
177 if ContainerFile:\r
178 pass\r
f7496d71
LG
179 HelpTxt = None\r
180 HelpStr = ''\r
181\r
4234283c
LG
182 for Item in GenericComment:\r
183 CommentLine = Item[0]\r
184 Comment = CleanString2(CommentLine)[1]\r
185 if SkipTag is not None and Comment.startswith(SkipTag):\r
186 Comment = Comment.replace(SkipTag, '', 1)\r
187 HelpStr += Comment + '\n'\r
f7496d71 188\r
4234283c
LG
189 if HelpStr:\r
190 HelpTxt = TextObject()\r
191 if HelpStr.endswith('\n') and not HelpStr.endswith('\n\n') and HelpStr != '\n':\r
192 HelpStr = HelpStr[:-1]\r
193 HelpTxt.SetString(HelpStr)\r
194\r
195 return HelpTxt\r
196\r
421ccda3
HC
197## ParsePcdErrorCode\r
198#\r
f7496d71 199# @param Value: original ErrorCode value\r
421ccda3 200# @param ContainerFile: Input value for filename of Dec file\r
f7496d71
LG
201# @param LineNum: Line Num\r
202#\r
203def ParsePcdErrorCode (Value = None, ContainerFile = None, LineNum = None):\r
204 try:\r
421ccda3
HC
205 if Value.strip().startswith((TAB_HEX_START, TAB_CAPHEX_START)):\r
206 Base = 16\r
207 else:\r
208 Base = 10\r
174a9d3c 209 ErrorCode = int(Value, Base)\r
421ccda3 210 if ErrorCode > PCD_ERR_CODE_MAX_SIZE or ErrorCode < 0:\r
f7496d71 211 Logger.Error('Parser',\r
421ccda3
HC
212 FORMAT_NOT_SUPPORTED,\r
213 "The format %s of ErrorCode is not valid, should be UNIT32 type or long type" % Value,\r
f7496d71 214 File = ContainerFile,\r
421ccda3 215 Line = LineNum)\r
174a9d3c
ZF
216 ErrorCode = '0x%x' % ErrorCode\r
217 return ErrorCode\r
5b0671c1 218 except ValueError as XStr:\r
421ccda3
HC
219 if XStr:\r
220 pass\r
f7496d71 221 Logger.Error('Parser',\r
421ccda3
HC
222 FORMAT_NOT_SUPPORTED,\r
223 "The format %s of ErrorCode is not valid, should be UNIT32 type or long type" % Value,\r
f7496d71 224 File = ContainerFile,\r
421ccda3 225 Line = LineNum)\r
f7496d71 226\r
4234283c
LG
227## ParseDecPcdGenericComment\r
228#\r
f7496d71 229# @param GenericComment: Generic comment list, element of (CommentLine,\r
4234283c
LG
230# LineNum)\r
231# @param ContainerFile: Input value for filename of Dec file\r
f7496d71
LG
232#\r
233def ParseDecPcdGenericComment (GenericComment, ContainerFile, TokenSpaceGuidCName, CName, MacroReplaceDict):\r
234 HelpStr = ''\r
421ccda3 235 PromptStr = ''\r
4234283c 236 PcdErr = None\r
421ccda3
HC
237 PcdErrList = []\r
238 ValidValueNum = 0\r
239 ValidRangeNum = 0\r
240 ExpressionNum = 0\r
f7496d71 241\r
4234283c
LG
242 for (CommentLine, LineNum) in GenericComment:\r
243 Comment = CleanString2(CommentLine)[1]\r
421ccda3
HC
244 #\r
245 # To replace Macro\r
246 #\r
247 MACRO_PATTERN = '[\t\s]*\$\([A-Z][_A-Z0-9]*\)'\r
248 MatchedStrs = re.findall(MACRO_PATTERN, Comment)\r
249 for MatchedStr in MatchedStrs:\r
250 if MatchedStr:\r
251 Macro = MatchedStr.strip().lstrip('$(').rstrip(')').strip()\r
252 if Macro in MacroReplaceDict:\r
f7496d71 253 Comment = Comment.replace(MatchedStr, MacroReplaceDict[Macro])\r
421ccda3
HC
254 if Comment.startswith(TAB_PCD_VALIDRANGE):\r
255 if ValidValueNum > 0 or ExpressionNum > 0:\r
f7496d71 256 Logger.Error('Parser',\r
4234283c
LG
257 FORMAT_NOT_SUPPORTED,\r
258 ST.WRN_MULTI_PCD_RANGES,\r
f7496d71 259 File = ContainerFile,\r
4234283c 260 Line = LineNum)\r
421ccda3 261 else:\r
4234283c 262 PcdErr = PcdErrorObject()\r
421ccda3
HC
263 PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName)\r
264 PcdErr.SetCName(CName)\r
265 PcdErr.SetFileLine(Comment)\r
266 PcdErr.SetLineNum(LineNum)\r
267 ValidRangeNum += 1\r
268 ValidRange = Comment.replace(TAB_PCD_VALIDRANGE, "", 1).strip()\r
269 Valid, Cause = _CheckRangeExpression(ValidRange)\r
270 if Valid:\r
271 ValueList = ValidRange.split(TAB_VALUE_SPLIT)\r
272 if len(ValueList) > 1:\r
273 PcdErr.SetValidValueRange((TAB_VALUE_SPLIT.join(ValueList[1:])).strip())\r
274 PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum))\r
275 else:\r
276 PcdErr.SetValidValueRange(ValidRange)\r
277 PcdErrList.append(PcdErr)\r
278 else:\r
279 Logger.Error("Parser",\r
280 FORMAT_NOT_SUPPORTED,\r
f7496d71
LG
281 Cause,\r
282 ContainerFile,\r
421ccda3
HC
283 LineNum)\r
284 elif Comment.startswith(TAB_PCD_VALIDLIST):\r
285 if ValidRangeNum > 0 or ExpressionNum > 0:\r
f7496d71 286 Logger.Error('Parser',\r
4234283c
LG
287 FORMAT_NOT_SUPPORTED,\r
288 ST.WRN_MULTI_PCD_RANGES,\r
f7496d71 289 File = ContainerFile,\r
4234283c 290 Line = LineNum)\r
421ccda3 291 elif ValidValueNum > 0:\r
f7496d71 292 Logger.Error('Parser',\r
421ccda3
HC
293 FORMAT_NOT_SUPPORTED,\r
294 ST.WRN_MULTI_PCD_VALIDVALUE,\r
f7496d71 295 File = ContainerFile,\r
421ccda3
HC
296 Line = LineNum)\r
297 else:\r
298 PcdErr = PcdErrorObject()\r
299 PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName)\r
300 PcdErr.SetCName(CName)\r
301 PcdErr.SetFileLine(Comment)\r
302 PcdErr.SetLineNum(LineNum)\r
303 ValidValueNum += 1\r
304 ValidValueExpr = Comment.replace(TAB_PCD_VALIDLIST, "", 1).strip()\r
305 Valid, Cause = _CheckListExpression(ValidValueExpr)\r
306 if Valid:\r
307 ValidValue = Comment.replace(TAB_PCD_VALIDLIST, "", 1).replace(TAB_COMMA_SPLIT, TAB_SPACE_SPLIT)\r
308 ValueList = ValidValue.split(TAB_VALUE_SPLIT)\r
309 if len(ValueList) > 1:\r
310 PcdErr.SetValidValue((TAB_VALUE_SPLIT.join(ValueList[1:])).strip())\r
311 PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum))\r
312 else:\r
313 PcdErr.SetValidValue(ValidValue)\r
314 PcdErrList.append(PcdErr)\r
315 else:\r
316 Logger.Error("Parser",\r
317 FORMAT_NOT_SUPPORTED,\r
f7496d71
LG
318 Cause,\r
319 ContainerFile,\r
421ccda3
HC
320 LineNum)\r
321 elif Comment.startswith(TAB_PCD_EXPRESSION):\r
322 if ValidRangeNum > 0 or ValidValueNum > 0:\r
f7496d71 323 Logger.Error('Parser',\r
4234283c
LG
324 FORMAT_NOT_SUPPORTED,\r
325 ST.WRN_MULTI_PCD_RANGES,\r
f7496d71 326 File = ContainerFile,\r
4234283c 327 Line = LineNum)\r
421ccda3 328 else:\r
4234283c 329 PcdErr = PcdErrorObject()\r
421ccda3
HC
330 PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName)\r
331 PcdErr.SetCName(CName)\r
332 PcdErr.SetFileLine(Comment)\r
333 PcdErr.SetLineNum(LineNum)\r
334 ExpressionNum += 1\r
335 Expression = Comment.replace(TAB_PCD_EXPRESSION, "", 1).strip()\r
336 Valid, Cause = _CheckExpression(Expression)\r
337 if Valid:\r
338 ValueList = Expression.split(TAB_VALUE_SPLIT)\r
339 if len(ValueList) > 1:\r
340 PcdErr.SetExpression((TAB_VALUE_SPLIT.join(ValueList[1:])).strip())\r
341 PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum))\r
342 else:\r
343 PcdErr.SetExpression(Expression)\r
344 PcdErrList.append(PcdErr)\r
f7496d71 345 else:\r
421ccda3
HC
346 Logger.Error("Parser",\r
347 FORMAT_NOT_SUPPORTED,\r
f7496d71
LG
348 Cause,\r
349 ContainerFile,\r
350 LineNum)\r
421ccda3
HC
351 elif Comment.startswith(TAB_PCD_PROMPT):\r
352 if PromptStr:\r
f7496d71 353 Logger.Error('Parser',\r
421ccda3
HC
354 FORMAT_NOT_SUPPORTED,\r
355 ST.WRN_MULTI_PCD_PROMPT,\r
f7496d71 356 File = ContainerFile,\r
421ccda3
HC
357 Line = LineNum)\r
358 PromptStr = Comment.replace(TAB_PCD_PROMPT, "", 1).strip()\r
4234283c 359 else:\r
421ccda3
HC
360 if Comment:\r
361 HelpStr += Comment + '\n'\r
f7496d71 362\r
4234283c
LG
363 #\r
364 # remove the last EOL if the comment is of format 'FOO\n'\r
365 #\r
366 if HelpStr.endswith('\n'):\r
367 if HelpStr != '\n' and not HelpStr.endswith('\n\n'):\r
368 HelpStr = HelpStr[:-1]\r
369\r
421ccda3 370 return HelpStr, PcdErrList, PromptStr\r
4234283c
LG
371\r
372## ParseDecPcdTailComment\r
373#\r
374# @param TailCommentList: Tail comment list of Pcd, item of format (Comment, LineNum)\r
375# @param ContainerFile: Input value for filename of Dec file\r
376# @retVal SupModuleList: The supported module type list detected\r
377# @retVal HelpStr: The generic help text string detected\r
378#\r
379def ParseDecPcdTailComment (TailCommentList, ContainerFile):\r
380 assert(len(TailCommentList) == 1)\r
381 TailComment = TailCommentList[0][0]\r
382 LineNum = TailCommentList[0][1]\r
383\r
384 Comment = TailComment.lstrip(" #")\r
f7496d71 385\r
4234283c 386 ReFindFirstWordRe = re.compile(r"""^([^ #]*)""", re.DOTALL)\r
f7496d71 387\r
4234283c
LG
388 #\r
389 # get first word and compare with SUP_MODULE_LIST\r
390 #\r
391 MatchObject = ReFindFirstWordRe.match(Comment)\r
392 if not (MatchObject and MatchObject.group(1) in SUP_MODULE_LIST):\r
393 return None, Comment\r
394\r
395 #\r
396 # parse line, it must have supported module type specified\r
397 #\r
398 if Comment.find(TAB_COMMENT_SPLIT) == -1:\r
f7496d71 399 Comment += TAB_COMMENT_SPLIT\r
4234283c
LG
400 SupMode, HelpStr = GetSplitValueList(Comment, TAB_COMMENT_SPLIT, 1)\r
401 SupModuleList = []\r
402 for Mod in GetSplitValueList(SupMode, TAB_SPACE_SPLIT):\r
403 if not Mod:\r
404 continue\r
405 elif Mod not in SUP_MODULE_LIST:\r
406 Logger.Error("UPT",\r
407 FORMAT_INVALID,\r
f7496d71
LG
408 ST.WRN_INVALID_MODULE_TYPE%Mod,\r
409 ContainerFile,\r
4234283c
LG
410 LineNum)\r
411 else:\r
412 SupModuleList.append(Mod)\r
413\r
414 return SupModuleList, HelpStr\r
415\r
421ccda3
HC
416## _CheckListExpression\r
417#\r
f7496d71 418# @param Expression: Pcd value list expression\r
421ccda3
HC
419#\r
420def _CheckListExpression(Expression):\r
421 ListExpr = ''\r
422 if TAB_VALUE_SPLIT in Expression:\r
f7496d71 423 ListExpr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:]\r
421ccda3
HC
424 else:\r
425 ListExpr = Expression\r
f7496d71 426\r
421ccda3
HC
427 return IsValidListExpr(ListExpr)\r
428\r
429## _CheckExpreesion\r
430#\r
431# @param Expression: Pcd value expression\r
432#\r
433def _CheckExpression(Expression):\r
434 Expr = ''\r
435 if TAB_VALUE_SPLIT in Expression:\r
436 Expr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:]\r
437 else:\r
438 Expr = Expression\r
439 return IsValidLogicalExpr(Expr, True)\r
4234283c
LG
440\r
441## _CheckRangeExpression\r
442#\r
443# @param Expression: Pcd range expression\r
f7496d71 444#\r
4234283c 445def _CheckRangeExpression(Expression):\r
421ccda3
HC
446 RangeExpr = ''\r
447 if TAB_VALUE_SPLIT in Expression:\r
448 RangeExpr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:]\r
449 else:\r
450 RangeExpr = Expression\r
f7496d71 451\r
421ccda3 452 return IsValidRangeExpr(RangeExpr)\r
4234283c
LG
453\r
454## ValidateCopyright\r
455#\r
456#\r
457#\r
458def ValidateCopyright(Result, ErrType, FileName, LineNo, ErrMsg):\r
459 if not Result:\r
f7496d71 460 Logger.Warn("\nUPT", ErrType, FileName, LineNo, ErrMsg)\r
4234283c
LG
461\r
462## _ValidateCopyright\r
463#\r
464# @param Line: Line that contains copyright information, # stripped\r
f7496d71 465#\r
4234283c
LG
466# @retval Result: True if line is conformed to Spec format, False else\r
467# @retval ErrMsg: the detailed error description\r
f7496d71 468#\r
4234283c
LG
469def _ValidateCopyright(Line):\r
470 if Line:\r
471 pass\r
472 Result = True\r
473 ErrMsg = ''\r
f7496d71 474\r
4234283c
LG
475 return Result, ErrMsg\r
476\r
477def GenerateTokenList (Comment):\r
478 #\r
479 # Tokenize Comment using '#' and ' ' as token seperators\r
480 #\r
f7496d71 481 RelplacedComment = None\r
4234283c
LG
482 while Comment != RelplacedComment:\r
483 RelplacedComment = Comment\r
484 Comment = Comment.replace('##', '#').replace(' ', ' ').replace(' ', '#').strip('# ')\r
485 return Comment.split('#')\r
486\r
487\r
488#\r
489# Comment - Comment to parse\r
490# TypeTokens - A dictionary of type token synonyms\r
491# RemoveTokens - A list of tokens to remove from help text\r
492# ParseVariable - True for parsing [Guids]. Otherwise False\r
493#\r
494def ParseComment (Comment, UsageTokens, TypeTokens, RemoveTokens, ParseVariable):\r
495 #\r
496 # Initialize return values\r
497 #\r
498 Usage = None\r
499 Type = None\r
500 String = None\r
f7496d71 501\r
4234283c 502 Comment = Comment[0]\r
f7496d71
LG
503\r
504 NumTokens = 2\r
4234283c 505 if ParseVariable:\r
f7496d71
LG
506 #\r
507 # Remove white space around first instance of ':' from Comment if 'Variable'\r
4234283c
LG
508 # is in front of ':' and Variable is the 1st or 2nd token in Comment.\r
509 #\r
f7496d71 510 List = Comment.split(':', 1)\r
4234283c
LG
511 if len(List) > 1:\r
512 SubList = GenerateTokenList (List[0].strip())\r
513 if len(SubList) in [1, 2] and SubList[-1] == 'Variable':\r
f7496d71 514 if List[1].strip().find('L"') == 0:\r
4234283c 515 Comment = List[0].strip() + ':' + List[1].strip()\r
f7496d71
LG
516\r
517 #\r
4234283c 518 # Remove first instance of L"<VariableName> from Comment and put into String\r
f7496d71 519 # if and only if L"<VariableName>" is the 1st token, the 2nd token. Or\r
4234283c
LG
520 # L"<VariableName>" is the third token immediately following 'Variable:'.\r
521 #\r
522 End = -1\r
523 Start = Comment.find('Variable:L"')\r
524 if Start >= 0:\r
525 String = Comment[Start + 9:]\r
526 End = String[2:].find('"')\r
527 else:\r
528 Start = Comment.find('L"')\r
529 if Start >= 0:\r
530 String = Comment[Start:]\r
531 End = String[2:].find('"')\r
532 if End >= 0:\r
533 SubList = GenerateTokenList (Comment[:Start])\r
f7496d71 534 if len(SubList) < 2:\r
4234283c
LG
535 Comment = Comment[:Start] + String[End + 3:]\r
536 String = String[:End + 3]\r
537 Type = 'Variable'\r
f7496d71
LG
538 NumTokens = 1\r
539\r
4234283c 540 #\r
f7496d71 541 # Initialze HelpText to Comment.\r
4234283c 542 # Content will be remove from HelpText as matching tokens are found\r
f7496d71 543 #\r
4234283c 544 HelpText = Comment\r
f7496d71 545\r
4234283c
LG
546 #\r
547 # Tokenize Comment using '#' and ' ' as token seperators\r
548 #\r
549 List = GenerateTokenList (Comment)\r
f7496d71 550\r
4234283c 551 #\r
f7496d71 552 # Search first two tokens for Usage and Type and remove any matching tokens\r
4234283c
LG
553 # from HelpText\r
554 #\r
555 for Token in List[0:NumTokens]:\r
4231a819 556 if Usage is None and Token in UsageTokens:\r
4234283c
LG
557 Usage = UsageTokens[Token]\r
558 HelpText = HelpText.replace(Token, '')\r
4231a819 559 if Usage is not None or not ParseVariable:\r
4234283c 560 for Token in List[0:NumTokens]:\r
4231a819 561 if Type is None and Token in TypeTokens:\r
4234283c
LG
562 Type = TypeTokens[Token]\r
563 HelpText = HelpText.replace(Token, '')\r
f7496d71 564 if Usage is not None:\r
4234283c
LG
565 for Token in List[0:NumTokens]:\r
566 if Token in RemoveTokens:\r
567 HelpText = HelpText.replace(Token, '')\r
f7496d71 568\r
4234283c
LG
569 #\r
570 # If no Usage token is present and set Usage to UNDEFINED\r
f7496d71 571 #\r
4231a819 572 if Usage is None:\r
4234283c 573 Usage = 'UNDEFINED'\r
f7496d71 574\r
4234283c
LG
575 #\r
576 # If no Type token is present and set Type to UNDEFINED\r
f7496d71 577 #\r
4231a819 578 if Type is None:\r
4234283c 579 Type = 'UNDEFINED'\r
f7496d71 580\r
4234283c
LG
581 #\r
582 # If Type is not 'Variable:', then set String to None\r
f7496d71 583 #\r
4234283c 584 if Type != 'Variable':\r
f7496d71
LG
585 String = None\r
586\r
4234283c
LG
587 #\r
588 # Strip ' ' and '#' from the beginning of HelpText\r
f7496d71 589 # If HelpText is an empty string after all parsing is\r
4234283c 590 # complete then set HelpText to None\r
f7496d71 591 #\r
4234283c
LG
592 HelpText = HelpText.lstrip('# ')\r
593 if HelpText == '':\r
594 HelpText = None\r
f7496d71 595\r
4234283c
LG
596 #\r
597 # Return parsing results\r
f7496d71
LG
598 #\r
599 return Usage, Type, String, HelpText\r