Refactor construction variable expansion.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 12 Oct 2001 02:17:49 +0000 (02:17 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 12 Oct 2001 02:17:49 +0000 (02:17 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@96 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Builder.py
src/engine/SCons/Environment.py
src/engine/SCons/EnvironmentTests.py
src/engine/SCons/Util.py
src/engine/SCons/UtilTests.py

index 9e84a7d8d25870f4cf3762e78a2991e5ec148545..ac24e7f4c1202ca722d1b49bae884bfb1168e39a 100644 (file)
@@ -33,7 +33,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 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
 
@@ -210,21 +210,25 @@ class CommandAction(ActionBase):
        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
index 16032b9ef6d8da3fb655bf251555528e6be65f0b..468c9b4f5303371a00a18386402dee69ffa52447 100644 (file)
@@ -49,10 +49,6 @@ def InstallAs():
 
 
 
-_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
@@ -173,20 +169,11 @@ class Environment:
     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, {})
index 9035cd4f5f38c941df1c42e5ceea43e38fbfb69d..07e84a4eee31f1191ea970e3f41c07af654d92d7 100644 (file)
@@ -172,10 +172,10 @@ class EnvironmentTestCase(unittest.TestCase):
         """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)
 
@@ -192,13 +192,13 @@ class EnvironmentTestCase(unittest.TestCase):
        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
 
 
index 2a6858c2254032f3b90ae3d09b4f632ba5aa04ff..00a833010ae6b1379cb9f38b93e8d611732fbf5b 100644 (file)
@@ -158,32 +158,31 @@ class PathList(UserList):
         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 = {}
-        key = m.group(1)
-        if key[0] == '{':
-            if key[-1] == '}':
-                key = key[1:-1]
-            else:
-                raise SyntaxError, "Bad regular expression"
-
-        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
 
+_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[: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
 
index db4d7a14b86b3856ec10d4680428370589aced39..bbaf851f5d4fd2b569d9cb47c166cc80fc4deac6 100644 (file)
@@ -28,7 +28,7 @@ import os.path
 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):
@@ -72,43 +72,45 @@ 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"