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