ConfHandler.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. def init(data):
  30. if not bb.data.getVar('TOPDIR', data):
  31. bb.data.setVar('TOPDIR', os.getcwd(), data)
  32. if not bb.data.getVar('BBPATH', data):
  33. bb.data.setVar('BBPATH', os.path.join(sys.prefix, 'share', 'bitbake'), data)
  34. def supports(fn, d):
  35. return localpath(fn, d)[-5:] == ".conf"
  36. def localpath(fn, d):
  37. if os.path.exists(fn):
  38. return fn
  39. localfn = None
  40. try:
  41. localfn = bb.fetch.localpath(fn, d)
  42. except bb.MalformedUrl:
  43. pass
  44. if not localfn:
  45. localfn = fn
  46. return localfn
  47. def obtain(fn, data):
  48. import sys, bb
  49. fn = bb.data.expand(fn, data)
  50. localfn = bb.data.expand(localpath(fn, data), data)
  51. if localfn != fn:
  52. dldir = bb.data.getVar('DL_DIR', data, 1)
  53. if not dldir:
  54. bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: DL_DIR not defined")
  55. return localfn
  56. bb.mkdirhier(dldir)
  57. try:
  58. bb.fetch.init([fn])
  59. except bb.fetch.NoMethodError:
  60. (type, value, traceback) = sys.exc_info()
  61. bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: no method: %s" % value)
  62. return localfn
  63. try:
  64. bb.fetch.go(data)
  65. except bb.fetch.MissingParameterError:
  66. (type, value, traceback) = sys.exc_info()
  67. bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: missing parameters: %s" % value)
  68. return localfn
  69. except bb.fetch.FetchError:
  70. (type, value, traceback) = sys.exc_info()
  71. bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: failed: %s" % value)
  72. return localfn
  73. return localfn
  74. def include(oldfn, fn, data, error_out):
  75. """
  76. error_out If True a ParseError will be reaised if the to be included
  77. """
  78. if oldfn == fn: # prevent infinate recursion
  79. return None
  80. import bb
  81. fn = bb.data.expand(fn, data)
  82. oldfn = bb.data.expand(oldfn, data)
  83. from bb.parse import handle
  84. try:
  85. ret = handle(fn, data, True)
  86. except IOError:
  87. if error_out:
  88. raise ParseError("Could not %(error_out)s file %(fn)s" % vars() )
  89. bb.msg.debug(2, bb.msg.domain.Parsing, "CONF file '%s' not found" % fn)
  90. def handle(fn, data, include = 0):
  91. if include:
  92. inc_string = "including"
  93. else:
  94. inc_string = "reading"
  95. init(data)
  96. if include == 0:
  97. bb.data.inheritFromOS(data)
  98. oldfile = None
  99. else:
  100. oldfile = bb.data.getVar('FILE', data)
  101. fn = obtain(fn, data)
  102. if not os.path.isabs(fn):
  103. f = None
  104. bbpath = bb.data.getVar("BBPATH", data, 1) or []
  105. for p in bbpath.split(":"):
  106. currname = os.path.join(p, fn)
  107. if os.access(currname, os.R_OK):
  108. f = open(currname, 'r')
  109. abs_fn = currname
  110. bb.msg.debug(2, bb.msg.domain.Parsing, "CONF %s %s" % (inc_string, currname))
  111. break
  112. if f is None:
  113. raise IOError("file '%s' not found" % fn)
  114. else:
  115. f = open(fn,'r')
  116. bb.msg.debug(1, bb.msg.domain.Parsing, "CONF %s %s" % (inc_string,fn))
  117. abs_fn = fn
  118. if include:
  119. bb.parse.mark_dependency(data, abs_fn)
  120. lineno = 0
  121. bb.data.setVar('FILE', fn, data)
  122. while 1:
  123. lineno = lineno + 1
  124. s = f.readline()
  125. if not s: break
  126. w = s.strip()
  127. if not w: continue # skip empty lines
  128. s = s.rstrip()
  129. if s[0] == '#': continue # skip comments
  130. while s[-1] == '\\':
  131. s2 = f.readline()[:-1].strip()
  132. lineno = lineno + 1
  133. s = s[:-1] + s2
  134. feeder(lineno, s, fn, data)
  135. if oldfile:
  136. bb.data.setVar('FILE', oldfile, data)
  137. return data
  138. def feeder(lineno, s, fn, data):
  139. m = __config_regexp__.match(s)
  140. if m:
  141. groupd = m.groupdict()
  142. key = groupd["var"]
  143. if "exp" in groupd and groupd["exp"] != None:
  144. bb.data.setVarFlag(key, "export", 1, data)
  145. if "ques" in groupd and groupd["ques"] != None:
  146. val = bb.data.getVar(key, data)
  147. if val == None:
  148. val = groupd["value"]
  149. elif "colon" in groupd and groupd["colon"] != None:
  150. val = bb.data.expand(groupd["value"], data)
  151. elif "append" in groupd and groupd["append"] != None:
  152. val = "%s %s" % ((bb.data.getVar(key, data) or ""), groupd["value"])
  153. elif "prepend" in groupd and groupd["prepend"] != None:
  154. val = "%s %s" % (groupd["value"], (bb.data.getVar(key, data) or ""))
  155. elif "postdot" in groupd and groupd["postdot"] != None:
  156. val = "%s%s" % ((bb.data.getVar(key, data) or ""), groupd["value"])
  157. elif "predot" in groupd and groupd["predot"] != None:
  158. val = "%s%s" % (groupd["value"], (bb.data.getVar(key, data) or ""))
  159. else:
  160. val = groupd["value"]
  161. if 'flag' in groupd and groupd['flag'] != None:
  162. bb.msg.debug(3, bb.msg.domain.Parsing, "setVarFlag(%s, %s, %s, data)" % (key, groupd['flag'], val))
  163. bb.data.setVarFlag(key, groupd['flag'], val, data)
  164. else:
  165. bb.data.setVar(key, val, data)
  166. return
  167. m = __include_regexp__.match(s)
  168. if m:
  169. s = bb.data.expand(m.group(1), data)
  170. bb.msg.debug(3, bb.msg.domain.Parsing, "CONF %s:%d: including %s" % (fn, lineno, s))
  171. include(fn, s, data, False)
  172. return
  173. m = __require_regexp__.match(s)
  174. if m:
  175. s = bb.data.expand(m.group(1), data)
  176. include(fn, s, data, "include required")
  177. return
  178. raise ParseError("%s:%d: unparsed line: '%s'" % (fn, lineno, s));
  179. # Add us to the handlers list
  180. from bb.parse import handlers
  181. handlers.append({'supports': supports, 'handle': handle, 'init': init})
  182. del handlers