text: ## @file
  #
  # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
  #
  # This program and the accompanying materials are licensed and made available
  # under the terms and conditions of the BSD License which accompanies this
  # distribution. The full text of the license may be found at
  # http://opensource.org/licenses/bsd-license.php
  #
  # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  #
  
  import plugins.EdkPlugins.basemodel.ini as ini
  import re, os
  from plugins.EdkPlugins.basemodel.message import *
  
  class DECFile(ini.BaseINIFile):
  
      def GetSectionInstance(self, parent, name, isCombined=False):
          return DECSection(parent, name, isCombined)
  
      def GetComponents(self):
          return self.GetSectionByName('Components')
  
      def GetPackageRootPath(self):
          return os.path.dirname(self.GetFilename()).strip()
  
      def GetBaseName(self):
          return self.GetDefine("PACKAGE_NAME").strip()
  
      def GetVersion(self):
          return self.GetDefine("PACKAGE_VERSION").strip()
  
      def GetSectionObjectsByName(self, name, arch=None):
          arr = []
          sects = self.GetSectionByName(name)
          for sect in sects:
              # skip unmatched archtecture content
              if not sect.IsArchMatch(arch):
                  continue
  
              for obj in sect.GetObjects():
                  arr.append(obj)
  
          return arr
  
  class DECSection(ini.BaseINISection):
      def GetSectionINIObject(self, parent):
          type = self.GetType()
  
          if type.lower().find('defines') != -1:
              return DECDefineSectionObject(self)
          if type.lower().find('includes') != -1:
              return DECIncludeObject(self)
          if type.lower().find('pcd') != -1:
              return DECPcdObject(self)
          if type.lower() == 'libraryclasses':
              return DECLibraryClassObject(self)
          if type.lower() == 'guids':
              return DECGuidObject(self)
          if type.lower() == 'ppis':
              return DECPpiObject(self)
          if type.lower() == 'protocols':
              return DECProtocolObject(self)
  
          return DECSectionObject(self)
  
      def GetType(self):
          arr = self._name.split('.')
          return arr[0].strip()
  
      def GetArch(self):
          arr = self._name.split('.')
          if len(arr) == 1:
              return 'common'
          return arr[1]
  
      def IsArchMatch(self, arch):
          if arch == None or self.GetArch() == 'common':
              return True
  
          if self.GetArch().lower() != arch.lower():
              return False
  
          return True
  
  class DECSectionObject(ini.BaseINISectionObject):
      def GetArch(self):
          return self.GetParent().GetArch()
  
  class DECDefineSectionObject(DECSectionObject):
      def __init__(self, parent):
          DECSectionObject.__init__(self, parent)
          self._key = None
          self._value = None
  
      def Parse(self):
          assert (self._start == self._end), 'The object in define section must be in single line'
  
          line = self.GetLineByOffset(self._start).strip()
  
          line = line.split('#')[0]
          arr  = line.split('=')
          if len(arr) != 2:
              ErrorMsg('Invalid define section object',
                     self.GetFilename(),
                     self.GetParent().GetName()
                     )
              return False
  
          self._key   = arr[0].strip()
          self._value = arr[1].strip()
  
          return True
  
      def GetKey(self):
          return self._key
  
      def GetValue(self):
          return self._value
  
  class DECGuidObject(DECSectionObject):
      _objs = {}
  
      def __init__(self, parent):
          DECSectionObject.__init__(self, parent)
          self._name = None
  
      def Parse(self):
          line = self.GetLineByOffset(self._start).strip().split('#')[0]
          self._name = line.split('=')[0].strip()
          self._guid = line.split('=')[1].strip()
          objdict = DECGuidObject._objs
          if self._name not in objdict.keys():
              objdict[self._name] = [self]
          else:
              objdict[self._name].append(self)
  
          return True
  
      def GetName(self):
          return self._name
  
      def GetGuid(self):
          return self._guid
  
      def Destroy(self):
          objdict = DECGuidObject._objs
          objdict[self._name].remove(self)
          if len(objdict[self._name]) == 0:
              del objdict[self._name]
  
      @staticmethod
      def GetObjectDict():
          return DECGuidObject._objs
  
  class DECPpiObject(DECSectionObject):
      _objs = {}
      def __init__(self, parent):
          DECSectionObject.__init__(self, parent)
          self._name = None
  
      def Parse(self):
          line = self.GetLineByOffset(self._start).strip().split('#')[0]
          self._name = line.split('=')[0].strip()
          self._guid = line.split('=')[1].strip()
          objdict = DECPpiObject._objs
          if self._name not in objdict.keys():
              objdict[self._name] = [self]
          else:
              objdict[self._name].append(self)
  
          return True
  
      def GetName(self):
          return self._name
  
      def GetGuid(self):
          return self._guid
  
      def Destroy(self):
          objdict = DECPpiObject._objs
          objdict[self._name].remove(self)
          if len(objdict[self._name]) == 0:
              del objdict[self._name]
  
      @staticmethod
      def GetObjectDict():
          return DECPpiObject._objs
  
  class DECProtocolObject(DECSectionObject):
      _objs = {}
  
      def __init__(self, parent):
          DECSectionObject.__init__(self, parent)
          self._name = None
  
      def Parse(self):
          line = self.GetLineByOffset(self._start).strip().split('#')[0]
          self._name = line.split('=')[0].strip()
          self._guid = line.split('=')[1].strip()
          objdict = DECProtocolObject._objs
          if self._name not in objdict.keys():
              objdict[self._name] = [self]
          else:
              objdict[self._name].append(self)
  
          return True
  
      def GetName(self):
          return self._name
  
      def GetGuid(self):
          return self._guid
  
      def Destroy(self):
          objdict = DECProtocolObject._objs
          objdict[self._name].remove(self)
          if len(objdict[self._name]) == 0:
              del objdict[self._name]
  
  
      @staticmethod
      def GetObjectDict():
          return DECProtocolObject._objs
  
  class DECLibraryClassObject(DECSectionObject):
      _objs = {}
  
      def __init__(self, parent):
          DECSectionObject.__init__(self, parent)
          self.mClassName = None
          self.mHeaderFile = None
  
      def Parse(self):
          line = self.GetLineByOffset(self._start).strip().split('#')[0]
          self.mClassName, self.mHeaderFile = line.split('|')
          objdict = DECLibraryClassObject._objs
          if self.mClassName not in objdict.keys():
              objdict[self.mClassName] = [self]
          else:
              objdict[self.mClassName].append(self)
          return True
  
      def GetClassName(self):
          return self.mClassName
  
      def GetName(self):
          return self.mClassName
  
      def GetHeaderFile(self):
          return self.mHeaderFile
  
      def Destroy(self):
          objdict = DECLibraryClassObject._objs
          objdict[self.mClassName].remove(self)
          if len(objdict[self.mClassName]) == 0:
              del objdict[self.mClassName]
  
      @staticmethod
      def GetObjectDict():
          return DECLibraryClassObject._objs
  
  class DECIncludeObject(DECSectionObject):
      def __init__(self, parent):
          DECSectionObject.__init__(self, parent)
  
      def GetPath(self):
          return self.GetLineByOffset(self._start).split('#')[0].strip()
  
  class DECPcdObject(DECSectionObject):
      _objs = {}
  
      def __init__(self, parent):
          DECSectionObject.__init__(self, parent)
          self.mPcdName           = None
          self.mPcdDefaultValue   = None
          self.mPcdDataType       = None
          self.mPcdToken          = None
  
      def Parse(self):
          line = self.GetLineByOffset(self._start).strip().split('#')[0]
          (self.mPcdName, self.mPcdDefaultValue, self.mPcdDataType, self.mPcdToken) = line.split('|')
          objdict = DECPcdObject._objs
          if self.mPcdName not in objdict.keys():
              objdict[self.mPcdName] = [self]
          else:
              objdict[self.mPcdName].append(self)
  
          return True
  
      def Destroy(self):
          objdict = DECPcdObject._objs
          objdict[self.mPcdName].remove(self)
          if len(objdict[self.mPcdName]) == 0:
              del objdict[self.mPcdName]
  
      def GetPcdType(self):
          return self.GetParent().GetType()
  
      def GetPcdName(self):
          return self.mPcdName
  
      def GetPcdValue(self):
          return self.mPcdDefaultValue
  
      def GetPcdDataType(self):
          return self.mPcdDataType
  
      def GetPcdToken(self):
          return self.mPcdToken
  
      def GetName(self):
          return self.GetPcdName().split('.')[1]
  
      @staticmethod
      def GetObjectDict():
          return DECPcdObject._objs
  