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