Commits

Anonymous committed a5c8113

Refactor construction variable expansion.

  • Participants
  • Parent commits 9adbdb4

Comments (0)

Files changed (5)

File src/engine/SCons/Builder.py

 
 import os
 import SCons.Node.FS
-from SCons.Util import PathList, scons_str2nodes, scons_varrepl
+from SCons.Util import PathList, scons_str2nodes, scons_subst
 import string
 import types
 
 	self.command = string
 
     def execute(self, **kw):
-        try:
-            t = kw['target']
-            if type(t) is types.StringType:
-                t = [t]
-            tgt = PathList(map(os.path.normpath, t))
-        except:
-            tgt = PathList()
-        try:
-            s = kw['source']
-            if type(s) is types.StringType:
-                s = [s]
-            src = PathList(map(os.path.normpath, s))
-        except:
-            src = PathList()
-        cmd = scons_varrepl(self.command, tgt, src)
+	loc = {}
+	if kw.has_key('target'):
+	    t = kw['target']
+	    if type(t) is type(""):
+	        t = [t]
+	    loc['targets'] = PathList(map(os.path.normpath, t))
+	    loc['target'] = loc['targets'][0]
+	if kw.has_key('source'):
+	    s = kw['source']
+	    if type(s) is type(""):
+	        s = [s]
+            loc['sources'] = PathList(map(os.path.normpath, s))
+
+	try:
+	    glob = self.env.Dictionary()
+	except:
+	    glob = {}
+
+	cmd = scons_subst(self.command, loc, glob)
 	if print_actions:
 	    self.show(cmd)
 	ret = 0

File src/engine/SCons/Environment.py

 
 
 
-_cv = re.compile(r'%([_a-zA-Z]\w*|{[_a-zA-Z]\w*})')
-
-
-
 def _deepcopy_atomic(x, memo):
 	return x
 copy._deepcopy_dispatch[types.ModuleType] = _deepcopy_atomic
     def subst(self, string):
 	"""Recursively interpolates construction variables from the
 	Environment into the specified string, returning the expanded
-	result.  Construction variables are specified by a % prefix
+	result.  Construction variables are specified by a $ prefix
 	in the string and begin with an initial underscore or
 	alphabetic character followed by any number of underscores
 	or alphanumeric characters.  The construction variable names
 	may be surrounded by curly braces to separate the name from
 	trailing characters.
 	"""
-	def repl(m, _self=self):
-	    key = m.group(1)
-	    if key[:1] == '{' and key[-1:] == '}':
-		key = key[1:-1]
-	    if _self._dict.has_key(key): return _self._dict[key]
-	    else: return ''
-	n = 1
-	while n != 0:
-	    string, n = _cv.subn(repl, string)
-	return string
+	return SCons.Util.scons_subst(string, self._dict, {})

File src/engine/SCons/EnvironmentTests.py

         """Test the Command() method."""
         env = Environment()
         t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'],
-                        action='buildfoo %(target)s %(source)s')
+                        action='buildfoo $target $source')
         assert t.derived
         assert t.builder.action.__class__.__name__ == 'CommandAction'
-        assert t.builder.action.command == 'buildfoo %(target)s %(source)s'
+        assert t.builder.action.command == 'buildfoo $target $source'
         assert 'foo1.in' in map(lambda x: x.path, t.sources)
         assert 'foo2.in' in map(lambda x: x.path, t.sources)
 
 	of variables into other variables.
 	"""
 	env = Environment(AAA = 'a', BBB = 'b')
-	str = env.subst("%AAA %{AAA}A %BBBB %BBB")
+	str = env.subst("$AAA ${AAA}A $BBBB $BBB")
 	assert str == "a aA  b", str
-	env = Environment(AAA = '%BBB', BBB = 'b', BBBA = 'foo')
-	str = env.subst("%AAA %{AAA}A %{AAA}B %BBB")
+	env = Environment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
+	str = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
 	assert str == "b foo  b", str
-	env = Environment(AAA = '%BBB', BBB = '%CCC', CCC = 'c')
-	str = env.subst("%AAA %{AAA}A %{AAA}B %BBB")
+	env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
+	str = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
 	assert str == "c   c", str
 
 

File src/engine/SCons/Util.py

         return self.__class__([ UserList.__getitem__(self, item), ])
 
 
-__tcv = re.compile(r'\$(\{?targets?(\[[0-9:]+\])?(\.[a-z]+)?\}?)')
-__scv = re.compile(r'\$(\{?sources(\[[0-9:]+\])?(\.[a-z]+)?\}?)')
-def scons_varrepl(command, targets, sources):
-    """This routine handles variable interpolation for the $targets and
-    $sources variables in the 'command' argument. The targets and sources
-    given in the other arguements must be lists containing 'Node's."""
 
-    def repl(m, targets=targets, sources=sources):
-	globals = {}
+_tok = r'[_a-zA-Z]\w*'
+_cv = re.compile(r'\$(%s|{%s(\[[-0-9:]*\])?(\.\w+)?})' % (_tok, _tok))
+
+def scons_subst(string, locals, globals):
+    """Recursively interpolates dictionary variables into
+    the specified string, returning the expanded result.
+    Variables are specified by a $ prefix in the string and
+    begin with an initial underscore or alphabetic character
+    followed by any number of underscores or alphanumeric
+    characters.  The construction variable names may be
+    surrounded by curly braces to separate the name from
+    trailing characters.
+    """
+    def repl(m, locals=locals, globals=globals):
         key = m.group(1)
-        if key[0] == '{':
-            if key[-1] == '}':
-                key = key[1:-1]
-            else:
-                raise SyntaxError, "Bad regular expression"
+        if key[:1] == '{' and key[-1:] == '}':
+            key = key[1:-1]
+	try:
+	    s = str(eval(key, locals, globals))
+	except NameError:
+	    s = ''
+	return s
+    n = 1
+    while n != 0:
+        string, n = _cv.subn(repl, string)
+    return string
 
-        if key[:6] == 'target':
-	    globals['targets'] = targets
-	    globals['target'] = targets[0]
-	if key[:7] == 'sources':
-	    globals['sources'] = sources
-	if globals:
-            return str(eval(key, globals ))
-
-    command = __tcv.sub(repl, command)
-    command = __scv.sub(repl, command)
-    return command
-
-

File src/engine/SCons/UtilTests.py

 import unittest
 import SCons.Node
 import SCons.Node.FS
-from SCons.Util import scons_str2nodes, scons_varrepl, PathList
+from SCons.Util import scons_str2nodes, scons_subst, PathList
 
 
 class UtilTestCase(unittest.TestCase):
 	node = scons_str2nodes(OtherNode())
 
 
-    def test_varrepl(self):
-	"""Test the varrepl function."""
-        targets = PathList(map(os.path.normpath, [ "./foo/bar.exe",
-                                                   "/bar/baz.obj",
-                                                   "../foo/baz.obj" ]))
-        sources = PathList(map(os.path.normpath, [ "./foo/blah.cpp",
-                                                   "/bar/ack.cpp",
-                                                   "../foo/ack.c" ]))
+    def test_subst(self):
+	"""Test the subst function."""
+	loc = {}
+        loc['targets'] = PathList(map(os.path.normpath, [ "./foo/bar.exe",
+                                                          "/bar/baz.obj",
+                                                          "../foo/baz.obj" ]))
+	loc['target'] = loc['targets'][0]
+        loc['sources'] = PathList(map(os.path.normpath, [ "./foo/blah.cpp",
+                                                          "/bar/ack.cpp",
+                                                          "../foo/ack.c" ]))
 
-        newcom = scons_varrepl("test $targets $sources", targets, sources)
+        newcom = scons_subst("test $targets $sources", loc, {})
 	assert newcom == "test foo/bar.exe /bar/baz.obj ../foo/baz.obj foo/blah.cpp /bar/ack.cpp ../foo/ack.c"
 
-        newcom = scons_varrepl("test $targets[:] $sources[0]", targets, sources)
+        newcom = scons_subst("test ${targets[:]} ${sources[0]}", loc, {})
 	assert newcom == "test foo/bar.exe /bar/baz.obj ../foo/baz.obj foo/blah.cpp"
 
-        newcom = scons_varrepl("test ${targets[1:]}v", targets, sources)
+        newcom = scons_subst("test ${targets[1:]}v", loc, {})
 	assert newcom == "test /bar/baz.obj ../foo/baz.objv"
 
-        newcom = scons_varrepl("test $target", targets, sources)
+        newcom = scons_subst("test $target", loc, {})
 	assert newcom == "test foo/bar.exe"
 
-        newcom = scons_varrepl("test $target$source[0]", targets, sources)
-	assert newcom == "test foo/bar.exe$source[0]"
+        newcom = scons_subst("test $target$source[0]", loc, {})
+	assert newcom == "test foo/bar.exe[0]"
 
-        newcom = scons_varrepl("test ${target.file}", targets, sources)
+        newcom = scons_subst("test ${target.file}", loc, {})
 	assert newcom == "test bar.exe"
 
-        newcom = scons_varrepl("test ${target.filebase}", targets, sources)
+        newcom = scons_subst("test ${target.filebase}", loc, {})
 	assert newcom == "test bar"
 
-        newcom = scons_varrepl("test ${target.suffix}", targets, sources)
+        newcom = scons_subst("test ${target.suffix}", loc, {})
 	assert newcom == "test .exe"
 
-        newcom = scons_varrepl("test ${target.base}", targets, sources)
+        newcom = scons_subst("test ${target.base}", loc, {})
 	assert newcom == "test foo/bar"
 
-        newcom = scons_varrepl("test ${target.dir}", targets, sources)
+        newcom = scons_subst("test ${target.dir}", loc, {})
 	assert newcom == "test foo"