]>
Commit | Line | Data |
---|---|---|
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 | |
10 | CommentParsing\r | |
11 | '''\r | |
12 | \r | |
13 | ##\r | |
14 | # Import Modules\r | |
15 | #\r | |
16 | import re\r | |
17 | \r | |
64285f15 YZ |
18 | from Library.StringUtils import GetSplitValueList\r |
19 | from Library.StringUtils import CleanString2\r | |
4234283c LG |
20 | from Library.DataType import HEADER_COMMENT_NOT_STARTED\r |
21 | from Library.DataType import TAB_COMMENT_SPLIT\r | |
22 | from Library.DataType import HEADER_COMMENT_LICENSE\r | |
23 | from Library.DataType import HEADER_COMMENT_ABSTRACT\r | |
24 | from Library.DataType import HEADER_COMMENT_COPYRIGHT\r | |
25 | from Library.DataType import HEADER_COMMENT_DESCRIPTION\r | |
26 | from Library.DataType import TAB_SPACE_SPLIT\r | |
27 | from Library.DataType import TAB_COMMA_SPLIT\r | |
28 | from Library.DataType import SUP_MODULE_LIST\r | |
421ccda3 HC |
29 | from Library.DataType import TAB_VALUE_SPLIT\r |
30 | from Library.DataType import TAB_PCD_VALIDRANGE\r | |
31 | from Library.DataType import TAB_PCD_VALIDLIST\r | |
32 | from Library.DataType import TAB_PCD_EXPRESSION\r | |
33 | from Library.DataType import TAB_PCD_PROMPT\r | |
34 | from Library.DataType import TAB_CAPHEX_START\r | |
35 | from Library.DataType import TAB_HEX_START\r | |
36 | from Library.DataType import PCD_ERR_CODE_MAX_SIZE\r | |
37 | from Library.ExpressionValidate import IsValidRangeExpr\r | |
38 | from Library.ExpressionValidate import IsValidListExpr\r | |
39 | from Library.ExpressionValidate import IsValidLogicalExpr\r | |
4234283c LG |
40 | from Object.POM.CommonObject import TextObject\r |
41 | from Object.POM.CommonObject import PcdErrorObject\r | |
42 | import Logger.Log as Logger\r | |
43 | from Logger.ToolError import FORMAT_INVALID\r | |
44 | from Logger.ToolError import FORMAT_NOT_SUPPORTED\r | |
45 | from 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 | 55 | def 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 | |
154 | def _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 |
170 | def 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 | |
197 | def 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 |
227 | def 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 | |
373 | def 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 |
414 | def _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 | |
427 | def _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 | 439 | def _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 | |
452 | def 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 |
463 | def _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 | |
471 | def 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 | |
488 | def 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 |