1## @file
2#
3# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
4#
5# SPDX-License-Identifier: BSD-2-Clause-Patent
6#
7
8from plugins.EdkPlugins.basemodel import ini
9import re, os
10from plugins.EdkPlugins.basemodel.message import *
11
12class DSCFile(ini.BaseINIFile):
13    def GetSectionInstance(self, parent, name, isCombined=False):
14        return DSCSection(parent, name, isCombined)
15
16    def GetComponents(self):
17        return self.GetSectionObjectsByName('Components')
18
19class DSCSection(ini.BaseINISection):
20    def GetSectionINIObject(self, parent):
21        type = self.GetType()
22
23        if type.lower() == 'components':
24            return DSCComponentObject(self)
25        if type.lower() == 'libraryclasses':
26            return DSCLibraryClassObject(self)
27        if type.lower() == 'defines':
28            return ini.BaseINISectionObject(self)
29        if type.lower() == 'pcdsfeatureflag' or \
30           type.lower() == 'pcdsfixedatbuild' or \
31           type.lower() == 'pcdspatchableinmodule' or\
32           type.lower() == 'pcdsdynamicdefault' or \
33           type.lower() == 'pcdsdynamicex' or \
34           type.lower() == 'pcdsdynamichii' or \
35           type.lower() == 'pcdsdynamicvpd':
36            return DSCPcdObject(self)
37
38        return DSCSectionObject(self)
39
40    def GetType(self):
41        arr = self._name.split('.')
42        return arr[0].strip()
43
44    def GetArch(self):
45        arr = self._name.split('.')
46        if len(arr) == 1:
47            return 'common'
48        return arr[1]
49
50    def GetModuleType(self):
51        arr = self._name.split('.')
52        if len(arr) < 3:
53            return 'common'
54        return arr[2]
55
56class DSCSectionObject(ini.BaseINISectionObject):
57    def GetArch(self):
58        return self.GetParent().GetArch()
59
60class DSCPcdObject(DSCSectionObject):
61
62    def __init__(self, parent):
63        ini.BaseINISectionObject.__init__(self, parent)
64        self._name = None
65
66    def Parse(self):
67        line = self.GetLineByOffset(self._start).strip().split('#')[0]
68        self._name   = line.split('|')[0]
69        self._value  = line.split('|')[1]
70        return True
71
72    def GetPcdName(self):
73        return self._name
74
75    def GetPcdType(self):
76        return self.GetParent().GetType()
77
78    def GetPcdValue(self):
79        return self._value
80
81class DSCLibraryClassObject(DSCSectionObject):
82    def __init__(self, parent):
83        ini.BaseINISectionObject.__init__(self, parent)
84
85    def GetClass(self):
86        line = self.GetLineByOffset(self._start)
87        return line.split('#')[0].split('|')[0].strip()
88
89    def GetInstance(self):
90        line = self.GetLineByOffset(self._start)
91        return line.split('#')[0].split('|')[1].strip()
92
93    def GetArch(self):
94        return self.GetParent().GetArch()
95
96    def GetModuleType(self):
97        return self.GetParent().GetModuleType()
98
99class DSCComponentObject(DSCSectionObject):
100
101    def __init__(self, parent):
102        ini.BaseINISectionObject.__init__(self, parent)
103        self._OveridePcds      = {}
104        self._OverideLibraries = {}
105        self._Filename         = ''
106
107    def __del__(self):
108        self._OverideLibraries.clear()
109        self._OverideLibraries.clear()
110        ini.BaseINISectionObject.__del__(self)
111
112    def AddOverideLib(self, libclass, libinstPath):
113        if libclass not in self._OverideLibraries.keys():
114            self._OverideLibraries[libclass] = libinstPath
115
116    def AddOveridePcd(self, name, type, value=None):
117        if type not in self._OveridePcds.keys():
118            self._OveridePcds[type] = []
119        self._OveridePcds[type].append((name, value))
120
121    def GetOverideLibs(self):
122        return self._OverideLibraries
123
124    def GetArch(self):
125        return self.GetParent().GetArch()
126
127    def GetOveridePcds(self):
128        return self._OveridePcds
129
130    def GetFilename(self):
131        return self.GetLineByOffset(self._start).split('#')[0].split('{')[0].strip()
132
133    def SetFilename(self, fName):
134        self._Filename = fName
135
136    def Parse(self):
137        if (self._start < self._end):
138            #
139            # The first line is inf path and could be ignored
140            # The end line is '}' and could be ignored
141            #
142            curr = self._start + 1
143            end  = self._end - 1
144            OverideName = ''
145            while (curr <= end):
146                line = self.GetLineByOffset(curr).strip()
147                if len(line) > 0 and line[0] != '#':
148                    line = line.split('#')[0].strip()
149                    if line[0] == '<':
150                        OverideName = line[1:len(line)-1]
151                    elif OverideName.lower() == 'libraryclasses':
152                        arr = line.split('|')
153                        self._OverideLibraries[arr[0].strip()] = arr[1].strip()
154                    elif OverideName.lower() == 'pcds':
155                        ErrorMsg('EDES does not support PCD overide',
156                                 self.GetFileName(),
157                                 self.GetParent().GetLinenumberByOffset(curr))
158                curr = curr + 1
159        return True
160
161    def GenerateLines(self):
162        lines = []
163        hasLib = False
164        hasPcd = False
165        if len(self._OverideLibraries) != 0:
166            hasLib = True
167        if len(self._OveridePcds) != 0:
168            hasPcd = True
169
170        if hasLib or hasPcd:
171            lines.append(('  %s {\n' % self._Filename))
172        else:
173            lines.append(('  %s \n' % self._Filename))
174            return lines
175
176        if hasLib:
177            lines.append('    <LibraryClasses>\n')
178            for libKey in self._OverideLibraries.keys():
179                lines.append('      %s|%s\n' % (libKey, self._OverideLibraries[libKey]))
180
181        if hasPcd:
182            for key in self._OveridePcds.keys():
183                lines.append('    <%s>\n' % key)
184
185                for name, value in self._OveridePcds[key]:
186                    if value is not None:
187                        lines.append('      %s|%s\n' % (name, value))
188                    else:
189                        lines.append('      %s\n' % name)
190
191        if hasLib or hasPcd:
192            lines.append('  }\n')
193
194        return lines
195
196