Commits

Anonymous committed 7a4a72d

Create a specific CScanner subclass.

Comments (0)

Files changed (2)

src/engine/SCons/Scanner/C.py

 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 
+import copy
+import os.path
+import re
 import SCons.Scanner
-import re
-import os.path
 import SCons.Util
 
 angle_re = re.compile('^[ \t]*#[ \t]*include[ \t]+<([\\w./\\\\]+)>', re.M)
 quote_re = re.compile('^[ \t]*#[ \t]*include[ \t]+"([\\w./\\\\]+)"', re.M)
 
-def CScan():
+def CScan(fs = SCons.Node.FS.default_fs):
     "Return a prototype Scanner instance for scanning C/C++ source files"
-    return SCons.Scanner.Recursive(scan, "CScan",
-                                   SCons.Node.FS.default_fs.File,
-                                   [".c", ".C", ".cxx", ".cpp", ".c++",
-                                    ".h", ".H", ".hxx", ".hpp"])
+    cs = CScanner(scan, "CScan", [fs, ()],
+                  [".c", ".C", ".cxx", ".cpp", ".c++",
+                   ".h", ".H", ".hxx", ".hpp"])
+    cs.fs = fs
+    return cs
 
-def scan(filename, env, node_factory):
+class CScanner(SCons.Scanner.Recursive):
+    def __init__(self, *args, **kw):
+        apply(SCons.Scanner.Recursive.__init__, (self,) + args, kw)
+        self.pathscanners = {}
+
+    def instance(self, env):
+        """
+        Return a unique instance of a C scanner object for a
+        given environment.
+        """
+        try:
+            dirs = tuple(SCons.Util.scons_str2nodes(env.Dictionary('CPPPATH'),
+                                                    self.fs.Dir))
+        except:
+            dirs = ()
+        if not self.pathscanners.has_key(dirs):
+            clone = copy.copy(self)
+	    clone.argument = [self.fs, dirs]	# XXX reaching into object
+            self.pathscanners[dirs] = clone
+        return self.pathscanners[dirs]
+
+def scan(filename, env, args = [SCons.Node.FS.default_fs, ()]):
     """
     scan(str, Environment) -> [str]
 
     dependencies.
     """
 
-    fs = SCons.Node.FS.default_fs
-    try:
-        paths = map(lambda x, dir=fs.Dir: dir(x),
-                    env.Dictionary("CPPPATH"))
-    except KeyError:
-        paths = []
+    fs, cpppath = args
 
     try:
         file = open(filename)
 
         dir = os.path.dirname(filename)
         if dir:
-            source_dir = [fs.Dir(dir)]
+            source_dir = (fs.Dir(dir),)
         else:
-            source_dir = []
+            source_dir = ()
         
-        return (SCons.Util.find_files(angle_includes, paths + source_dir,
-                                      node_factory)
-                + SCons.Util.find_files(quote_includes, source_dir + paths,
-                                        node_factory))
+        return (SCons.Util.find_files(angle_includes, cpppath + source_dir,
+                                      fs.File)
+                + SCons.Util.find_files(quote_includes, source_dir + cpppath,
+                                        fs.File))
     except (IOError, OSError):
         return []

src/engine/SCons/Scanner/CTests.py

 import SCons.Scanner.C
 import unittest
 import sys
+import os
 import os.path
 
 test = TestCmd.TestCmd(workdir = '')
 
+os.chdir(test.workpath(''))
+
 # create some source files and headers:
 
 test.write('f1.cpp',"""
     def runTest(self):
         env = DummyEnvironment([])
         s = SCons.Scanner.C.CScan()
-        deps = s.scan(test.workpath('f1.cpp'), env)
+        deps = s.instance(env).scan(test.workpath('f1.cpp'), env)
 	headers = ['f1.h', 'f2.h', 'fi.h']
         deps_match(self, deps, headers)
 
     def runTest(self):
         env = DummyEnvironment([test.workpath("d1")])
         s = SCons.Scanner.C.CScan()
-        deps = s.scan(test.workpath('f1.cpp'), env)
+        deps = s.instance(env).scan(test.workpath('f1.cpp'), env)
         headers = ['f1.h', 'd1/f2.h']
         deps_match(self, deps, headers)
 
     def runTest(self):
         env = DummyEnvironment([test.workpath("d1")])
         s = SCons.Scanner.C.CScan()
-        deps = s.scan(test.workpath('f2.cpp'), env)
+        deps = s.instance(env).scan(test.workpath('f2.cpp'), env)
         headers = ['f1.h', 'd1/f1.h', 'd1/d2/f1.h']
         deps_match(self, deps, headers)
 
     def runTest(self):
         env = DummyEnvironment([test.workpath("d1"), test.workpath("d1/d2")])
         s = SCons.Scanner.C.CScan()
-        deps = s.scan(test.workpath('f2.cpp'), env)
+        deps = s.instance(env).scan(test.workpath('f2.cpp'), env)
         headers =  ['f1.h', 'd1/f1.h', 'd1/d2/f1.h', 'd1/d2/f4.h']
         deps_match(self, deps, headers)
         
     def runTest(self):
         env = DummyEnvironment([])
         s = SCons.Scanner.C.CScan()
-        deps = s.scan(test.workpath('f3.cpp'), env)
+        deps = s.instance(env).scan(test.workpath('f3.cpp'), env)
         headers =  ['f1.h', 'f2.h', 'f3.h', 'fi.h', 'fj.h',
                     'd1/f1.h', 'd1/f2.h', 'd1/f3.h']
         deps_match(self, deps, headers)
 
+class CScannerTestCase6(unittest.TestCase):
+    def runTest(self):
+        env1 = DummyEnvironment([test.workpath("d1")])
+        env2 = DummyEnvironment([test.workpath("d1/d2")])
+        s = SCons.Scanner.C.CScan()
+	s1 = s.instance(env1)
+	s2 = s.instance(env2)
+	s3 = s.instance(env1)
+	assert not s1 is s2
+	assert s1 is s3
+        deps1 = s1.scan(test.workpath('f1.cpp'), None)
+        deps2 = s2.scan(test.workpath('f1.cpp'), None)
+        headers1 =  ['f1.h', 'd1/f2.h']
+        headers2 =  ['f1.h', 'd1/d2/f2.h']
+        deps_match(self, deps1, headers1)
+        deps_match(self, deps2, headers2)
+
 def suite():
     suite = unittest.TestSuite()
     suite.addTest(CScannerTestCase1())
     suite.addTest(CScannerTestCase3())
     suite.addTest(CScannerTestCase4())
     suite.addTest(CScannerTestCase5())
+    suite.addTest(CScannerTestCase6())
     return suite
 
 if __name__ == "__main__":