]>
Commit | Line | Data |
---|---|---|
f51461c8 LG |
1 | ## @file\r |
2 | # Common routines used by all tools\r | |
3 | #\r | |
64285f15 | 4 | # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r |
f51461c8 | 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 | |
f51461c8 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 | |
16 | Misc\r | |
17 | '''\r | |
18 | \r | |
19 | ##\r | |
20 | # Import Modules\r | |
21 | #\r | |
22 | import os.path\r | |
23 | from os import access\r | |
24 | from os import F_OK\r | |
25 | from os import makedirs\r | |
26 | from os import getcwd\r | |
27 | from os import chdir\r | |
28 | from os import listdir\r | |
29 | from os import remove\r | |
30 | from os import rmdir\r | |
31 | from os import linesep\r | |
32 | from os import walk\r | |
33 | from os import environ\r | |
34 | import re\r | |
1b2e0772 | 35 | from collections import UserDict as IterableUserDict\r |
f51461c8 LG |
36 | \r |
37 | import Logger.Log as Logger\r | |
38 | from Logger import StringTable as ST\r | |
39 | from Logger import ToolError\r | |
40 | from Library import GlobalData\r | |
41 | from Library.DataType import SUP_MODULE_LIST\r | |
42 | from Library.DataType import END_OF_LINE\r | |
43 | from Library.DataType import TAB_SPLIT\r | |
421ccda3 HC |
44 | from Library.DataType import TAB_LANGUAGE_EN_US\r |
45 | from Library.DataType import TAB_LANGUAGE_EN\r | |
46 | from Library.DataType import TAB_LANGUAGE_EN_X\r | |
47 | from Library.DataType import TAB_UNI_FILE_SUFFIXS\r | |
64285f15 | 48 | from Library.StringUtils import GetSplitValueList\r |
f51461c8 LG |
49 | from Library.ParserValidate import IsValidHexVersion\r |
50 | from Library.ParserValidate import IsValidPath\r | |
51 | from Object.POM.CommonObject import TextObject\r | |
421ccda3 | 52 | from Core.FileHook import __FileHookOpen__\r |
8145b63e | 53 | from Common.MultipleWorkspace import MultipleWorkspace as mws\r |
f51461c8 | 54 | \r |
f7496d71 | 55 | ## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C\r |
f51461c8 LG |
56 | # structure style\r |
57 | #\r | |
58 | # @param Guid: The GUID string\r | |
59 | #\r | |
60 | def GuidStringToGuidStructureString(Guid):\r | |
61 | GuidList = Guid.split('-')\r | |
62 | Result = '{'\r | |
63 | for Index in range(0, 3, 1):\r | |
64 | Result = Result + '0x' + GuidList[Index] + ', '\r | |
65 | Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4]\r | |
66 | for Index in range(0, 12, 2):\r | |
67 | Result = Result + ', 0x' + GuidList[4][Index:Index + 2]\r | |
68 | Result += '}}'\r | |
69 | return Result\r | |
70 | \r | |
71 | ## Check whether GUID string is of format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r | |
72 | #\r | |
73 | # @param GuidValue: The GUID value\r | |
74 | #\r | |
75 | def CheckGuidRegFormat(GuidValue):\r | |
76 | ## Regular expression used to find out register format of GUID\r | |
77 | #\r | |
78 | RegFormatGuidPattern = re.compile("^\s*([0-9a-fA-F]){8}-"\r | |
79 | "([0-9a-fA-F]){4}-"\r | |
80 | "([0-9a-fA-F]){4}-"\r | |
81 | "([0-9a-fA-F]){4}-"\r | |
82 | "([0-9a-fA-F]){12}\s*$")\r | |
83 | \r | |
84 | if RegFormatGuidPattern.match(GuidValue):\r | |
85 | return True\r | |
86 | else:\r | |
87 | return False\r | |
88 | \r | |
89 | \r | |
f7496d71 | 90 | ## Convert GUID string in C structure style to\r |
f51461c8 LG |
91 | # xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r |
92 | #\r | |
93 | # @param GuidValue: The GUID value in C structure format\r | |
94 | #\r | |
95 | def GuidStructureStringToGuidString(GuidValue):\r | |
96 | GuidValueString = GuidValue.lower().replace("{", "").replace("}", "").\\r | |
97 | replace(" ", "").replace(";", "")\r | |
98 | GuidValueList = GuidValueString.split(",")\r | |
99 | if len(GuidValueList) != 11:\r | |
100 | return ''\r | |
101 | try:\r | |
102 | return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (\r | |
103 | int(GuidValueList[0], 16),\r | |
104 | int(GuidValueList[1], 16),\r | |
105 | int(GuidValueList[2], 16),\r | |
106 | int(GuidValueList[3], 16),\r | |
107 | int(GuidValueList[4], 16),\r | |
108 | int(GuidValueList[5], 16),\r | |
109 | int(GuidValueList[6], 16),\r | |
110 | int(GuidValueList[7], 16),\r | |
111 | int(GuidValueList[8], 16),\r | |
112 | int(GuidValueList[9], 16),\r | |
113 | int(GuidValueList[10], 16)\r | |
114 | )\r | |
115 | except BaseException:\r | |
116 | return ''\r | |
117 | \r | |
118 | ## Create directories\r | |
119 | #\r | |
120 | # @param Directory: The directory name\r | |
121 | #\r | |
122 | def CreateDirectory(Directory):\r | |
4231a819 | 123 | if Directory is None or Directory.strip() == "":\r |
f51461c8 LG |
124 | return True\r |
125 | try:\r | |
126 | if not access(Directory, F_OK):\r | |
127 | makedirs(Directory)\r | |
128 | except BaseException:\r | |
129 | return False\r | |
130 | return True\r | |
131 | \r | |
132 | ## Remove directories, including files and sub-directories in it\r | |
133 | #\r | |
134 | # @param Directory: The directory name\r | |
135 | #\r | |
136 | def RemoveDirectory(Directory, Recursively=False):\r | |
4231a819 | 137 | if Directory is None or Directory.strip() == "" or not \\r |
f51461c8 LG |
138 | os.path.exists(Directory):\r |
139 | return\r | |
140 | if Recursively:\r | |
141 | CurrentDirectory = getcwd()\r | |
142 | chdir(Directory)\r | |
143 | for File in listdir("."):\r | |
144 | if os.path.isdir(File):\r | |
145 | RemoveDirectory(File, Recursively)\r | |
146 | else:\r | |
147 | remove(File)\r | |
148 | chdir(CurrentDirectory)\r | |
149 | rmdir(Directory)\r | |
150 | \r | |
151 | ## Store content in file\r | |
152 | #\r | |
153 | # This method is used to save file only when its content is changed. This is\r | |
f7496d71 | 154 | # quite useful for "make" system to decide what will be re-built and what\r |
f51461c8 LG |
155 | # won't.\r |
156 | #\r | |
157 | # @param File: The path of file\r | |
158 | # @param Content: The new content of the file\r | |
f7496d71 | 159 | # @param IsBinaryFile: The flag indicating if the file is binary file\r |
f51461c8 LG |
160 | # or not\r |
161 | #\r | |
162 | def SaveFileOnChange(File, Content, IsBinaryFile=True):\r | |
f51461c8 LG |
163 | if os.path.exists(File):\r |
164 | try:\r | |
1b2e0772 YZ |
165 | if isinstance(Content, bytes):\r |
166 | if Content == __FileHookOpen__(File, "rb").read():\r | |
167 | return False\r | |
168 | else:\r | |
169 | if Content == __FileHookOpen__(File, "r").read():\r | |
170 | return False\r | |
f51461c8 LG |
171 | except BaseException:\r |
172 | Logger.Error(None, ToolError.FILE_OPEN_FAILURE, ExtraData=File)\r | |
173 | \r | |
174 | CreateDirectory(os.path.dirname(File))\r | |
175 | try:\r | |
1b2e0772 YZ |
176 | if isinstance(Content, bytes):\r |
177 | FileFd = __FileHookOpen__(File, "wb")\r | |
178 | else:\r | |
179 | FileFd = __FileHookOpen__(File, "w")\r | |
f51461c8 LG |
180 | FileFd.write(Content)\r |
181 | FileFd.close()\r | |
182 | except BaseException:\r | |
183 | Logger.Error(None, ToolError.FILE_CREATE_FAILURE, ExtraData=File)\r | |
184 | \r | |
185 | return True\r | |
186 | \r | |
187 | ## Get all files of a directory\r | |
188 | #\r | |
189 | # @param Root: Root dir\r | |
190 | # @param SkipList : The files need be skipped\r | |
191 | #\r | |
192 | def GetFiles(Root, SkipList=None, FullPath=True):\r | |
193 | OriPath = os.path.normpath(Root)\r | |
194 | FileList = []\r | |
195 | for Root, Dirs, Files in walk(Root):\r | |
196 | if SkipList:\r | |
197 | for Item in SkipList:\r | |
198 | if Item in Dirs:\r | |
199 | Dirs.remove(Item)\r | |
421ccda3 HC |
200 | if Item in Files:\r |
201 | Files.remove(Item)\r | |
f51461c8 LG |
202 | for Dir in Dirs:\r |
203 | if Dir.startswith('.'):\r | |
204 | Dirs.remove(Dir)\r | |
205 | \r | |
206 | for File in Files:\r | |
207 | if File.startswith('.'):\r | |
208 | continue\r | |
209 | File = os.path.normpath(os.path.join(Root, File))\r | |
210 | if not FullPath:\r | |
211 | File = File[len(OriPath) + 1:]\r | |
212 | FileList.append(File)\r | |
213 | \r | |
214 | return FileList\r | |
215 | \r | |
216 | ## Get all non-metadata files of a directory\r | |
217 | #\r | |
218 | # @param Root: Root Dir\r | |
219 | # @param SkipList : List of path need be skipped\r | |
220 | # @param FullPath: True if the returned file should be full path\r | |
221 | # @param PrefixPath: the path that need to be added to the files found\r | |
222 | # @return: the list of files found\r | |
f7496d71 | 223 | #\r |
f51461c8 LG |
224 | def GetNonMetaDataFiles(Root, SkipList, FullPath, PrefixPath):\r |
225 | FileList = GetFiles(Root, SkipList, FullPath)\r | |
226 | NewFileList = []\r | |
227 | for File in FileList:\r | |
228 | ExtName = os.path.splitext(File)[1]\r | |
229 | #\r | |
230 | # skip '.dec', '.inf', '.dsc', '.fdf' files\r | |
231 | #\r | |
232 | if ExtName.lower() not in ['.dec', '.inf', '.dsc', '.fdf']:\r | |
233 | NewFileList.append(os.path.normpath(os.path.join(PrefixPath, File)))\r | |
234 | \r | |
235 | return NewFileList\r | |
236 | \r | |
237 | ## Check if given file exists or not\r | |
238 | #\r | |
239 | # @param File: File name or path to be checked\r | |
240 | # @param Dir: The directory the file is relative to\r | |
241 | #\r | |
242 | def ValidFile(File, Ext=None):\r | |
243 | File = File.replace('\\', '/')\r | |
4231a819 | 244 | if Ext is not None:\r |
f51461c8 LG |
245 | FileExt = os.path.splitext(File)[1]\r |
246 | if FileExt.lower() != Ext.lower():\r | |
247 | return False\r | |
248 | if not os.path.exists(File):\r | |
249 | return False\r | |
250 | return True\r | |
251 | \r | |
252 | ## RealPath\r | |
253 | #\r | |
254 | # @param File: File name or path to be checked\r | |
255 | # @param Dir: The directory the file is relative to\r | |
256 | # @param OverrideDir: The override directory\r | |
257 | #\r | |
258 | def RealPath(File, Dir='', OverrideDir=''):\r | |
259 | NewFile = os.path.normpath(os.path.join(Dir, File))\r | |
260 | NewFile = GlobalData.gALL_FILES[NewFile]\r | |
261 | if not NewFile and OverrideDir:\r | |
262 | NewFile = os.path.normpath(os.path.join(OverrideDir, File))\r | |
263 | NewFile = GlobalData.gALL_FILES[NewFile]\r | |
264 | return NewFile\r | |
265 | \r | |
266 | ## RealPath2\r | |
267 | #\r | |
268 | # @param File: File name or path to be checked\r | |
269 | # @param Dir: The directory the file is relative to\r | |
270 | # @param OverrideDir: The override directory\r | |
271 | #\r | |
272 | def RealPath2(File, Dir='', OverrideDir=''):\r | |
273 | if OverrideDir:\r | |
274 | NewFile = GlobalData.gALL_FILES[os.path.normpath(os.path.join\\r | |
275 | (OverrideDir, File))]\r | |
276 | if NewFile:\r | |
277 | if OverrideDir[-1] == os.path.sep:\r | |
278 | return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)]\r | |
279 | else:\r | |
280 | return NewFile[len(OverrideDir) + 1:], \\r | |
281 | NewFile[0:len(OverrideDir)]\r | |
282 | \r | |
283 | NewFile = GlobalData.gALL_FILES[os.path.normpath(os.path.join(Dir, File))]\r | |
284 | if NewFile:\r | |
285 | if Dir:\r | |
286 | if Dir[-1] == os.path.sep:\r | |
287 | return NewFile[len(Dir):], NewFile[0:len(Dir)]\r | |
288 | else:\r | |
289 | return NewFile[len(Dir) + 1:], NewFile[0:len(Dir)]\r | |
290 | else:\r | |
291 | return NewFile, ''\r | |
292 | \r | |
293 | return None, None\r | |
294 | \r | |
295 | ## A dict which can access its keys and/or values orderly\r | |
296 | #\r | |
297 | # The class implements a new kind of dict which its keys or values can be\r | |
298 | # accessed in the order they are added into the dict. It guarantees the order\r | |
299 | # by making use of an internal list to keep a copy of keys.\r | |
300 | #\r | |
301 | class Sdict(IterableUserDict):\r | |
302 | ## Constructor\r | |
303 | #\r | |
304 | def __init__(self):\r | |
305 | IterableUserDict.__init__(self)\r | |
306 | self._key_list = []\r | |
307 | \r | |
308 | ## [] operator\r | |
309 | #\r | |
310 | def __setitem__(self, Key, Value):\r | |
311 | if Key not in self._key_list:\r | |
312 | self._key_list.append(Key)\r | |
313 | IterableUserDict.__setitem__(self, Key, Value)\r | |
314 | \r | |
315 | ## del operator\r | |
316 | #\r | |
317 | def __delitem__(self, Key):\r | |
318 | self._key_list.remove(Key)\r | |
319 | IterableUserDict.__delitem__(self, Key)\r | |
320 | \r | |
321 | ## used in "for k in dict" loop to ensure the correct order\r | |
322 | #\r | |
323 | def __iter__(self):\r | |
324 | return self.iterkeys()\r | |
325 | \r | |
326 | ## len() support\r | |
327 | #\r | |
328 | def __len__(self):\r | |
329 | return len(self._key_list)\r | |
330 | \r | |
331 | ## "in" test support\r | |
332 | #\r | |
333 | def __contains__(self, Key):\r | |
334 | return Key in self._key_list\r | |
335 | \r | |
336 | ## indexof support\r | |
337 | #\r | |
338 | def index(self, Key):\r | |
339 | return self._key_list.index(Key)\r | |
340 | \r | |
341 | ## insert support\r | |
342 | #\r | |
343 | def insert(self, Key, Newkey, Newvalue, Order):\r | |
344 | Index = self._key_list.index(Key)\r | |
345 | if Order == 'BEFORE':\r | |
346 | self._key_list.insert(Index, Newkey)\r | |
347 | IterableUserDict.__setitem__(self, Newkey, Newvalue)\r | |
348 | elif Order == 'AFTER':\r | |
349 | self._key_list.insert(Index + 1, Newkey)\r | |
350 | IterableUserDict.__setitem__(self, Newkey, Newvalue)\r | |
351 | \r | |
352 | ## append support\r | |
353 | #\r | |
354 | def append(self, Sdict2):\r | |
355 | for Key in Sdict2:\r | |
356 | if Key not in self._key_list:\r | |
357 | self._key_list.append(Key)\r | |
358 | IterableUserDict.__setitem__(self, Key, Sdict2[Key])\r | |
359 | ## hash key\r | |
360 | #\r | |
361 | def has_key(self, Key):\r | |
362 | return Key in self._key_list\r | |
363 | \r | |
364 | ## Empty the dict\r | |
365 | #\r | |
366 | def clear(self):\r | |
367 | self._key_list = []\r | |
368 | IterableUserDict.clear(self)\r | |
369 | \r | |
370 | ## Return a copy of keys\r | |
371 | #\r | |
372 | def keys(self):\r | |
373 | Keys = []\r | |
374 | for Key in self._key_list:\r | |
375 | Keys.append(Key)\r | |
376 | return Keys\r | |
377 | \r | |
378 | ## Return a copy of values\r | |
379 | #\r | |
380 | def values(self):\r | |
381 | Values = []\r | |
382 | for Key in self._key_list:\r | |
383 | Values.append(self[Key])\r | |
384 | return Values\r | |
385 | \r | |
386 | ## Return a copy of (key, value) list\r | |
387 | #\r | |
388 | def items(self):\r | |
389 | Items = []\r | |
390 | for Key in self._key_list:\r | |
391 | Items.append((Key, self[Key]))\r | |
392 | return Items\r | |
393 | \r | |
394 | ## Iteration support\r | |
395 | #\r | |
396 | def iteritems(self):\r | |
397 | return iter(self.items())\r | |
398 | \r | |
399 | ## Keys interation support\r | |
400 | #\r | |
401 | def iterkeys(self):\r | |
402 | return iter(self.keys())\r | |
403 | \r | |
404 | ## Values interation support\r | |
405 | #\r | |
406 | def itervalues(self):\r | |
407 | return iter(self.values())\r | |
408 | \r | |
409 | ## Return value related to a key, and remove the (key, value) from the dict\r | |
410 | #\r | |
411 | def pop(self, Key, *Dv):\r | |
412 | Value = None\r | |
413 | if Key in self._key_list:\r | |
414 | Value = self[Key]\r | |
415 | self.__delitem__(Key)\r | |
416 | elif len(Dv) != 0 :\r | |
417 | Value = Dv[0]\r | |
418 | return Value\r | |
419 | \r | |
420 | ## Return (key, value) pair, and remove the (key, value) from the dict\r | |
421 | #\r | |
422 | def popitem(self):\r | |
423 | Key = self._key_list[-1]\r | |
424 | Value = self[Key]\r | |
425 | self.__delitem__(Key)\r | |
426 | return Key, Value\r | |
427 | ## update method\r | |
428 | #\r | |
429 | def update(self, Dict=None, **Kwargs):\r | |
4231a819 | 430 | if Dict is not None:\r |
f51461c8 LG |
431 | for Key1, Val1 in Dict.items():\r |
432 | self[Key1] = Val1\r | |
433 | if len(Kwargs):\r | |
434 | for Key1, Val1 in Kwargs.items():\r | |
435 | self[Key1] = Val1\r | |
436 | \r | |
437 | ## CommonPath\r | |
438 | #\r | |
439 | # @param PathList: PathList\r | |
440 | #\r | |
441 | def CommonPath(PathList):\r | |
442 | Path1 = min(PathList).split(os.path.sep)\r | |
443 | Path2 = max(PathList).split(os.path.sep)\r | |
1b2e0772 | 444 | for Index in range(min(len(Path1), len(Path2))):\r |
f51461c8 LG |
445 | if Path1[Index] != Path2[Index]:\r |
446 | return os.path.sep.join(Path1[:Index])\r | |
447 | return os.path.sep.join(Path1)\r | |
448 | \r | |
449 | ## PathClass\r | |
450 | #\r | |
451 | class PathClass(object):\r | |
452 | def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False,\r | |
453 | Arch='COMMON', ToolChainFamily='', Target='', TagName='', \\r | |
454 | ToolCode=''):\r | |
455 | self.Arch = Arch\r | |
456 | self.File = str(File)\r | |
457 | if os.path.isabs(self.File):\r | |
458 | self.Root = ''\r | |
459 | self.AlterRoot = ''\r | |
460 | else:\r | |
461 | self.Root = str(Root)\r | |
462 | self.AlterRoot = str(AlterRoot)\r | |
463 | \r | |
464 | #\r | |
465 | # Remove any '.' and '..' in path\r | |
466 | #\r | |
467 | if self.Root:\r | |
468 | self.Path = os.path.normpath(os.path.join(self.Root, self.File))\r | |
469 | self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))\r | |
470 | #\r | |
471 | # eliminate the side-effect of 'C:'\r | |
472 | #\r | |
473 | if self.Root[-1] == ':':\r | |
474 | self.Root += os.path.sep\r | |
475 | #\r | |
476 | # file path should not start with path separator\r | |
477 | #\r | |
478 | if self.Root[-1] == os.path.sep:\r | |
479 | self.File = self.Path[len(self.Root):]\r | |
480 | else:\r | |
481 | self.File = self.Path[len(self.Root) + 1:]\r | |
482 | else:\r | |
483 | self.Path = os.path.normpath(self.File)\r | |
484 | \r | |
485 | self.SubDir, self.Name = os.path.split(self.File)\r | |
486 | self.BaseName, self.Ext = os.path.splitext(self.Name)\r | |
487 | \r | |
488 | if self.Root:\r | |
489 | if self.SubDir:\r | |
490 | self.Dir = os.path.join(self.Root, self.SubDir)\r | |
491 | else:\r | |
492 | self.Dir = self.Root\r | |
493 | else:\r | |
494 | self.Dir = self.SubDir\r | |
495 | \r | |
496 | if IsBinary:\r | |
497 | self.Type = Type\r | |
498 | else:\r | |
499 | self.Type = self.Ext.lower()\r | |
500 | \r | |
501 | self.IsBinary = IsBinary\r | |
502 | self.Target = Target\r | |
503 | self.TagName = TagName\r | |
504 | self.ToolCode = ToolCode\r | |
505 | self.ToolChainFamily = ToolChainFamily\r | |
506 | \r | |
507 | self._Key = None\r | |
508 | \r | |
509 | ## Convert the object of this class to a string\r | |
510 | #\r | |
511 | # Convert member Path of the class to a string\r | |
512 | #\r | |
513 | def __str__(self):\r | |
514 | return self.Path\r | |
515 | \r | |
516 | ## Override __eq__ function\r | |
517 | #\r | |
518 | # Check whether PathClass are the same\r | |
519 | #\r | |
520 | def __eq__(self, Other):\r | |
0d1f5b2b | 521 | if isinstance(Other, type(self)):\r |
f51461c8 LG |
522 | return self.Path == Other.Path\r |
523 | else:\r | |
524 | return self.Path == str(Other)\r | |
525 | \r | |
526 | ## Override __hash__ function\r | |
527 | #\r | |
528 | # Use Path as key in hash table\r | |
529 | #\r | |
530 | def __hash__(self):\r | |
531 | return hash(self.Path)\r | |
532 | \r | |
533 | ## _GetFileKey\r | |
534 | #\r | |
535 | def _GetFileKey(self):\r | |
4231a819 | 536 | if self._Key is None:\r |
f51461c8 LG |
537 | self._Key = self.Path.upper()\r |
538 | return self._Key\r | |
539 | ## Validate\r | |
540 | #\r | |
541 | def Validate(self, Type='', CaseSensitive=True):\r | |
542 | if GlobalData.gCASE_INSENSITIVE:\r | |
543 | CaseSensitive = False\r | |
544 | if Type and Type.lower() != self.Type:\r | |
545 | return ToolError.FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % \\r | |
546 | (self.File, Type, self.Type)\r | |
547 | \r | |
548 | RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot)\r | |
549 | if not RealRoot and not RealFile:\r | |
550 | RealFile = self.File\r | |
551 | if self.AlterRoot:\r | |
552 | RealFile = os.path.join(self.AlterRoot, self.File)\r | |
553 | elif self.Root:\r | |
554 | RealFile = os.path.join(self.Root, self.File)\r | |
555 | return ToolError.FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)\r | |
556 | \r | |
557 | ErrorCode = 0\r | |
558 | ErrorInfo = ''\r | |
559 | if RealRoot != self.Root or RealFile != self.File:\r | |
560 | if CaseSensitive and (RealFile != self.File or \\r | |
561 | (RealRoot != self.Root and RealRoot != \\r | |
562 | self.AlterRoot)):\r | |
563 | ErrorCode = ToolError.FILE_CASE_MISMATCH\r | |
564 | ErrorInfo = self.File + '\n\t' + RealFile + \\r | |
565 | " [in file system]"\r | |
566 | \r | |
567 | self.SubDir, self.Name = os.path.split(RealFile)\r | |
568 | self.BaseName, self.Ext = os.path.splitext(self.Name)\r | |
569 | if self.SubDir:\r | |
570 | self.Dir = os.path.join(RealRoot, self.SubDir)\r | |
571 | else:\r | |
572 | self.Dir = RealRoot\r | |
573 | self.File = RealFile\r | |
574 | self.Root = RealRoot\r | |
575 | self.Path = os.path.join(RealRoot, RealFile)\r | |
576 | return ErrorCode, ErrorInfo\r | |
577 | \r | |
578 | Key = property(_GetFileKey)\r | |
579 | \r | |
421ccda3 | 580 | ## Get current workspace\r |
f51461c8 | 581 | #\r |
421ccda3 | 582 | # get WORKSPACE from environment variable if present,if not use current working directory as WORKSPACE\r |
f51461c8 | 583 | #\r |
421ccda3 | 584 | def GetWorkspace():\r |
f51461c8 LG |
585 | #\r |
586 | # check WORKSPACE\r | |
587 | #\r | |
421ccda3 HC |
588 | if "WORKSPACE" in environ:\r |
589 | WorkspaceDir = os.path.normpath(environ["WORKSPACE"])\r | |
590 | if not os.path.exists(WorkspaceDir):\r | |
591 | Logger.Error("UPT",\r | |
592 | ToolError.UPT_ENVIRON_MISSING_ERROR,\r | |
593 | ST.ERR_WORKSPACE_NOTEXIST,\r | |
594 | ExtraData="%s" % WorkspaceDir)\r | |
595 | else:\r | |
596 | WorkspaceDir = os.getcwd()\r | |
f51461c8 | 597 | \r |
421ccda3 HC |
598 | if WorkspaceDir[-1] == ':':\r |
599 | WorkspaceDir += os.sep\r | |
fb0f8067 HC |
600 | \r |
601 | PackagesPath = os.environ.get("PACKAGES_PATH")\r | |
602 | mws.setWs(WorkspaceDir, PackagesPath)\r | |
603 | \r | |
604 | return WorkspaceDir, mws.PACKAGES_PATH\r | |
421ccda3 HC |
605 | \r |
606 | ## Get relative path\r | |
607 | #\r | |
608 | # use full path and workspace to get relative path\r | |
f7496d71 | 609 | # the destination of this function is mainly to resolve the root path issue(like c: or c:\)\r |
421ccda3 HC |
610 | #\r |
611 | # @param Fullpath: a string of fullpath\r | |
612 | # @param Workspace: a string of workspace\r | |
613 | #\r | |
614 | def GetRelativePath(Fullpath, Workspace):\r | |
f7496d71 | 615 | \r |
421ccda3 HC |
616 | RelativePath = ''\r |
617 | if Workspace.endswith(os.sep):\r | |
618 | RelativePath = Fullpath[Fullpath.upper().find(Workspace.upper())+len(Workspace):]\r | |
619 | else:\r | |
620 | RelativePath = Fullpath[Fullpath.upper().find(Workspace.upper())+len(Workspace)+1:]\r | |
f7496d71 | 621 | \r |
421ccda3 | 622 | return RelativePath\r |
f7496d71 | 623 | \r |
f51461c8 LG |
624 | ## Check whether all module types are in list\r |
625 | #\r | |
626 | # check whether all module types (SUP_MODULE_LIST) are in list\r | |
f7496d71 | 627 | #\r |
f51461c8 LG |
628 | # @param ModuleList: a list of ModuleType\r |
629 | #\r | |
630 | def IsAllModuleList(ModuleList):\r | |
631 | NewModuleList = [Module.upper() for Module in ModuleList]\r | |
632 | for Module in SUP_MODULE_LIST:\r | |
633 | if Module not in NewModuleList:\r | |
634 | return False\r | |
635 | else:\r | |
636 | return True\r | |
637 | \r | |
638 | ## Dictionary that use comment(GenericComment, TailComment) as value,\r | |
f7496d71 | 639 | # if a new comment which key already in the dic is inserted, then the\r |
f51461c8 | 640 | # comment will be merged.\r |
f7496d71 | 641 | # Key is (Statement, SupArch), when TailComment is added, it will ident\r |
f51461c8 LG |
642 | # according to Statement\r |
643 | #\r | |
644 | class MergeCommentDict(dict):\r | |
645 | ## []= operator\r | |
646 | #\r | |
647 | def __setitem__(self, Key, CommentVal):\r | |
648 | GenericComment, TailComment = CommentVal\r | |
649 | if Key in self:\r | |
650 | OrigVal1, OrigVal2 = dict.__getitem__(self, Key)\r | |
651 | Statement = Key[0]\r | |
652 | dict.__setitem__(self, Key, (OrigVal1 + GenericComment, OrigVal2 \\r | |
653 | + len(Statement) * ' ' + TailComment))\r | |
654 | else:\r | |
655 | dict.__setitem__(self, Key, (GenericComment, TailComment))\r | |
656 | \r | |
657 | ## =[] operator\r | |
658 | #\r | |
659 | def __getitem__(self, Key):\r | |
660 | return dict.__getitem__(self, Key)\r | |
661 | \r | |
662 | \r | |
663 | ## GenDummyHelpTextObj\r | |
664 | #\r | |
665 | # @retval HelpTxt: Generated dummy help text object\r | |
666 | #\r | |
667 | def GenDummyHelpTextObj():\r | |
668 | HelpTxt = TextObject()\r | |
421ccda3 | 669 | HelpTxt.SetLang(TAB_LANGUAGE_EN_US)\r |
f51461c8 LG |
670 | HelpTxt.SetString(' ')\r |
671 | return HelpTxt\r | |
672 | \r | |
673 | ## ConvertVersionToDecimal, the minor version should be within 0 - 99\r | |
674 | # <HexVersion> ::= "0x" <Major> <Minor>\r | |
675 | # <Major> ::= (a-fA-F0-9){4}\r | |
676 | # <Minor> ::= (a-fA-F0-9){4}\r | |
677 | # <DecVersion> ::= (0-65535) ["." (0-99)]\r | |
f7496d71 | 678 | #\r |
f51461c8 LG |
679 | # @param StringIn: The string contains version defined in INF file.\r |
680 | # It can be Decimal or Hex\r | |
681 | #\r | |
682 | def ConvertVersionToDecimal(StringIn):\r | |
683 | if IsValidHexVersion(StringIn):\r | |
684 | Value = int(StringIn, 16)\r | |
685 | Major = Value >> 16\r | |
686 | Minor = Value & 0xFFFF\r | |
687 | MinorStr = str(Minor)\r | |
688 | if len(MinorStr) == 1:\r | |
689 | MinorStr = '0' + MinorStr\r | |
690 | return str(Major) + '.' + MinorStr\r | |
691 | else:\r | |
692 | if StringIn.find(TAB_SPLIT) != -1:\r | |
693 | return StringIn\r | |
694 | elif StringIn:\r | |
695 | return StringIn + '.0'\r | |
696 | else:\r | |
697 | #\r | |
698 | # when StringIn is '', return it directly\r | |
699 | #\r | |
700 | return StringIn\r | |
701 | \r | |
702 | ## GetHelpStringByRemoveHashKey\r | |
703 | #\r | |
704 | # Remove hash key at the header of string and return the remain.\r | |
705 | #\r | |
706 | # @param String: The string need to be processed.\r | |
707 | #\r | |
708 | def GetHelpStringByRemoveHashKey(String):\r | |
709 | ReturnString = ''\r | |
710 | PattenRemoveHashKey = re.compile(r"^[#+\s]+", re.DOTALL)\r | |
711 | String = String.strip()\r | |
712 | if String == '':\r | |
713 | return String\r | |
714 | \r | |
715 | LineList = GetSplitValueList(String, END_OF_LINE)\r | |
716 | for Line in LineList:\r | |
717 | ValueList = PattenRemoveHashKey.split(Line)\r | |
718 | if len(ValueList) == 1:\r | |
719 | ReturnString += ValueList[0] + END_OF_LINE\r | |
720 | else:\r | |
721 | ReturnString += ValueList[1] + END_OF_LINE\r | |
722 | \r | |
723 | if ReturnString.endswith('\n') and not ReturnString.endswith('\n\n') and ReturnString != '\n':\r | |
724 | ReturnString = ReturnString[:-1]\r | |
725 | \r | |
726 | return ReturnString\r | |
727 | \r | |
728 | ## ConvPathFromAbsToRel\r | |
729 | #\r | |
730 | # Get relative file path from absolute path.\r | |
731 | #\r | |
732 | # @param Path: The string contain file absolute path.\r | |
733 | # @param Root: The string contain the parent path of Path in.\r | |
734 | #\r | |
735 | #\r | |
736 | def ConvPathFromAbsToRel(Path, Root):\r | |
737 | Path = os.path.normpath(Path)\r | |
738 | Root = os.path.normpath(Root)\r | |
739 | FullPath = os.path.normpath(os.path.join(Root, Path))\r | |
740 | \r | |
741 | #\r | |
742 | # If Path is absolute path.\r | |
743 | # It should be in Root.\r | |
744 | #\r | |
745 | if os.path.isabs(Path):\r | |
746 | return FullPath[FullPath.find(Root) + len(Root) + 1:]\r | |
747 | \r | |
748 | else:\r | |
749 | return Path\r | |
750 | \r | |
751 | ## ConvertPath\r | |
752 | #\r | |
753 | # Convert special characters to '_', '\' to '/'\r | |
754 | # return converted path: Test!1.inf -> Test_1.inf\r | |
755 | #\r | |
756 | # @param Path: Path to be converted\r | |
757 | #\r | |
758 | def ConvertPath(Path):\r | |
759 | RetPath = ''\r | |
760 | for Char in Path.strip():\r | |
761 | if Char.isalnum() or Char in '.-_/':\r | |
762 | RetPath = RetPath + Char\r | |
763 | elif Char == '\\':\r | |
764 | RetPath = RetPath + '/'\r | |
765 | else:\r | |
766 | RetPath = RetPath + '_'\r | |
767 | return RetPath\r | |
768 | \r | |
769 | ## ConvertSpec\r | |
770 | #\r | |
f7496d71 | 771 | # during install, convert the Spec string extract from UPD into INF allowable definition,\r |
f51461c8 LG |
772 | # the difference is period is allowed in the former (not the first letter) but not in the latter.\r |
773 | # return converted Spec string\r | |
774 | #\r | |
775 | # @param SpecStr: SpecStr to be converted\r | |
776 | #\r | |
777 | def ConvertSpec(SpecStr):\r | |
778 | RetStr = ''\r | |
779 | for Char in SpecStr:\r | |
780 | if Char.isalnum() or Char == '_':\r | |
781 | RetStr = RetStr + Char\r | |
782 | else:\r | |
783 | RetStr = RetStr + '_'\r | |
784 | \r | |
785 | return RetStr\r | |
786 | \r | |
787 | \r | |
788 | ## IsEqualList\r | |
789 | #\r | |
790 | # Judge two lists are identical(contain same item).\r | |
791 | # The rule is elements in List A are in List B and elements in List B are in List A.\r | |
792 | #\r | |
793 | # @param ListA, ListB Lists need to be judged.\r | |
f7496d71 | 794 | #\r |
f51461c8 LG |
795 | # @return True ListA and ListB are identical\r |
796 | # @return False ListA and ListB are different with each other\r | |
797 | #\r | |
798 | def IsEqualList(ListA, ListB):\r | |
799 | if ListA == ListB:\r | |
800 | return True\r | |
801 | \r | |
802 | for ItemA in ListA:\r | |
803 | if not ItemA in ListB:\r | |
804 | return False\r | |
805 | \r | |
806 | for ItemB in ListB:\r | |
807 | if not ItemB in ListA:\r | |
808 | return False\r | |
809 | \r | |
810 | return True\r | |
811 | \r | |
812 | ## ConvertArchList\r | |
813 | #\r | |
814 | # Convert item in ArchList if the start character is lower case.\r | |
f7496d71 | 815 | # In UDP spec, Arch is only allowed as: [A-Z]([a-zA-Z0-9])*\r |
f51461c8 LG |
816 | #\r |
817 | # @param ArchList The ArchList need to be converted.\r | |
f7496d71 | 818 | #\r |
f51461c8 LG |
819 | # @return NewList The ArchList been converted.\r |
820 | #\r | |
821 | def ConvertArchList(ArchList):\r | |
822 | NewArchList = []\r | |
823 | if not ArchList:\r | |
824 | return NewArchList\r | |
825 | \r | |
0d1f5b2b | 826 | if isinstance(ArchList, list):\r |
f51461c8 LG |
827 | for Arch in ArchList:\r |
828 | Arch = Arch.upper()\r | |
829 | NewArchList.append(Arch)\r | |
0d1f5b2b | 830 | elif isinstance(ArchList, str):\r |
f51461c8 LG |
831 | ArchList = ArchList.upper()\r |
832 | NewArchList.append(ArchList)\r | |
833 | \r | |
834 | return NewArchList\r | |
835 | \r | |
836 | ## ProcessLineExtender\r | |
837 | #\r | |
838 | # Process the LineExtender of Line in LineList.\r | |
839 | # If one line ends with a line extender, then it will be combined together with next line.\r | |
840 | #\r | |
841 | # @param LineList The LineList need to be processed.\r | |
f7496d71 | 842 | #\r |
f51461c8 LG |
843 | # @return NewList The ArchList been processed.\r |
844 | #\r | |
845 | def ProcessLineExtender(LineList):\r | |
846 | NewList = []\r | |
847 | Count = 0\r | |
848 | while Count < len(LineList):\r | |
849 | if LineList[Count].strip().endswith("\\") and Count + 1 < len(LineList):\r | |
850 | NewList.append(LineList[Count].strip()[:-2] + LineList[Count + 1])\r | |
851 | Count = Count + 1\r | |
852 | else:\r | |
853 | NewList.append(LineList[Count])\r | |
854 | \r | |
855 | Count = Count + 1\r | |
856 | \r | |
857 | return NewList\r | |
858 | \r | |
859 | ## ProcessEdkComment\r | |
860 | #\r | |
f7496d71 | 861 | # Process EDK style comment in LineList: c style /* */ comment or cpp style // comment\r |
f51461c8 LG |
862 | #\r |
863 | #\r | |
864 | # @param LineList The LineList need to be processed.\r | |
f7496d71 | 865 | #\r |
f51461c8 LG |
866 | # @return LineList The LineList been processed.\r |
867 | # @return FirstPos Where Edk comment is first found, -1 if not found\r | |
868 | #\r | |
869 | def ProcessEdkComment(LineList):\r | |
870 | FindEdkBlockComment = False\r | |
871 | Count = 0\r | |
872 | StartPos = -1\r | |
873 | EndPos = -1\r | |
874 | FirstPos = -1\r | |
f7496d71 | 875 | \r |
f51461c8 LG |
876 | while(Count < len(LineList)):\r |
877 | Line = LineList[Count].strip()\r | |
878 | if Line.startswith("/*"):\r | |
879 | #\r | |
880 | # handling c style comment\r | |
881 | #\r | |
882 | StartPos = Count\r | |
883 | while Count < len(LineList):\r | |
884 | Line = LineList[Count].strip()\r | |
885 | if Line.endswith("*/"):\r | |
886 | if (Count == StartPos) and Line.strip() == '/*/':\r | |
887 | Count = Count + 1\r | |
888 | continue\r | |
889 | EndPos = Count\r | |
890 | FindEdkBlockComment = True\r | |
891 | break\r | |
892 | Count = Count + 1\r | |
f7496d71 | 893 | \r |
f51461c8 LG |
894 | if FindEdkBlockComment:\r |
895 | if FirstPos == -1:\r | |
896 | FirstPos = StartPos\r | |
1b2e0772 | 897 | for Index in range(StartPos, EndPos+1):\r |
f51461c8 LG |
898 | LineList[Index] = ''\r |
899 | FindEdkBlockComment = False\r | |
900 | elif Line.find("//") != -1 and not Line.startswith("#"):\r | |
901 | #\r | |
902 | # handling cpp style comment\r | |
903 | #\r | |
904 | LineList[Count] = Line.replace("//", '#')\r | |
905 | if FirstPos == -1:\r | |
906 | FirstPos = Count\r | |
f7496d71 | 907 | \r |
f51461c8 | 908 | Count = Count + 1\r |
f7496d71 | 909 | \r |
f51461c8 LG |
910 | return LineList, FirstPos\r |
911 | \r | |
912 | ## GetLibInstanceInfo\r | |
913 | #\r | |
914 | # Get the information from Library Instance INF file.\r | |
915 | #\r | |
916 | # @param string. A string start with # and followed by INF file path\r | |
917 | # @param WorkSpace. The WorkSpace directory used to combined with INF file path.\r | |
918 | #\r | |
919 | # @return GUID, Version\r | |
920 | def GetLibInstanceInfo(String, WorkSpace, LineNo):\r | |
921 | \r | |
922 | FileGuidString = ""\r | |
923 | VerString = ""\r | |
924 | \r | |
925 | OrignalString = String\r | |
926 | String = String.strip()\r | |
927 | if not String:\r | |
928 | return None, None\r | |
929 | #\r | |
930 | # Remove "#" characters at the beginning\r | |
931 | #\r | |
932 | String = GetHelpStringByRemoveHashKey(String)\r | |
933 | String = String.strip()\r | |
934 | \r | |
935 | #\r | |
936 | # Validate file name exist.\r | |
937 | #\r | |
938 | FullFileName = os.path.normpath(os.path.realpath(os.path.join(WorkSpace, String)))\r | |
939 | if not (ValidFile(FullFileName)):\r | |
940 | Logger.Error("InfParser",\r | |
941 | ToolError.FORMAT_INVALID,\r | |
942 | ST.ERR_FILELIST_EXIST % (String),\r | |
943 | File=GlobalData.gINF_MODULE_NAME,\r | |
944 | Line=LineNo,\r | |
945 | ExtraData=OrignalString)\r | |
946 | \r | |
947 | #\r | |
948 | # Validate file exist/format.\r | |
949 | #\r | |
950 | if IsValidPath(String, WorkSpace):\r | |
951 | IsValidFileFlag = True\r | |
952 | else:\r | |
953 | Logger.Error("InfParser",\r | |
954 | ToolError.FORMAT_INVALID,\r | |
955 | ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID % (String),\r | |
956 | File=GlobalData.gINF_MODULE_NAME,\r | |
957 | Line=LineNo,\r | |
958 | ExtraData=OrignalString)\r | |
959 | return False\r | |
960 | if IsValidFileFlag:\r | |
961 | FileLinesList = []\r | |
962 | \r | |
963 | try:\r | |
1b2e0772 | 964 | FInputfile = open(FullFileName, "r")\r |
f51461c8 LG |
965 | try:\r |
966 | FileLinesList = FInputfile.readlines()\r | |
967 | except BaseException:\r | |
968 | Logger.Error("InfParser",\r | |
969 | ToolError.FILE_READ_FAILURE,\r | |
970 | ST.ERR_FILE_OPEN_FAILURE,\r | |
971 | File=FullFileName)\r | |
972 | finally:\r | |
973 | FInputfile.close()\r | |
974 | except BaseException:\r | |
975 | Logger.Error("InfParser",\r | |
976 | ToolError.FILE_READ_FAILURE,\r | |
977 | ST.ERR_FILE_OPEN_FAILURE,\r | |
978 | File=FullFileName)\r | |
979 | \r | |
980 | ReFileGuidPattern = re.compile("^\s*FILE_GUID\s*=.*$")\r | |
981 | ReVerStringPattern = re.compile("^\s*VERSION_STRING\s*=.*$")\r | |
982 | \r | |
983 | FileLinesList = ProcessLineExtender(FileLinesList)\r | |
984 | \r | |
985 | for Line in FileLinesList:\r | |
986 | if ReFileGuidPattern.match(Line):\r | |
987 | FileGuidString = Line\r | |
988 | if ReVerStringPattern.match(Line):\r | |
989 | VerString = Line\r | |
990 | \r | |
991 | if FileGuidString:\r | |
992 | FileGuidString = GetSplitValueList(FileGuidString, '=', 1)[1]\r | |
993 | if VerString:\r | |
994 | VerString = GetSplitValueList(VerString, '=', 1)[1]\r | |
995 | \r | |
996 | return FileGuidString, VerString\r | |
421ccda3 HC |
997 | \r |
998 | ## GetLocalValue\r | |
999 | #\r | |
1000 | # Generate the local value for INF and DEC file. If Lang attribute not present, then use this value.\r | |
f7496d71 LG |
1001 | # If present, and there is no element without the Lang attribute, and one of the elements has the rfc1766 code is\r |
1002 | # "en-x-tianocore", or "en-US" if "en-x-tianocore" was not found, or "en" if "en-US" was not found, or startswith 'en'\r | |
421ccda3 HC |
1003 | # if 'en' was not found, then use this value.\r |
1004 | # If multiple entries of a tag exist which have the same language code, use the last entry.\r | |
1005 | #\r | |
1006 | # @param ValueList A list need to be processed.\r | |
f7496d71 | 1007 | # @param UseFirstValue: True to use the first value, False to use the last value\r |
421ccda3 HC |
1008 | #\r |
1009 | # @return LocalValue\r | |
1010 | def GetLocalValue(ValueList, UseFirstValue=False):\r | |
1011 | Value1 = ''\r | |
1012 | Value2 = ''\r | |
1013 | Value3 = ''\r | |
1014 | Value4 = ''\r | |
1015 | Value5 = ''\r | |
1016 | for (Key, Value) in ValueList:\r | |
1017 | if Key == TAB_LANGUAGE_EN_X:\r | |
1018 | if UseFirstValue:\r | |
1019 | if not Value1:\r | |
1020 | Value1 = Value\r | |
1021 | else:\r | |
1022 | Value1 = Value\r | |
1023 | if Key == TAB_LANGUAGE_EN_US:\r | |
1024 | if UseFirstValue:\r | |
1025 | if not Value2:\r | |
1026 | Value2 = Value\r | |
1027 | else:\r | |
1028 | Value2 = Value\r | |
1029 | if Key == TAB_LANGUAGE_EN:\r | |
1030 | if UseFirstValue:\r | |
1031 | if not Value3:\r | |
1032 | Value3 = Value\r | |
1033 | else:\r | |
1034 | Value3 = Value\r | |
1035 | if Key.startswith(TAB_LANGUAGE_EN):\r | |
1036 | if UseFirstValue:\r | |
1037 | if not Value4:\r | |
1038 | Value4 = Value\r | |
1039 | else:\r | |
1040 | Value4 = Value\r | |
1041 | if Key == '':\r | |
1042 | if UseFirstValue:\r | |
1043 | if not Value5:\r | |
1044 | Value5 = Value\r | |
1045 | else:\r | |
1046 | Value5 = Value\r | |
f7496d71 | 1047 | \r |
421ccda3 HC |
1048 | if Value1:\r |
1049 | return Value1\r | |
1050 | if Value2:\r | |
1051 | return Value2\r | |
1052 | if Value3:\r | |
1053 | return Value3\r | |
1054 | if Value4:\r | |
1055 | return Value4\r | |
1056 | if Value5:\r | |
1057 | return Value5\r | |
f7496d71 | 1058 | \r |
421ccda3 HC |
1059 | return ''\r |
1060 | \r | |
1061 | \r | |
1062 | ## GetCharIndexOutStr\r | |
1063 | #\r | |
1064 | # Get comment character index outside a string\r | |
1065 | #\r | |
1066 | # @param Line: The string to be checked\r | |
1067 | # @param CommentCharacter: Comment char, used to ignore comment content\r | |
1068 | #\r | |
1069 | # @retval Index\r | |
1070 | #\r | |
1071 | def GetCharIndexOutStr(CommentCharacter, Line):\r | |
1072 | #\r | |
1073 | # remove whitespace\r | |
1074 | #\r | |
1075 | Line = Line.strip()\r | |
1076 | \r | |
1077 | #\r | |
1078 | # Check whether comment character is in a string\r | |
1079 | #\r | |
1080 | InString = False\r | |
1081 | for Index in range(0, len(Line)):\r | |
1082 | if Line[Index] == '"':\r | |
1083 | InString = not InString\r | |
1084 | elif Line[Index] == CommentCharacter and InString :\r | |
1085 | pass\r | |
1086 | elif Line[Index] == CommentCharacter and (Index +1) < len(Line) and Line[Index+1] == CommentCharacter \\r | |
1087 | and not InString :\r | |
1088 | return Index\r | |
1089 | return -1\r | |
1090 | \r | |
1091 | ## ValidateUNIFilePath\r | |
1092 | #\r | |
1093 | # Check the UNI file path\r | |
1094 | #\r | |
f7496d71 | 1095 | # @param FilePath: The UNI file path\r |
421ccda3 HC |
1096 | #\r |
1097 | def ValidateUNIFilePath(Path):\r | |
1098 | Suffix = Path[Path.rfind(TAB_SPLIT):]\r | |
f7496d71 | 1099 | \r |
421ccda3 | 1100 | #\r |
f7496d71 | 1101 | # Check if the suffix is one of the '.uni', '.UNI', '.Uni'\r |
421ccda3 HC |
1102 | #\r |
1103 | if Suffix not in TAB_UNI_FILE_SUFFIXS:\r | |
f7496d71 LG |
1104 | Logger.Error("Unicode File Parser",\r |
1105 | ToolError.FORMAT_INVALID,\r | |
1106 | Message=ST.ERR_UNI_FILE_SUFFIX_WRONG,\r | |
1107 | ExtraData=Path)\r | |
1108 | \r | |
421ccda3 HC |
1109 | #\r |
1110 | # Check if '..' in the file name(without suffixe)\r | |
1111 | #\r | |
1112 | if (TAB_SPLIT + TAB_SPLIT) in Path:\r | |
f7496d71 LG |
1113 | Logger.Error("Unicode File Parser",\r |
1114 | ToolError.FORMAT_INVALID,\r | |
1115 | Message=ST.ERR_UNI_FILE_NAME_INVALID,\r | |
1116 | ExtraData=Path)\r | |
1117 | \r | |
421ccda3 HC |
1118 | #\r |
1119 | # Check if the file name is valid according to the DEC and INF specification\r | |
1120 | #\r | |
1121 | Pattern = '[a-zA-Z0-9_][a-zA-Z0-9_\-\.]*'\r | |
1122 | FileName = Path.replace(Suffix, '')\r | |
1123 | InvalidCh = re.sub(Pattern, '', FileName)\r | |
1124 | if InvalidCh:\r | |
f7496d71 LG |
1125 | Logger.Error("Unicode File Parser",\r |
1126 | ToolError.FORMAT_INVALID,\r | |
1127 | Message=ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID,\r | |
1128 | ExtraData=Path)\r | |
421ccda3 | 1129 | \r |