]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/UPT/Library/CommentParsing.py
BaseTools: Clean up source files
[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
77 for Index in xrange(len(CommentList)-1, 0, -1):\r
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
209 ErrorCode = long(Value, Base)\r
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
HC
215 Line = LineNum)\r
216 #\r
217 # To delete the tailing 'L'\r
218 #\r
219 return hex(ErrorCode)[:-1]\r
5b0671c1 220 except ValueError as XStr:\r
421ccda3
HC
221 if XStr:\r
222 pass\r
f7496d71 223 Logger.Error('Parser',\r
421ccda3
HC
224 FORMAT_NOT_SUPPORTED,\r
225 "The format %s of ErrorCode is not valid, should be UNIT32 type or long type" % Value,\r
f7496d71 226 File = ContainerFile,\r
421ccda3 227 Line = LineNum)\r
f7496d71 228\r
4234283c
LG
229## ParseDecPcdGenericComment\r
230#\r
f7496d71 231# @param GenericComment: Generic comment list, element of (CommentLine,\r
4234283c
LG
232# LineNum)\r
233# @param ContainerFile: Input value for filename of Dec file\r
f7496d71
LG
234#\r
235def ParseDecPcdGenericComment (GenericComment, ContainerFile, TokenSpaceGuidCName, CName, MacroReplaceDict):\r
236 HelpStr = ''\r
421ccda3 237 PromptStr = ''\r
4234283c 238 PcdErr = None\r
421ccda3
HC
239 PcdErrList = []\r
240 ValidValueNum = 0\r
241 ValidRangeNum = 0\r
242 ExpressionNum = 0\r
f7496d71 243\r
4234283c
LG
244 for (CommentLine, LineNum) in GenericComment:\r
245 Comment = CleanString2(CommentLine)[1]\r
421ccda3
HC
246 #\r
247 # To replace Macro\r
248 #\r
249 MACRO_PATTERN = '[\t\s]*\$\([A-Z][_A-Z0-9]*\)'\r
250 MatchedStrs = re.findall(MACRO_PATTERN, Comment)\r
251 for MatchedStr in MatchedStrs:\r
252 if MatchedStr:\r
253 Macro = MatchedStr.strip().lstrip('$(').rstrip(')').strip()\r
254 if Macro in MacroReplaceDict:\r
f7496d71 255 Comment = Comment.replace(MatchedStr, MacroReplaceDict[Macro])\r
421ccda3
HC
256 if Comment.startswith(TAB_PCD_VALIDRANGE):\r
257 if ValidValueNum > 0 or ExpressionNum > 0:\r
f7496d71 258 Logger.Error('Parser',\r
4234283c
LG
259 FORMAT_NOT_SUPPORTED,\r
260 ST.WRN_MULTI_PCD_RANGES,\r
f7496d71 261 File = ContainerFile,\r
4234283c 262 Line = LineNum)\r
421ccda3 263 else:\r
4234283c 264 PcdErr = PcdErrorObject()\r
421ccda3
HC
265 PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName)\r
266 PcdErr.SetCName(CName)\r
267 PcdErr.SetFileLine(Comment)\r
268 PcdErr.SetLineNum(LineNum)\r
269 ValidRangeNum += 1\r
270 ValidRange = Comment.replace(TAB_PCD_VALIDRANGE, "", 1).strip()\r
271 Valid, Cause = _CheckRangeExpression(ValidRange)\r
272 if Valid:\r
273 ValueList = ValidRange.split(TAB_VALUE_SPLIT)\r
274 if len(ValueList) > 1:\r
275 PcdErr.SetValidValueRange((TAB_VALUE_SPLIT.join(ValueList[1:])).strip())\r
276 PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum))\r
277 else:\r
278 PcdErr.SetValidValueRange(ValidRange)\r
279 PcdErrList.append(PcdErr)\r
280 else:\r
281 Logger.Error("Parser",\r
282 FORMAT_NOT_SUPPORTED,\r
f7496d71
LG
283 Cause,\r
284 ContainerFile,\r
421ccda3
HC
285 LineNum)\r
286 elif Comment.startswith(TAB_PCD_VALIDLIST):\r
287 if ValidRangeNum > 0 or ExpressionNum > 0:\r
f7496d71 288 Logger.Error('Parser',\r
4234283c
LG
289 FORMAT_NOT_SUPPORTED,\r
290 ST.WRN_MULTI_PCD_RANGES,\r
f7496d71 291 File = ContainerFile,\r
4234283c 292 Line = LineNum)\r
421ccda3 293 elif ValidValueNum > 0:\r
f7496d71 294 Logger.Error('Parser',\r
421ccda3
HC
295 FORMAT_NOT_SUPPORTED,\r
296 ST.WRN_MULTI_PCD_VALIDVALUE,\r
f7496d71 297 File = ContainerFile,\r
421ccda3
HC
298 Line = LineNum)\r
299 else:\r
300 PcdErr = PcdErrorObject()\r
301 PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName)\r
302 PcdErr.SetCName(CName)\r
303 PcdErr.SetFileLine(Comment)\r
304 PcdErr.SetLineNum(LineNum)\r
305 ValidValueNum += 1\r
306 ValidValueExpr = Comment.replace(TAB_PCD_VALIDLIST, "", 1).strip()\r
307 Valid, Cause = _CheckListExpression(ValidValueExpr)\r
308 if Valid:\r
309 ValidValue = Comment.replace(TAB_PCD_VALIDLIST, "", 1).replace(TAB_COMMA_SPLIT, TAB_SPACE_SPLIT)\r
310 ValueList = ValidValue.split(TAB_VALUE_SPLIT)\r
311 if len(ValueList) > 1:\r
312 PcdErr.SetValidValue((TAB_VALUE_SPLIT.join(ValueList[1:])).strip())\r
313 PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum))\r
314 else:\r
315 PcdErr.SetValidValue(ValidValue)\r
316 PcdErrList.append(PcdErr)\r
317 else:\r
318 Logger.Error("Parser",\r
319 FORMAT_NOT_SUPPORTED,\r
f7496d71
LG
320 Cause,\r
321 ContainerFile,\r
421ccda3
HC
322 LineNum)\r
323 elif Comment.startswith(TAB_PCD_EXPRESSION):\r
324 if ValidRangeNum > 0 or ValidValueNum > 0:\r
f7496d71 325 Logger.Error('Parser',\r
4234283c
LG
326 FORMAT_NOT_SUPPORTED,\r
327 ST.WRN_MULTI_PCD_RANGES,\r
f7496d71 328 File = ContainerFile,\r
4234283c 329 Line = LineNum)\r
421ccda3 330 else:\r
4234283c 331 PcdErr = PcdErrorObject()\r
421ccda3
HC
332 PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName)\r
333 PcdErr.SetCName(CName)\r
334 PcdErr.SetFileLine(Comment)\r
335 PcdErr.SetLineNum(LineNum)\r
336 ExpressionNum += 1\r
337 Expression = Comment.replace(TAB_PCD_EXPRESSION, "", 1).strip()\r
338 Valid, Cause = _CheckExpression(Expression)\r
339 if Valid:\r
340 ValueList = Expression.split(TAB_VALUE_SPLIT)\r
341 if len(ValueList) > 1:\r
342 PcdErr.SetExpression((TAB_VALUE_SPLIT.join(ValueList[1:])).strip())\r
343 PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum))\r
344 else:\r
345 PcdErr.SetExpression(Expression)\r
346 PcdErrList.append(PcdErr)\r
f7496d71 347 else:\r
421ccda3
HC
348 Logger.Error("Parser",\r
349 FORMAT_NOT_SUPPORTED,\r
f7496d71
LG
350 Cause,\r
351 ContainerFile,\r
352 LineNum)\r
421ccda3
HC
353 elif Comment.startswith(TAB_PCD_PROMPT):\r
354 if PromptStr:\r
f7496d71 355 Logger.Error('Parser',\r
421ccda3
HC
356 FORMAT_NOT_SUPPORTED,\r
357 ST.WRN_MULTI_PCD_PROMPT,\r
f7496d71 358 File = ContainerFile,\r
421ccda3
HC
359 Line = LineNum)\r
360 PromptStr = Comment.replace(TAB_PCD_PROMPT, "", 1).strip()\r
4234283c 361 else:\r
421ccda3
HC
362 if Comment:\r
363 HelpStr += Comment + '\n'\r
f7496d71 364\r
4234283c
LG
365 #\r
366 # remove the last EOL if the comment is of format 'FOO\n'\r
367 #\r
368 if HelpStr.endswith('\n'):\r
369 if HelpStr != '\n' and not HelpStr.endswith('\n\n'):\r
370 HelpStr = HelpStr[:-1]\r
371\r
421ccda3 372 return HelpStr, PcdErrList, PromptStr\r
4234283c
LG
373\r
374## ParseDecPcdTailComment\r
375#\r
376# @param TailCommentList: Tail comment list of Pcd, item of format (Comment, LineNum)\r
377# @param ContainerFile: Input value for filename of Dec file\r
378# @retVal SupModuleList: The supported module type list detected\r
379# @retVal HelpStr: The generic help text string detected\r
380#\r
381def ParseDecPcdTailComment (TailCommentList, ContainerFile):\r
382 assert(len(TailCommentList) == 1)\r
383 TailComment = TailCommentList[0][0]\r
384 LineNum = TailCommentList[0][1]\r
385\r
386 Comment = TailComment.lstrip(" #")\r
f7496d71 387\r
4234283c 388 ReFindFirstWordRe = re.compile(r"""^([^ #]*)""", re.DOTALL)\r
f7496d71 389\r
4234283c
LG
390 #\r
391 # get first word and compare with SUP_MODULE_LIST\r
392 #\r
393 MatchObject = ReFindFirstWordRe.match(Comment)\r
394 if not (MatchObject and MatchObject.group(1) in SUP_MODULE_LIST):\r
395 return None, Comment\r
396\r
397 #\r
398 # parse line, it must have supported module type specified\r
399 #\r
400 if Comment.find(TAB_COMMENT_SPLIT) == -1:\r
f7496d71 401 Comment += TAB_COMMENT_SPLIT\r
4234283c
LG
402 SupMode, HelpStr = GetSplitValueList(Comment, TAB_COMMENT_SPLIT, 1)\r
403 SupModuleList = []\r
404 for Mod in GetSplitValueList(SupMode, TAB_SPACE_SPLIT):\r
405 if not Mod:\r
406 continue\r
407 elif Mod not in SUP_MODULE_LIST:\r
408 Logger.Error("UPT",\r
409 FORMAT_INVALID,\r
f7496d71
LG
410 ST.WRN_INVALID_MODULE_TYPE%Mod,\r
411 ContainerFile,\r
4234283c
LG
412 LineNum)\r
413 else:\r
414 SupModuleList.append(Mod)\r
415\r
416 return SupModuleList, HelpStr\r
417\r
421ccda3
HC
418## _CheckListExpression\r
419#\r
f7496d71 420# @param Expression: Pcd value list expression\r
421ccda3
HC
421#\r
422def _CheckListExpression(Expression):\r
423 ListExpr = ''\r
424 if TAB_VALUE_SPLIT in Expression:\r
f7496d71 425 ListExpr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:]\r
421ccda3
HC
426 else:\r
427 ListExpr = Expression\r
f7496d71 428\r
421ccda3
HC
429 return IsValidListExpr(ListExpr)\r
430\r
431## _CheckExpreesion\r
432#\r
433# @param Expression: Pcd value expression\r
434#\r
435def _CheckExpression(Expression):\r
436 Expr = ''\r
437 if TAB_VALUE_SPLIT in Expression:\r
438 Expr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:]\r
439 else:\r
440 Expr = Expression\r
441 return IsValidLogicalExpr(Expr, True)\r
4234283c
LG
442\r
443## _CheckRangeExpression\r
444#\r
445# @param Expression: Pcd range expression\r
f7496d71 446#\r
4234283c 447def _CheckRangeExpression(Expression):\r
421ccda3
HC
448 RangeExpr = ''\r
449 if TAB_VALUE_SPLIT in Expression:\r
450 RangeExpr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:]\r
451 else:\r
452 RangeExpr = Expression\r
f7496d71 453\r
421ccda3 454 return IsValidRangeExpr(RangeExpr)\r
4234283c
LG
455\r
456## ValidateCopyright\r
457#\r
458#\r
459#\r
460def ValidateCopyright(Result, ErrType, FileName, LineNo, ErrMsg):\r
461 if not Result:\r
f7496d71 462 Logger.Warn("\nUPT", ErrType, FileName, LineNo, ErrMsg)\r
4234283c
LG
463\r
464## _ValidateCopyright\r
465#\r
466# @param Line: Line that contains copyright information, # stripped\r
f7496d71 467#\r
4234283c
LG
468# @retval Result: True if line is conformed to Spec format, False else\r
469# @retval ErrMsg: the detailed error description\r
f7496d71 470#\r
4234283c
LG
471def _ValidateCopyright(Line):\r
472 if Line:\r
473 pass\r
474 Result = True\r
475 ErrMsg = ''\r
f7496d71 476\r
4234283c
LG
477 return Result, ErrMsg\r
478\r
479def GenerateTokenList (Comment):\r
480 #\r
481 # Tokenize Comment using '#' and ' ' as token seperators\r
482 #\r
f7496d71 483 RelplacedComment = None\r
4234283c
LG
484 while Comment != RelplacedComment:\r
485 RelplacedComment = Comment\r
486 Comment = Comment.replace('##', '#').replace(' ', ' ').replace(' ', '#').strip('# ')\r
487 return Comment.split('#')\r
488\r
489\r
490#\r
491# Comment - Comment to parse\r
492# TypeTokens - A dictionary of type token synonyms\r
493# RemoveTokens - A list of tokens to remove from help text\r
494# ParseVariable - True for parsing [Guids]. Otherwise False\r
495#\r
496def ParseComment (Comment, UsageTokens, TypeTokens, RemoveTokens, ParseVariable):\r
497 #\r
498 # Initialize return values\r
499 #\r
500 Usage = None\r
501 Type = None\r
502 String = None\r
f7496d71 503\r
4234283c 504 Comment = Comment[0]\r
f7496d71
LG
505\r
506 NumTokens = 2\r
4234283c 507 if ParseVariable:\r
f7496d71
LG
508 #\r
509 # Remove white space around first instance of ':' from Comment if 'Variable'\r
4234283c
LG
510 # is in front of ':' and Variable is the 1st or 2nd token in Comment.\r
511 #\r
f7496d71 512 List = Comment.split(':', 1)\r
4234283c
LG
513 if len(List) > 1:\r
514 SubList = GenerateTokenList (List[0].strip())\r
515 if len(SubList) in [1, 2] and SubList[-1] == 'Variable':\r
f7496d71 516 if List[1].strip().find('L"') == 0:\r
4234283c 517 Comment = List[0].strip() + ':' + List[1].strip()\r
f7496d71
LG
518\r
519 #\r
4234283c 520 # Remove first instance of L"<VariableName> from Comment and put into String\r
f7496d71 521 # if and only if L"<VariableName>" is the 1st token, the 2nd token. Or\r
4234283c
LG
522 # L"<VariableName>" is the third token immediately following 'Variable:'.\r
523 #\r
524 End = -1\r
525 Start = Comment.find('Variable:L"')\r
526 if Start >= 0:\r
527 String = Comment[Start + 9:]\r
528 End = String[2:].find('"')\r
529 else:\r
530 Start = Comment.find('L"')\r
531 if Start >= 0:\r
532 String = Comment[Start:]\r
533 End = String[2:].find('"')\r
534 if End >= 0:\r
535 SubList = GenerateTokenList (Comment[:Start])\r
f7496d71 536 if len(SubList) < 2:\r
4234283c
LG
537 Comment = Comment[:Start] + String[End + 3:]\r
538 String = String[:End + 3]\r
539 Type = 'Variable'\r
f7496d71
LG
540 NumTokens = 1\r
541\r
4234283c 542 #\r
f7496d71 543 # Initialze HelpText to Comment.\r
4234283c 544 # Content will be remove from HelpText as matching tokens are found\r
f7496d71 545 #\r
4234283c 546 HelpText = Comment\r
f7496d71 547\r
4234283c
LG
548 #\r
549 # Tokenize Comment using '#' and ' ' as token seperators\r
550 #\r
551 List = GenerateTokenList (Comment)\r
f7496d71 552\r
4234283c 553 #\r
f7496d71 554 # Search first two tokens for Usage and Type and remove any matching tokens\r
4234283c
LG
555 # from HelpText\r
556 #\r
557 for Token in List[0:NumTokens]:\r
4231a819 558 if Usage is None and Token in UsageTokens:\r
4234283c
LG
559 Usage = UsageTokens[Token]\r
560 HelpText = HelpText.replace(Token, '')\r
4231a819 561 if Usage is not None or not ParseVariable:\r
4234283c 562 for Token in List[0:NumTokens]:\r
4231a819 563 if Type is None and Token in TypeTokens:\r
4234283c
LG
564 Type = TypeTokens[Token]\r
565 HelpText = HelpText.replace(Token, '')\r
f7496d71 566 if Usage is not None:\r
4234283c
LG
567 for Token in List[0:NumTokens]:\r
568 if Token in RemoveTokens:\r
569 HelpText = HelpText.replace(Token, '')\r
f7496d71 570\r
4234283c
LG
571 #\r
572 # If no Usage token is present and set Usage to UNDEFINED\r
f7496d71 573 #\r
4231a819 574 if Usage is None:\r
4234283c 575 Usage = 'UNDEFINED'\r
f7496d71 576\r
4234283c
LG
577 #\r
578 # If no Type token is present and set Type to UNDEFINED\r
f7496d71 579 #\r
4231a819 580 if Type is None:\r
4234283c 581 Type = 'UNDEFINED'\r
f7496d71 582\r
4234283c
LG
583 #\r
584 # If Type is not 'Variable:', then set String to None\r
f7496d71 585 #\r
4234283c 586 if Type != 'Variable':\r
f7496d71
LG
587 String = None\r
588\r
4234283c
LG
589 #\r
590 # Strip ' ' and '#' from the beginning of HelpText\r
f7496d71 591 # If HelpText is an empty string after all parsing is\r
4234283c 592 # complete then set HelpText to None\r
f7496d71 593 #\r
4234283c
LG
594 HelpText = HelpText.lstrip('# ')\r
595 if HelpText == '':\r
596 HelpText = None\r
f7496d71 597\r
4234283c
LG
598 #\r
599 # Return parsing results\r
f7496d71
LG
600 #\r
601 return Usage, Type, String, HelpText\r