ConfHandler.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #!/usr/bin/env python
  2. # ex:ts=4:sw=4:sts=4:et
  3. # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
  4. """
  5. class for handling configuration data files
  6. Reads a .conf file and obtains its metadata
  7. """
  8. # Copyright (C) 2003, 2004 Chris Larson
  9. # Copyright (C) 2003, 2004 Phil Blundell
  10. #
  11. # This program is free software; you can redistribute it and/or modify
  12. # it under the terms of the GNU General Public License version 2 as
  13. # published by the Free Software Foundation.
  14. #
  15. # This program is distributed in the hope that it will be useful,
  16. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. # GNU General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU General Public License along
  21. # with this program; if not, write to the Free Software Foundation, Inc.,
  22. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  23. import re, bb.data, os, sys
  24. from bb.parse import ParseError
  25. #__config_regexp__ = re.compile( r"(?P<exp>export\s*)?(?P<var>[a-zA-Z0-9\-_+.${}]+)\s*(?P<colon>:)?(?P<ques>\?)?=\s*(?P<apo>['\"]?)(?P<value>.*)(?P=apo)$")
  26. __config_regexp__ = re.compile( r"(?P<exp>export\s*)?(?P<var>[a-zA-Z0-9\-_+.${}/]+)(\[(?P<flag>[a-zA-Z0-9\-_+.]+)\])?\s*((?P<colon>:=)|(?P<ques>\?=)|(?P<append>\+=)|(?P<prepend>=\+)|(?P<predot>=\.)|(?P<postdot>\.=)|=)\s*(?P<apo>['\"]?)(?P<value>.*)(?P=apo)$")
  27. __include_regexp__ = re.compile( r"include\s+(.+)" )
  28. __require_regexp__ = re.compile( r"require\s+(.+)" )
  29. __export_regexp__ = re.compile( r"export\s+(.+)" )
  30. def init(data):
  31. topdir = bb.data.getVar('TOPDIR', data)
  32. if not topdir:
  33. topdir = os.getcwd()
  34. bb.data.setVar('TOPDIR', topdir, data)
  35. if not bb.data.getVar('BBPATH', data):
  36. from pkg_resources import Requirement, resource_filename
  37. bitbake = Requirement.parse("bitbake")
  38. datadir = resource_filename(bitbake, "../share/bitbake")
  39. basedir = resource_filename(bitbake, "..")
  40. bb.data.setVar('BBPATH', '%s:%s:%s' % (topdir, datadir, basedir), data)
  41. def supports(fn, d):
  42. return localpath(fn, d)[-5:] == ".conf"
  43. def localpath(fn, d):
  44. if os.path.exists(fn):
  45. return fn
  46. if "://" not in fn:
  47. return fn
  48. localfn = None
  49. try:
  50. localfn = bb.fetch.localpath(fn, d, False)
  51. except bb.MalformedUrl:
  52. pass
  53. if not localfn:
  54. return fn
  55. return localfn
  56. def obtain(fn, data):
  57. import sys, bb
  58. fn = bb.data.expand(fn, data)
  59. localfn = bb.data.expand(localpath(fn, data), data)
  60. if localfn != fn:
  61. dldir = bb.data.getVar('DL_DIR', data, 1)
  62. if not dldir:
  63. bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: DL_DIR not defined")
  64. return localfn
  65. bb.mkdirhier(dldir)
  66. try:
  67. bb.fetch.init([fn], data)
  68. except bb.fetch.NoMethodError:
  69. (type, value, traceback) = sys.exc_info()
  70. bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: no method: %s" % value)
  71. return localfn
  72. try:
  73. bb.fetch.go(data)
  74. except bb.fetch.MissingParameterError:
  75. (type, value, traceback) = sys.exc_info()
  76. bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: missing parameters: %s" % value)
  77. return localfn
  78. except bb.fetch.FetchError:
  79. (type, value, traceback) = sys.exc_info()
  80. bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: failed: %s" % value)
  81. return localfn
  82. return localfn
  83. def include(oldfn, fn, data, error_out):
  84. """
  85. error_out If True a ParseError will be reaised if the to be included
  86. """
  87. if oldfn == fn: # prevent infinate recursion
  88. return None
  89. import bb
  90. fn = bb.data.expand(fn, data)
  91. oldfn = bb.data.expand(oldfn, data)
  92. if not os.path.isabs(fn):
  93. dname = os.path.dirname(oldfn)
  94. bbpath = "%s:%s" % (dname, bb.data.getVar("BBPATH", data, 1))
  95. abs_fn = bb.which(bbpath, fn)
  96. if abs_fn:
  97. fn = abs_fn
  98. from bb.parse import handle
  99. try:
  100. ret = handle(fn, data, True)
  101. except IOError:
  102. if error_out:
  103. raise ParseError("Could not %(error_out)s file %(fn)s" % vars() )
  104. bb.msg.debug(2, bb.msg.domain.Parsing, "CONF file '%s' not found" % fn)
  105. def handle(fn, data, include = 0):
  106. if include:
  107. inc_string = "including"
  108. else:
  109. inc_string = "reading"
  110. init(data)
  111. if include == 0:
  112. oldfile = None
  113. else:
  114. oldfile = bb.data.getVar('FILE', data)
  115. fn = obtain(fn, data)
  116. if not os.path.isabs(fn):
  117. f = None
  118. bbpath = bb.data.getVar("BBPATH", data, 1) or []
  119. for p in bbpath.split(":"):
  120. currname = os.path.join(p, fn)
  121. if os.access(currname, os.R_OK):
  122. f = open(currname, 'r')
  123. abs_fn = currname
  124. bb.msg.debug(2, bb.msg.domain.Parsing, "CONF %s %s" % (inc_string, currname))
  125. break
  126. if f is None:
  127. raise IOError("file '%s' not found" % fn)
  128. else:
  129. f = open(fn,'r')
  130. bb.msg.debug(1, bb.msg.domain.Parsing, "CONF %s %s" % (inc_string,fn))
  131. abs_fn = fn
  132. if include:
  133. bb.parse.mark_dependency(data, abs_fn)
  134. lineno = 0
  135. bb.data.setVar('FILE', fn, data)
  136. while 1:
  137. lineno = lineno + 1
  138. s = f.readline()
  139. if not s: break
  140. w = s.strip()
  141. if not w: continue # skip empty lines
  142. s = s.rstrip()
  143. if s[0] == '#': continue # skip comments
  144. while s[-1] == '\\':
  145. s2 = f.readline()[:-1].strip()
  146. lineno = lineno + 1
  147. s = s[:-1] + s2
  148. feeder(lineno, s, fn, data)
  149. if oldfile:
  150. bb.data.setVar('FILE', oldfile, data)
  151. return data
  152. def feeder(lineno, s, fn, data):
  153. def getFunc(groupd, key, data):
  154. if 'flag' in groupd and groupd['flag'] != None:
  155. return bb.data.getVarFlag(key, groupd['flag'], data)
  156. else:
  157. return bb.data.getVar(key, data)
  158. m = __config_regexp__.match(s)
  159. if m:
  160. groupd = m.groupdict()
  161. key = groupd["var"]
  162. if "exp" in groupd and groupd["exp"] != None:
  163. bb.data.setVarFlag(key, "export", 1, data)
  164. if "ques" in groupd and groupd["ques"] != None:
  165. val = getFunc(groupd, key, data)
  166. if val == None:
  167. val = groupd["value"]
  168. elif "colon" in groupd and groupd["colon"] != None:
  169. e = data.createCopy()
  170. bb.data.update_data(e)
  171. val = bb.data.expand(groupd["value"], e)
  172. elif "append" in groupd and groupd["append"] != None:
  173. val = "%s %s" % ((getFunc(groupd, key, data) or ""), groupd["value"])
  174. elif "prepend" in groupd and groupd["prepend"] != None:
  175. val = "%s %s" % (groupd["value"], (getFunc(groupd, key, data) or ""))
  176. elif "postdot" in groupd and groupd["postdot"] != None:
  177. val = "%s%s" % ((getFunc(groupd, key, data) or ""), groupd["value"])
  178. elif "predot" in groupd and groupd["predot"] != None:
  179. val = "%s%s" % (groupd["value"], (getFunc(groupd, key, data) or ""))
  180. else:
  181. val = groupd["value"]
  182. if 'flag' in groupd and groupd['flag'] != None:
  183. bb.msg.debug(3, bb.msg.domain.Parsing, "setVarFlag(%s, %s, %s, data)" % (key, groupd['flag'], val))
  184. bb.data.setVarFlag(key, groupd['flag'], val, data)
  185. else:
  186. bb.data.setVar(key, val, data)
  187. return
  188. m = __include_regexp__.match(s)
  189. if m:
  190. s = bb.data.expand(m.group(1), data)
  191. bb.msg.debug(3, bb.msg.domain.Parsing, "CONF %s:%d: including %s" % (fn, lineno, s))
  192. include(fn, s, data, False)
  193. return
  194. m = __require_regexp__.match(s)
  195. if m:
  196. s = bb.data.expand(m.group(1), data)
  197. include(fn, s, data, "include required")
  198. return
  199. m = __export_regexp__.match(s)
  200. if m:
  201. bb.data.setVarFlag(m.group(1), "export", 1, data)
  202. return
  203. raise ParseError("%s:%d: unparsed line: '%s'" % (fn, lineno, s));
  204. # Add us to the handlers list
  205. from bb.parse import handlers
  206. handlers.append({'supports': supports, 'handle': handle, 'init': init})
  207. del handlers