]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/ini.py
d5299e60bcdbdf8903cb65e0807e066ca615df4d
3 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials are licensed and made available
6 # under the terms and conditions of the BSD License which accompanies this
7 # distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 from .message
import *
18 section_re
= re
.compile(r
'^\[([\w., "]+)\]')
20 class BaseINIFile(object):
22 def __new__(cls
, *args
, **kwargs
):
23 """Maintain only a single instance of this object
24 @return: instance of this class
27 if len(args
) == 0: return object.__new
__(cls
)
33 key
= os
.path
.normpath(filename
)
34 if key
not in cls
._objs
.keys():
35 cls
._objs
[key
] = object.__new
__(cls
)
37 if parent
is not None:
38 cls
._objs
[key
].AddParent(parent
)
42 def __init__(self
, filename
=None, parent
=None):
45 self
._filename
= filename
49 def AddParent(self
, parent
):
50 if parent
is None: return
51 if not hasattr(self
, "_parents"):
54 if parent
in self
._parents
:
55 ErrorMsg("Duplicate parent is found for INI file %s" % self
._filename
)
57 self
._parents
.append(parent
)
59 def GetFilename(self
):
60 return os
.path
.normpath(self
._filename
)
65 def Modify(self
, modify
=True, obj
=None):
66 if modify
== self
._isModify
: return
67 self
._isModify
= modify
69 for parent
in self
._parents
:
70 parent
.Modify(True, self
)
72 def _ReadLines(self
, filename
):
76 if not os
.path
.exists(filename
):
80 handle
= open(filename
, 'r')
81 self
._lines
= handle
.readlines()
84 raise EdkException("Fail to open file %s" % filename
)
88 def GetSectionInstance(self
, parent
, name
, isCombined
=False):
89 return BaseINISection(parent
, name
, isCombined
)
91 def GetSectionByName(self
, name
):
93 for key
in self
._sections
.keys():
96 for item
in self
._sections
[key
]:
97 if item
.GetBaseName().lower().find(name
.lower()) != -1:
101 def GetSectionObjectsByName(self
, name
):
103 sects
= self
.GetSectionByName(name
)
105 for obj
in sect
.GetObjects():
110 if not self
._isModify
: return True
111 if not self
._ReadLines
(self
._filename
): return False
116 for index
in range(len(self
._lines
)):
117 templine
= self
._lines
[index
].strip()
119 if len(templine
) == 0: continue
120 if re
.match("^\[=*\]", templine
) or re
.match("^#", templine
) or \
121 re
.match("\*+/", templine
):
124 m
= section_re
.match(templine
)
125 if m
is not None: # found a section
127 # Finish the latest section first
130 sObj
._end
= index
- 1
132 ErrorMsg("Fail to parse section %s" % sObj
.GetBaseName(),
137 sname_arr
= m
.groups()[0].split(',')
139 for name
in sname_arr
:
140 sObj
= self
.GetSectionInstance(self
, name
, (len(sname_arr
) > 1))
143 if name
.lower() not in self
._sections
:
144 self
._sections
[name
.lower()] = [sObj
]
146 self
._sections
[name
.lower()].append(sObj
)
147 elif inGlobal
: # not start any section and find global object
148 gObj
= BaseINIGlobalObject(self
)
151 self
._globals
.append(gObj
)
153 # Finish the last section
158 ErrorMsg("Fail to parse section %s" % sObj
.GetBaseName(),
162 self
._isModify
= False
165 def Destroy(self
, parent
):
167 # check referenced parent
168 if parent
is not None:
169 assert parent
in self
._parents
, "when destory ini object, can not found parent reference!"
170 self
._parents
.remove(parent
)
172 if len(self
._parents
) != 0: return
174 for sects
in self
._sections
.values():
178 # dereference from _objs array
179 assert self
.GetFilename() in self
._objs
.keys(), "When destroy ini object, can not find obj reference!"
180 assert self
in self
._objs
.values(), "When destroy ini object, can not find obj reference!"
181 del self
._objs
[self
.GetFilename()]
186 def GetDefine(self
, name
):
187 sects
= self
.GetSectionByName('Defines')
189 for obj
in sect
.GetObjects():
190 line
= obj
.GetLineByOffset(obj
._start
).split('#')[0].strip()
191 arr
= line
.split('=')
192 if arr
[0].strip().lower() == name
.strip().lower():
193 return arr
[1].strip()
197 for sects
in self
._sections
.values():
200 self
._sections
.clear()
201 for gObj
in self
._globals
:
211 self
._isModify
= False
214 def AddNewSection(self
, sectName
):
215 if sectName
.lower() in self
._sections
.keys():
216 ErrorMsg('Section %s can not be created for conflict with existing section')
219 sectionObj
= self
.GetSectionInstance(self
, sectName
)
220 sectionObj
._start
= len(self
._lines
)
221 sectionObj
._end
= len(self
._lines
) + 1
222 self
._lines
.append('[%s]\n' % sectName
)
223 self
._lines
.append('\n\n')
224 self
._sections
[sectName
.lower()] = sectionObj
227 def CopySectionsByName(self
, oldDscObj
, nameStr
):
228 sects
= oldDscObj
.GetSectionByName(nameStr
)
230 sectObj
= self
.AddNewSection(sect
.GetName())
234 return ''.join(self
._lines
)
236 ## Get file header's comment from basic INI file.
237 # The file comments has two style:
241 def GetFileHeader(self
):
243 lineArr
= self
._lines
245 for num
in range(len(self
._lines
)):
246 line
= lineArr
[num
].strip()
247 if not inHeader
and (line
.startswith("#/**") or line
.startswith("##")) and \
248 line
.find("@file") != -1:
251 if inHeader
and (line
.startswith("#**/") or line
.startswith('##')):
255 prefixIndex
= line
.find('#')
256 if prefixIndex
== -1:
259 desc
.append(line
[prefixIndex
+ 1:])
260 return '<br>\n'.join(desc
)
262 class BaseINISection(object):
263 def __init__(self
, parent
, name
, isCombined
=False):
264 self
._parent
= parent
266 self
._isCombined
= isCombined
272 for obj
in self
._objs
:
279 def GetObjects(self
):
285 def GetStartLinenumber(self
):
288 def GetEndLinenumber(self
):
291 def GetLine(self
, linenumber
):
292 return self
._parent
._lines
[linenumber
]
294 def GetFilename(self
):
295 return self
._parent
.GetFilename()
297 def GetSectionINIObject(self
, parent
):
298 return BaseINISectionObject(parent
)
301 # skip first line in section, it is used by section name
302 visit
= self
._start
+ 1
304 while (visit
<= self
._end
):
305 line
= self
.GetLine(visit
).strip()
306 if re
.match("^\[=*\]", line
) or re
.match("^#", line
) or len(line
) == 0:
309 line
= line
.split('#')[0].strip()
310 if iniObj
is not None:
311 if line
.endswith('}'):
312 iniObj
._end
= visit
- self
._start
313 if not iniObj
.Parse():
314 ErrorMsg("Fail to parse ini object",
316 iniObj
.GetStartLinenumber())
318 self
._objs
.append(iniObj
)
321 iniObj
= self
.GetSectionINIObject(self
)
322 iniObj
._start
= visit
- self
._start
323 if not line
.endswith('{'):
324 iniObj
._end
= visit
- self
._start
325 if not iniObj
.Parse():
326 ErrorMsg("Fail to parse ini object",
328 iniObj
.GetStartLinenumber())
330 self
._objs
.append(iniObj
)
336 for obj
in self
._objs
:
339 def GetBaseName(self
):
342 def AddLine(self
, line
):
343 end
= self
.GetEndLinenumber()
344 self
._parent
._lines
.insert(end
, line
)
347 def Copy(self
, sectObj
):
348 index
= sectObj
.GetStartLinenumber() + 1
349 while index
< sectObj
.GetEndLinenumber():
350 line
= sectObj
.GetLine(index
)
351 if not line
.strip().startswith('#'):
355 def AddObject(self
, obj
):
356 lines
= obj
.GenerateLines()
360 def GetComment(self
):
362 start
= self
._start
- 1
366 line
= self
.GetLine(start
).strip()
370 if line
.startswith('##'):
372 index
= line
.rfind('#')
373 if (index
+ 1) < len(line
):
374 comments
.append(line
[index
+ 1:])
376 if line
.startswith('#'):
382 while (end
< self
._start
):
383 line
= self
.GetLine(end
).strip()
384 if len(line
) == 0: break
385 if not line
.startswith('#'): break
386 index
= line
.rfind('#')
387 if (index
+ 1) < len(line
):
388 comments
.append(line
[index
+ 1:])
392 class BaseINIGlobalObject(object):
393 def __init__(self
, parent
):
401 return parent
._lines
[self
._start
]
406 class BaseINISectionObject(object):
407 def __init__(self
, parent
):
410 self
._parent
= parent
418 def GetFilename(self
):
419 return self
.GetParent().GetFilename()
421 def GetPackageName(self
):
422 return self
.GetFilename()
424 def GetFileObj(self
):
425 return self
.GetParent().GetParent()
427 def GetStartLinenumber(self
):
428 return self
.GetParent()._start
+ self
._start
430 def GetLineByOffset(self
, offset
):
431 sect_start
= self
._parent
.GetStartLinenumber()
432 linenumber
= sect_start
+ offset
433 return self
._parent
.GetLine(linenumber
)
435 def GetLinenumberByOffset(self
, offset
):
436 return offset
+ self
._parent
.GetStartLinenumber()
445 return self
.GetLineByOffset(self
._start
).strip()
447 def GenerateLines(self
):
448 return ['default setion object string\n']
450 def GetComment(self
):
452 start
= self
.GetStartLinenumber() - 1
456 line
= self
.GetParent().GetLine(start
).strip()
460 if line
.startswith('##'):
462 index
= line
.rfind('#')
463 if (index
+ 1) < len(line
):
464 comments
.append(line
[index
+ 1:])
466 if line
.startswith('#'):
472 while (end
<= self
.GetStartLinenumber() - 1):
473 line
= self
.GetParent().GetLine(end
).strip()
474 if len(line
) == 0: break
475 if not line
.startswith('#'): break
476 index
= line
.rfind('#')
477 if (index
+ 1) < len(line
):
478 comments
.append(line
[index
+ 1:])