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