#
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#
#
#
# gen_base.py -- infrastructure for generating makefiles, dependencies, etc.
#

import collections
import os
import sys
import glob
import re
import fileinput
import filecmp
try:
  # Python >=3.0
  import configparser
except ImportError:
  # Python <3.0
  import ConfigParser as configparser
import generator.swig

import getversion


def _warning(msg):
  sys.stderr.write("WARNING: %s\n" % msg)

def _error(msg):
  sys.stderr.write("ERROR: %s\n" % msg)
  sys.exit(1)

class GeneratorBase:

  #
  # Derived classes should define a class attribute named _extension_map.
  # This attribute should be a dictionary of the form:
  #     { (target-type, file-type): file-extension ...}
  #
  # where: target-type is 'exe', 'lib', ...
  #        file-type is 'target', 'object', ...
  #

  def __init__(self, fname, verfname, options=None):
    # Retrieve major version from the C header, to avoid duplicating it in
    # build.conf - it is required because some file names include it.
    try:
      vsn_parser = getversion.Parser()
      vsn_parser.search('SVN_VER_MAJOR', 'libver')
      self.version = vsn_parser.parse(verfname).libver
    except:
      raise GenError('Unable to extract version.')

    # Read options
    self.release_mode = None
    for opt, val in options:
      if opt == '--release':
        self.release_mode = 1

    # Now read and parse build.conf
    parser = configparser.ConfigParser()
    parser.readfp(open(fname))

    self.conf = build_path(os.path.abspath(fname))

    self.sections = { }
    self.graph = DependencyGraph()

    # Allow derived classes to suppress certain configuration sections
    if not hasattr(self, 'skip_sections'):
      self.skip_sections = { }

    # The 'options' section does not represent a build target,
    # it simply contains global options
    self.skip_sections['options'] = None

    # Read in the global options
    self.includes = \
        _collect_paths(parser.get('options', 'includes'))
    self.private_includes = \
        _collect_paths(parser.get('options', 'private-includes'))
    self.private_built_includes = \
        parser.get('options', 'private-built-includes').split()
    self.scripts = \
        _collect_paths(parser.get('options', 'test-scripts'))
    self.bdb_scripts = \
        _collect_paths(parser.get('options', 'bdb-test-scripts'))

    self.include_wildcards = \
      parser.get('options', 'include-wildcards').split()
    self.swig_lang = parser.get('options', 'swig-languages').split()
    self.swig_dirs = parser.get('options', 'swig-dirs').split()

    # SWIG Generator
    self.swig = generator.swig.Generator(self.conf, "swig")

    # Visual C++ projects - contents are either TargetProject instances,
    # or other targets with an external-project attribute.
    self.projects = []

    # Lists of pathnames of various kinds
    self.test_deps = []      # Non-BDB dependent items to build for the tests
    self.test_progs = []     # Subset of the above to actually execute
    self.test_helpers = []   # $ {test_deps} \setminus {test_progs} $
    self.bdb_test_deps = []  # BDB-dependent items to build for the tests
    self.bdb_test_progs = [] # Subset of the above to actually execute
    self.target_dirs = []    # Directories in which files are built
    self.manpages = []       # Manpages

    # Collect the build targets and have a reproducible ordering
    parser_sections = sorted(parser.sections())
    for section_name in parser_sections:
      if section_name in self.skip_sections:
        continue

      options = {}
      for option in parser.options(section_name):
        options[option] = parser.get(section_name, option)

      type = options.get('type')

      target_class = _build_types.get(type)
      if not target_class:
        raise GenError('ERROR: unknown build type for ' + section_name)

      section = target_class.Section(target_class, section_name, options, self)

      self.sections[section_name] = section

      section.create_targets()

    # Compute intra-library dependencies
    for section in self.sections.values():
      dependencies = (( DT_LINK,   section.options.get('libs',    "") ),
                      ( DT_NONLIB, section.options.get('nonlibs', "") ))

      for dep_type, dep_names in dependencies:
        # Translate string names to Section objects
        dep_section_objects = []
        for section_name in dep_names.split():
          if section_name in self.sections:
            dep_section_objects.append(self.sections[section_name])

        # For each dep_section that this section declares a dependency on,
        # take the targets of this section, and register a dependency on
        # any 'matching' targets of the dep_section.
        #
        # At the moment, the concept of multiple targets per section is
        # employed only for the SWIG modules, which have 1 target
        # per language. Then, 'matching' means being of the same language.
        for dep_section in dep_section_objects:
          for target in section.get_targets():
            self.graph.bulk_add(dep_type, target.name,
                                dep_section.get_dep_targets(target))

  def compute_hdrs(self):
    """Get a list of the header files"""
    all_includes = list(map(native_path, self.includes + self.private_includes))
    for d in unique(self.target_dirs):
      for wildcard in self.include_wildcards:
        hdrs = glob.glob(os.path.join(native_path(d), wildcard))
        all_includes.extend(hdrs)
    return all_includes

  def compute_hdr_deps(self):
    """Compute the dependencies of each header file"""

    include_deps = IncludeDependencyInfo(self.compute_hdrs(),
        list(map(native_path, self.private_built_includes)))

    for objectfile, sources in self.graph.get_deps(DT_OBJECT):
      assert len(sources) == 1
      source = sources[0]

      # Generated .c files must depend on all headers their parent .i file
      # includes
      if isinstance(objectfile, SWIGObject):
        swigsources = self.graph.get_sources(DT_SWIG_C, source)
        assert len(swigsources) == 1
        ifile = swigsources[0]
        assert isinstance(ifile, SWIGSource)

        c_includes, swig_includes = \
            include_deps.query_swig(native_path(ifile.filename))
        for include_file in c_includes:
          self.graph.add(DT_OBJECT, objectfile, build_path(include_file))
        for include_file in swig_includes:
          self.graph.add(DT_SWIG_C, source, build_path(include_file))

      # Any non-swig C/C++ object must depend on the headers its parent
      # .c or .cpp includes. Note that 'object' includes gettext .mo files,
      # Java .class files, and .h files generated from Java classes, so
      # we must filter here.
      elif isinstance(source, SourceFile) and \
          os.path.splitext(source.filename)[1] in ('.c', '.cpp'):
        for include_file in include_deps.query(native_path(source.filename)):
          self.graph.add(DT_OBJECT, objectfile, build_path(include_file))

  def write_sqlite_headers(self):
    "Transform sql files into header files"

    import transform_sql
    for hdrfile, sqlfile in self.graph.get_deps(DT_SQLHDR):
      new_hdrfile = hdrfile + ".new"
      new_file = open(new_hdrfile, 'w')
      transform_sql.main(sqlfile[0], new_file)
      new_file.close()

      def identical(file1, file2):
        try:
          if filecmp.cmp(new_hdrfile, hdrfile):
            return True
          else:
            return False
        except:
          return False

      if identical(new_hdrfile, hdrfile):
        os.remove(new_hdrfile)
      else:
        try:
          os.remove(hdrfile)
        except: pass
        os.rename(new_hdrfile, hdrfile)

  def write_file_if_changed(self, fname, new_contents):
    """Rewrite the file if NEW_CONTENTS are different than its current content.

    If you have your windows projects open and generate the projects
    it's not a small thing for windows to re-read all projects so
    only update those that have changed.

    Under Python >=3, NEW_CONTENTS must be a 'str', not a 'bytes'.
    """
    if sys.version_info[0] >= 3:
      new_contents = new_contents.encode()

    try:
      old_contents = open(fname, 'rb').read()
    except IOError:
      old_contents = None
    if old_contents != new_contents:
      open(fname, 'wb').write(new_contents)
      print("Wrote: %s" % fname)


  def write_errno_table(self):
    # ### We generate errorcode.inc at autogen.sh time (here!).
    # ###
    # ### Currently it's only used by maintainer-mode builds.  If this
    # ### functionality ever moves to release builds, it will have to move
    # ### to configure-time (but remember that Python cannot be assumed to
    # ### be available from 'configure').
    import errno

    lines = [
        '/* This file was generated by build/generator/gen_base.py */',
        ''
    ]

    def write_struct(name, codes):
      lines.extend([
          'static struct {',
          '  int errcode;',
          '  const char *errname;',
          '} %s[] = {' % (name,),
        ])

      for num, val in sorted(codes):
        lines.extend([
            '  { %d, "%s" },' % (num, val),
          ])

       # Remove ',' for c89 compatibility
      lines[-1] = lines[-1][0:-1]

      lines.extend([
          '};',
          '',
        ])

    write_struct('svn__errno', errno.errorcode.items())

    # Fetch and write apr_errno.h codes.
    aprerr = []
    for line in open(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])),
                                  'tools', 'dev', 'aprerr.txt')):
      # aprerr.txt parsing duplicated in which-error.py
      if line.startswith('#'):
         continue
      key, _, val = line.split()
      aprerr += [(int(val), key)]
    write_struct('svn__apr_errno', aprerr)
    aprdict = dict(aprerr)
    del aprerr

    ## sanity check
    intersection = set(errno.errorcode.keys()) & set(aprdict.keys())
    intersection = filter(lambda x: errno.errorcode[x] != aprdict[x],
                          intersection)
    if self.errno_filter(intersection):
        print("WARNING: errno intersects APR error codes; "
              "runtime computation of symbolic error names for the following numeric codes might be wrong: "
              "%r" % (intersection,))

    self.write_file_if_changed('subversion/libsvn_subr/errorcode.inc',
                               '\n'.join(lines))

  def errno_filter(self, codes):
    return codes

  class FileSectionOptionEnum(object):
    # These are accessed via getattr() later on
    file = object()
    section = object()
    option = object()

  def _client_configuration_defines(self):
    """Return an iterator over SVN_CONFIG_* #define's in the "Client
    configuration files strings" section of svn_config.h."""

    pattern = re.compile(
      r'^\s*#\s*define\s+'
      r'(?P<macro>SVN_CONFIG_(?P<kind>CATEGORY|SECTION|OPTION)_[A-Z0-9a-z_]+)'
    )
    kind = {
      'CATEGORY': self.FileSectionOptionEnum.file,
      'SECTION': self.FileSectionOptionEnum.section,
      'OPTION': self.FileSectionOptionEnum.option,
    }

    fname = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])),
                         'subversion', 'include', 'svn_config.h')
    lines = iter(open(fname))
    for line in lines:
      if "@name Client configuration files strings" in line:
        break
    else:
      raise Exception("Unable to parse svn_config.h")

    for line in lines:
      if "@{" in line:
        break
    else:
      raise Exception("Unable to parse svn_config.h")

    for line in lines:
      if "@}" in line:
        break
      match = pattern.match(line)
      if match:
        yield (
          match.group('macro'),
          kind[match.group('kind')],
        )
    else:
      raise Exception("Unable to parse svn_config.h")

  def write_config_keys(self):
    groupby = collections.defaultdict(list)
    empty_sections = []
    previous = (None, None)
    for macro, kind in self._client_configuration_defines():
      if kind is previous[1] is self.FileSectionOptionEnum.section:
        empty_sections.append(previous[0])
      groupby[kind].append(macro)
      previous = (macro, kind)
    else:
      # If the last (macro, kind) is a section, then it's an empty section.
      if kind is self.FileSectionOptionEnum.section:
        empty_sections.append(macro)

    lines = []
    lines.append('/* Automatically generated by %s:write_config_keys() */'
                 % (__file__,))
    lines.append('')

    for kind in ('file', 'section', 'option'):
      macros = groupby[getattr(self.FileSectionOptionEnum, kind)]
      lines.append('static const char *svn__valid_config_%ss[] = {' % (kind,))
      for macro in macros:
        lines.append('  %s,' % (macro,))
      # Remove ',' for c89 compatibility
      lines[-1] = lines[-1][0:-1]
      lines.append('};')
      lines.append('')

    lines.append('static const char *svn__empty_config_sections[] = {');
    for section in empty_sections:
      lines.append('  %s,' % (section,))
    # Remove ',' for c89 compatibility
    lines[-1] = lines[-1][0:-1]
    lines.append('};')
    lines.append('')

    self.write_file_if_changed('subversion/libsvn_subr/config_keys.inc',
                               '\n'.join(lines))

class DependencyGraph:
  """Record dependencies between build items.

  See the DT_* values for the different dependency types. For each type,
  the target and source objects recorded will be different. They could
  be file names, Target objects, install types, etc.
  """

  def __init__(self):
    self.deps = { }     # type -> { target -> [ source ... ] }
    for dt in dep_types:
      self.deps[dt] = { }

  def add(self, type, target, source):
    if target in self.deps[type]:
      self.deps[type][target].append(source)
    else:
      self.deps[type][target] = [ source ]

  def remove(self, type, target, source):
    if target in self.deps[type] and source in self.deps[type][target]:
      self.deps[type][target].remove(source)

  def bulk_add(self, type, target, sources):
    if target in self.deps[type]:
      self.deps[type][target].extend(sources)
    else:
      self.deps[type][target] = sources[:]

  def get_sources(self, type, target, cls=None):
    sources = self.deps[type].get(target, [ ])
    if not cls:
      return sources
    filtered = [ ]
    for src in sources:
      if isinstance(src, cls):
        filtered.append(src)
    return filtered

  def get_all_sources(self, type):
    sources = [ ]
    for group in self.deps[type].values():
      sources.extend(group)
    return sources

  def get_deps(self, type):
    return list(self.deps[type].items())

# dependency types
dep_types = [
  'DT_INSTALL',  # install areas. e.g. 'lib', 'base-lib'
  'DT_OBJECT',   # an object filename, depending upon .c filenames
  'DT_SWIG_C',   # a swig-generated .c file, depending upon .i filename(s)
  'DT_LINK',     # a libtool-linked filename, depending upon object fnames
  'DT_NONLIB',   # filename depends on object fnames, but isn't linked to them
  'DT_SQLHDR',   # header generated from a .sql file
  ]

# create some variables for these
for _dt in dep_types:
  # e.g. DT_INSTALL = 'DT_INSTALL'
  globals()[_dt] = _dt

class DependencyNode:
  def __init__(self, filename, when = None):
    self.filename = filename
    self.when = when

  def __str__(self):
    return self.filename

class ObjectFile(DependencyNode):
  def __init__(self, filename, compile_cmd = None, when = None):
    DependencyNode.__init__(self, filename, when)
    self.compile_cmd = compile_cmd
    self.source_generated = 0

class SWIGObject(ObjectFile):
  def __init__(self, filename, lang, release_mode):
    ObjectFile.__init__(self, filename)
    self.lang = lang
    self.lang_abbrev = lang_abbrev[lang]
    # in release mode the sources are not generated by the build
    # but rather by the packager
    if release_mode:
      self.source_generated = 0
    else:
      self.source_generated = 1
    ### hmm. this is Makefile-specific
    self.compile_cmd = '$(COMPILE_%s_WRAPPER)' % self.lang_abbrev.upper()

class HeaderFile(DependencyNode):
  def __init__(self, filename, classname = None, compile_cmd = None):
    DependencyNode.__init__(self, filename)
    self.classname = classname
    self.compile_cmd = compile_cmd

class SourceFile(DependencyNode):
  def __init__(self, filename, reldir):
    DependencyNode.__init__(self, filename)
    self.reldir = reldir

class SWIGSource(SourceFile):
  def __init__(self, filename):
    SourceFile.__init__(self, filename, build_path_dirname(filename))


lang_abbrev = {
  'python' : 'py',
  'perl' : 'pl',
  'ruby' : 'rb',
  }

lang_full_name = {
  'python' : 'Python',
  'perl' : 'Perl',
  'ruby' : 'Ruby',
  }

lang_utillib_suffix = {
  'python' : 'py',
  'perl' : 'perl',
  'ruby' : 'ruby',
  }

class Target(DependencyNode):
  "A build target is a node in our dependency graph."

  def __init__(self, name, options, gen_obj):
    self.name = name
    self.gen_obj = gen_obj
    self.desc = options.get('description')
    self.when = options.get('when')
    self.path = options.get('path', '')
    self.add_deps = options.get('add-deps', '')
    self.add_install_deps = options.get('add-install-deps', '')
    self.msvc_name = options.get('msvc-name') # override project name

  def add_dependencies(self):
    # subclasses should override to provide behavior, as appropriate
    raise NotImplementedError

  class Section:
    """Represents an individual section of build.conf

    The Section class is sort of a factory class which is responsible for
    creating and keeping track of Target instances associated with a section
    of the configuration file. By default it only allows one Target per
    section, but subclasses may create multiple Targets.
    """

    def __init__(self, target_class, name, options, gen_obj):
      self.target_class = target_class
      self.name = name
      self.options = options
      self.gen_obj = gen_obj

    def create_targets(self):
      """Create target instances"""
      self.target = self.target_class(self.name, self.options, self.gen_obj)
      self.target.add_dependencies()

    def get_targets(self):
      """Return list of target instances associated with this section"""
      return [self.target]

    def get_dep_targets(self, target):
      """Return list of targets from this section that "target" depends on"""
      return [self.target]

class TargetLinked(Target):
  "The target is linked (by libtool) against other libraries."

  def __init__(self, name, options, gen_obj):
    Target.__init__(self, name, options, gen_obj)
    self.install = options.get('install')
    self.compile_cmd = options.get('compile-cmd')
    self.sources = options.get('sources', '*.c *.cpp')
    self.link_cmd = options.get('link-cmd', '$(LINK)')

    self.external_lib = options.get('external-lib')
    self.external_project = options.get('external-project')
    self.msvc_libs = options.get('msvc-libs', '').split()
    self.msvc_delayload_targets = []

  def add_dependencies(self):
    if self.external_lib or self.external_project:
      if self.external_project:
        self.gen_obj.projects.append(self)
      return

    # the specified install area depends upon this target
    self.gen_obj.graph.add(DT_INSTALL, self.install, self)

    sources = sorted(_collect_paths(self.sources, self.path))

    for src, reldir in sources:
        if glob.glob(src):
          if src[-2:] == '.c':
            objname = src[:-2] + self.objext
          elif src[-3:] == '.cc':
            objname = src[:-3] + self.objext
          elif src[-4:] == '.cpp':
            objname = src[:-4] + self.objext
          else:
            raise GenError('ERROR: unknown file extension on ' + src)

          ofile = ObjectFile(objname, self.compile_cmd, self.when)

          # object depends upon source
          self.gen_obj.graph.add(DT_OBJECT, ofile, SourceFile(src, reldir))

          # target (a linked item) depends upon object
          self.gen_obj.graph.add(DT_LINK, self.name, ofile)

    # collect all the paths where stuff might get built
    ### we should collect this from the dependency nodes rather than
    ### the sources. "what dir are you going to put yourself into?"
    self.gen_obj.target_dirs.append(self.path)
    for pattern in self.sources.split():
      dirname = build_path_dirname(pattern)
      if dirname:
        self.gen_obj.target_dirs.append(build_path_join(self.path, dirname))

class TargetExe(TargetLinked):
  def __init__(self, name, options, gen_obj):
    TargetLinked.__init__(self, name, options, gen_obj)

    if not (self.external_lib or self.external_project):
      extmap = self.gen_obj._extension_map
      self.objext = extmap['exe', 'object']
      self.filename = build_path_join(self.path, name + extmap['exe', 'target'])

    self.manpages = options.get('manpages', '')
    self.testing = options.get('testing')

    self.msvc_force_static = options.get('msvc-force-static') == 'yes'

  def add_dependencies(self):
    TargetLinked.add_dependencies(self)

    # collect test programs
    if 'svnauthz' in self.name: # special case
      self.gen_obj.test_deps.append(self.filename)
      self.gen_obj.test_helpers.append(self.filename)
    elif self.install == 'test':
      self.gen_obj.test_deps.append(self.filename)
      if self.testing != 'skip':
        self.gen_obj.test_progs.append(self.filename)
      else:
        self.gen_obj.test_helpers.append(self.filename)
    elif self.install == 'bdb-test':
      self.gen_obj.bdb_test_deps.append(self.filename)
      if self.testing != 'skip':
        self.gen_obj.bdb_test_progs.append(self.filename)

    self.gen_obj.manpages.extend(self.manpages.split())

class TargetScript(Target):
  def add_dependencies(self):
    # we don't need to "compile" the sources, so there are no dependencies
    # to add here, except to get the script installed in the proper area.
    # note that the script might itself be generated, but that isn't a
    # concern here.
    self.gen_obj.graph.add(DT_INSTALL, self.install, self)

class TargetLib(TargetLinked):
  def __init__(self, name, options, gen_obj):
    TargetLinked.__init__(self, name, options, gen_obj)

    if not (self.external_lib or self.external_project):
      extmap = gen_obj._extension_map
      self.objext = extmap['lib', 'object']

      # the target file is the name, version, and appropriate extension
      tfile = '%s-%s%s' % (name, gen_obj.version, extmap['lib', 'target'])
      self.filename = build_path_join(self.path, tfile)

    # Is a library referencing symbols which are undefined at link time.
    self.undefined_lib_symbols = options.get('undefined-lib-symbols') == 'yes'

    self.link_cmd = options.get('link-cmd', '$(LINK_LIB)')

    self.msvc_static = options.get('msvc-static') == 'yes' # is a static lib
    self.msvc_delayload = options.get('msvc-delayload') == 'yes' # Delay dll load
    self.msvc_fake = options.get('msvc-fake') == 'yes' # has fake target
    self.msvc_export = options.get('msvc-export', '').split()

  def disable_shared(self):
    "tries to disable building as a shared library,"

    self.msvc_static = True

class TargetApacheMod(TargetLib):

  def __init__(self, name, options, gen_obj):
    TargetLib.__init__(self, name, options, gen_obj)

    tfile = name + self.gen_obj._extension_map['lib', 'target']
    self.filename = build_path_join(self.path, tfile)

    # we have a custom linking rule
    ### hmm. this is Makefile-specific
    self.compile_cmd = '$(COMPILE_APACHE_MOD)'
    self.link_cmd = '$(LINK_APACHE_MOD)'

class TargetRaModule(TargetLib):
  pass

class TargetFsModule(TargetLib):
  pass

class TargetDoc(Target):
  pass

class TargetI18N(Target):
  "The target is a collection of .po files to be compiled by msgfmt."

  def __init__(self, name, options, gen_obj):
    Target.__init__(self, name, options, gen_obj)
    self.install = options.get('install')
    self.sources = options.get('sources')
    # Let the Makefile determine this via .SUFFIXES
    self.compile_cmd = None
    self.objext = '.mo'
    self.external_project = options.get('external-project')

  def add_dependencies(self):
    self.gen_obj.graph.add(DT_INSTALL, self.install, self)

    sources = sorted(_collect_paths(self.sources or '*.po', self.path))

    for src, reldir in sources:
      if src[-3:] == '.po':
        objname = src[:-3] + self.objext
      else:
        raise GenError('ERROR: unknown file extension on ' + src)

      ofile = ObjectFile(objname, self.compile_cmd, self.when)

      # object depends upon source
      self.gen_obj.graph.add(DT_OBJECT, ofile, SourceFile(src, reldir))

      # target depends upon object
      self.gen_obj.graph.add(DT_LINK, self.name, ofile)

    # Add us to the list of target dirs, so we're created in mkdir-init.
    self.gen_obj.target_dirs.append(self.path)

class TargetSWIG(TargetLib):
  def __init__(self, name, options, gen_obj, lang):
    TargetLib.__init__(self, name, options, gen_obj)
    self.lang = lang
    self.desc = self.desc + ' for ' + lang_full_name[lang]

    ### hmm. this is Makefile-specific
    self.link_cmd = '$(LINK_%s_WRAPPER)' % lang_abbrev[lang].upper()

  def add_dependencies(self):
    # Look in source directory for dependencies
    self.gen_obj.target_dirs.append(self.path)

    sources = _collect_paths(self.sources, self.path)
    assert len(sources) == 1  ### simple assertions for now

    # get path to SWIG .i file
    ipath = sources[0][0]
    iname = build_path_basename(ipath)

    assert iname[-2:] == '.i'
    cname = iname[:-2] + '.c'
    oname = iname[:-2] + self.gen_obj._extension_map['pyd', 'object']

    # Extract SWIG module name from .i file name
    module_name = iname[:4] != 'svn_' and iname[:-2] or iname[4:-2]

    lib_extension = self.gen_obj._extension_map['lib', 'target']
    if self.lang == "python":
      lib_extension = self.gen_obj._extension_map['pyd', 'target']
      lib_filename = '_' + module_name + lib_extension
    elif self.lang == "ruby":
      lib_extension = self.gen_obj._extension_map['so', 'target']
      lib_filename = module_name + lib_extension
    elif self.lang == "perl":
      lib_filename = '_' + module_name.capitalize() + lib_extension
    else:
      lib_filename = module_name + lib_extension

    self.name = self.lang + '_' + module_name
    self.path = build_path_join(self.path, self.lang)
    if self.lang == "perl":
      self.path = build_path_join(self.path, "native")
    self.filename = build_path_join(self.path, lib_filename)

    ifile = SWIGSource(ipath)
    cfile = SWIGObject(build_path_join(self.path, cname), self.lang,
                       self.gen_obj.release_mode)
    ofile = SWIGObject(build_path_join(self.path, oname), self.lang,
                       self.gen_obj.release_mode)

    # the .c file depends upon the .i file
    self.gen_obj.graph.add(DT_SWIG_C, cfile, ifile)

    # the object depends upon the .c file
    self.gen_obj.graph.add(DT_OBJECT, ofile, cfile)

    # the library depends upon the object
    self.gen_obj.graph.add(DT_LINK, self.name, ofile)

    # the specified install area depends upon the library
    self.gen_obj.graph.add(DT_INSTALL, 'swig-' + lang_abbrev[self.lang], self)

  class Section(TargetLib.Section):
    def create_targets(self):
      self.targets = { }
      for lang in self.gen_obj.swig_lang:
        target = self.target_class(self.name, self.options, self.gen_obj, lang)
        target.add_dependencies()
        self.targets[lang] = target

    def get_targets(self):
      return list(self.targets.values())

    def get_dep_targets(self, target):
      target = self.targets.get(target.lang, None)
      return target and [target] or [ ]

class TargetSWIGLib(TargetLib):
  def __init__(self, name, options, gen_obj):
    TargetLib.__init__(self, name, options, gen_obj)
    self.lang = options.get('lang')

  class Section(TargetLib.Section):
    def get_dep_targets(self, target):
      if target.lang == self.target.lang:
        return [ self.target ]
      return [ ]

  def disable_shared(self):
    "disables building shared libraries"

    return # Explicit NO-OP


class TargetProject(Target):
  def __init__(self, name, options, gen_obj):
    Target.__init__(self, name, options, gen_obj)
    self.cmd = options.get('cmd')
    self.release = options.get('release')
    self.debug = options.get('debug')

  def add_dependencies(self):
    self.gen_obj.projects.append(self)

class TargetSWIGProject(TargetProject):
  def __init__(self, name, options, gen_obj):
    TargetProject.__init__(self, name, options, gen_obj)
    self.lang = options.get('lang')

class TargetJava(TargetLinked):
  def __init__(self, name, options, gen_obj):
    TargetLinked.__init__(self, name, options, gen_obj)
    self.link_cmd = options.get('link-cmd')
    self.packages = options.get('package-roots', '').split()
    self.jar = options.get('jar')
    self.deps = [ ]

class TargetJavaHeaders(TargetJava):
  def __init__(self, name, options, gen_obj):
    TargetJava.__init__(self, name, options, gen_obj)
    self.objext = '.class'
    self.javah_objext = '.h'
    self.headers = options.get('headers')
    self.classes = options.get('classes')
    self.package = options.get('package')
    self.output_dir = self.headers

  def add_dependencies(self):
    sources = _collect_paths(self.sources, self.path)

    for src, reldir in sources:
      if src[-5:] != '.java':
        raise GenError('ERROR: unknown file extension on ' + src)

      class_name = build_path_basename(src[:-5])

      class_header = build_path_join(self.headers, class_name + '.h')
      class_header_win = build_path_join(self.headers,
                                         self.package.replace(".", "_")
                                         + "_" + class_name + '.h')
      class_pkg_list = self.package.split('.')
      class_pkg = build_path_join(*class_pkg_list)
      class_file = ObjectFile(build_path_join(self.classes, class_pkg,
                                              class_name + self.objext),
                              self.when)
      class_file.source_generated = 1
      class_file.class_name = class_name
      hfile = HeaderFile(class_header, self.package + '.' + class_name,
                         self.compile_cmd)
      hfile.filename_win = class_header_win
      hfile.source_generated = 1
      self.gen_obj.graph.add(DT_OBJECT, hfile, class_file)
      self.deps.append(hfile)

      # target (a linked item) depends upon object
      self.gen_obj.graph.add(DT_LINK, self.name, hfile)


    # collect all the paths where stuff might get built
    ### we should collect this from the dependency nodes rather than
    ### the sources. "what dir are you going to put yourself into?"
    self.gen_obj.target_dirs.append(self.path)
    self.gen_obj.target_dirs.append(self.classes)
    self.gen_obj.target_dirs.append(self.headers)
    for pattern in self.sources.split():
      dirname = build_path_dirname(pattern)
      if dirname:
        self.gen_obj.target_dirs.append(build_path_join(self.path, dirname))

    self.gen_obj.graph.add(DT_INSTALL, self.name, self)

class TargetJavaClasses(TargetJava):
  def __init__(self, name, options, gen_obj):
    TargetJava.__init__(self, name, options, gen_obj)
    self.objext = '.class'
    self.lang = 'java'
    self.classes = options.get('classes')
    self.output_dir = self.classes

  def add_dependencies(self):
    sources = []
    for p in self.path.split():
      sources.extend(_collect_paths(self.sources, p))

    for src, reldir in sources:
      if src[-5:] == '.java':
        objname = src[:-5] + self.objext

        # As .class files are likely not generated into the same
        # directory as the source files, the object path may need
        # adjustment.  To this effect, take "target_ob.classes" into
        # account.
        dirs = build_path_split(objname)
        sourcedirs = dirs[:-1]  # Last element is the .class file name.
        while sourcedirs:
          if sourcedirs.pop() in self.packages:
            sourcepath = build_path_join(*sourcedirs)
            objname = build_path_join(self.classes, *dirs[len(sourcedirs):])
            break
        else:
          raise GenError('Unable to find Java package root in path "%s"' % objname)
      else:
        raise GenError('ERROR: unknown file extension on "' + src + '"')

      ofile = ObjectFile(objname, self.compile_cmd, self.when)
      sfile = SourceFile(src, reldir)
      sfile.sourcepath = sourcepath

      # object depends upon source
      self.gen_obj.graph.add(DT_OBJECT, ofile, sfile)

      # target (a linked item) depends upon object
      self.gen_obj.graph.add(DT_LINK, self.name, ofile)

      # Add the class file to the dependency tree for this target
      self.deps.append(ofile)

    # collect all the paths where stuff might get built
    ### we should collect this from the dependency nodes rather than
    ### the sources. "what dir are you going to put yourself into?"
    self.gen_obj.target_dirs.extend(self.path.split())
    self.gen_obj.target_dirs.append(self.classes)
    for pattern in self.sources.split():
      dirname = build_path_dirname(pattern)
      if dirname:
        self.gen_obj.target_dirs.append(build_path_join(self.path, dirname))

    self.gen_obj.graph.add(DT_INSTALL, self.name, self)

class TargetSQLHeader(Target):
  def __init__(self, name, options, gen_obj):
    Target.__init__(self, name, options, gen_obj)
    self.sources = options.get('sources')

  _re_sql_include = re.compile('-- *include: *([-a-z]+)')
  def add_dependencies(self):

    sources = _collect_paths(self.sources, self.path)
    assert len(sources) == 1  # support for just one source, for now

    source, reldir = sources[0]
    assert reldir == ''  # no support for reldir right now
    assert source.endswith('.sql')

    output = source[:-4] + '.h'

    self.gen_obj.graph.add(DT_SQLHDR, output, source)

    for line in fileinput.input(source):
      match = self._re_sql_include.match(line)
      if not match:
        continue
      file = match.group(1)
      self.gen_obj.graph.add(DT_SQLHDR, output,
                             os.path.join(os.path.dirname(source), file + '.sql'))

_build_types = {
  'exe' : TargetExe,
  'script' : TargetScript,
  'lib' : TargetLib,
  'doc' : TargetDoc,
  'swig' : TargetSWIG,
  'project' : TargetProject,
  'swig_lib' : TargetSWIGLib,
  'swig_project' : TargetSWIGProject,
  'ra-module': TargetRaModule,
  'fs-module': TargetFsModule,
  'apache-mod': TargetApacheMod,
  'javah' : TargetJavaHeaders,
  'java' : TargetJavaClasses,
  'i18n' : TargetI18N,
  'sql-header' : TargetSQLHeader,
  }


class GenError(Exception):
  pass


# Path Handling Functions
#
# Build paths specified in build.conf are assumed to be always separated
# by forward slashes, regardless of the current running os.
#
# Native paths are paths separated by os.sep.

def native_path(path):
  """Convert a build path to a native path"""
  return path.replace('/', os.sep)

def build_path(path):
  """Convert a native path to a build path"""
  path = path.replace(os.sep, '/')
  if os.altsep:
    path = path.replace(os.altsep, '/')
  return path

def build_path_join(*path_parts):
  """Join path components into a build path"""
  return '/'.join(path_parts)

def build_path_split(path):
  """Return list of components in a build path"""
  return path.split('/')

def build_path_splitfile(path):
  """Return the filename and directory portions of a file path"""
  pos = path.rfind('/')
  if pos > 0:
    return path[:pos], path[pos+1:]
  elif pos == 0:
    return path[0], path[1:]
  else:
    return "", path

def build_path_dirname(path):
  """Return the directory portion of a file path"""
  return build_path_splitfile(path)[0]

def build_path_basename(path):
  """Return the filename portion of a file path"""
  return build_path_splitfile(path)[1]

def build_path_retreat(path):
  "Given a relative directory, return ../ paths to retreat to the origin."
  return ".." + "/.." * path.count('/')

def build_path_strip(path, files):
  "Strip the given path from each file."
  l = len(path)
  result = [ ]
  for file in files:
    if len(file) > l and file[:l] == path and file[l] == '/':
      result.append(file[l+1:])
    else:
      result.append(file)
  return result

def _collect_paths(pats, path=None):
  """Find files matching a space separated list of globs

  pats (string) is the list of glob patterns

  path (string), if specified, is a path that will be prepended to each
    glob pattern before it is evaluated

  If path is None the return value is a list of filenames, otherwise
  the return value is a list of 2-tuples. The first element in each tuple
  is a matching filename and the second element is the portion of the
  glob pattern which matched the file before its last forward slash (/)

  If no files are found matching a pattern, then include the pattern itself
  as a filename in the results.
  """
  result = [ ]
  for base_pat in pats.split():
    if path:
      pattern = build_path_join(path, base_pat)
    else:
      pattern = base_pat
    files = sorted(glob.glob(native_path(pattern))) or [pattern]

    if path is None:
      # just append the names to the result list
      for file in files:
        result.append(build_path(file))
    else:
      # if we have paths, then we need to record how each source is located
      # relative to the specified path
      reldir = build_path_dirname(base_pat)
      for file in files:
        result.append((build_path(file), reldir))

  return result

_re_public_include = re.compile(r'^subversion/include/(\w+)\.h$')
def _is_public_include(fname):
  return _re_public_include.match(build_path(fname))

def _swig_include_wrapper(fname):
  return native_path(_re_public_include.sub(
    r"subversion/bindings/swig/proxy/\1_h.swg", build_path(fname)))

def _path_endswith(path, subpath):
  """Check if SUBPATH is a true path suffix of PATH.
  """
  path_len = len(path)
  subpath_len = len(subpath)

  return (subpath_len > 0 and path_len >= subpath_len
          and path[-subpath_len:] == subpath
          and (path_len == subpath_len
               or (subpath[0] == os.sep and path[-subpath_len] == os.sep)
               or path[-subpath_len - 1] == os.sep))

class IncludeDependencyInfo:
  """Finds all dependencies between a named set of headers, and computes
  closure, so that individual C and SWIG source files can then be scanned, and
  the stored dependency data used to return all directly and indirectly
  referenced headers.

  Note that where SWIG is concerned, there are two different kinds of include:
  (1) those that include files in SWIG processing, and so matter to the
      generation of .c files. (These are %include, %import).
  (2) those that include references to C headers in the generated output,
      and so are not required at .c generation, only at .o generation.
      (These are %{ #include ... %}).

  This class works exclusively in native-style paths."""

  def __init__(self, filenames, fnames_nonexist):
    """Operation of an IncludeDependencyInfo instance is restricted to a
    'domain' - a set of header files which are considered interesting when
    following and reporting dependencies.  This is done to avoid creating any
    dependencies on system header files.  The domain is defined by three
    factors:
    (1) FILENAMES is a list of headers which are in the domain, and should be
        scanned to discover how they inter-relate.
    (2) FNAMES_NONEXIST is a list of headers which are in the domain, but will
        be created by the build process, and so are not available to be
        scanned - they will be assumed not to depend on any other interesting
        headers.
    (3) Files in subversion/bindings/swig/proxy/, which are based
        autogenerated based on files in subversion/include/, will be added to
        the domain when a file in subversion/include/ is processed, and
        dependencies will be deduced by special-case logic.
    """

    # This defines the domain (i.e. set of files) in which dependencies are
    # being located. Its structure is:
    # { 'basename.h': [ 'path/to/something/named/basename.h',
    #                   'path/to/another/named/basename.h', ] }
    self._domain = {}
    for fname in filenames + fnames_nonexist:
      bname = os.path.basename(fname)
      self._domain.setdefault(bname, []).append(fname)
      if _is_public_include(fname):
        swig_fname = _swig_include_wrapper(fname)
        swig_bname = os.path.basename(swig_fname)
        self._domain.setdefault(swig_bname, []).append(swig_fname)

    # This data structure is:
    # { 'full/path/to/header.h': { 'full/path/to/dependency.h': TYPECODE, } }
    # TYPECODE is '#', denoting a C include, or '%' denoting a SWIG include.
    self._deps = {}
    for fname in filenames:
      self._deps[fname] = self._scan_for_includes(fname)
      if _is_public_include(fname):
        hdrs = { self._domain["proxy.swg"][0]: '%',
                 self._domain["apr.swg"][0]: '%',
                 fname: '%' }
        for h in self._deps[fname].keys():
          if (_is_public_include(h)
              or h == os.path.join('subversion', 'include', 'private',
                                    'svn_debug.h')):
            hdrs[_swig_include_wrapper(h)] = '%'
          else:
            raise RuntimeError("Public include '%s' depends on '%s', " \
                "which is not a public include! What's going on?" % (fname, h))
        swig_fname = _swig_include_wrapper(fname)
        swig_bname = os.path.basename(swig_fname)
        self._deps[swig_fname] = hdrs
    for fname in fnames_nonexist:
      self._deps[fname] = {}

    # Keep recomputing closures until we see no more changes
    while True:
      changes = 0
      for fname in self._deps.keys():
        changes = self._include_closure(self._deps[fname]) or changes
      if not changes:
        break

  def query_swig(self, fname):
    """Scan the C or SWIG file FNAME, and return the full paths of each
    include file that is a direct or indirect dependency, as a 2-tuple:
      (C_INCLUDES, SWIG_INCLUDES)."""
    if fname in self._deps:
      hdrs = self._deps[fname]
    else:
      hdrs = self._scan_for_includes(fname)
      self._include_closure(hdrs)
    c_filenames = []
    swig_filenames = []
    for hdr, hdr_type in hdrs.items():
      if hdr_type == '#':
        c_filenames.append(hdr)
      else: # hdr_type == '%'
        swig_filenames.append(hdr)
    # Be independent of hash ordering
    c_filenames.sort()
    swig_filenames.sort()
    return (c_filenames, swig_filenames)

  def query(self, fname):
    """Same as SELF.QUERY_SWIG(FNAME), but assert that there are no SWIG
    includes, and return only C includes as a single list."""
    c_includes, swig_includes = self.query_swig(fname)
    assert len(swig_includes) == 0
    return c_includes

  def _include_closure(self, hdrs):
    """Mutate the passed dictionary HDRS, by performing a single pass
    through the listed headers, adding the headers on which the first group
    of headers depend, if not already present.

    HDRS is of the form { 'path/to/header.h': TYPECODE, }

    Return a boolean indicating whether any changes were made."""
    items = list(hdrs.items())
    for this_hdr, this_type in items:
      for dependency_hdr, dependency_type in self._deps[this_hdr].items():
        self._upd_dep_hash(hdrs, dependency_hdr, dependency_type)
    return (len(items) != len(hdrs))

  def _upd_dep_hash(self, hash, hdr, type):
    """Mutate HASH (a data structure of the form
    { 'path/to/header.h': TYPECODE, } ) to include additional info of a
    dependency of type TYPE on the file HDR."""
    # '%' (SWIG, .c: .i) has precedence over '#' (C, .o: .c)
    if hash.get(hdr) != '%':
      hash[hdr] = type

  _re_include = \
      re.compile(r'^\s*([#%])\s*(?:include|import)\s*([<"])?([^<">;\s]+)')
  def _scan_for_includes(self, fname):
    """Scan C source file FNAME and return the basenames of any headers
    which are directly included, and within the set defined when this
    IncludeDependencyProcessor was initialized.

    Return a dictionary with included full file names as keys and None as
    values."""
    hdrs = { }
    for line in fileinput.input(fname):
      match = self._re_include.match(line)
      if not match:
        continue
      include_param = native_path(match.group(3))
      type_code = match.group(1)
      direct_possibility_fname = os.path.normpath(os.path.join(
        os.path.dirname(fname), include_param))
      domain_fnames = self._domain.get(os.path.basename(include_param), [])
      if os.sep.join(['libsvn_subr', 'error.c']) in fname \
           and 'errorcode.inc' == include_param:
        continue # generated by GeneratorBase.write_errno_table
      if os.sep.join(['libsvn_subr', 'cmdline.c']) in fname \
           and 'config_keys.inc' == include_param:
        continue # generated by GeneratorBase.write_config_keys
      elif direct_possibility_fname in domain_fnames:
        self._upd_dep_hash(hdrs, direct_possibility_fname, type_code)
      elif (len(domain_fnames) == 1
            and (include_param.find(os.sep) == -1
                 or _path_endswith(domain_fnames[0], include_param))):
        self._upd_dep_hash(hdrs, domain_fnames[0], type_code)
      else:
        # None found
        if include_param.find(os.sep) == -1 and len(domain_fnames) > 1:
          _error(
              "Unable to determine which file is being included\n"
              "  Include Parameter: '%s'\n"
              "  Including File: '%s'\n"
              "  Direct possibility: '%s'\n"
              "  Other possibilities: %s\n"
              % (include_param, fname, direct_possibility_fname,
                domain_fnames))
        if match.group(2) == '"':
          _warning('"%s" header not found, file %s' % (include_param, fname))
        continue
      if match.group(2) == '<':
        _warning('<%s> header *found*, file %s' % (include_param, fname))
      # The above warnings help to avoid the following problems:
      # - If header is uses the correct <> or "" convention, then the warnings
      #   reveal if the build generator does/does not make dependencies for it
      #   when it should not/should - e.g. might reveal changes needed to
      #   build.conf.
      #   ...and...
      # - If the generator is correct, them the warnings reveal incorrect use
      #   of <>/"" convention.
    return hdrs

class FileInfo:
    def __init__(self, filename, when, target=None):
        self.filename = filename
        self.when = when
        self.target = target

def _sorted_files(graph, area):
  "Given a list of targets, sort them based on their dependencies."

  # we're going to just go with a naive algorithm here. these lists are
  # going to be so short, that we can use O(n^2) or whatever this is.

  inst_targets = graph.get_sources(DT_INSTALL, area)

  # first we need our own copy of the target list since we're going to
  # munge it.
  targets = inst_targets[:]

  # the output list of the targets' files
  files = [ ]

  # loop while we have targets remaining:
  while targets:
    # find a target that has no dependencies in our current targets list.
    for t in targets:
      s = graph.get_sources(DT_LINK, t.name, Target) \
          + graph.get_sources(DT_NONLIB, t.name, Target)
      for d in s:
        if d in targets:
          break
      else:
        # no dependencies found in the targets list. this is a good "base"
        # to add to the files list now.
        if isinstance(t, TargetJava):
          # Java targets have no filename, and we just ignore them.
          pass
        elif isinstance(t, TargetI18N):
          # I18N targets have no filename, we recurse one level deeper, and
          # get the filenames of their dependencies.
          s = graph.get_sources(DT_LINK, t.name)
          for d in s:
            if d not in targets:
              files.append(FileInfo(d.filename, d.when, d))
        else:
          files.append(FileInfo(t.filename, t.when, t))

        # don't consider this target any more
        targets.remove(t)

        # break out of search through targets
        break
    else:
      # we went through the entire target list and everything had at least
      # one dependency on another target. thus, we have a circular dependency
      # tree. somebody messed up the .conf file, or the app truly does have
      # a loop (and if so, they're screwed; libtool can't relink a lib at
      # install time if the dependent libs haven't been installed yet)
      raise CircularDependencies()

  return files

class CircularDependencies(Exception):
  pass

def unique(seq):
  "Eliminate duplicates from a sequence"
  list = [ ]
  dupes = { }
  for e in seq:
    if e not in dupes:
      dupes[e] = None
      list.append(e)
  return list

### End of file.
