diff options
Diffstat (limited to 'src/engine/SCons/Scanner')
-rw-r--r-- | src/engine/SCons/Scanner/C.py | 11 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/CTests.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/D.py | 20 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/DTests.py | 282 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/Dir.py | 6 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/DirTests.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/Fortran.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/FortranTests.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/IDL.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/IDLTests.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/LaTeX.py | 129 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/LaTeXTests.py | 19 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/Prog.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/ProgTests.py | 6 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/RC.py | 27 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/RCTests.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/SWIG.py | 4 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/ScannerTests.py | 38 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/__init__.py | 42 | ||||
-rw-r--r-- | src/engine/SCons/Scanner/__init__.xml | 2 |
20 files changed, 504 insertions, 114 deletions
diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index d78bd05..6cdab4a 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -5,7 +5,7 @@ This module implements the dependency scanner for C/C++ code. """ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ This module implements the dependency scanner for C/C++ code. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/C.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/C.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons.Node.FS import SCons.Scanner @@ -58,12 +58,11 @@ class SConsCPPScanner(SCons.cpp.PreProcessor): return result def read_file(self, file): try: - fp = open(str(file.rfile())) - except EnvironmentError, e: + with open(str(file.rfile())) as fp: + return fp.read() + except EnvironmentError as e: self.missing.append((file, self.current_file)) return '' - else: - return fp.read() def dictify_CPPDEFINES(env): cppdefines = env.get('CPPDEFINES', {}) diff --git a/src/engine/SCons/Scanner/CTests.py b/src/engine/SCons/Scanner/CTests.py index abbc25a..f7b2b16 100644 --- a/src/engine/SCons/Scanner/CTests.py +++ b/src/engine/SCons/Scanner/CTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/CTests.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/CTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons.compat diff --git a/src/engine/SCons/Scanner/D.py b/src/engine/SCons/Scanner/D.py index 0df6406..3b6f2f9 100644 --- a/src/engine/SCons/Scanner/D.py +++ b/src/engine/SCons/Scanner/D.py @@ -8,7 +8,7 @@ Coded by Andy Friesen """ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,9 +30,7 @@ Coded by Andy Friesen # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/D.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" - -import re +__revision__ = "src/engine/SCons/Scanner/D.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons.Scanner @@ -43,13 +41,13 @@ def DScanner(): class D(SCons.Scanner.Classic): def __init__ (self): - SCons.Scanner.Classic.__init__ (self, + SCons.Scanner.Classic.__init__ ( + self, name = "DScanner", suffixes = '$DSUFFIXES', path_variable = 'DPATH', - regex = 'import\s+(?:[a-zA-Z0-9_.]+)\s*(?:,\s*(?:[a-zA-Z0-9_.]+)\s*)*;') - - self.cre2 = re.compile ('(?:import\s)?\s*([a-zA-Z0-9_.]+)\s*(?:,|;)', re.M) + regex = '(?:import\s+)([\w\s=,.]+)(?:\s*:[\s\w,=]+)?(?:;)' + ) def find_include(self, include, source_dir, path): # translate dots (package separators) to slashes @@ -62,8 +60,10 @@ class D(SCons.Scanner.Classic): def find_include_names(self, node): includes = [] - for i in self.cre.findall(node.get_text_contents()): - includes = includes + self.cre2.findall(i) + for iii in self.cre.findall(node.get_text_contents()): + for jjj in iii.split(','): + kkk = jjj.split('=')[-1] + includes.append(kkk.strip()) return includes # Local Variables: diff --git a/src/engine/SCons/Scanner/DTests.py b/src/engine/SCons/Scanner/DTests.py new file mode 100644 index 0000000..58fbe76 --- /dev/null +++ b/src/engine/SCons/Scanner/DTests.py @@ -0,0 +1,282 @@ +# +# Copyright (c) 2001 - 2017 The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "src/engine/SCons/Scanner/DTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" + +import unittest + +import TestCmd +import TestUnit + +import SCons.Scanner.D + +test = TestCmd.TestCmd(workdir = '') + +import collections +import os + +class DummyEnvironment(collections.UserDict): + def __init__(self, **kw): + collections.UserDict.__init__(self) + self.data.update(kw) + self.fs = SCons.Node.FS.FS(test.workpath('')) + + def Dictionary(self, *args): + return self.data + + def subst(self, strSubst, target=None, source=None, conv=None): + if strSubst[0] == '$': + return self.data[strSubst[1:]] + return strSubst + + def subst_list(self, strSubst, target=None, source=None, conv=None): + if strSubst[0] == '$': + return [self.data[strSubst[1:]]] + return [[strSubst]] + + def subst_path(self, path, target=None, source=None, conv=None): + if not isinstance(path, list): + path = [path] + return list(map(self.subst, path)) + + def get_calculator(self): + return None + + def get_factory(self, factory): + return factory or self.fs.File + + def Dir(self, filename): + return self.fs.Dir(filename) + + def File(self, filename): + return self.fs.File(filename) + +if os.path.normcase('foo') == os.path.normcase('FOO'): + my_normpath = os.path.normcase +else: + my_normpath = os.path.normpath + +def deps_match(self, deps, headers): + global my_normpath + scanned = list(map(my_normpath, list(map(str, deps)))) + expect = list(map(my_normpath, headers)) + self.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) + +""" +Examples from https://dlang.org/spec/module.html + +D Language: 2.071.1 +Accessed: 11 August 2016 +""" + +# Regular import +test.write('basic.d',""" +import A; + +void main() {} +""") + +# Static import +test.write('static.d',""" +static import A; + +void main() +{ + std.stdio.writeln("hello!"); // ok, writeln is fully qualified +} +""") + +# Public import +test.write('public.d',""" +public import A; + +void main() {} +""") + +# Renamed import +test.write('rename.d',""" +import B = A; + +void main() +{ + io.writeln("hello!"); // ok, calls std.stdio.writeln +} +""") + +# Selective import +test.write('selective.d',""" +import A : B, C; + +void main() +{ + writeln("hello!"); // ok, writeln bound into current namespace + foo("world"); // ok, calls std.stdio.write() +} +""") + +# Renamed and Selective import +test.write('renameAndSelective.d',""" +import B = A : C = D; + +void main() +{ +} +""") + +# Scoped import +test.write('scoped.d',""" +void main() +{ + import A; +} +""") + +# Combinatorial import +test.write('combinatorial.d',""" +import A, B, CCC = C, DDD = D : EEE = FFF; + +void main() +{ +} +""") + +# Subdirs import +test.write('subdirs.d',""" +import X.Y, X.Z, X.X.X; + +void main() {} +""") + +# Multiple import +test.write('multiple.d',""" +public import B; +static import C; + +import X = X.Y : Q, R, S, T = U; +void main() +{ + import A; +} +""") + +# Multiline import +test.write('multiline.d',""" +import +A; + +void main() {} +""") + +test.write('A.d',""" +module A; +void main() {} +""") + +test.write('B.d',""" +module B; +void main() {} +""") + +test.write('C.d',""" +module C; +void main() {} +""") + +test.write('D.d',""" +module D; +void main() {} +""") + +test.subdir('X', os.path.join('X','X')) + +test.write(os.path.join('X','Y.d'),""" +module Y; +void main() {} +""") + +test.write(os.path.join('X','Z.d'),""" +module Z; +void main() {} +""") + +test.write(os.path.join('X','X','X.d'),""" +module X; +void main() {} +""") + +class DScannerTestCase(unittest.TestCase): + def helper(self, filename, headers): + env = DummyEnvironment() + s = SCons.Scanner.D.DScanner() + path = s.path(env) + deps = s(env.File(filename), env, path) + deps_match(self, deps, headers) + + def test_BasicImport(self): + self.helper('basic.d', ['A.d']) + + def test_StaticImport(self): + self.helper('static.d', ['A.d']) + + def test_publicImport(self): + self.helper('public.d', ['A.d']) + + def test_RenameImport(self): + self.helper('rename.d', ['A.d']) + + def test_SelectiveImport(self): + self.helper('selective.d', ['A.d']) + + def test_RenameAndSelectiveImport(self): + self.helper('renameAndSelective.d', ['A.d']) + + def test_ScopedImport(self): + self.helper('scoped.d', ['A.d']) + + def test_CombinatorialImport(self): + self.helper('combinatorial.d', ['A.d', 'B.d', 'C.d', 'D.d']) + + def test_SubdirsImport(self): + self.helper('subdirs.d', [os.path.join('X','X','X.d'), os.path.join('X','Y.d'), os.path.join('X','Z.d')]) + + def test_MultipleImport(self): + self.helper('multiple.d', ['A.d', 'B.d', 'C.d', os.path.join('X','Y.d')]) + + def test_MultilineImport(self): + self.helper('multiline.d', ['A.d']) + +if __name__ == "__main__": + suite = unittest.TestSuite() + tclasses = [ + DScannerTestCase, + ] + for tclass in tclasses: + names = unittest.getTestCaseNames(tclass, 'test_') + suite.addTests(list(map(tclass, names))) + TestUnit.run(suite) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Scanner/Dir.py b/src/engine/SCons/Scanner/Dir.py index eefba8b..66d5b6d 100644 --- a/src/engine/SCons/Scanner/Dir.py +++ b/src/engine/SCons/Scanner/Dir.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,14 +20,14 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Scanner/Dir.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/Dir.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons.Node.FS import SCons.Scanner def only_dirs(nodes): is_Dir = lambda n: isinstance(n.disambiguate(), SCons.Node.FS.Dir) - return list(filter(is_Dir, nodes)) + return [node for node in nodes if is_Dir(node)] def DirScanner(**kw): """Return a prototype Scanner instance for scanning diff --git a/src/engine/SCons/Scanner/DirTests.py b/src/engine/SCons/Scanner/DirTests.py index 6c0e6f4..12f1844 100644 --- a/src/engine/SCons/Scanner/DirTests.py +++ b/src/engine/SCons/Scanner/DirTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/DirTests.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/DirTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import os.path import sys diff --git a/src/engine/SCons/Scanner/Fortran.py b/src/engine/SCons/Scanner/Fortran.py index 179c8db..8a8f3eb 100644 --- a/src/engine/SCons/Scanner/Fortran.py +++ b/src/engine/SCons/Scanner/Fortran.py @@ -5,7 +5,7 @@ This module implements the dependency scanner for Fortran code. """ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ This module implements the dependency scanner for Fortran code. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Scanner/Fortran.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/Fortran.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import re diff --git a/src/engine/SCons/Scanner/FortranTests.py b/src/engine/SCons/Scanner/FortranTests.py index b5575db..4194018 100644 --- a/src/engine/SCons/Scanner/FortranTests.py +++ b/src/engine/SCons/Scanner/FortranTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/FortranTests.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/FortranTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import os import os.path diff --git a/src/engine/SCons/Scanner/IDL.py b/src/engine/SCons/Scanner/IDL.py index b7b76fd..706ff41 100644 --- a/src/engine/SCons/Scanner/IDL.py +++ b/src/engine/SCons/Scanner/IDL.py @@ -6,7 +6,7 @@ Definition Language) files. """ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Definition Language) files. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/IDL.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/IDL.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons.Node.FS import SCons.Scanner diff --git a/src/engine/SCons/Scanner/IDLTests.py b/src/engine/SCons/Scanner/IDLTests.py index b2a7ba3..f1b64c0 100644 --- a/src/engine/SCons/Scanner/IDLTests.py +++ b/src/engine/SCons/Scanner/IDLTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/IDLTests.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/IDLTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import unittest import sys diff --git a/src/engine/SCons/Scanner/LaTeX.py b/src/engine/SCons/Scanner/LaTeX.py index 0a68b7e..69154bd 100644 --- a/src/engine/SCons/Scanner/LaTeX.py +++ b/src/engine/SCons/Scanner/LaTeX.py @@ -5,7 +5,7 @@ This module implements the dependency scanner for LaTeX code. """ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ This module implements the dependency scanner for LaTeX code. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/LaTeX.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/LaTeX.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import os.path import re @@ -37,7 +37,9 @@ import SCons.Util # list of graphics file extensions for TeX and LaTeX TexGraphics = ['.eps', '.ps'] -LatexGraphics = ['.pdf', '.png', '.jpg', '.gif', '.tif'] +#LatexGraphics = ['.pdf', '.png', '.jpg', '.gif', '.tif'] +LatexGraphics = [ '.png', '.jpg', '.gif', '.tif'] + # Used as a return value of modify_env_var if the variable is not set. class _Null(object): @@ -76,8 +78,10 @@ def modify_env_var(env, var, abspath): return save class FindENVPathDirs(object): - """A class to bind a specific *PATH variable name to a function that - will return all of the *path directories.""" + """ + A class to bind a specific E{*}PATH variable name to a function that + will return all of the E{*}path directories. + """ def __init__(self, variable): self.variable = variable def __call__(self, env, dir=None, target=None, source=None, argument=None): @@ -94,7 +98,8 @@ class FindENVPathDirs(object): def LaTeXScanner(): - """Return a prototype Scanner instance for scanning LaTeX source files + """ + Return a prototype Scanner instance for scanning LaTeX source files when built with latex. """ ds = LaTeX(name = "LaTeXScanner", @@ -105,7 +110,8 @@ def LaTeXScanner(): return ds def PDFLaTeXScanner(): - """Return a prototype Scanner instance for scanning LaTeX source files + """ + Return a prototype Scanner instance for scanning LaTeX source files when built with pdflatex. """ ds = LaTeX(name = "PDFLaTeXScanner", @@ -116,7 +122,8 @@ def PDFLaTeXScanner(): return ds class LaTeX(SCons.Scanner.Base): - """Class for scanning LaTeX files for included files. + """ + Class for scanning LaTeX files for included files. Unlike most scanners, which use regular expressions that just return the included file name, this returns a tuple consisting @@ -133,10 +140,12 @@ class LaTeX(SCons.Scanner.Base): The actual subset and search order may be altered by DeclareGraphicsExtensions command. This complication is ignored. - The default order corresponds to experimentation with teTeX + The default order corresponds to experimentation with teTeX:: + $ latex --version pdfeTeX 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.4 + The order is: ['.eps', '.ps'] for latex ['.png', '.pdf', '.jpg', '.tif']. @@ -148,8 +157,7 @@ class LaTeX(SCons.Scanner.Base): env['TEXINPUTS'] for "lstinputlisting" keyword env['BIBINPUTS'] for "bibliography" keyword env['BSTINPUTS'] for "bibliographystyle" keyword - env['INDEXSTYLE'] for "makeindex" keyword, no scanning support needed - just allows user to set it if needed. + env['INDEXSTYLE'] for "makeindex" keyword, no scanning support needed just allows user to set it if needed. FIXME: also look for the class or style in document[class|style]{} FIXME: also look for the argument of bibliographystyle{} @@ -166,6 +174,9 @@ class LaTeX(SCons.Scanner.Base): 'usepackage': 'TEXINPUTS', 'lstinputlisting': 'TEXINPUTS'} env_variables = SCons.Util.unique(list(keyword_paths.values())) + two_arg_commands = ['import', 'subimport', + 'includefrom', 'subincludefrom', + 'inputfrom', 'subinputfrom'] def __init__(self, name, suffixes, graphics_extensions, *args, **kw): @@ -175,8 +186,29 @@ class LaTeX(SCons.Scanner.Base): # line followed by one or more newline characters (i.e. blank # lines), interfering with a match on the next line. # add option for whitespace before the '[options]' or the '{filename}' - regex = r'^[^%\n]*\\(include|includegraphics(?:\s*\[[^\]]+\])?|lstinputlisting(?:\[[^\]]+\])?|input|bibliography|addbibresource|addglobalbib|addsectionbib|usepackage)\s*{([^}]*)}' - self.cre = re.compile(regex, re.M) + regex = r''' + ^[^%\n]* + \\( + include + | includegraphics(?:\s*\[[^\]]+\])? + | lstinputlisting(?:\[[^\]]+\])? + | input + | import + | subimport + | includefrom + | subincludefrom + | inputfrom + | subinputfrom + | bibliography + | addbibresource + | addglobalbib + | addsectionbib + | usepackage + ) + \s*{([^}]*)} # first arg + (?: \s*{([^}]*)} )? # maybe another arg + ''' + self.cre = re.compile(regex, re.M | re.X) self.comment_re = re.compile(r'^((?:(?:\\%)|[^%\n])*)(.*)$', re.M) self.graphics_extensions = graphics_extensions @@ -236,23 +268,26 @@ class LaTeX(SCons.Scanner.Base): SCons.Scanner.Base.__init__(self, *args, **kw) - def _latex_names(self, include): - filename = include[1] - if include[0] == 'input': + def _latex_names(self, include_type, filename): + if include_type == 'input': + base, ext = os.path.splitext( filename ) + if ext == "": + return [filename + '.tex'] + if include_type in ('include', 'import', 'subimport', + 'includefrom', 'subincludefrom', + 'inputfrom', 'subinputfrom'): base, ext = os.path.splitext( filename ) if ext == "": return [filename + '.tex'] - if (include[0] == 'include'): - return [filename + '.tex'] - if include[0] == 'bibliography': + if include_type == 'bibliography': base, ext = os.path.splitext( filename ) if ext == "": return [filename + '.bib'] - if include[0] == 'usepackage': + if include_type == 'usepackage': base, ext = os.path.splitext( filename ) if ext == "": return [filename + '.sty'] - if include[0] == 'includegraphics': + if include_type == 'includegraphics': base, ext = os.path.splitext( filename ) if ext == "": #return [filename+e for e in self.graphics_extensions + TexGraphics] @@ -267,21 +302,26 @@ class LaTeX(SCons.Scanner.Base): return SCons.Node.FS._my_normcase(str(include)) def find_include(self, include, source_dir, path): + inc_type, inc_subdir, inc_filename = include try: - sub_path = path[include[0]] + sub_paths = path[inc_type] except (IndexError, KeyError): - sub_path = () - try_names = self._latex_names(include) + sub_paths = ((), ()) + try_names = self._latex_names(inc_type, inc_filename) + + # There are three search paths to try: + # 1. current directory "source_dir" + # 2. env[var] + # 3. env['ENV'][var] + search_paths = [(source_dir,)] + list(sub_paths) + for n in try_names: - # see if we find it using the path in env[var] - i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[0]) - if i: - return i, include - # see if we find it using the path in env['ENV'][var] - i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[1]) - if i: - return i, include - return i, include + for search_path in search_paths: + paths = tuple([d.Dir(inc_subdir) for d in search_path]) + i = SCons.Node.FS.find_file(n, paths) + if i: + return i, include + return None, include def canonical_text(self, text): """Standardize an input TeX-file contents. @@ -300,7 +340,7 @@ class LaTeX(SCons.Scanner.Base): line_continues_a_comment = len(comment) > 0 return '\n'.join(out).rstrip()+'\n' - def scan(self, node): + def scan(self, node, subdir='.'): # Modify the default scan function to allow for the regular # expression to return a comma separated list of file names # as can be the case with the bibliography keyword. @@ -326,9 +366,14 @@ class LaTeX(SCons.Scanner.Base): split_includes = [] for include in includes: inc_type = noopt_cre.sub('', include[0]) - inc_list = include[1].split(',') + inc_subdir = subdir + if inc_type in self.two_arg_commands: + inc_subdir = os.path.join(subdir, include[1]) + inc_list = include[2].split(',') + else: + inc_list = include[1].split(',') for j in range(len(inc_list)): - split_includes.append( (inc_type, inc_list[j]) ) + split_includes.append( (inc_type, inc_subdir, inc_list[j]) ) # includes = split_includes node.includes = includes @@ -359,11 +404,13 @@ class LaTeX(SCons.Scanner.Base): while queue: include = queue.pop() + inc_type, inc_subdir, inc_filename = include + try: - if seen[include[1]] == 1: + if seen[inc_filename] == 1: continue except KeyError: - seen[include[1]] = 1 + seen[inc_filename] = 1 # # Handle multiple filenames in include[1] @@ -372,14 +419,14 @@ class LaTeX(SCons.Scanner.Base): if n is None: # Do not bother with 'usepackage' warnings, as they most # likely refer to system-level files - if include[0] != 'usepackage': + if inc_type != 'usepackage': SCons.Warnings.warn(SCons.Warnings.DependencyWarning, "No dependency generated for file: %s (included from: %s) -- file not found" % (i, node)) else: sortkey = self.sort_key(n) nodes.append((sortkey, n)) - # recurse down - queue.extend( self.scan(n) ) + # recurse down + queue.extend( self.scan(n, inc_subdir) ) return [pair[1] for pair in sorted(nodes)] diff --git a/src/engine/SCons/Scanner/LaTeXTests.py b/src/engine/SCons/Scanner/LaTeXTests.py index 3f09fdc..93729d4 100644 --- a/src/engine/SCons/Scanner/LaTeXTests.py +++ b/src/engine/SCons/Scanner/LaTeXTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/LaTeXTests.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/LaTeXTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons.compat @@ -44,6 +44,12 @@ test.write('test1.latex',""" include{incNO} %\include{incNO} xyzzy \include{inc6} +\subimport{subdir}{inc3} +\import{subdir}{inc3a} +\includefrom{subdir}{inc3b} +\subincludefrom{subdir}{inc3c} +\inputfrom{subdir}{inc3d} +\subinputfrom{subdir}{inc3e} """) test.write('test2.latex',""" @@ -61,6 +67,10 @@ test.subdir('subdir') test.write('inc1.tex',"\n") test.write('inc2.tex',"\n") test.write(['subdir', 'inc3.tex'], "\n") +for suffix in 'abcde': + test.write(['subdir', 'inc3%s.tex' % suffix], "\n") +test.write(['subdir', 'inc3b.tex'], "\n") +test.write(['subdir', 'inc3c.tex'], "\n") test.write(['subdir', 'inc4.eps'], "\n") test.write('inc5.xyz', "\n") test.write('inc6.tex', "\n") @@ -122,7 +132,10 @@ class LaTeXScannerTestCase1(unittest.TestCase): s = SCons.Scanner.LaTeX.LaTeXScanner() path = s.path(env) deps = s(env.File('test1.latex'), env, path) - headers = ['inc1.tex', 'inc2.tex', 'inc6.tex'] + headers = ['inc1.tex', 'inc2.tex', 'inc6.tex', + 'subdir/inc3.tex', 'subdir/inc3a.tex', + 'subdir/inc3b.tex', 'subdir/inc3c.tex', + 'subdir/inc3d.tex', 'subdir/inc3e.tex'] deps_match(self, deps, headers) class LaTeXScannerTestCase2(unittest.TestCase): diff --git a/src/engine/SCons/Scanner/Prog.py b/src/engine/SCons/Scanner/Prog.py index 8e3245e..63d5a38 100644 --- a/src/engine/SCons/Scanner/Prog.py +++ b/src/engine/SCons/Scanner/Prog.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/Prog.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/Prog.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons.Node import SCons.Node.FS diff --git a/src/engine/SCons/Scanner/ProgTests.py b/src/engine/SCons/Scanner/ProgTests.py index 9871627..1f4dfb5 100644 --- a/src/engine/SCons/Scanner/ProgTests.py +++ b/src/engine/SCons/Scanner/ProgTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/ProgTests.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/ProgTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import os.path import sys @@ -270,7 +270,7 @@ def suite(): assert deps_match(deps, ['d1/l2.lib', 'd1/d2/l3.lib']), map(str, deps) suite.addTest(ProgramScannerTestCase4()) \n""" - exec code + exec(code) return suite if __name__ == "__main__": diff --git a/src/engine/SCons/Scanner/RC.py b/src/engine/SCons/Scanner/RC.py index 57e9e7f..4202362 100644 --- a/src/engine/SCons/Scanner/RC.py +++ b/src/engine/SCons/Scanner/RC.py @@ -6,7 +6,7 @@ Definition Language) files. """ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,23 +28,34 @@ Definition Language) files. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/RC.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/RC.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" + +import re import SCons.Node.FS import SCons.Scanner -import re + + +def no_tlb(nodes): + """ + Filter out .tlb files as they are binary and shouldn't be scanned + """ + # print("Nodes:%s"%[str(n) for n in nodes]) + return [n for n in nodes if str(n)[-4:] != '.tlb'] + def RCScan(): """Return a prototype Scanner instance for scanning RC source files""" - + res_re= r'^(?:\s*#\s*(?:include)|' \ '.*?\s+(?:ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)' \ '\s*.*?)' \ '\s*(<|"| )([^>"\s]+)(?:[>"\s])*$' - resScanner = SCons.Scanner.ClassicCPP( "ResourceScanner", - "$RCSUFFIXES", - "CPPPATH", - res_re ) + resScanner = SCons.Scanner.ClassicCPP("ResourceScanner", + "$RCSUFFIXES", + "CPPPATH", + res_re, + recursive=no_tlb) return resScanner diff --git a/src/engine/SCons/Scanner/RCTests.py b/src/engine/SCons/Scanner/RCTests.py index f0b9fff..fa0a9b4 100644 --- a/src/engine/SCons/Scanner/RCTests.py +++ b/src/engine/SCons/Scanner/RCTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/RCTests.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/RCTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import unittest import sys diff --git a/src/engine/SCons/Scanner/SWIG.py b/src/engine/SCons/Scanner/SWIG.py index 4114c1f..048574c 100644 --- a/src/engine/SCons/Scanner/SWIG.py +++ b/src/engine/SCons/Scanner/SWIG.py @@ -5,7 +5,7 @@ This module implements the dependency scanner for SWIG code. """ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ This module implements the dependency scanner for SWIG code. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/SWIG.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/SWIG.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons.Scanner diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index b6ede69..a962a4c 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,7 +20,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Scanner/ScannerTests.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/ScannerTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons.compat @@ -105,7 +105,7 @@ class ScannerTestCase(unittest.TestCase): assert str(s) == 'fooscan', str(s) assert s.argument == 888, s.argument - + class BaseTestCase(unittest.TestCase): class skey_node(object): @@ -236,7 +236,7 @@ class BaseTestCase(unittest.TestCase): def test___cmp__(self): """Test the Scanner.Base class __cmp__() method""" s = SCons.Scanner.Base(self.func, "Cmp") - assert cmp(s, None) + assert s != None def test_hash(self): """Test the Scanner.Base class __hash__() method""" @@ -447,6 +447,17 @@ class CurrentTestCase(unittest.TestCase): self.failUnless(ic.func_called, "did not call func()") class ClassicTestCase(unittest.TestCase): + + def func(self, filename, env, target, *args): + self.filename = filename + self.env = env + self.target = target + + if len(args) > 0: + self.arg = args[0] + + return self.deps + def test_find_include(self): """Test the Scanner.Classic find_include() method""" env = DummyEnvironment() @@ -548,6 +559,25 @@ class ClassicTestCase(unittest.TestCase): ret = s.function(n, env, ('foo5',)) assert ret == ['jkl', 'mno'], ret + def test_recursive(self): + """Test the Scanner.Classic class recursive flag""" + nodes = [1, 2, 3, 4] + + + s = SCons.Scanner.Classic("Test", [], None, "", function=self.func, recursive=1) + n = s.recurse_nodes(nodes) + self.failUnless(n == n, + "recursive = 1 didn't return all nodes: %s" % n) + + def odd_only(nodes): + return [n for n in nodes if n % 2] + + s = SCons.Scanner.Classic("Test", [], None, "", function=self.func, recursive=odd_only) + n = s.recurse_nodes(nodes) + self.failUnless(n == [1, 3], + "recursive = 1 didn't return all nodes: %s" % n) + + class ClassicCPPTestCase(unittest.TestCase): diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index 81617a4..73e8c09 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -5,7 +5,7 @@ The Scanner package for the SCons software construction utility. """ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ The Scanner package for the SCons software construction utility. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/__init__.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import re @@ -62,8 +62,10 @@ def Scanner(function, *args, **kw): class FindPathDirs(object): - """A class to bind a specific *PATH variable name to a function that - will return all of the *path directories.""" + """ + A class to bind a specific E{*}PATH variable name to a function that + will return all of the E{*}path directories. + """ def __init__(self, variable): self.variable = variable def __call__(self, env, dir=None, target=None, source=None, argument=None): @@ -188,12 +190,12 @@ class Base(object): def path(self, env, dir=None, target=None, source=None): if not self.path_function: return () - if not self.argument is _null: + if self.argument is not _null: return self.path_function(env, dir, target, source, self.argument) else: return self.path_function(env, dir, target, source) - def __call__(self, node, env, path = ()): + def __call__(self, node, env, path=()): """ This method scans a single object. 'node' is the node that will be passed to the scanner function, and 'env' is the @@ -206,27 +208,27 @@ class Base(object): self = self.select(node) if not self.argument is _null: - list = self.function(node, env, path, self.argument) + node_list = self.function(node, env, path, self.argument) else: - list = self.function(node, env, path) + node_list = self.function(node, env, path) kw = {} if hasattr(node, 'dir'): kw['directory'] = node.dir node_factory = env.get_factory(self.node_factory) nodes = [] - for l in list: + for l in node_list: if self.node_class and not isinstance(l, self.node_class): l = node_factory(l, **kw) nodes.append(l) return nodes - def __cmp__(self, other): + def __eq__(self, other): try: - return cmp(self.__dict__, other.__dict__) + return self.__dict__ == other.__dict__ except AttributeError: # other probably doesn't have a __dict__ - return cmp(self.__dict__, other) + return self.__dict__ == other def __hash__(self): return id(self) @@ -259,7 +261,7 @@ class Base(object): def _recurse_no_nodes(self, nodes): return [] - recurse_nodes = _recurse_no_nodes + # recurse_nodes = _recurse_no_nodes def add_scanner(self, skey, scanner): self.function[skey] = scanner @@ -283,7 +285,7 @@ class Selector(Base): self.dict = dict self.skeys = list(dict.keys()) - def __call__(self, node, env, path = ()): + def __call__(self, node, env, path=()): return self.select(node)(node, env, path) def select(self, node): @@ -326,7 +328,7 @@ class Classic(Current): self.cre = re.compile(regex, re.M) - def _scan(node, env, path=(), self=self): + def _scan(node, _, path=(), self=self): node = node.rfile() if not node.exists(): return [] @@ -334,7 +336,12 @@ class Classic(Current): kw['function'] = _scan kw['path_function'] = FindPathDirs(path_variable) - kw['recursive'] = 1 + + # Allow recursive to propagate if child class specifies. + # In this case resource scanner needs to specify a filter on which files + # get recursively processed. Previously was hardcoded to 1 instead of + # defaulted to 1. + kw['recursive'] = kw.get('recursive', 1) kw['skeys'] = suffixes kw['name'] = name @@ -356,7 +363,7 @@ class Classic(Current): if node.includes is not None: includes = node.includes else: - includes = self.find_include_names (node) + includes = self.find_include_names(node) # Intern the names of the include files. Saves some memory # if the same header is included many times. node.includes = list(map(SCons.Util.silent_intern, includes)) @@ -393,6 +400,7 @@ class ClassicCPP(Classic): the contained filename in group 1. """ def find_include(self, include, source_dir, path): + include = list(map(SCons.Util.to_str, include)) if include[0] == '"': paths = (source_dir,) + tuple(path) else: diff --git a/src/engine/SCons/Scanner/__init__.xml b/src/engine/SCons/Scanner/__init__.xml index 6cd3950..db2d14b 100644 --- a/src/engine/SCons/Scanner/__init__.xml +++ b/src/engine/SCons/Scanner/__init__.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2016 The SCons Foundation +Copyright (c) 2001 - 2017 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. |