From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../plugins/EdkPlugins/basemodel/ini.py | 475 +++++++++++++++++++++ 1 file changed, 475 insertions(+) create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/ini.py (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/ini.py') diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/ini.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/ini.py new file mode 100755 index 00000000..6d61b7a2 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/ini.py @@ -0,0 +1,475 @@ +## @file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +from __future__ import absolute_import +from .message import * +import re +import os + +section_re = re.compile(r'^\[([\w., "]+)\]') + +class BaseINIFile(object): + _objs = {} + def __new__(cls, *args, **kwargs): + """Maintain only a single instance of this object + @return: instance of this class + + """ + if len(args) == 0: return object.__new__(cls) + filename = args[0] + parent = None + if len(args) > 1: + parent = args[1] + + key = os.path.normpath(filename) + if key not in cls._objs.keys(): + cls._objs[key] = object.__new__(cls) + + if parent is not None: + cls._objs[key].AddParent(parent) + + return cls._objs[key] + + def __init__(self, filename=None, parent=None): + self._lines = [] + self._sections = {} + self._filename = filename + self._globals = [] + self._isModify = True + + def AddParent(self, parent): + if parent is None: return + if not hasattr(self, "_parents"): + self._parents = [] + + if parent in self._parents: + ErrorMsg("Duplicate parent is found for INI file %s" % self._filename) + return + self._parents.append(parent) + + def GetFilename(self): + return os.path.normpath(self._filename) + + def IsModified(self): + return self._isModify + + def Modify(self, modify=True, obj=None): + if modify == self._isModify: return + self._isModify = modify + if modify: + for parent in self._parents: + parent.Modify(True, self) + + def _ReadLines(self, filename): + # + # try to open file + # + if not os.path.exists(filename): + return False + + try: + handle = open(filename, 'r') + self._lines = handle.readlines() + handle.close() + except: + raise EdkException("Fail to open file %s" % filename) + + return True + + def GetSectionInstance(self, parent, name, isCombined=False): + return BaseINISection(parent, name, isCombined) + + def GetSectionByName(self, name): + arr = [] + for key in self._sections.keys(): + if '.private' in key: + continue + for item in self._sections[key]: + if item.GetBaseName().lower().find(name.lower()) != -1: + arr.append(item) + return arr + + def GetSectionObjectsByName(self, name): + arr = [] + sects = self.GetSectionByName(name) + for sect in sects: + for obj in sect.GetObjects(): + arr.append(obj) + return arr + + def Parse(self): + if not self._isModify: return True + if not self._ReadLines(self._filename): return False + + sObjs = [] + inGlobal = True + # process line + for index in range(len(self._lines)): + templine = self._lines[index].strip() + # skip comments + if len(templine) == 0: continue + if re.match("^\[=*\]", templine) or re.match("^#", templine) or \ + re.match("\*+/", templine): + continue + + m = section_re.match(templine) + if m is not None: # found a section + inGlobal = False + # Finish the latest section first + if len(sObjs) != 0: + for sObj in sObjs: + sObj._end = index - 1 + if not sObj.Parse(): + ErrorMsg("Fail to parse section %s" % sObj.GetBaseName(), + self._filename, + sObj._start) + + # start new section + sname_arr = m.groups()[0].split(',') + sObjs = [] + for name in sname_arr: + sObj = self.GetSectionInstance(self, name, (len(sname_arr) > 1)) + sObj._start = index + sObjs.append(sObj) + if name.lower() not in self._sections: + self._sections[name.lower()] = [sObj] + else: + self._sections[name.lower()].append(sObj) + elif inGlobal: # not start any section and find global object + gObj = BaseINIGlobalObject(self) + gObj._start = index + gObj.Parse() + self._globals.append(gObj) + + # Finish the last section + if len(sObjs) != 0: + for sObj in sObjs: + sObj._end = index + if not sObj.Parse(): + ErrorMsg("Fail to parse section %s" % sObj.GetBaseName(), + self._filename, + sObj._start) + + self._isModify = False + return True + + def Destroy(self, parent): + + # check referenced parent + if parent is not None: + assert parent in self._parents, "when destory ini object, can not found parent reference!" + self._parents.remove(parent) + + if len(self._parents) != 0: return + + for sects in self._sections.values(): + for sect in sects: + sect.Destroy() + + # dereference from _objs array + assert self.GetFilename() in self._objs.keys(), "When destroy ini object, can not find obj reference!" + assert self in self._objs.values(), "When destroy ini object, can not find obj reference!" + del self._objs[self.GetFilename()] + + # dereference self + self.Clear() + + def GetDefine(self, name): + sects = self.GetSectionByName('Defines') + for sect in sects: + for obj in sect.GetObjects(): + line = obj.GetLineByOffset(obj._start).split('#')[0].strip() + arr = line.split('=') + if arr[0].strip().lower() == name.strip().lower(): + return arr[1].strip() + return None + + def Clear(self): + for sects in self._sections.values(): + for sect in sects: + del sect + self._sections.clear() + for gObj in self._globals: + del gObj + + del self._globals[:] + del self._lines[:] + + def Reload(self): + self.Clear() + ret = self.Parse() + if ret: + self._isModify = False + return ret + + def AddNewSection(self, sectName): + if sectName.lower() in self._sections.keys(): + ErrorMsg('Section %s can not be created for conflict with existing section') + return None + + sectionObj = self.GetSectionInstance(self, sectName) + sectionObj._start = len(self._lines) + sectionObj._end = len(self._lines) + 1 + self._lines.append('[%s]\n' % sectName) + self._lines.append('\n\n') + self._sections[sectName.lower()] = sectionObj + return sectionObj + + def CopySectionsByName(self, oldDscObj, nameStr): + sects = oldDscObj.GetSectionByName(nameStr) + for sect in sects: + sectObj = self.AddNewSection(sect.GetName()) + sectObj.Copy(sect) + + def __str__(self): + return ''.join(self._lines) + + ## Get file header's comment from basic INI file. + # The file comments has two style: + # 1) #/** @file + # 2) ## @file + # + def GetFileHeader(self): + desc = [] + lineArr = self._lines + inHeader = False + for num in range(len(self._lines)): + line = lineArr[num].strip() + if not inHeader and (line.startswith("#/**") or line.startswith("##")) and \ + line.find("@file") != -1: + inHeader = True + continue + if inHeader and (line.startswith("#**/") or line.startswith('##')): + inHeader = False + break + if inHeader: + prefixIndex = line.find('#') + if prefixIndex == -1: + desc.append(line) + else: + desc.append(line[prefixIndex + 1:]) + return '
\n'.join(desc) + +class BaseINISection(object): + def __init__(self, parent, name, isCombined=False): + self._parent = parent + self._name = name + self._isCombined = isCombined + self._start = 0 + self._end = 0 + self._objs = [] + + def __del__(self): + for obj in self._objs: + del obj + del self._objs[:] + + def GetName(self): + return self._name + + def GetObjects(self): + return self._objs + + def GetParent(self): + return self._parent + + def GetStartLinenumber(self): + return self._start + + def GetEndLinenumber(self): + return self._end + + def GetLine(self, linenumber): + return self._parent._lines[linenumber] + + def GetFilename(self): + return self._parent.GetFilename() + + def GetSectionINIObject(self, parent): + return BaseINISectionObject(parent) + + def Parse(self): + # skip first line in section, it is used by section name + visit = self._start + 1 + iniObj = None + while (visit <= self._end): + line = self.GetLine(visit).strip() + if re.match("^\[=*\]", line) or re.match("^#", line) or len(line) == 0: + visit += 1 + continue + line = line.split('#')[0].strip() + if iniObj is not None: + if line.endswith('}'): + iniObj._end = visit - self._start + if not iniObj.Parse(): + ErrorMsg("Fail to parse ini object", + self.GetFilename(), + iniObj.GetStartLinenumber()) + else: + self._objs.append(iniObj) + iniObj = None + else: + iniObj = self.GetSectionINIObject(self) + iniObj._start = visit - self._start + if not line.endswith('{'): + iniObj._end = visit - self._start + if not iniObj.Parse(): + ErrorMsg("Fail to parse ini object", + self.GetFilename(), + iniObj.GetStartLinenumber()) + else: + self._objs.append(iniObj) + iniObj = None + visit += 1 + return True + + def Destroy(self): + for obj in self._objs: + obj.Destroy() + + def GetBaseName(self): + return self._name + + def AddLine(self, line): + end = self.GetEndLinenumber() + self._parent._lines.insert(end, line) + self._end += 1 + + def Copy(self, sectObj): + index = sectObj.GetStartLinenumber() + 1 + while index < sectObj.GetEndLinenumber(): + line = sectObj.GetLine(index) + if not line.strip().startswith('#'): + self.AddLine(line) + index += 1 + + def AddObject(self, obj): + lines = obj.GenerateLines() + for line in lines: + self.AddLine(line) + + def GetComment(self): + comments = [] + start = self._start - 1 + bFound = False + + while (start > 0): + line = self.GetLine(start).strip() + if len(line) == 0: + start -= 1 + continue + if line.startswith('##'): + bFound = True + index = line.rfind('#') + if (index + 1) < len(line): + comments.append(line[index + 1:]) + break + if line.startswith('#'): + start -= 1 + continue + break + if bFound: + end = start + 1 + while (end < self._start): + line = self.GetLine(end).strip() + if len(line) == 0: break + if not line.startswith('#'): break + index = line.rfind('#') + if (index + 1) < len(line): + comments.append(line[index + 1:]) + end += 1 + return comments + +class BaseINIGlobalObject(object): + def __init__(self, parent): + self._start = 0 + self._end = 0 + + def Parse(self): + return True + + def __str__(self): + return parent._lines[self._start] + + def __del__(self): + pass + +class BaseINISectionObject(object): + def __init__(self, parent): + self._start = 0 + self._end = 0 + self._parent = parent + + def __del__(self): + self._parent = None + + def GetParent(self): + return self._parent + + def GetFilename(self): + return self.GetParent().GetFilename() + + def GetPackageName(self): + return self.GetFilename() + + def GetFileObj(self): + return self.GetParent().GetParent() + + def GetStartLinenumber(self): + return self.GetParent()._start + self._start + + def GetLineByOffset(self, offset): + sect_start = self._parent.GetStartLinenumber() + linenumber = sect_start + offset + return self._parent.GetLine(linenumber) + + def GetLinenumberByOffset(self, offset): + return offset + self._parent.GetStartLinenumber() + + def Parse(self): + return True + + def Destroy(self): + pass + + def __str__(self): + return self.GetLineByOffset(self._start).strip() + + def GenerateLines(self): + return ['default setion object string\n'] + + def GetComment(self): + comments = [] + start = self.GetStartLinenumber() - 1 + bFound = False + + while (start > 0): + line = self.GetParent().GetLine(start).strip() + if len(line) == 0: + start -= 1 + continue + if line.startswith('##'): + bFound = True + index = line.rfind('#') + if (index + 1) < len(line): + comments.append(line[index + 1:]) + break + if line.startswith('#'): + start -= 1 + continue + break + if bFound: + end = start + 1 + while (end <= self.GetStartLinenumber() - 1): + line = self.GetParent().GetLine(end).strip() + if len(line) == 0: break + if not line.startswith('#'): break + index = line.rfind('#') + if (index + 1) < len(line): + comments.append(line[index + 1:]) + end += 1 + return comments -- cgit v1.2.3