diff options
Diffstat (limited to 'third_party/scons/scons-local/SCons/Scanner')
9 files changed, 229 insertions, 44 deletions
diff --git a/third_party/scons/scons-local/SCons/Scanner/C.py b/third_party/scons/scons-local/SCons/Scanner/C.py index 08feafe..a097089 100644 --- a/third_party/scons/scons-local/SCons/Scanner/C.py +++ b/third_party/scons/scons-local/SCons/Scanner/C.py @@ -27,7 +27,7 @@ This module implements the depenency scanner for C/C++ code. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/C.py 3424 2008/09/15 11:22:20 scons" +__revision__ = "src/engine/SCons/Scanner/C.py 3603 2008/10/10 05:46:45 scons" import SCons.Node.FS import SCons.Scanner diff --git a/third_party/scons/scons-local/SCons/Scanner/D.py b/third_party/scons/scons-local/SCons/Scanner/D.py index 39a2e01..b997e30 100644 --- a/third_party/scons/scons-local/SCons/Scanner/D.py +++ b/third_party/scons/scons-local/SCons/Scanner/D.py @@ -30,7 +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 3424 2008/09/15 11:22:20 scons" +__revision__ = "src/engine/SCons/Scanner/D.py 3603 2008/10/10 05:46:45 scons" import re import string diff --git a/third_party/scons/scons-local/SCons/Scanner/Dir.py b/third_party/scons/scons-local/SCons/Scanner/Dir.py index 0f62803..dbb282a 100644 --- a/third_party/scons/scons-local/SCons/Scanner/Dir.py +++ b/third_party/scons/scons-local/SCons/Scanner/Dir.py @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/Dir.py 3424 2008/09/15 11:22:20 scons" +__revision__ = "src/engine/SCons/Scanner/Dir.py 3603 2008/10/10 05:46:45 scons" import SCons.Node.FS import SCons.Scanner diff --git a/third_party/scons/scons-local/SCons/Scanner/Fortran.py b/third_party/scons/scons-local/SCons/Scanner/Fortran.py index 406810f..3d963ca 100644 --- a/third_party/scons/scons-local/SCons/Scanner/Fortran.py +++ b/third_party/scons/scons-local/SCons/Scanner/Fortran.py @@ -27,7 +27,7 @@ This module implements the dependency scanner for Fortran code. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/Fortran.py 3424 2008/09/15 11:22:20 scons" +__revision__ = "src/engine/SCons/Scanner/Fortran.py 3603 2008/10/10 05:46:45 scons" import re import string diff --git a/third_party/scons/scons-local/SCons/Scanner/IDL.py b/third_party/scons/scons-local/SCons/Scanner/IDL.py index 3a3311f..e47a41f 100644 --- a/third_party/scons/scons-local/SCons/Scanner/IDL.py +++ b/third_party/scons/scons-local/SCons/Scanner/IDL.py @@ -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 3424 2008/09/15 11:22:20 scons" +__revision__ = "src/engine/SCons/Scanner/IDL.py 3603 2008/10/10 05:46:45 scons" import SCons.Node.FS import SCons.Scanner diff --git a/third_party/scons/scons-local/SCons/Scanner/LaTeX.py b/third_party/scons/scons-local/SCons/Scanner/LaTeX.py index 0542d05..fefeb14 100644 --- a/third_party/scons/scons-local/SCons/Scanner/LaTeX.py +++ b/third_party/scons/scons-local/SCons/Scanner/LaTeX.py @@ -27,23 +27,37 @@ 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 3424 2008/09/15 11:22:20 scons" +__revision__ = "src/engine/SCons/Scanner/LaTeX.py 3603 2008/10/10 05:46:45 scons" import os.path import string +import re import SCons.Scanner 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", suffixes = '$LATEXSUFFIXES', - path_variable = 'TEXINPUTS', - regex = '\\\\(include|includegraphics(?:\[[^\]]+\])?|input|bibliography|usepackage){([^}]*)}', + # in the search order, see below in LaTeX class docstring + graphics_extensions = ['.eps', '.ps'], + recursive = 0) + return ds + +def PDFLaTeXScanner(): + """Return a prototype Scanner instance for scanning LaTeX source files + when built with pdflatex. + """ + ds = LaTeX(name = "PDFLaTeXScanner", + suffixes = '$LATEXSUFFIXES', + # in the search order, see below in LaTeX class docstring + graphics_extensions = ['.pdf', '.png', '.jpg', '.gif', '.tif'], recursive = 0) return ds -class LaTeX(SCons.Scanner.Classic): +class LaTeX(SCons.Scanner.Base): """Class for scanning LaTeX files for included files. Unlike most scanners, which use regular expressions that just @@ -51,76 +65,198 @@ class LaTeX(SCons.Scanner.Classic): of the keyword for the inclusion ("include", "includegraphics", "input", or "bibliography"), and then the file name itself. Based on a quick look at LaTeX documentation, it seems that we - need a should append .tex suffix for the "include" keywords, - append .tex if there is no extension for the "input" keyword, - but leave the file name untouched for "includegraphics." For - the "bibliography" keyword we need to add .bib if there is - no extension. (This need to be revisited since if there - is no extension for an "includegraphics" keyword latex will - append .ps or .eps to find the file; while pdftex will use - other extensions.) + should append .tex suffix for the "include" keywords, append .tex if + there is no extension for the "input" keyword, and need to add .bib + for the "bibliography" keyword that does not accept extensions by itself. + + Finally, if there is no extension for an "includegraphics" keyword + latex will append .ps or .eps to find the file, while pdftex may use .pdf, + .jpg, .tif, .mps, or .png. + + The actual subset and search order may be altered by + DeclareGraphicsExtensions command. This complication is ignored. + 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']. + + Another difference is that the search path is determined by the type + of the file being searched: + env['TEXINPUTS'] for "input" and "include" keywords + env['TEXINPUTS'] for "includegraphics" keyword + env['BIBINPUTS'] for "bibliography" keyword + env['BSTINPUTS'] for "bibliographystyle" keyword + + FIXME: also look for the class or style in document[class|style]{} + FIXME: also look for the argument of bibliographystyle{} """ - def latex_name(self, include): + keyword_paths = {'include': 'TEXINPUTS', + 'input': 'TEXINPUTS', + 'includegraphics': 'TEXINPUTS', + 'bibliography': 'BIBINPUTS', + 'bibliographystyle': 'BSTINPUTS', + 'usepackage': 'TEXINPUTS'} + env_variables = SCons.Util.unique(keyword_paths.values()) + + def __init__(self, name, suffixes, graphics_extensions, *args, **kw): + + # We have to include \n with the % we exclude from the first part + # part of the regex because the expression is compiled with re.M. + # Without the \n, the ^ could match the beginning of a *previous* + # line followed by one or more newline characters (i.e. blank + # lines), interfering with a match on the next line. + regex = r'^[^%\n]*\\(include|includegraphics(?:\[[^\]]+\])?|input|bibliography|usepackage){([^}]*)}' + self.cre = re.compile(regex, re.M) + self.graphics_extensions = graphics_extensions + + def _scan(node, env, path=(), self=self): + node = node.rfile() + if not node.exists(): + return [] + return self.scan(node, path) + + class FindMultiPathDirs: + """The stock FindPathDirs function has the wrong granularity: + it is called once per target, while we need the path that depends + on what kind of included files is being searched. This wrapper + hides multiple instances of FindPathDirs, one per the LaTeX path + variable in the environment. When invoked, the function calculates + and returns all the required paths as a dictionary (converted into + a tuple to become hashable). Then the scan function converts it + back and uses a dictionary of tuples rather than a single tuple + of paths. + """ + def __init__(self, dictionary): + self.dictionary = {} + for k,n in dictionary.items(): + self.dictionary[k] = SCons.Scanner.FindPathDirs(n) + + def __call__(self, env, dir=None, target=None, source=None, + argument=None): + di = {} + for k,c in self.dictionary.items(): + di[k] = c(env, dir=None, target=None, source=None, + argument=None) + # To prevent "dict is not hashable error" + return tuple(di.items()) + + class LaTeXScanCheck: + """Skip all but LaTeX source files, i.e., do not scan *.eps, + *.pdf, *.jpg, etc. + """ + def __init__(self, suffixes): + self.suffixes = suffixes + def __call__(self, node, env): + current = not node.has_builder() or node.is_up_to_date() + scannable = node.get_suffix() in env.subst_list(self.suffixes)[0] + # Returning false means that the file is not scanned. + return scannable and current + + kw['function'] = _scan + kw['path_function'] = FindMultiPathDirs(LaTeX.keyword_paths) + kw['recursive'] = 1 + kw['skeys'] = suffixes + kw['scan_check'] = LaTeXScanCheck(suffixes) + kw['name'] = name + + apply(SCons.Scanner.Base.__init__, (self,) + args, kw) + + def _latex_names(self, include): filename = include[1] if include[0] == 'input': base, ext = os.path.splitext( filename ) if ext == "": - filename = filename + '.tex' + return [filename + '.tex'] if (include[0] == 'include'): - filename = filename + '.tex' + return [filename + '.tex'] if include[0] == 'bibliography': base, ext = os.path.splitext( filename ) if ext == "": - filename = filename + '.bib' + return [filename + '.bib'] if include[0] == 'usepackage': base, ext = os.path.splitext( filename ) if ext == "": - filename = filename + '.sty' - return filename + return [filename + '.sty'] + if include[0] == 'includegraphics': + base, ext = os.path.splitext( filename ) + if ext == "": + #TODO(1.5) return [filename + e for e in self.graphics_extensions] + return map(lambda e, f=filename: f+e, self.graphics_extensions) + return [filename] + def sort_key(self, include): - return SCons.Node.FS._my_normcase(self.latex_name(include)) + return SCons.Node.FS._my_normcase(str(include)) + def find_include(self, include, source_dir, path): - i = SCons.Node.FS.find_file(self.latex_name(include), - (source_dir,) + path) + try: + sub_path = path[include[0]] + except (IndexError, KeyError): + sub_path = () + try_names = self._latex_names(include) + for n in try_names: + i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path) + if i: + return i, include return i, include def scan(self, node, path=()): - # # 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. - # - # cache the includes list in node so we only scan it once: + + # Cache the includes list in node so we only scan it once: + path_dict = dict(list(path)) + noopt_cre = re.compile('\[.*$') if node.includes != None: includes = node.includes else: includes = self.cre.findall(node.get_contents()) + # 1. Split comma-separated lines, e.g. + # ('bibliography', 'phys,comp') + # should become two entries + # ('bibliography', 'phys') + # ('bibliography', 'comp') + # 2. Remove the options, e.g., such as + # ('includegraphics[clip,width=0.7\\linewidth]', 'picture.eps') + # should become + # ('includegraphics', 'picture.eps') + split_includes = [] + for include in includes: + inc_type = noopt_cre.sub('', include[0]) + inc_list = string.split(include[1],',') + for j in range(len(inc_list)): + split_includes.append( (inc_type, inc_list[j]) ) + # + includes = split_includes node.includes = includes # This is a hand-coded DSU (decorate-sort-undecorate, or # Schwartzian transform) pattern. The sort key is the raw name - # of the file as specifed on the #include line (including the - # " or <, since that may affect what file is found), which lets + # of the file as specifed on the \include, \input, etc. line. + # TODO: what about the comment in the original Classic scanner: + # """which lets # us keep the sort order constant regardless of whether the file - # is actually found in a Repository or locally. + # is actually found in a Repository or locally.""" nodes = [] source_dir = node.get_dir() for include in includes: # # Handle multiple filenames in include[1] # - inc_list = string.split(include[1],',') - for j in range(len(inc_list)): - include_local = [include[0],inc_list[j]] - n, i = self.find_include(include_local, source_dir, path) - + n, i = self.find_include(include, source_dir, path_dict) if n is None: - SCons.Warnings.warn(SCons.Warnings.DependencyWarning, - "No dependency generated for file: %s (included from: %s) -- file not found" % (i, node)) + # Do not bother with 'usepackage' warnings, as they most + # likely refer to system-level files + if include[0] != '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(include) + sortkey = self.sort_key(n) nodes.append((sortkey, n)) - + # nodes.sort() nodes = map(lambda pair: pair[1], nodes) return nodes diff --git a/third_party/scons/scons-local/SCons/Scanner/Prog.py b/third_party/scons/scons-local/SCons/Scanner/Prog.py index 4b5f2be..048266a 100644 --- a/third_party/scons/scons-local/SCons/Scanner/Prog.py +++ b/third_party/scons/scons-local/SCons/Scanner/Prog.py @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/Prog.py 3424 2008/09/15 11:22:20 scons" +__revision__ = "src/engine/SCons/Scanner/Prog.py 3603 2008/10/10 05:46:45 scons" import string diff --git a/third_party/scons/scons-local/SCons/Scanner/RC.py b/third_party/scons/scons-local/SCons/Scanner/RC.py new file mode 100644 index 0000000..051eb3d --- /dev/null +++ b/third_party/scons/scons-local/SCons/Scanner/RC.py @@ -0,0 +1,49 @@ +"""SCons.Scanner.RC + +This module implements the depenency scanner for RC (Interface +Definition Language) files. + +""" + +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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/RC.py 3603 2008/10/10 05:46:45 scons" + +import SCons.Node.FS +import SCons.Scanner +import re + +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]+)(?:[>" ])*$' + resScanner = SCons.Scanner.ClassicCPP( "ResourceScanner", + "$RCSUFFIXES", + "CPPPATH", + res_re ) + + return resScanner diff --git a/third_party/scons/scons-local/SCons/Scanner/__init__.py b/third_party/scons/scons-local/SCons/Scanner/__init__.py index fe6ce86..2df41c1 100644 --- a/third_party/scons/scons-local/SCons/Scanner/__init__.py +++ b/third_party/scons/scons-local/SCons/Scanner/__init__.py @@ -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 3424 2008/09/15 11:22:20 scons" +__revision__ = "src/engine/SCons/Scanner/__init__.py 3603 2008/10/10 05:46:45 scons" import re import string |