]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/ini.py
6e6f3f4b97952d572d145980955b40bcab7a36aa
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 __future__
import absolute_import
15 from .message
import *
19 section_re
= re
.compile(r
'^\[([\w., "]+)\]')
21 class BaseINIFile(object):
23 def __new__(cls
, *args
, **kwargs
):
24 """Maintain only a single instance of this object
25 @return: instance of this class
28 if len(args
) == 0: return object.__new
__(cls
, *args
, **kwargs
)
34 key
= os
.path
.normpath(filename
)
35 if key
not in cls
._objs
.keys():
36 cls
._objs
[key
] = object.__new
__(cls
, *args
, **kwargs
)
38 if parent
is not None:
39 cls
._objs
[key
].AddParent(parent
)
43 def __init__(self
, filename
=None, parent
=None):
46 self
._filename
= filename
50 def AddParent(self
, parent
):
51 if parent
is None: return
52 if not hasattr(self
, "_parents"):
55 if parent
in self
._parents
:
56 ErrorMsg("Duplicate parent is found for INI file %s" % self
._filename
)
58 self
._parents
.append(parent
)
60 def GetFilename(self
):
61 return os
.path
.normpath(self
._filename
)
66 def Modify(self
, modify
=True, obj
=None):
67 if modify
== self
._isModify
: return
68 self
._isModify
= modify
70 for parent
in self
._parents
:
71 parent
.Modify(True, self
)
73 def _ReadLines(self
, filename
):
77 if not os
.path
.exists(filename
):
81 handle
= open(filename
, 'r')
82 self
._lines
= handle
.readlines()
85 raise EdkException("Fail to open file %s" % filename
)
89 def GetSectionInstance(self
, parent
, name
, isCombined
=False):
90 return BaseINISection(parent
, name
, isCombined
)
92 def GetSectionByName(self
, name
):
94 for key
in self
._sections
.keys():
97 for item
in self
._sections
[key
]:
98 if item
.GetBaseName().lower().find(name
.lower()) != -1:
102 def GetSectionObjectsByName(self
, name
):
104 sects
= self
.GetSectionByName(name
)
106 for obj
in sect
.GetObjects():
111 if not self
._isModify
: return True
112 if not self
._ReadLines
(self
._filename
): return False
117 for index
in range(len(self
._lines
)):
118 templine
= self
._lines
[index
].strip()
120 if len(templine
) == 0: continue
121 if re
.match("^\[=*\]", templine
) or re
.match("^#", templine
) or \
122 re
.match("\*+/", templine
):
125 m
= section_re
.match(templine
)
126 if m
is not None: # found a section
128 # Finish the latest section first
131 sObj
._end
= index
- 1
133 ErrorMsg("Fail to parse section %s" % sObj
.GetBaseName(),
138 sname_arr
= m
.groups()[0].split(',')
140 for name
in sname_arr
:
141 sObj
= self
.GetSectionInstance(self
, name
, (len(sname_arr
) > 1))
144 if name
.lower() not in self
._sections
:
145 self
._sections
[name
.lower()] = [sObj
]
147 self
._sections
[name
.lower()].append(sObj
)
148 elif inGlobal
: # not start any section and find global object
149 gObj
= BaseINIGlobalObject(self
)
152 self
._globals
.append(gObj
)
154 # Finish the last section
159 ErrorMsg("Fail to parse section %s" % sObj
.GetBaseName(),
163 self
._isModify
= False
166 def Destroy(self
, parent
):
168 # check referenced parent
169 if parent
is not None:
170 assert parent
in self
._parents
, "when destory ini object, can not found parent reference!"
171 self
._parents
.remove(parent
)
173 if len(self
._parents
) != 0: return
175 for sects
in self
._sections
.values():
179 # dereference from _objs array
180 assert self
.GetFilename() in self
._objs
.keys(), "When destroy ini object, can not find obj reference!"
181 assert self
in self
._objs
.values(), "When destroy ini object, can not find obj reference!"
182 del self
._objs
[self
.GetFilename()]
187 def GetDefine(self
, name
):
188 sects
= self
.GetSectionByName('Defines')
190 for obj
in sect
.GetObjects():
191 line
= obj
.GetLineByOffset(obj
._start
).split('#')[0].strip()
192 arr
= line
.split('=')
193 if arr
[0].strip().lower() == name
.strip().lower():
194 return arr
[1].strip()
198 for sects
in self
._sections
.values():
201 self
._sections
.clear()
202 for gObj
in self
._globals
:
212 self
._isModify
= False
215 def AddNewSection(self
, sectName
):
216 if sectName
.lower() in self
._sections
.keys():
217 ErrorMsg('Section %s can not be created for conflict with existing section')
220 sectionObj
= self
.GetSectionInstance(self
, sectName
)
221 sectionObj
._start
= len(self
._lines
)
222 sectionObj
._end
= len(self
._lines
) + 1
223 self
._lines
.append('[%s]\n' % sectName
)
224 self
._lines
.append('\n\n')
225 self
._sections
[sectName
.lower()] = sectionObj
228 def CopySectionsByName(self
, oldDscObj
, nameStr
):
229 sects
= oldDscObj
.GetSectionByName(nameStr
)
231 sectObj
= self
.AddNewSection(sect
.GetName())
235 return ''.join(self
._lines
)
237 ## Get file header's comment from basic INI file.
238 # The file comments has two style:
242 def GetFileHeader(self
):
244 lineArr
= self
._lines
246 for num
in range(len(self
._lines
)):
247 line
= lineArr
[num
].strip()
248 if not inHeader
and (line
.startswith("#/**") or line
.startswith("##")) and \
249 line
.find("@file") != -1:
252 if inHeader
and (line
.startswith("#**/") or line
.startswith('##')):
256 prefixIndex
= line
.find('#')
257 if prefixIndex
== -1:
260 desc
.append(line
[prefixIndex
+ 1:])
261 return '<br>\n'.join(desc
)
263 class BaseINISection(object):
264 def __init__(self
, parent
, name
, isCombined
=False):
265 self
._parent
= parent
267 self
._isCombined
= isCombined
273 for obj
in self
._objs
:
280 def GetObjects(self
):
286 def GetStartLinenumber(self
):
289 def GetEndLinenumber(self
):
292 def GetLine(self
, linenumber
):
293 return self
._parent
._lines
[linenumber
]
295 def GetFilename(self
):
296 return self
._parent
.GetFilename()
298 def GetSectionINIObject(self
, parent
):
299 return BaseINISectionObject(parent
)
302 # skip first line in section, it is used by section name
303 visit
= self
._start
+ 1
305 while (visit
<= self
._end
):
306 line
= self
.GetLine(visit
).strip()
307 if re
.match("^\[=*\]", line
) or re
.match("^#", line
) or len(line
) == 0:
310 line
= line
.split('#')[0].strip()
311 if iniObj
is not None:
312 if line
.endswith('}'):
313 iniObj
._end
= visit
- self
._start
314 if not iniObj
.Parse():
315 ErrorMsg("Fail to parse ini object",
317 iniObj
.GetStartLinenumber())
319 self
._objs
.append(iniObj
)
322 iniObj
= self
.GetSectionINIObject(self
)
323 iniObj
._start
= visit
- self
._start
324 if not line
.endswith('{'):
325 iniObj
._end
= visit
- self
._start
326 if not iniObj
.Parse():
327 ErrorMsg("Fail to parse ini object",
329 iniObj
.GetStartLinenumber())
331 self
._objs
.append(iniObj
)
337 for obj
in self
._objs
:
340 def GetBaseName(self
):
343 def AddLine(self
, line
):
344 end
= self
.GetEndLinenumber()
345 self
._parent
._lines
.insert(end
, line
)
348 def Copy(self
, sectObj
):
349 index
= sectObj
.GetStartLinenumber() + 1
350 while index
< sectObj
.GetEndLinenumber():
351 line
= sectObj
.GetLine(index
)
352 if not line
.strip().startswith('#'):
356 def AddObject(self
, obj
):
357 lines
= obj
.GenerateLines()
361 def GetComment(self
):
363 start
= self
._start
- 1
367 line
= self
.GetLine(start
).strip()
371 if line
.startswith('##'):
373 index
= line
.rfind('#')
374 if (index
+ 1) < len(line
):
375 comments
.append(line
[index
+ 1:])
377 if line
.startswith('#'):
383 while (end
< self
._start
):
384 line
= self
.GetLine(end
).strip()
385 if len(line
) == 0: break
386 if not line
.startswith('#'): break
387 index
= line
.rfind('#')
388 if (index
+ 1) < len(line
):
389 comments
.append(line
[index
+ 1:])
393 class BaseINIGlobalObject(object):
394 def __init__(self
, parent
):
402 return parent
._lines
[self
._start
]
407 class BaseINISectionObject(object):
408 def __init__(self
, parent
):
411 self
._parent
= parent
419 def GetFilename(self
):
420 return self
.GetParent().GetFilename()
422 def GetPackageName(self
):
423 return self
.GetFilename()
425 def GetFileObj(self
):
426 return self
.GetParent().GetParent()
428 def GetStartLinenumber(self
):
429 return self
.GetParent()._start
+ self
._start
431 def GetLineByOffset(self
, offset
):
432 sect_start
= self
._parent
.GetStartLinenumber()
433 linenumber
= sect_start
+ offset
434 return self
._parent
.GetLine(linenumber
)
436 def GetLinenumberByOffset(self
, offset
):
437 return offset
+ self
._parent
.GetStartLinenumber()
446 return self
.GetLineByOffset(self
._start
).strip()
448 def GenerateLines(self
):
449 return ['default setion object string\n']
451 def GetComment(self
):
453 start
= self
.GetStartLinenumber() - 1
457 line
= self
.GetParent().GetLine(start
).strip()
461 if line
.startswith('##'):
463 index
= line
.rfind('#')
464 if (index
+ 1) < len(line
):
465 comments
.append(line
[index
+ 1:])
467 if line
.startswith('#'):
473 while (end
<= self
.GetStartLinenumber() - 1):
474 line
= self
.GetParent().GetLine(end
).strip()
475 if len(line
) == 0: break
476 if not line
.startswith('#'): break
477 index
= line
.rfind('#')
478 if (index
+ 1) < len(line
):
479 comments
.append(line
[index
+ 1:])