# Copyright (c) 2012 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from compiler.ast import Const
from compiler.ast import Dict
from compiler.ast import Discard
from compiler.ast import List
from compiler.ast import Module
from compiler.ast import Node
from compiler.ast import Stmt
import compiler
import copy
import gyp.common
import multiprocessing
import optparse
import os.path
import re
import shlex
import signal
import subprocess
import sys
import threading
import time
from gyp.common import GypError


# A list of types that are treated as linkable.
linkable_types = ['executable', 'shared_library', 'loadable_module']

# A list of sections that contain links to other targets.
dependency_sections = ['dependencies', 'export_dependent_settings']

# base_path_sections is a list of sections defined by GYP that contain
# pathnames.  The generators can provide more keys, the two lists are merged
# into path_sections, but you should call IsPathSection instead of using either
# list directly.
base_path_sections = [
  'destination',
  'files',
  'include_dirs',
  'include_dirs_target',
  'include_dirs_host',
  'inputs',
  'libraries',
  'outputs',
  'sources',
]
path_sections = []


def IsPathSection(section):
  # If section ends in one of these characters, it's applied to a section
  # without the trailing characters.  '/' is notably absent from this list,
  # because there's no way for a regular expression to be treated as a path.
  while section[-1:] in ('=', '+', '?', '!'):
    section = section[0:-1]

  if section in path_sections or \
     section.endswith('_dir') or section.endswith('_dirs') or \
     section.endswith('_file') or section.endswith('_files') or \
     section.endswith('_path') or section.endswith('_paths'):
    return True
  return False


# base_non_configuraiton_keys is a list of key names that belong in the target
# itself and should not be propagated into its configurations.  It is merged
# with a list that can come from the generator to
# create non_configuration_keys.
base_non_configuration_keys = [
  # Sections that must exist inside targets and not configurations.
  'actions',
  'configurations',
  'copies',
  'default_configuration',
  'default_project',
  'dependencies',
  'dependencies_original',
  'link_languages',
  'libraries',
  'postbuilds',
  'product_dir',
  'product_extension',
  'product_name',
  'product_prefix',
  'rules',
  'run_as',
  'sources',
  'standalone_static_library',
  'suppress_wildcard',
  'target_name',
  'toolset',
  'toolsets',
  'type',
  'variants',

  # Sections that can be found inside targets or configurations, but that
  # should not be propagated from targets into their configurations.
  'variables',
]
non_configuration_keys = []

# Keys that do not belong inside a configuration dictionary.
invalid_configuration_keys = [
  'actions',
  'all_dependent_settings',
  'configurations',
  'dependencies',
  'direct_dependent_settings',
  'link_settings',
  'sources',
  'standalone_static_library',
  'target_name',
  'type',
]

# Controls how the generator want the build file paths.
absolute_build_file_paths = False

# Controls whether or not the generator supports multiple toolsets.
multiple_toolsets = False


def GetIncludedBuildFiles(build_file_path, aux_data, included=None):
  """Return a list of all build files included into build_file_path.

  The returned list will contain build_file_path as well as all other files
  that it included, either directly or indirectly.  Note that the list may
  contain files that were included into a conditional section that evaluated
  to false and was not merged into build_file_path's dict.

  aux_data is a dict containing a key for each build file or included build
  file.  Those keys provide access to dicts whose "included" keys contain
  lists of all other files included by the build file.

  included should be left at its default None value by external callers.  It
  is used for recursion.

  The returned list will not contain any duplicate entries.  Each build file
  in the list will be relative to the current directory.
  """

  if included == None:
    included = []

  if build_file_path in included:
    return included

  included.append(build_file_path)

  for included_build_file in aux_data[build_file_path].get('included', []):
    GetIncludedBuildFiles(included_build_file, aux_data, included)

  return included


def CheckedEval(file_contents):
  """Return the eval of a gyp file.

  The gyp file is restricted to dictionaries and lists only, and
  repeated keys are not allowed.

  Note that this is slower than eval() is.
  """

  ast = compiler.parse(file_contents)
  assert isinstance(ast, Module)
  c1 = ast.getChildren()
  assert c1[0] is None
  assert isinstance(c1[1], Stmt)
  c2 = c1[1].getChildren()
  assert isinstance(c2[0], Discard)
  c3 = c2[0].getChildren()
  assert len(c3) == 1
  return CheckNode(c3[0], [])


def CheckNode(node, keypath):
  if isinstance(node, Dict):
    c = node.getChildren()
    dict = {}
    for n in range(0, len(c), 2):
      assert isinstance(c[n], Const)
      key = c[n].getChildren()[0]
      if key in dict:
        raise GypError("Key '" + key + "' repeated at level " +
              repr(len(keypath) + 1) + " with key path '" +
              '.'.join(keypath) + "'")
      kp = list(keypath)  # Make a copy of the list for descending this node.
      kp.append(key)
      dict[key] = CheckNode(c[n + 1], kp)
    return dict
  elif isinstance(node, List):
    c = node.getChildren()
    children = []
    for index, child in enumerate(c):
      kp = list(keypath)  # Copy list.
      kp.append(repr(index))
      children.append(CheckNode(child, kp))
    return children
  elif isinstance(node, Const):
    return node.getChildren()[0]
  else:
    raise TypeError, "Unknown AST node at key path '" + '.'.join(keypath) + \
         "': " + repr(node)


def LoadOneBuildFile(build_file_path, data, aux_data, variables, includes,
                     is_target, check):
  if build_file_path in data:
    return data[build_file_path]

  if os.path.exists(build_file_path):
    build_file_contents = open(build_file_path).read()
  else:
    raise GypError("%s not found (cwd: %s)" % (build_file_path, os.getcwd()))

  build_file_data = None
  try:
    if check:
      build_file_data = CheckedEval(build_file_contents)
    else:
      build_file_data = eval(build_file_contents, {'__builtins__': None},
                             None)
  except SyntaxError, e:
    e.filename = build_file_path
    raise
  except Exception, e:
    gyp.common.ExceptionAppend(e, 'while reading ' + build_file_path)
    raise

  data[build_file_path] = build_file_data
  aux_data[build_file_path] = {}

  # Scan for includes and merge them in.
  try:
    if is_target:
      LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data,
                                    aux_data, variables, includes, check)
    else:
      LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data,
                                    aux_data, variables, None, check)
  except Exception, e:
    gyp.common.ExceptionAppend(e,
                               'while reading includes of ' + build_file_path)
    raise

  return build_file_data


def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data,
                                  variables, includes, check):
  includes_list = []
  if includes != None:
    includes_list.extend(includes)
  if 'includes' in subdict:
    for include in subdict['includes']:
      # "include" is specified relative to subdict_path, so compute the real
      # path to include by appending the provided "include" to the directory
      # in which subdict_path resides.
      relative_include = \
          os.path.normpath(os.path.join(os.path.dirname(subdict_path), include))
      includes_list.append(relative_include)
    # Unhook the includes list, it's no longer needed.
    del subdict['includes']

  # Merge in the included files.
  for include in includes_list:
    if not 'included' in aux_data[subdict_path]:
      aux_data[subdict_path]['included'] = []
    aux_data[subdict_path]['included'].append(include)

    gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'" % include)

    MergeDicts(subdict,
               LoadOneBuildFile(include, data, aux_data, variables, None,
                                False, check),
               subdict_path, include)

  # Recurse into subdictionaries.
  for k, v in subdict.iteritems():
    if v.__class__ == dict:
      LoadBuildFileIncludesIntoDict(v, subdict_path, data, aux_data, variables,
                                    None, check)
    elif v.__class__ == list:
      LoadBuildFileIncludesIntoList(v, subdict_path, data, aux_data, variables,
                                    check)


# This recurses into lists so that it can look for dicts.
def LoadBuildFileIncludesIntoList(sublist, sublist_path, data, aux_data,
                                  variables, check):
  for item in sublist:
    if item.__class__ == dict:
      LoadBuildFileIncludesIntoDict(item, sublist_path, data, aux_data,
                                    variables, None, check)
    elif item.__class__ == list:
      LoadBuildFileIncludesIntoList(item, sublist_path, data, aux_data,
                                    variables, check)

# Processes toolsets in all the targets. This recurses into condition entries
# since they can contain toolsets as well.
def ProcessToolsetsInDict(data):
  if 'targets' in data:
    target_list = data['targets']
    new_target_list = []
    for target in target_list:
      # If this target already has an explicit 'toolset', and no 'toolsets'
      # list, don't modify it further.
      if 'toolset' in target and 'toolsets' not in target:
        new_target_list.append(target)
        continue
      if multiple_toolsets:
        toolsets = target.get('toolsets', ['target'])
      else:
        toolsets = ['target']
      # Make sure this 'toolsets' definition is only processed once.
      if 'toolsets' in target:
        del target['toolsets']
      if len(toolsets) > 0:
        # Optimization: only do copies if more than one toolset is specified.
        for build in toolsets[1:]:
          new_target = copy.deepcopy(target)
          new_target['toolset'] = build
          new_target_list.append(new_target)
        target['toolset'] = toolsets[0]
        new_target_list.append(target)
    data['targets'] = new_target_list
  if 'conditions' in data:
    for condition in data['conditions']:
      if isinstance(condition, list):
        for condition_dict in condition[1:]:
          ProcessToolsetsInDict(condition_dict)


# TODO(mark): I don't love this name.  It just means that it's going to load
# a build file that contains targets and is expected to provide a targets dict
# that contains the targets...
def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes,
                        depth, check, load_dependencies):
  # If depth is set, predefine the DEPTH variable to be a relative path from
  # this build file's directory to the directory identified by depth.
  if depth:
    # TODO(dglazkov) The backslash/forward-slash replacement at the end is a
    # temporary measure. This should really be addressed by keeping all paths
    # in POSIX until actual project generation.
    d = gyp.common.RelativePath(depth, os.path.dirname(build_file_path))
    if d == '':
      variables['DEPTH'] = '.'
    else:
      variables['DEPTH'] = d.replace('\\', '/')

  # If the generator needs absolue paths, then do so.
  if absolute_build_file_paths:
    build_file_path = os.path.abspath(build_file_path)

  if build_file_path in data['target_build_files']:
    # Already loaded.
    return False
  data['target_build_files'].add(build_file_path)

  gyp.DebugOutput(gyp.DEBUG_INCLUDES,
                  "Loading Target Build File '%s'" % build_file_path)

  build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, variables,
                                     includes, True, check)

  # Store DEPTH for later use in generators.
  build_file_data['_DEPTH'] = depth

  # Set up the included_files key indicating which .gyp files contributed to
  # this target dict.
  if 'included_files' in build_file_data:
    raise GypError(build_file_path + ' must not contain included_files key')

  included = GetIncludedBuildFiles(build_file_path, aux_data)
  build_file_data['included_files'] = []
  for included_file in included:
    # included_file is relative to the current directory, but it needs to
    # be made relative to build_file_path's directory.
    included_relative = \
        gyp.common.RelativePath(included_file,
                                os.path.dirname(build_file_path))
    build_file_data['included_files'].append(included_relative)

  # Do a first round of toolsets expansion so that conditions can be defined
  # per toolset.
  ProcessToolsetsInDict(build_file_data)

  # Apply "pre"/"early" variable expansions and condition evaluations.
  ProcessVariablesAndConditionsInDict(
      build_file_data, PHASE_EARLY, variables, build_file_path)

  # Since some toolsets might have been defined conditionally, perform
  # a second round of toolsets expansion now.
  ProcessToolsetsInDict(build_file_data)

  # Look at each project's target_defaults dict, and merge settings into
  # targets.
  if 'target_defaults' in build_file_data:
    if 'targets' not in build_file_data:
      raise GypError("Unable to find targets in build file %s" %
                     build_file_path)

    index = 0
    while index < len(build_file_data['targets']):
      # This procedure needs to give the impression that target_defaults is
      # used as defaults, and the individual targets inherit from that.
      # The individual targets need to be merged into the defaults.  Make
      # a deep copy of the defaults for each target, merge the target dict
      # as found in the input file into that copy, and then hook up the
      # copy with the target-specific data merged into it as the replacement
      # target dict.
      old_target_dict = build_file_data['targets'][index]
      new_target_dict = copy.deepcopy(build_file_data['target_defaults'])
      MergeDicts(new_target_dict, old_target_dict,
                 build_file_path, build_file_path)
      build_file_data['targets'][index] = new_target_dict
      index += 1

    # No longer needed.
    del build_file_data['target_defaults']

  # Look for dependencies.  This means that dependency resolution occurs
  # after "pre" conditionals and variable expansion, but before "post" -
  # in other words, you can't put a "dependencies" section inside a "post"
  # conditional within a target.

  dependencies = []
  if 'targets' in build_file_data:
    for target_dict in build_file_data['targets']:
      if 'dependencies' not in target_dict:
        continue
      for dependency in target_dict['dependencies']:
        dependencies.append(
            gyp.common.ResolveTarget(build_file_path, dependency, None)[0])

  if load_dependencies:
    for dependency in dependencies:
      try:
        LoadTargetBuildFile(dependency, data, aux_data, variables,
                            includes, depth, check, load_dependencies)
      except Exception, e:
        gyp.common.ExceptionAppend(
          e, 'while loading dependencies of %s' % build_file_path)
        raise
  else:
    return (build_file_path, dependencies)


def CallLoadTargetBuildFile(global_flags,
                            build_file_path, data,
                            aux_data, variables,
                            includes, depth, check):
  """Wrapper around LoadTargetBuildFile for parallel processing.

     This wrapper is used when LoadTargetBuildFile is executed in
     a worker process.
  """

  try:
    signal.signal(signal.SIGINT, signal.SIG_IGN)

    # Apply globals so that the worker process behaves the same.
    for key, value in global_flags.iteritems():
      globals()[key] = value

    # Save the keys so we can return data that changed.
    data_keys = set(data)
    aux_data_keys = set(aux_data)

    result = LoadTargetBuildFile(build_file_path, data,
                                 aux_data, variables,
                                 includes, depth, check, False)
    if not result:
      return result

    (build_file_path, dependencies) = result

    data_out = {}
    for key in data:
      if key == 'target_build_files':
        continue
      if key not in data_keys:
        data_out[key] = data[key]
    aux_data_out = {}
    for key in aux_data:
      if key not in aux_data_keys:
        aux_data_out[key] = aux_data[key]

    # This gets serialized and sent back to the main process via a pipe.
    # It's handled in LoadTargetBuildFileCallback.
    return (build_file_path,
            data_out,
            aux_data_out,
            dependencies)
  except Exception, e:
    print "Exception: ", e
    return None


class ParallelProcessingError(Exception):
  pass


class ParallelState(object):
  """Class to keep track of state when processing input files in parallel.

  If build files are loaded in parallel, use this to keep track of
  state during farming out and processing parallel jobs. It's stored
  in a global so that the callback function can have access to it.
  """

  def __init__(self):
    # The multiprocessing pool.
    self.pool = None
    # The condition variable used to protect this object and notify
    # the main loop when there might be more data to process.
    self.condition = None
    # The "data" dict that was passed to LoadTargetBuildFileParallel
    self.data = None
    # The "aux_data" dict that was passed to LoadTargetBuildFileParallel
    self.aux_data = None
    # The number of parallel calls outstanding; decremented when a response
    # was received.
    self.pending = 0
    # The set of all build files that have been scheduled, so we don't
    # schedule the same one twice.
    self.scheduled = set()
    # A list of dependency build file paths that haven't been scheduled yet.
    self.dependencies = []
    # Flag to indicate if there was an error in a child process.
    self.error = False

  def LoadTargetBuildFileCallback(self, result):
    """Handle the results of running LoadTargetBuildFile in another process.
    """
    self.condition.acquire()
    if not result:
      self.error = True
      self.condition.notify()
      self.condition.release()
      return
    (build_file_path0, data0, aux_data0, dependencies0) = result
    self.data['target_build_files'].add(build_file_path0)
    for key in data0:
      self.data[key] = data0[key]
    for key in aux_data0:
      self.aux_data[key] = aux_data0[key]
    for new_dependency in dependencies0:
      if new_dependency not in self.scheduled:
        self.scheduled.add(new_dependency)
        self.dependencies.append(new_dependency)
    self.pending -= 1
    self.condition.notify()
    self.condition.release()


def LoadTargetBuildFileParallel(build_file_path, data, aux_data,
                                variables, includes, depth, check):
  parallel_state = ParallelState()
  parallel_state.condition = threading.Condition()
  parallel_state.dependencies = [build_file_path]
  parallel_state.scheduled = set([build_file_path])
  parallel_state.pending = 0
  parallel_state.data = data
  parallel_state.aux_data = aux_data

  try:
    parallel_state.condition.acquire()
    while parallel_state.dependencies or parallel_state.pending:
      if parallel_state.error:
        break
      if not parallel_state.dependencies:
        parallel_state.condition.wait()
        continue

      dependency = parallel_state.dependencies.pop()

      parallel_state.pending += 1
      data_in = {}
      data_in['target_build_files'] = data['target_build_files']
      aux_data_in = {}
      global_flags = {
        'path_sections': globals()['path_sections'],
        'non_configuration_keys': globals()['non_configuration_keys'],
        'absolute_build_file_paths': globals()['absolute_build_file_paths'],
        'multiple_toolsets': globals()['multiple_toolsets']}

      if not parallel_state.pool:
        parallel_state.pool = multiprocessing.Pool(8)
      parallel_state.pool.apply_async(
          CallLoadTargetBuildFile,
          args = (global_flags, dependency,
                  data_in, aux_data_in,
                  variables, includes, depth, check),
          callback = parallel_state.LoadTargetBuildFileCallback)
  except KeyboardInterrupt, e:
    parallel_state.pool.terminate()
    raise e

  parallel_state.condition.release()
  if parallel_state.error:
    sys.exit()


# Look for the bracket that matches the first bracket seen in a
# string, and return the start and end as a tuple.  For example, if
# the input is something like "<(foo <(bar)) blah", then it would
# return (1, 13), indicating the entire string except for the leading
# "<" and trailing " blah".
def FindEnclosingBracketGroup(input):
  brackets = { '}': '{',
               ']': '[',
               ')': '(', }
  stack = []
  count = 0
  start = -1
  for char in input:
    if char in brackets.values():
      stack.append(char)
      if start == -1:
        start = count
    if char in brackets.keys():
      try:
        last_bracket = stack.pop()
      except IndexError:
        return (-1, -1)
      if last_bracket != brackets[char]:
        return (-1, -1)
      if len(stack) == 0:
        return (start, count + 1)
    count = count + 1
  return (-1, -1)


canonical_int_re = re.compile('^(0|-?[1-9][0-9]*)$')


def IsStrCanonicalInt(string):
  """Returns True if |string| is in its canonical integer form.

  The canonical form is such that str(int(string)) == string.
  """
  if not isinstance(string, str) or not canonical_int_re.match(string):
    return False

  return True


# This matches things like "<(asdf)", "<!(cmd)", "<!@(cmd)", "<|(list)",
# "<!interpreter(arguments)", "<([list])", and even "<([)" and "<(<())".
# In the last case, the inner "<()" is captured in match['content'].
early_variable_re = re.compile(
    '(?P<replace>(?P<type><(?:(?:!?@?)|\|)?)'
    '(?P<command_string>[-a-zA-Z0-9_.]+)?'
    '\((?P<is_array>\s*\[?)'
    '(?P<content>.*?)(\]?)\))')

# This matches the same as early_variable_re, but with '>' instead of '<'.
late_variable_re = re.compile(
    '(?P<replace>(?P<type>>(?:(?:!?@?)|\|)?)'
    '(?P<command_string>[-a-zA-Z0-9_.]+)?'
    '\((?P<is_array>\s*\[?)'
    '(?P<content>.*?)(\]?)\))')

# This matches the same as early_variable_re, but with '^' instead of '<'.
latelate_variable_re = re.compile(
    '(?P<replace>(?P<type>[\^](?:(?:!?@?)|\|)?)'
    '(?P<command_string>[-a-zA-Z0-9_.]+)?'
    '\((?P<is_array>\s*\[?)'
    '(?P<content>.*?)(\]?)\))')

# Global cache of results from running commands so they don't have to be run
# more then once.
cached_command_results = {}


def FixupPlatformCommand(cmd):
  if sys.platform == 'win32':
    if type(cmd) == list:
      cmd = [re.sub('^cat ', 'type ', cmd[0])] + cmd[1:]
    else:
      cmd = re.sub('^cat ', 'type ', cmd)
  return cmd


PHASE_EARLY = 0
PHASE_LATE = 1
PHASE_LATELATE = 2


def ExpandVariables(input, phase, variables, build_file):
  # Look for the pattern that gets expanded into variables
  if phase == PHASE_EARLY:
    variable_re = early_variable_re
    expansion_symbol = '<'
  elif phase == PHASE_LATE:
    variable_re = late_variable_re
    expansion_symbol = '>'
  elif phase == PHASE_LATELATE:
    variable_re = latelate_variable_re
    expansion_symbol = '^'
  else:
    assert False

  input_str = str(input)
  if IsStrCanonicalInt(input_str):
    return int(input_str)

  # Do a quick scan to determine if an expensive regex search is warranted.
  if expansion_symbol not in input_str:
    return input_str

  # Get the entire list of matches as a list of MatchObject instances.
  # (using findall here would return strings instead of MatchObjects).
  matches = [match for match in variable_re.finditer(input_str)]
  if not matches:
    return input_str

  output = input_str
  # Reverse the list of matches so that replacements are done right-to-left.
  # That ensures that earlier replacements won't mess up the string in a
  # way that causes later calls to find the earlier substituted text instead
  # of what's intended for replacement.
  matches.reverse()
  for match_group in matches:
    match = match_group.groupdict()
    gyp.DebugOutput(gyp.DEBUG_VARIABLES,
                    "Matches: %s" % repr(match))
    # match['replace'] is the substring to look for, match['type']
    # is the character code for the replacement type (< > <! >! <| >| <@
    # >@ <!@ >!@), match['is_array'] contains a '[' for command
    # arrays, and match['content'] is the name of the variable (< >)
    # or command to run (<! >!). match['command_string'] is an optional
    # command string. Currently, only 'pymod_do_main' is supported.

    # run_command is true if a ! variant is used.
    run_command = '!' in match['type']
    command_string = match['command_string']

    # file_list is true if a | variant is used.
    file_list = '|' in match['type']

    # Capture these now so we can adjust them later.
    replace_start = match_group.start('replace')
    replace_end = match_group.end('replace')

    # Find the ending paren, and re-evaluate the contained string.
    (c_start, c_end) = FindEnclosingBracketGroup(input_str[replace_start:])

    # Adjust the replacement range to match the entire command
    # found by FindEnclosingBracketGroup (since the variable_re
    # probably doesn't match the entire command if it contained
    # nested variables).
    replace_end = replace_start + c_end

    # Find the "real" replacement, matching the appropriate closing
    # paren, and adjust the replacement start and end.
    replacement = input_str[replace_start:replace_end]

    # Figure out what the contents of the variable parens are.
    contents_start = replace_start + c_start + 1
    contents_end = replace_end - 1
    contents = input_str[contents_start:contents_end]

    # Do filter substitution now for <|().
    # Admittedly, this is different than the evaluation order in other
    # contexts. However, since filtration has no chance to run on <|(),
    # this seems like the only obvious way to give them access to filters.
    if file_list:
      processed_variables = copy.deepcopy(variables)
      ProcessListFiltersInDict(contents, processed_variables)
      # Recurse to expand variables in the contents
      contents = ExpandVariables(contents, phase,
                                 processed_variables, build_file)
    else:
      # Recurse to expand variables in the contents
      contents = ExpandVariables(contents, phase, variables, build_file)

    # Strip off leading/trailing whitespace so that variable matches are
    # simpler below (and because they are rarely needed).
    contents = contents.strip()

    # expand_to_list is true if an @ variant is used.  In that case,
    # the expansion should result in a list.  Note that the caller
    # is to be expecting a list in return, and not all callers do
    # because not all are working in list context.  Also, for list
    # expansions, there can be no other text besides the variable
    # expansion in the input string.
    expand_to_list = '@' in match['type'] and input_str == replacement

    if run_command or file_list:
      # Find the build file's directory, so commands can be run or file lists
      # generated relative to it.
      build_file_dir = os.path.dirname(build_file)
      if build_file_dir == '':
        # If build_file is just a leaf filename indicating a file in the
        # current directory, build_file_dir might be an empty string.  Set
        # it to None to signal to subprocess.Popen that it should run the
        # command in the current directory.
        build_file_dir = None

    # Support <|(listfile.txt ...) which generates a file
    # containing items from a gyp list, generated at gyp time.
    # This works around actions/rules which have more inputs than will
    # fit on the command line.
    if file_list:
      if type(contents) == list:
        contents_list = contents
      else:
        contents_list = contents.split(' ')
      replacement = contents_list[0]
      path = replacement
      if not os.path.isabs(path):
        path = os.path.join(build_file_dir, path)
      f = gyp.common.WriteOnDiff(path)
      for i in contents_list[1:]:
        f.write('%s\n' % i)
      f.close()

    elif run_command:
      use_shell = True
      if match['is_array']:
        contents = eval(contents)
        use_shell = False

      # Check for a cached value to avoid executing commands, or generating
      # file lists more than once.
      # TODO(http://code.google.com/p/gyp/issues/detail?id=112): It is
      # possible that the command being invoked depends on the current
      # directory. For that case the syntax needs to be extended so that the
      # directory is also used in cache_key (it becomes a tuple).
      # TODO(http://code.google.com/p/gyp/issues/detail?id=111): In theory,
      # someone could author a set of GYP files where each time the command
      # is invoked it produces different output by design. When the need
      # arises, the syntax should be extended to support no caching off a
      # command's output so it is run every time.
      cache_key = str(contents)
      cached_value = cached_command_results.get(cache_key, None)
      if cached_value is None:
        gyp.DebugOutput(gyp.DEBUG_VARIABLES,
                        "Executing command '%s' in directory '%s'" %
                        (contents,build_file_dir))

        replacement = ''

        if command_string == 'pymod_do_main':
          # <!pymod_do_main(modulename param eters) loads |modulename| as a
          # python module and then calls that module's DoMain() function,
          # passing ["param", "eters"] as a single list argument. For modules
          # that don't load quickly, this can be faster than
          # <!(python modulename param eters). Do this in |build_file_dir|.
          oldwd = os.getcwd()  # Python doesn't like os.open('.'): no fchdir.
          if build_file_dir:
            os.chdir(build_file_dir)

          parsed_contents = shlex.split(contents)

          # Import only imports the root package specified in the parameter,
          # even though all packages will be imported.  For example, if
          # 'foo.bar.gum' is passed in to __import__(), 'foo', 'foo.bar', and
          # 'foo.bar.gum' are all imported, but only 'foo' is returned.  To
          # get access to the package we specified to __import__(), we instead
          # pull it out of sys.modules after it has been imported.
          __import__(parsed_contents[0])
          py_module = sys.modules[parsed_contents[0]]

          replacement = str(py_module.DoMain(parsed_contents[1:])).rstrip()

          os.chdir(oldwd)
          assert replacement != None
        elif command_string:
          raise GypError("Unknown command string '%s' in '%s'." %
                         (command_string, contents))
        else:
          # Fix up command with platform specific workarounds.
          contents = FixupPlatformCommand(contents)
          p = subprocess.Popen(contents, shell=use_shell,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               stdin=subprocess.PIPE,
                               cwd=build_file_dir)

          p_stdout, p_stderr = p.communicate('')

          if p.wait() != 0 or p_stderr:
            sys.stderr.write(p_stderr)
            # Simulate check_call behavior, since check_call only exists
            # in python 2.5 and later.
            raise GypError("Call to '%s' returned exit status %d." %
                           (contents, p.returncode))
          replacement = p_stdout.rstrip()

        cached_command_results[cache_key] = replacement
      else:
        gyp.DebugOutput(gyp.DEBUG_VARIABLES,
                        "Had cache value for command '%s' in directory '%s'" %
                        (contents,build_file_dir))
        replacement = cached_value

    else:
      if not contents in variables:
        if contents[-1] in ['!', '/']:
          # In order to allow cross-compiles (nacl) to happen more naturally,
          # we will allow references to >(sources/) etc. to resolve to
          # and empty list if undefined. This allows actions to:
          # 'action!': [
          #   '>@(_sources!)',
          # ],
          # 'action/': [
          #   '>@(_sources/)',
          # ],
          replacement = []
        else:
          raise GypError('Undefined variable ' + contents +
                         ' in ' + build_file)
      else:
        replacement = variables[contents]

    if isinstance(replacement, list):
      for item in replacement:
        if (not contents[-1] == '/' and
            not isinstance(item, str) and not isinstance(item, int)):
          raise GypError('Variable ' + contents +
                         ' must expand to a string or list of strings; ' +
                         'list contains a ' +
                         item.__class__.__name__)
      # Run through the list and handle variable expansions in it.  Since
      # the list is guaranteed not to contain dicts, this won't do anything
      # with conditions sections.
      ProcessVariablesAndConditionsInList(replacement, phase, variables,
                                          build_file)
    elif not isinstance(replacement, str) and \
         not isinstance(replacement, int):
          raise GypError('Variable ' + contents +
                         ' must expand to a string or list of strings; ' +
                         'found a ' + replacement.__class__.__name__)

    if expand_to_list:
      # Expanding in list context.  It's guaranteed that there's only one
      # replacement to do in |input_str| and that it's this replacement.  See
      # above.
      if isinstance(replacement, list):
        # If it's already a list, make a copy.
        output = replacement[:]
      else:
        # Split it the same way sh would split arguments.
        output = shlex.split(str(replacement))
    else:
      # Expanding in string context.
      encoded_replacement = ''
      if isinstance(replacement, list):
        # When expanding a list into string context, turn the list items
        # into a string in a way that will work with a subprocess call.
        #
        # TODO(mark): This isn't completely correct.  This should
        # call a generator-provided function that observes the
        # proper list-to-argument quoting rules on a specific
        # platform instead of just calling the POSIX encoding
        # routine.
        encoded_replacement = gyp.common.EncodePOSIXShellList(replacement)
      else:
        encoded_replacement = replacement

      output = output[:replace_start] + str(encoded_replacement) + \
               output[replace_end:]
    # Prepare for the next match iteration.
    input_str = output

  # Look for more matches now that we've replaced some, to deal with
  # expanding local variables (variables defined in the same
  # variables block as this one).
  gyp.DebugOutput(gyp.DEBUG_VARIABLES,
                  "Found output %s, recursing." % repr(output))
  if isinstance(output, list):
    if output and isinstance(output[0], list):
      # Leave output alone if it's a list of lists.
      # We don't want such lists to be stringified.
      pass
    else:
      new_output = []
      for item in output:
        new_output.append(
            ExpandVariables(item, phase, variables, build_file))
      output = new_output
  else:
    output = ExpandVariables(output, phase, variables, build_file)

  # Convert all strings that are canonically-represented integers into integers.
  if isinstance(output, list):
    for index in xrange(0, len(output)):
      if IsStrCanonicalInt(output[index]):
        output[index] = int(output[index])
  elif IsStrCanonicalInt(output):
    output = int(output)

  return output


def ProcessConditionsInDict(the_dict, phase, variables, build_file):
  # Process a 'conditions' or 'target_conditions' section in the_dict,
  # depending on phase.
  # early -> conditions
  # late -> target_conditions
  # latelate -> no conditions
  #
  # Each item in a conditions list consists of cond_expr, a string expression
  # evaluated as the condition, and true_dict, a dict that will be merged into
  # the_dict if cond_expr evaluates to true.  Optionally, a third item,
  # false_dict, may be present.  false_dict is merged into the_dict if
  # cond_expr evaluates to false.
  #
  # Any dict merged into the_dict will be recursively processed for nested
  # conditionals and other expansions, also according to phase, immediately
  # prior to being merged.

  if phase == PHASE_EARLY:
    conditions_key = 'conditions'
  elif phase == PHASE_LATE:
    conditions_key = 'target_conditions'
  elif phase == PHASE_LATELATE:
    return
  else:
    assert False

  if not conditions_key in the_dict:
    return

  conditions_list = the_dict[conditions_key]
  # Unhook the conditions list, it's no longer needed.
  del the_dict[conditions_key]

  for condition in conditions_list:
    if not isinstance(condition, list):
      raise GypError(conditions_key + ' must be a list')
    if len(condition) != 2 and len(condition) != 3:
      # It's possible that condition[0] won't work in which case this
      # attempt will raise its own IndexError.  That's probably fine.
      raise GypError(conditions_key + ' ' + condition[0] +
                     ' must be length 2 or 3, not ' + str(len(condition)))

    [cond_expr, true_dict] = condition[0:2]
    false_dict = None
    if len(condition) == 3:
      false_dict = condition[2]

    # Do expansions on the condition itself.  Since the conditon can naturally
    # contain variable references without needing to resort to GYP expansion
    # syntax, this is of dubious value for variables, but someone might want to
    # use a command expansion directly inside a condition.
    cond_expr_expanded = ExpandVariables(cond_expr, phase, variables,
                                         build_file)
    if not isinstance(cond_expr_expanded, str) and \
       not isinstance(cond_expr_expanded, int):
      raise ValueError, \
            'Variable expansion in this context permits str and int ' + \
            'only, found ' + expanded.__class__.__name__

    try:
      ast_code = compile(cond_expr_expanded, '<string>', 'eval')

      if eval(ast_code, {'__builtins__': None}, variables):
        merge_dict = true_dict
      else:
        merge_dict = false_dict
    except SyntaxError, e:
      syntax_error = SyntaxError('%s while evaluating condition \'%s\' in %s '
                                 'at character %d.' %
                                 (str(e.args[0]), e.text, build_file, e.offset),
                                 e.filename, e.lineno, e.offset, e.text)
      raise syntax_error
    except NameError, e:
      gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s' %
                                 (cond_expr_expanded, build_file))
      raise

    if merge_dict != None:
      # Expand variables and nested conditinals in the merge_dict before
      # merging it.
      ProcessVariablesAndConditionsInDict(merge_dict, phase,
                                          variables, build_file)

      MergeDicts(the_dict, merge_dict, build_file, build_file)


def LoadAutomaticVariablesFromDict(variables, the_dict):
  # Any keys with plain string values in the_dict become automatic variables.
  # The variable name is the key name with a "_" character prepended.
  for key, value in the_dict.iteritems():
    if isinstance(value, str) or isinstance(value, int) or \
       isinstance(value, list):
      variables['_' + key] = value


def LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key):
  # Any keys in the_dict's "variables" dict, if it has one, becomes a
  # variable.  The variable name is the key name in the "variables" dict.
  # Variables that end with the % character are set only if they are unset in
  # the variables dict.  the_dict_key is the name of the key that accesses
  # the_dict in the_dict's parent dict.  If the_dict's parent is not a dict
  # (it could be a list or it could be parentless because it is a root dict),
  # the_dict_key will be None.
  for key, value in the_dict.get('variables', {}).iteritems():
    if not isinstance(value, str) and not isinstance(value, int) and \
       not isinstance(value, list):
      continue

    if key.endswith('%'):
      variable_name = key[:-1]
      if variable_name in variables:
        # If the variable is already set, don't set it.
        continue
      if the_dict_key is 'variables' and variable_name in the_dict:
        # If the variable is set without a % in the_dict, and the_dict is a
        # variables dict (making |variables| a varaibles sub-dict of a
        # variables dict), use the_dict's definition.
        value = the_dict[variable_name]
    elif key.endswith('!'):
      variable_name = key[:-1]
      if variable_name not in variables:
        # If the variable is not already set, we can't remove anything from it.
        continue
      remove_these = value
      filter_fn = lambda t: t not in remove_these
      # Remove these values from the original variable
      value = filter(filter_fn, variables[variable_name])
      # Remove these values from any copy of that variable we're about to process :)
      the_dict['variables'][variable_name] = filter(filter_fn, the_dict['variables'][variable_name])
    else:
      variable_name = key

    variables[variable_name] = value


def ProcessVariablesAndConditionsInDict(the_dict, phase, variables_in,
                                        build_file, the_dict_key=None):
  """Handle all variable and command expansion and conditional evaluation.

  This function is the public entry point for all variable expansions and
  conditional evaluations.  The variables_in dictionary will not be modified
  by this function.
  """

  # Make a copy of the variables_in dict that can be modified during the
  # loading of automatics and the loading of the variables dict.
  variables = variables_in.copy()
  LoadAutomaticVariablesFromDict(variables, the_dict)

  if 'variables' in the_dict:
    # Make sure all the local variables are added to the variables
    # list before we process them so that you can reference one
    # variable from another.  They will be fully expanded by recursion
    # in ExpandVariables.
    for key, value in the_dict['variables'].iteritems():
      variables[key] = value

    # Handle the associated variables dict first, so that any variable
    # references within can be resolved prior to using them as variables.
    # Pass a copy of the variables dict to avoid having it be tainted.
    # Otherwise, it would have extra automatics added for everything that
    # should just be an ordinary variable in this scope.
    ProcessVariablesAndConditionsInDict(the_dict['variables'], phase,
                                        variables, build_file, 'variables')

  LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)

  for key, value in the_dict.iteritems():
    # Skip "variables", which was already processed if present.
    if key != 'variables' and isinstance(value, str):
      expanded = ExpandVariables(value, phase, variables, build_file)
      if not isinstance(expanded, str) and not isinstance(expanded, int):
        raise ValueError, \
              'Variable expansion in this context permits str and int ' + \
              'only, found ' + expanded.__class__.__name__ + ' for ' + key
      the_dict[key] = expanded

  # Variable expansion may have resulted in changes to automatics.  Reload.
  # TODO(mark): Optimization: only reload if no changes were made.
  variables = variables_in.copy()
  LoadAutomaticVariablesFromDict(variables, the_dict)
  LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)

  # Process conditions in this dict.  This is done after variable expansion
  # so that conditions may take advantage of expanded variables.  For example,
  # if the_dict contains:
  #   {'type':       '<(library_type)',
  #    'conditions': [['_type=="static_library"', { ... }]]},
  # _type, as used in the condition, will only be set to the value of
  # library_type if variable expansion is performed before condition
  # processing.  However, condition processing should occur prior to recursion
  # so that variables (both automatic and "variables" dict type) may be
  # adjusted by conditions sections, merged into the_dict, and have the
  # intended impact on contained dicts.
  #
  # This arrangement means that a "conditions" section containing a "variables"
  # section will only have those variables effective in subdicts, not in
  # the_dict.  The workaround is to put a "conditions" section within a
  # "variables" section.  For example:
  #   {'conditions': [['os=="mac"', {'variables': {'define': 'IS_MAC'}}]],
  #    'defines':    ['<(define)'],
  #    'my_subdict': {'defines': ['<(define)']}},
  # will not result in "IS_MAC" being appended to the "defines" list in the
  # current scope but would result in it being appended to the "defines" list
  # within "my_subdict".  By comparison:
  #   {'variables': {'conditions': [['os=="mac"', {'define': 'IS_MAC'}]]},
  #    'defines':    ['<(define)'],
  #    'my_subdict': {'defines': ['<(define)']}},
  # will append "IS_MAC" to both "defines" lists.

  # Evaluate conditions sections, allowing variable expansions within them
  # as well as nested conditionals.  This will process a 'conditions' or
  # 'target_conditions' section, perform appropriate merging and recursive
  # conditional and variable processing, and then remove the conditions section
  # from the_dict if it is present.
  ProcessConditionsInDict(the_dict, phase, variables, build_file)

  # Conditional processing may have resulted in changes to automatics or the
  # variables dict.  Reload.
  variables = variables_in.copy()
  LoadAutomaticVariablesFromDict(variables, the_dict)
  LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)

  # Recurse into child dicts, or process child lists which may result in
  # further recursion into descendant dicts.
  for key, value in the_dict.iteritems():
    # Skip "variables" and string values, which were already processed if
    # present.
    if key == 'variables' or isinstance(value, str):
      continue
    if isinstance(value, dict):
      # Pass a copy of the variables dict so that subdicts can't influence
      # parents.
      ProcessVariablesAndConditionsInDict(value, phase, variables,
                                          build_file, key)
    elif isinstance(value, list):
      # The list itself can't influence the variables dict, and
      # ProcessVariablesAndConditionsInList will make copies of the variables
      # dict if it needs to pass it to something that can influence it.  No
      # copy is necessary here.
      ProcessVariablesAndConditionsInList(value, phase, variables,
                                          build_file)
    elif not isinstance(value, int):
      raise TypeError, 'Unknown type ' + value.__class__.__name__ + \
                       ' for ' + key


def ProcessVariablesAndConditionsInList(the_list, phase, variables,
                                        build_file):
  # Iterate using an index so that new values can be assigned into the_list.
  index = 0
  while index < len(the_list):
    item = the_list[index]
    if isinstance(item, dict):
      # Make a copy of the variables dict so that it won't influence anything
      # outside of its own scope.
      ProcessVariablesAndConditionsInDict(item, phase, variables, build_file)
    elif isinstance(item, list):
      ProcessVariablesAndConditionsInList(item, phase, variables, build_file)
    elif isinstance(item, str):
      expanded = ExpandVariables(item, phase, variables, build_file)
      if isinstance(expanded, str) or isinstance(expanded, int):
        the_list[index] = expanded
      elif isinstance(expanded, list):
        the_list[index:index+1] = expanded
        index += len(expanded)

        # index now identifies the next item to examine.  Continue right now
        # without falling into the index increment below.
        continue
      else:
        raise ValueError, \
              'Variable expansion in this context permits strings and ' + \
              'lists only, found ' + expanded.__class__.__name__ + ' at ' + \
              index
    elif not isinstance(item, int):
      raise TypeError, 'Unknown type ' + item.__class__.__name__ + \
                       ' at index ' + index
    index = index + 1


def BuildTargetsDict(data):
  """Builds a dict mapping fully-qualified target names to their target dicts.

  |data| is a dict mapping loaded build files by pathname relative to the
  current directory.  Values in |data| are build file contents.  For each
  |data| value with a "targets" key, the value of the "targets" key is taken
  as a list containing target dicts.  Each target's fully-qualified name is
  constructed from the pathname of the build file (|data| key) and its
  "target_name" property.  These fully-qualified names are used as the keys
  in the returned dict.  These keys provide access to the target dicts,
  the dicts in the "targets" lists.
  """

  targets = {}
  for build_file in data['target_build_files']:
    for target in data[build_file].get('targets', []):
      target_name = gyp.common.QualifiedTarget(build_file,
                                               target['target_name'],
                                               target['toolset'])
      if target_name in targets:
        raise GypError('Duplicate target definitions for ' + target_name)
      targets[target_name] = target

  return targets


def QualifyDependencies(targets):
  """Make dependency links fully-qualified relative to the current directory.

  |targets| is a dict mapping fully-qualified target names to their target
  dicts.  For each target in this dict, keys known to contain dependency
  links are examined, and any dependencies referenced will be rewritten
  so that they are fully-qualified and relative to the current directory.
  All rewritten dependencies are suitable for use as keys to |targets| or a
  similar dict.
  """

  all_dependency_sections = [dep + op
                             for dep in dependency_sections
                             for op in ('', '!', '/')]

  for target, target_dict in targets.iteritems():
    target_build_file = gyp.common.BuildFile(target)
    toolset = target_dict['toolset']
    for dependency_key in all_dependency_sections:
      dependencies = target_dict.get(dependency_key, [])
      for index in xrange(0, len(dependencies)):
        dep_file, dep_target, dep_toolset = gyp.common.ResolveTarget(
            target_build_file, dependencies[index], toolset)
        if not multiple_toolsets:
          # Ignore toolset specification in the dependency if it is specified.
          dep_toolset = toolset
        dependency = gyp.common.QualifiedTarget(dep_file,
                                                dep_target,
                                                dep_toolset)
        dependencies[index] = dependency

        # Make sure anything appearing in a list other than "dependencies" also
        # appears in the "dependencies" list.
        if dependency_key != 'dependencies' and \
           dependency not in target_dict['dependencies']:
          raise GypError('Found ' + dependency + ' in ' + dependency_key +
                         ' of ' + target + ', but not in dependencies')


def ExpandWildcardDependencies(targets, data):
  """Expands dependencies specified as build_file:*.

  For each target in |targets|, examines sections containing links to other
  targets.  If any such section contains a link of the form build_file:*, it
  is taken as a wildcard link, and is expanded to list each target in
  build_file.  The |data| dict provides access to build file dicts.

  Any target that does not wish to be included by wildcard can provide an
  optional "suppress_wildcard" key in its target dict.  When present and
  true, a wildcard dependency link will not include such targets.

  All dependency names, including the keys to |targets| and the values in each
  dependency list, must be qualified when this function is called.
  """

  for target, target_dict in targets.iteritems():
    toolset = target_dict['toolset']
    target_build_file = gyp.common.BuildFile(target)
    for dependency_key in dependency_sections:
      dependencies = target_dict.get(dependency_key, [])

      # Loop this way instead of "for dependency in" or "for index in xrange"
      # because the dependencies list will be modified within the loop body.
      index = 0
      while index < len(dependencies):
        (dependency_build_file, dependency_target, dependency_toolset) = \
            gyp.common.ParseQualifiedTarget(dependencies[index])
        if dependency_target != '*' and dependency_toolset != '*':
          # Not a wildcard.  Keep it moving.
          index = index + 1
          continue

        if dependency_build_file == target_build_file:
          # It's an error for a target to depend on all other targets in
          # the same file, because a target cannot depend on itself.
          raise GypError('Found wildcard in ' + dependency_key + ' of ' +
                         target + ' referring to same build file')

        # Take the wildcard out and adjust the index so that the next
        # dependency in the list will be processed the next time through the
        # loop.
        del dependencies[index]
        index = index - 1

        # Loop through the targets in the other build file, adding them to
        # this target's list of dependencies in place of the removed
        # wildcard.
        dependency_target_dicts = data[dependency_build_file]['targets']
        for dependency_target_dict in dependency_target_dicts:
          if int(dependency_target_dict.get('suppress_wildcard', False)):
            continue
          dependency_target_name = dependency_target_dict['target_name']
          if (dependency_target != '*' and
              dependency_target != dependency_target_name):
            continue
          dependency_target_toolset = dependency_target_dict['toolset']
          if (dependency_toolset != '*' and
              dependency_toolset != dependency_target_toolset):
            continue
          dependency = gyp.common.QualifiedTarget(dependency_build_file,
                                                  dependency_target_name,
                                                  dependency_target_toolset)
          index = index + 1
          dependencies.insert(index, dependency)

        index = index + 1


def Unify(l):
  """Removes duplicate elements from l, keeping the first element."""
  seen = {}
  return [seen.setdefault(e, e) for e in l if e not in seen]


def RemoveDuplicateDependencies(targets):
  """Makes sure every dependency appears only once in all targets's dependency
  lists."""
  for target_name, target_dict in targets.iteritems():
    for dependency_key in dependency_sections:
      dependencies = target_dict.get(dependency_key, [])
      if dependencies:
        target_dict[dependency_key] = Unify(dependencies)


class DependencyGraphNode(object):
  """

  Attributes:
    ref: A reference to an object that this DependencyGraphNode represents.
    dependencies: List of DependencyGraphNodes on which this one depends.
    dependents: List of DependencyGraphNodes that depend on this one.
  """

  class CircularException(GypError):
    pass

  def __init__(self, ref):
    self.ref = ref
    self.dependencies = []
    self.dependents = []

  def FlattenToList(self):
    # flat_list is the sorted list of dependencies - actually, the list items
    # are the "ref" attributes of DependencyGraphNodes.  Every target will
    # appear in flat_list after all of its dependencies, and before all of its
    # dependents.
    flat_list = []

    # in_degree_zeros is the list of DependencyGraphNodes that have no
    # dependencies not in flat_list.  Initially, it is a copy of the children
    # of this node, because when the graph was built, nodes with no
    # dependencies were made implicit dependents of the root node.
    in_degree_zeros = set(self.dependents[:])

    while in_degree_zeros:
      # Nodes in in_degree_zeros have no dependencies not in flat_list, so they
      # can be appended to flat_list.  Take these nodes out of in_degree_zeros
      # as work progresses, so that the next node to process from the list can
      # always be accessed at a consistent position.
      node = in_degree_zeros.pop()
      flat_list.append(node.ref)

      # Look at dependents of the node just added to flat_list.  Some of them
      # may now belong in in_degree_zeros.
      for node_dependent in node.dependents:
        is_in_degree_zero = True
        for node_dependent_dependency in node_dependent.dependencies:
          if not node_dependent_dependency.ref in flat_list:
            # The dependent one or more dependencies not in flat_list.  There
            # will be more chances to add it to flat_list when examining
            # it again as a dependent of those other dependencies, provided
            # that there are no cycles.
            is_in_degree_zero = False
            break

        if is_in_degree_zero:
          # All of the dependent's dependencies are already in flat_list.  Add
          # it to in_degree_zeros where it will be processed in a future
          # iteration of the outer loop.
          in_degree_zeros.add(node_dependent)

    return flat_list

  def DirectDependencies(self, dependencies=None):
    """Returns a list of just direct dependencies."""
    if dependencies == None:
      dependencies = []

    for dependency in self.dependencies:
      # Check for None, corresponding to the root node.
      if dependency.ref != None and dependency.ref not in dependencies:
        dependencies.append(dependency.ref)

    return dependencies

  def _AddImportedDependencies(self, targets, dependencies=None):
    """Given a list of direct dependencies, adds indirect dependencies that
    other dependencies have declared to export their settings.

    This method does not operate on self.  Rather, it operates on the list
    of dependencies in the |dependencies| argument.  For each dependency in
    that list, if any declares that it exports the settings of one of its
    own dependencies, those dependencies whose settings are "passed through"
    are added to the list.  As new items are added to the list, they too will
    be processed, so it is possible to import settings through multiple levels
    of dependencies.

    This method is not terribly useful on its own, it depends on being
    "primed" with a list of direct dependencies such as one provided by
    DirectDependencies.  DirectAndImportedDependencies is intended to be the
    public entry point.
    """

    if dependencies == None:
      dependencies = []

    index = 0
    while index < len(dependencies):
      dependency = dependencies[index]
      dependency_dict = targets[dependency]
      # Add any dependencies whose settings should be imported to the list
      # if not already present.  Newly-added items will be checked for
      # their own imports when the list iteration reaches them.
      # Rather than simply appending new items, insert them after the
      # dependency that exported them.  This is done to more closely match
      # the depth-first method used by DeepDependencies.
      add_index = 1
      for imported_dependency in \
          dependency_dict.get('export_dependent_settings', []):
        if imported_dependency not in dependencies:
          dependencies.insert(index + add_index, imported_dependency)
          add_index = add_index + 1
      index = index + 1

    return dependencies

  def DirectAndImportedDependencies(self, targets, dependencies=None):
    """Returns a list of a target's direct dependencies and all indirect
    dependencies that a dependency has advertised settings should be exported
    through the dependency for.
    """

    dependencies = self.DirectDependencies(dependencies)
    return self._AddImportedDependencies(targets, dependencies)

  def DeepDependencies(self, dependencies=None):
    """Returns a list of all of a target's dependencies, recursively."""
    if dependencies == None:
      dependencies = []

    for dependency in self.dependencies:
      # Check for None, corresponding to the root node.
      if dependency.ref != None and dependency.ref not in dependencies:
        dependencies.append(dependency.ref)
        dependency.DeepDependencies(dependencies)

    return dependencies

  def LinkDependencies(self, targets, dependencies=None, initial=True):
    """Returns a list of dependency targets that are linked into this target.

    This function has a split personality, depending on the setting of
    |initial|.  Outside callers should always leave |initial| at its default
    setting.

    When adding a target to the list of dependencies, this function will
    recurse into itself with |initial| set to False, to collect dependencies
    that are linked into the linkable target for which the list is being built.
    """
    if dependencies == None:
      dependencies = []

    # Check for None, corresponding to the root node.
    if self.ref == None:
      return dependencies

    # It's kind of sucky that |targets| has to be passed into this function,
    # but that's presently the easiest way to access the target dicts so that
    # this function can find target types.

    if 'target_name' not in targets[self.ref]:
      raise GypError("Missing 'target_name' field in target.")

    if 'type' not in targets[self.ref]:
      raise GypError("Missing 'type' field in target %s" %
                     targets[self.ref]['target_name'])

    target_type = targets[self.ref]['type']

    is_linkable = target_type in linkable_types

    if initial and not is_linkable:
      # If this is the first target being examined and it's not linkable,
      # return an empty list of link dependencies, because the link
      # dependencies are intended to apply to the target itself (initial is
      # True) and this target won't be linked.
      return dependencies

    # Don't traverse 'none' targets if explicitly excluded.
    if (target_type == 'none' and
        not targets[self.ref].get('dependencies_traverse', True)):
      if self.ref not in dependencies:
        dependencies.append(self.ref)
      return dependencies

    # Executables and loadable modules are already fully and finally linked.
    # Nothing else can be a link dependency of them, there can only be
    # dependencies in the sense that a dependent target might run an
    # executable or load the loadable_module.
    if not initial and target_type in ('executable', 'loadable_module'):
      return dependencies

    # The target is linkable, add it to the list of link dependencies.
    if self.ref not in dependencies:
      dependencies.append(self.ref)
      if initial or not is_linkable:
        # If this is a subsequent target and it's linkable, don't look any
        # further for linkable dependencies, as they'll already be linked into
        # this target linkable.  Always look at dependencies of the initial
        # target, and always look at dependencies of non-linkables.
        for dependency in self.dependencies:
          dependency.LinkDependencies(targets, dependencies, False)

    return dependencies


def BuildDependencyList(targets):
  # Create a DependencyGraphNode for each target.  Put it into a dict for easy
  # access.
  dependency_nodes = {}
  for target, spec in targets.iteritems():
    if target not in dependency_nodes:
      dependency_nodes[target] = DependencyGraphNode(target)

  # Set up the dependency links.  Targets that have no dependencies are treated
  # as dependent on root_node.
  root_node = DependencyGraphNode(None)
  for target, spec in targets.iteritems():
    target_node = dependency_nodes[target]
    target_build_file = gyp.common.BuildFile(target)
    dependencies = spec.get('dependencies')
    if not dependencies:
      target_node.dependencies = [root_node]
      root_node.dependents.append(target_node)
    else:
      for dependency in dependencies:
        dependency_node = dependency_nodes.get(dependency)
        if not dependency_node:
          raise GypError("Dependency '%s' not found while "
                         "trying to load target %s" % (dependency, target))
        target_node.dependencies.append(dependency_node)
        dependency_node.dependents.append(target_node)

  flat_list = root_node.FlattenToList()

  # If there's anything left unvisited, there must be a circular dependency
  # (cycle).  If you need to figure out what's wrong, look for elements of
  # targets that are not in flat_list.
  if len(flat_list) != len(targets):
    raise DependencyGraphNode.CircularException(
        'Some targets not reachable, cycle in dependency graph detected: ' +
        ' '.join(set(flat_list) ^ set(targets)))

  return [dependency_nodes, flat_list]


def VerifyNoGYPFileCircularDependencies(targets):
  # Create a DependencyGraphNode for each gyp file containing a target.  Put
  # it into a dict for easy access.
  dependency_nodes = {}
  for target in targets.iterkeys():
    build_file = gyp.common.BuildFile(target)
    if not build_file in dependency_nodes:
      dependency_nodes[build_file] = DependencyGraphNode(build_file)

  # Set up the dependency links.
  for target, spec in targets.iteritems():
    build_file = gyp.common.BuildFile(target)
    build_file_node = dependency_nodes[build_file]
    target_dependencies = spec.get('dependencies', [])
    for dependency in target_dependencies:
      try:
        dependency_build_file = gyp.common.BuildFile(dependency)
      except GypError, e:
        gyp.common.ExceptionAppend(
            e, 'while computing dependencies of .gyp file %s' % build_file)
        raise

      if dependency_build_file == build_file:
        # A .gyp file is allowed to refer back to itself.
        continue
      dependency_node = dependency_nodes.get(dependency_build_file)
      if not dependency_node:
        raise GypError("Dependancy '%s' not found" % dependency_build_file)
      if dependency_node not in build_file_node.dependencies:
        build_file_node.dependencies.append(dependency_node)
        dependency_node.dependents.append(build_file_node)


  # Files that have no dependencies are treated as dependent on root_node.
  root_node = DependencyGraphNode(None)
  for build_file_node in dependency_nodes.itervalues():
    if len(build_file_node.dependencies) == 0:
      build_file_node.dependencies.append(root_node)
      root_node.dependents.append(build_file_node)

  flat_list = root_node.FlattenToList()

  # If there's anything left unvisited, there must be a circular dependency
  # (cycle).
  if len(flat_list) != len(dependency_nodes):
    bad_files = []
    for file in dependency_nodes.iterkeys():
      if not file in flat_list:
        bad_files.append(file)
    raise DependencyGraphNode.CircularException, \
        'Some files not reachable, cycle in .gyp file dependency graph ' + \
        'detected involving some or all of: ' + \
        ' '.join(bad_files)


def DoDependentSettings(key, flat_list, targets, dependency_nodes):
  # key should be one of all_dependent_settings, direct_dependent_settings,
  # or link_settings.

  for target in flat_list:
    target_dict = targets[target]
    build_file = gyp.common.BuildFile(target)

    if key == 'all_dependent_settings':
      dependencies = dependency_nodes[target].DeepDependencies()
    elif key == 'direct_dependent_settings':
      dependencies = \
          dependency_nodes[target].DirectAndImportedDependencies(targets)
    elif key == 'link_settings':
      dependencies = dependency_nodes[target].LinkDependencies(targets)
    else:
      raise GypError("DoDependentSettings doesn't know how to determine "
                      'dependencies for ' + key)

    for dependency in dependencies:
      dependency_dict = targets[dependency]
      if not key in dependency_dict:
        continue
      dependency_build_file = gyp.common.BuildFile(dependency)
      MergeDicts(target_dict, dependency_dict[key],
                 build_file, dependency_build_file)


def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes,
                                    sort_dependencies):
  # Recompute target "dependencies" properties.  For each static library
  # target, remove "dependencies" entries referring to other static libraries,
  # unless the dependency has the "hard_dependency" attribute set.  For each
  # linkable target, add a "dependencies" entry referring to all of the
  # target's computed list of link dependencies (including static libraries
  # if no such entry is already present.
  for target in flat_list:
    target_dict = targets[target]
    target_type = target_dict['type']

    if target_type == 'static_library':
      if not 'dependencies' in target_dict:
        continue

      target_dict['dependencies_original'] = target_dict.get(
          'dependencies', [])[:]

      # A static library should not depend on another static library unless
      # the dependency relationship is "hard," which should only be done when
      # a dependent relies on some side effect other than just the build
      # product, like a rule or action output. Further, if a target has a
      # non-hard dependency, but that dependency exports a hard dependency,
      # the non-hard dependency can safely be removed, but the exported hard
      # dependency must be added to the target to keep the same dependency
      # ordering.
      dependencies = \
          dependency_nodes[target].DirectAndImportedDependencies(targets)
      index = 0
      while index < len(dependencies):
        dependency = dependencies[index]
        dependency_dict = targets[dependency]

        # Remove every non-hard static library dependency and remove every
        # non-static library dependency that isn't a direct dependency.
        if (dependency_dict['type'] == 'static_library' and \
            not dependency_dict.get('hard_dependency', False)) or \
           (dependency_dict['type'] != 'static_library' and \
            not dependency in target_dict['dependencies']):
          # Take the dependency out of the list, and don't increment index
          # because the next dependency to analyze will shift into the index
          # formerly occupied by the one being removed.
          del dependencies[index]
        else:
          index = index + 1

      # Update the dependencies. If the dependencies list is empty, it's not
      # needed, so unhook it.
      if len(dependencies) > 0:
        target_dict['dependencies'] = dependencies
      else:
        del target_dict['dependencies']

    elif target_type in linkable_types:
      # Get a list of dependency targets that should be linked into this
      # target.  Add them to the dependencies list if they're not already
      # present.

      link_dependencies = dependency_nodes[target].LinkDependencies(targets)
      for dependency in link_dependencies:
        if dependency == target:
          continue
        if not 'dependencies' in target_dict:
          target_dict['dependencies'] = []
        if not dependency in target_dict['dependencies']:
          target_dict['dependencies'].append(dependency)
      # Sort the dependencies list in the order from dependents to dependencies.
      # e.g. If A and B depend on C and C depends on D, sort them in A, B, C, D.
      # Note: flat_list is already sorted in the order from dependencies to
      # dependents.
      if sort_dependencies and 'dependencies' in target_dict:
        target_dict['dependencies'] = [dep for dep in reversed(flat_list)
                                       if dep in target_dict['dependencies']]


# Initialize this here to speed up MakePathRelative.
exception_re = re.compile(r'''["']?[-/$<>^]''')


def MakePathRelative(to_file, fro_file, item):
  # If item is a relative path, it's relative to the build file dict that it's
  # coming from.  Fix it up to make it relative to the build file dict that
  # it's going into.
  # Exception: any |item| that begins with these special characters is
  # returned without modification.
  #   /   Used when a path is already absolute (shortcut optimization;
  #       such paths would be returned as absolute anyway)
  #   $   Used for build environment variables
  #   -   Used for some build environment flags (such as -lapr-1 in a
  #       "libraries" section)
  #   <   Used for our own variable and command expansions (see ExpandVariables)
  #   >   Used for our own variable and command expansions (see ExpandVariables)
  #   ^   Used for our own variable and command expansions (see ExpandVariables)
  #
  #   "/' Used when a value is quoted.  If these are present, then we
  #       check the second character instead.
  #
  if to_file == fro_file or exception_re.match(item):
    return item
  else:
    # TODO(dglazkov) The backslash/forward-slash replacement at the end is a
    # temporary measure. This should really be addressed by keeping all paths
    # in POSIX until actual project generation.
    ret = os.path.normpath(os.path.join(
        gyp.common.RelativePath(os.path.dirname(fro_file),
                                os.path.dirname(to_file)),
                                item)).replace('\\', '/')
    if item[-1] == '/':
      ret += '/'
    return ret

def MergeLists(to, fro, to_file, fro_file, is_paths=False, append=True):
  def is_hashable(x):
    try:
      hash(x)
    except TypeError:
      return False
    return True
  # If x is hashable, returns whether x is in s. Else returns whether x is in l.
  def is_in_set_or_list(x, s, l):
    if is_hashable(x):
      return x in s
    return x in l

  prepend_index = 0

  # Make membership testing of hashables in |to| (in particular, strings)
  # faster.
  hashable_to_set = set([x for x in to if is_hashable(x)])

  for item in fro:
    singleton = False
    if isinstance(item, str) or isinstance(item, int):
      # The cheap and easy case.
      if is_paths:
        to_item = MakePathRelative(to_file, fro_file, item)
      else:
        to_item = item

      if not isinstance(item, str) or not item.startswith('-'):
        # Any string that doesn't begin with a "-" is a singleton - it can
        # only appear once in a list, to be enforced by the list merge append
        # or prepend.
        singleton = True
    elif isinstance(item, dict):
      # Make a copy of the dictionary, continuing to look for paths to fix.
      # The other intelligent aspects of merge processing won't apply because
      # item is being merged into an empty dict.
      to_item = {}
      MergeDicts(to_item, item, to_file, fro_file)
    elif isinstance(item, list):
      # Recurse, making a copy of the list.  If the list contains any
      # descendant dicts, path fixing will occur.  Note that here, custom
      # values for is_paths and append are dropped; those are only to be
      # applied to |to| and |fro|, not sublists of |fro|.  append shouldn't
      # matter anyway because the new |to_item| list is empty.
      to_item = []
      MergeLists(to_item, item, to_file, fro_file)
    else:
      raise TypeError, \
          'Attempt to merge list item of unsupported type ' + \
          item.__class__.__name__

    if append:
      # If appending a singleton that's already in the list, don't append.
      # This ensures that the earliest occurrence of the item will stay put.
      if not singleton or not is_in_set_or_list(to_item, hashable_to_set, to):
        to.append(to_item)
        if is_hashable(to_item):
          hashable_to_set.add(to_item)
    else:
      # If prepending a singleton that's already in the list, remove the
      # existing instance and proceed with the prepend.  This ensures that the
      # item appears at the earliest possible position in the list.
      while singleton and to_item in to:
        to.remove(to_item)

      # Don't just insert everything at index 0.  That would prepend the new
      # items to the list in reverse order, which would be an unwelcome
      # surprise.
      to.insert(prepend_index, to_item)
      if is_hashable(to_item):
        hashable_to_set.add(to_item)
      prepend_index = prepend_index + 1


def MergeDicts(to, fro, to_file, fro_file):
  # I wanted to name the parameter "from" but it's a Python keyword...
  for k, v in fro.iteritems():
    # It would be nice to do "if not k in to: to[k] = v" but that wouldn't give
    # copy semantics.  Something else may want to merge from the |fro| dict
    # later, and having the same dict ref pointed to twice in the tree isn't
    # what anyone wants considering that the dicts may subsequently be
    # modified.
    if k in to:
      bad_merge = False
      if isinstance(v, str) or isinstance(v, int):
        if not (isinstance(to[k], str) or isinstance(to[k], int)):
          bad_merge = True
      elif v.__class__ != to[k].__class__:
        bad_merge = True

      if bad_merge:
        raise TypeError, \
            'Attempt to merge dict value of type ' + v.__class__.__name__ + \
            ' into incompatible type ' + to[k].__class__.__name__ + \
            ' for key ' + k
    if isinstance(v, str) or isinstance(v, int):
      # Overwrite the existing value, if any.  Cheap and easy.
      is_path = IsPathSection(k)
      if is_path:
        to[k] = MakePathRelative(to_file, fro_file, v)
      else:
        to[k] = v
    elif isinstance(v, dict):
      # Recurse, guaranteeing copies will be made of objects that require it.
      if not k in to:
        to[k] = {}
      MergeDicts(to[k], v, to_file, fro_file)
    elif isinstance(v, list):
      # Lists in dicts can be merged with different policies, depending on
      # how the key in the "from" dict (k, the from-key) is written.
      #
      # If the from-key has          ...the to-list will have this action
      # this character appended:...     applied when receiving the from-list:
      #                           =  replace
      #                           +  prepend
      #                           ?  set, only if to-list does not yet exist
      #                      (none)  append
      #
      # This logic is list-specific, but since it relies on the associated
      # dict key, it's checked in this dict-oriented function.
      ext = k[-1]
      append = True
      if ext == '=':
        list_base = k[:-1]
        lists_incompatible = [list_base, list_base + '?']
        to[list_base] = []
      elif ext == '+':
        list_base = k[:-1]
        lists_incompatible = [list_base + '=', list_base + '?']
        append = False
      elif ext == '?':
        list_base = k[:-1]
        lists_incompatible = [list_base, list_base + '=', list_base + '+']
      else:
        list_base = k
        lists_incompatible = [list_base + '=', list_base + '?']

      # Some combinations of merge policies appearing together are meaningless.
      # It's stupid to replace and append simultaneously, for example.  Append
      # and prepend are the only policies that can coexist.
      for list_incompatible in lists_incompatible:
        if list_incompatible in fro:
          raise GypError('Incompatible list policies ' + k + ' and ' +
                         list_incompatible)

      if list_base in to:
        if ext == '?':
          # If the key ends in "?", the list will only be merged if it doesn't
          # already exist.
          continue
        if not isinstance(to[list_base], list):
          # This may not have been checked above if merging in a list with an
          # extension character.
          raise TypeError, \
              'Attempt to merge dict value of type ' + v.__class__.__name__ + \
              ' into incompatible type ' + to[list_base].__class__.__name__ + \
              ' for key ' + list_base + '(' + k + ')'
      else:
        to[list_base] = []

      # Call MergeLists, which will make copies of objects that require it.
      # MergeLists can recurse back into MergeDicts, although this will be
      # to make copies of dicts (with paths fixed), there will be no
      # subsequent dict "merging" once entering a list because lists are
      # always replaced, appended to, or prepended to.
      is_paths = IsPathSection(list_base)
      MergeLists(to[list_base], v, to_file, fro_file, is_paths, append)
    else:
      raise TypeError, \
          'Attempt to merge dict value of unsupported type ' + \
          v.__class__.__name__ + ' for key ' + k


def MergeConfigWithInheritance(new_configuration_dict, build_file,
                               target_dict, configuration, visited):
  # Skip if previously visted.
  if configuration in visited:
    return

  # Look at this configuration.
  configuration_dict = target_dict['configurations'][configuration]

  # Merge in parents.
  for parent in configuration_dict.get('inherit_from', []):
    MergeConfigWithInheritance(new_configuration_dict, build_file,
                               target_dict, parent, visited + [configuration])

  # Merge it into the new config.
  MergeDicts(new_configuration_dict, configuration_dict,
             build_file, build_file)

  # Drop abstract.
  if 'abstract' in new_configuration_dict:
    del new_configuration_dict['abstract']


def SetUpConfigurations(target, target_dict):
  # key_suffixes is a list of key suffixes that might appear on key names.
  # These suffixes are handled in conditional evaluations (for =, +, and ?)
  # and rules/exclude processing (for ! and /).  Keys with these suffixes
  # should be treated the same as keys without.
  key_suffixes = ['=', '+', '?', '!', '/']

  build_file = gyp.common.BuildFile(target)

  # Provide a single configuration by default if none exists.
  # TODO(mark): Signal an error if default_configurations exists but
  # configurations does not.
  if not 'configurations' in target_dict:
    target_dict['configurations'] = {'Default': {}}
  if not 'default_configuration' in target_dict:
    concrete = [i for i in target_dict['configurations'].keys()
                if not target_dict['configurations'][i].get('abstract')]
    target_dict['default_configuration'] = sorted(concrete)[0]

  for configuration in target_dict['configurations'].keys():
    old_configuration_dict = target_dict['configurations'][configuration]
    # Skip abstract configurations (saves work only).
    if old_configuration_dict.get('abstract'):
      continue
    # Configurations inherit (most) settings from the enclosing target scope.
    # Get the inheritance relationship right by making a copy of the target
    # dict.
    new_configuration_dict = copy.deepcopy(target_dict)

    # Take out the bits that don't belong in a "configurations" section.
    # Since configuration setup is done before conditional, exclude, and rules
    # processing, be careful with handling of the suffix characters used in
    # those phases.
    delete_keys = []
    for key in new_configuration_dict:
      key_ext = key[-1:]
      if key_ext in key_suffixes:
        key_base = key[:-1]
      else:
        key_base = key
      if key_base in non_configuration_keys:
        delete_keys.append(key)

    for key in delete_keys:
      del new_configuration_dict[key]

    # Merge in configuration (with all its parents first).
    MergeConfigWithInheritance(new_configuration_dict, build_file,
                               target_dict, configuration, [])

    # Put the new result back into the target dict as a configuration.
    target_dict['configurations'][configuration] = new_configuration_dict

  # Now drop all the abstract ones.
  for configuration in target_dict['configurations'].keys():
    old_configuration_dict = target_dict['configurations'][configuration]
    if old_configuration_dict.get('abstract'):
      del target_dict['configurations'][configuration]

  # Now that all of the target's configurations have been built, go through
  # the target dict's keys and remove everything that's been moved into a
  # "configurations" section.
  delete_keys = []
  for key in target_dict:
    key_ext = key[-1:]
    if key_ext in key_suffixes:
      key_base = key[:-1]
    else:
      key_base = key
    if not key_base in non_configuration_keys:
      delete_keys.append(key)
  for key in delete_keys:
    del target_dict[key]

  # Check the configurations to see if they contain invalid keys.
  for configuration in target_dict['configurations'].keys():
    configuration_dict = target_dict['configurations'][configuration]
    for key in configuration_dict.keys():
      if key in invalid_configuration_keys:
        raise GypError('%s not allowed in the %s configuration, found in '
                       'target %s' % (key, configuration, target))



def ProcessListFiltersInDict(name, the_dict):
  """Process regular expression and exclusion-based filters on lists.

  An exclusion list is in a dict key named with a trailing "!", like
  "sources!".  Every item in such a list is removed from the associated
  main list, which in this example, would be "sources".  Removed items are
  placed into a "sources_excluded" list in the dict.

  Regular expression (regex) filters are contained in dict keys named with a
  trailing "/", such as "sources/" to operate on the "sources" list.  Regex
  filters in a dict take the form:
    'sources/': [ ['exclude', '_(linux|mac|win)\\.cc$'],
                  ['include', '_mac\\.cc$'] ],
  The first filter says to exclude all files ending in _linux.cc, _mac.cc, and
  _win.cc.  The second filter then includes all files ending in _mac.cc that
  are now or were once in the "sources" list.  Items matching an "exclude"
  filter are subject to the same processing as would occur if they were listed
  by name in an exclusion list (ending in "!").  Items matching an "include"
  filter are brought back into the main list if previously excluded by an
  exclusion list or exclusion regex filter.  Subsequent matching "exclude"
  patterns can still cause items to be excluded after matching an "include".
  """

  # Look through the dictionary for any lists whose keys end in "!" or "/".
  # These are lists that will be treated as exclude lists and regular
  # expression-based exclude/include lists.  Collect the lists that are
  # needed first, looking for the lists that they operate on, and assemble
  # then into |lists|.  This is done in a separate loop up front, because
  # the _included and _excluded keys need to be added to the_dict, and that
  # can't be done while iterating through it.

  lists = []
  del_lists = []
  for key, value in the_dict.iteritems():
    operation = key[-1]
    if operation != '!' and operation != '/':
      continue

    if not isinstance(value, list):
      raise ValueError, name + ' key ' + key + ' must be list, not ' + \
                        value.__class__.__name__

    list_key = key[:-1]
    if list_key not in the_dict:
      # This happens when there's a list like "sources!" but no corresponding
      # "sources" list.  Since there's nothing for it to operate on, queue up
      # the "sources!" list for deletion now.
      del_lists.append(key)
      continue

    if not isinstance(the_dict[list_key], list):
      raise ValueError, name + ' key ' + list_key + \
                        ' must be list, not ' + \
                        value.__class__.__name__ + ' when applying ' + \
                        {'!': 'exclusion', '/': 'regex'}[operation]

    if not list_key in lists:
      lists.append(list_key)

  # Delete the lists that are known to be unneeded at this point.
  for del_list in del_lists:
    del the_dict[del_list]

  for list_key in lists:
    the_list = the_dict[list_key]

    # Initialize the list_actions list, which is parallel to the_list.  Each
    # item in list_actions identifies whether the corresponding item in
    # the_list should be excluded, unconditionally preserved (included), or
    # whether no exclusion or inclusion has been applied.  Items for which
    # no exclusion or inclusion has been applied (yet) have value -1, items
    # excluded have value 0, and items included have value 1.  Includes and
    # excludes override previous actions.  All items in list_actions are
    # initialized to -1 because no excludes or includes have been processed
    # yet.
    list_actions = list((-1,) * len(the_list))

    exclude_key = list_key + '!'
    if exclude_key in the_dict:
      for exclude_item in the_dict[exclude_key]:
        for index in xrange(0, len(the_list)):
          if exclude_item == the_list[index]:
            # This item matches the exclude_item, so set its action to 0
            # (exclude).
            list_actions[index] = 0

      # The "whatever!" list is no longer needed, dump it.
      del the_dict[exclude_key]

    regex_key = list_key + '/'
    if regex_key in the_dict:
      for regex_item in the_dict[regex_key]:
        [action, pattern] = regex_item
        pattern_re = re.compile(pattern)

        if action == 'exclude':
          # This item matches an exclude regex, so set its value to 0 (exclude).
          action_value = 0
        elif action == 'include':
          # This item matches an include regex, so set its value to 1 (include).
          action_value = 1
        else:
          # This is an action that doesn't make any sense.
          raise ValueError, 'Unrecognized action ' + action + ' in ' + name + \
                            ' key ' + regex_key

        for index in xrange(0, len(the_list)):
          list_item = the_list[index]
          if list_actions[index] == action_value:
            # Even if the regex matches, nothing will change so continue (regex
            # searches are expensive).
            continue
          if pattern_re.search(list_item):
            # Regular expression match.
            list_actions[index] = action_value

      # The "whatever/" list is no longer needed, dump it.
      del the_dict[regex_key]

    # Add excluded items to the excluded list.
    #
    # Note that exclude_key ("sources!") is different from excluded_key
    # ("sources_excluded").  The exclude_key list is input and it was already
    # processed and deleted; the excluded_key list is output and it's about
    # to be created.
    excluded_key = list_key + '_excluded'
    if excluded_key in the_dict:
      raise GypError(name + ' key ' + excluded_key +
                     ' must not be present prior '
                     ' to applying exclusion/regex filters for ' + list_key)

    excluded_list = []

    # Go backwards through the list_actions list so that as items are deleted,
    # the indices of items that haven't been seen yet don't shift.  That means
    # that things need to be prepended to excluded_list to maintain them in the
    # same order that they existed in the_list.
    for index in xrange(len(list_actions) - 1, -1, -1):
      if list_actions[index] == 0:
        # Dump anything with action 0 (exclude).  Keep anything with action 1
        # (include) or -1 (no include or exclude seen for the item).
        excluded_list.insert(0, the_list[index])
        del the_list[index]

    # If anything was excluded, put the excluded list into the_dict at
    # excluded_key.
    if len(excluded_list) > 0:
      the_dict[excluded_key] = excluded_list

  # Now recurse into subdicts and lists that may contain dicts.
  for key, value in the_dict.iteritems():
    if isinstance(value, dict):
      ProcessListFiltersInDict(key, value)
    elif isinstance(value, list):
      ProcessListFiltersInList(key, value)


def ProcessListFiltersInList(name, the_list):
  for item in the_list:
    if isinstance(item, dict):
      ProcessListFiltersInDict(name, item)
    elif isinstance(item, list):
      ProcessListFiltersInList(name, item)


def ValidateTargetType(target, target_dict):
  """Ensures the 'type' field on the target is one of the known types.

  Arguments:
    target: string, name of target.
    target_dict: dict, target spec.

  Raises an exception on error.
  """
  VALID_TARGET_TYPES = ('executable', 'loadable_module',
                        'static_library', 'shared_library',
                        'none')
  target_type = target_dict.get('type', None)
  if target_type not in VALID_TARGET_TYPES:
    raise GypError("Target %s has an invalid target type '%s'.  "
                   "Must be one of %s." %
                   (target, target_type, '/'.join(VALID_TARGET_TYPES)))
  if (target_dict.get('standalone_static_library', 0) and
      not target_type == 'static_library'):
    raise GypError('Target %s has type %s but standalone_static_library flag is'
                   ' only valid for static_library type.' % (target,
                                                             target_type))


def ValidateSourcesInTarget(target, target_dict, build_file):
  # TODO: Check if MSVC allows this for loadable_module targets.
  if target_dict.get('type', None) not in ('static_library', 'shared_library'):
    return
  sources = target_dict.get('sources', [])
  basenames = {}
  for source in sources:
    name, ext = os.path.splitext(source)
    is_compiled_file = ext in [
        '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S']
    if not is_compiled_file:
      continue
    basename = os.path.basename(name)  # Don't include extension.
    basenames.setdefault(basename, []).append(source)

  error = ''
  for basename, files in basenames.iteritems():
    if len(files) > 1:
      error += '  %s: %s\n' % (basename, ' '.join(files))

  if error:
    print('static library %s has several files with the same basename:\n' %
          target + error + 'Some build systems, e.g. MSVC08, '
          'cannot handle that.')
    raise GypError('Duplicate basenames in sources section, see list above')


def ValidateRulesInTarget(target, target_dict, extra_sources_for_rules):
  """Ensures that the rules sections in target_dict are valid and consistent,
  and determines which sources they apply to.

  Arguments:
    target: string, name of target.
    target_dict: dict, target spec containing "rules" and "sources" lists.
    extra_sources_for_rules: a list of keys to scan for rule matches in
        addition to 'sources'.
  """

  # Dicts to map between values found in rules' 'rule_name' and 'extension'
  # keys and the rule dicts themselves.
  rule_names = {}
  rule_extensions = {}

  rules = target_dict.get('rules', [])
  for rule in rules:
    # Make sure that there's no conflict among rule names and extensions.
    rule_name = rule['rule_name']
    if rule_name in rule_names:
      raise GypError('rule %s exists in duplicate, target %s' %
                     (rule_name, target))
    rule_names[rule_name] = rule

    rule_extension = rule['extension']
    if rule_extension in rule_extensions:
      raise GypError(('extension %s associated with multiple rules, ' +
                      'target %s rules %s and %s') %
                     (rule_extension, target,
                      rule_extensions[rule_extension]['rule_name'],
                      rule_name))
    rule_extensions[rule_extension] = rule

    # Make sure rule_sources isn't already there.  It's going to be
    # created below if needed.
    if 'rule_sources' in rule:
      raise GypError(
            'rule_sources must not exist in input, target %s rule %s' %
            (target, rule_name))
    extension = rule['extension']

    rule_sources = []
    source_keys = ['sources']
    source_keys.extend(extra_sources_for_rules)
    for source_key in source_keys:
      for source in target_dict.get(source_key, []):
        (source_root, source_extension) = os.path.splitext(source)
        if source_extension.startswith('.'):
          source_extension = source_extension[1:]
        if source_extension == extension:
          rule_sources.append(source)

    if len(rule_sources) > 0:
      rule['rule_sources'] = rule_sources


def ValidateRunAsInTarget(target, target_dict, build_file):
  target_name = target_dict.get('target_name')
  run_as = target_dict.get('run_as')
  if not run_as:
    return
  if not isinstance(run_as, dict):
    raise GypError("The 'run_as' in target %s from file %s should be a "
                   "dictionary." %
                   (target_name, build_file))
  action = run_as.get('action')
  if not action:
    raise GypError("The 'run_as' in target %s from file %s must have an "
                   "'action' section." %
                   (target_name, build_file))
  if not isinstance(action, list):
    raise GypError("The 'action' for 'run_as' in target %s from file %s "
                   "must be a list." %
                   (target_name, build_file))
  working_directory = run_as.get('working_directory')
  if working_directory and not isinstance(working_directory, str):
    raise GypError("The 'working_directory' for 'run_as' in target %s "
                   "in file %s should be a string." %
                   (target_name, build_file))
  environment = run_as.get('environment')
  if environment and not isinstance(environment, dict):
    raise GypError("The 'environment' for 'run_as' in target %s "
                   "in file %s should be a dictionary." %
                   (target_name, build_file))


def ValidateActionsInTarget(target, target_dict, build_file):
  '''Validates the inputs to the actions in a target.'''
  target_name = target_dict.get('target_name')
  actions = target_dict.get('actions', [])
  for action in actions:
    action_name = action.get('action_name')
    if not action_name:
      raise GypError("Anonymous action in target %s.  "
                     "An action must have an 'action_name' field." %
                     target_name)
    inputs = action.get('inputs', None)
    if inputs is None:
      raise GypError('Action in target %s has no inputs.' % target_name)
    action_command = action.get('action')
    if action_command and not action_command[0]:
      raise GypError("Empty action as command in target %s." % target_name)


def TurnIntIntoStrInDict(the_dict):
  """Given dict the_dict, recursively converts all integers into strings.
  """
  # Use items instead of iteritems because there's no need to try to look at
  # reinserted keys and their associated values.
  for k, v in the_dict.items():
    if isinstance(v, int):
      v = str(v)
      the_dict[k] = v
    elif isinstance(v, dict):
      TurnIntIntoStrInDict(v)
    elif isinstance(v, list):
      TurnIntIntoStrInList(v)

    if isinstance(k, int):
      the_dict[str(k)] = v
      del the_dict[k]


def TurnIntIntoStrInList(the_list):
  """Given list the_list, recursively converts all integers into strings.
  """
  for index in xrange(0, len(the_list)):
    item = the_list[index]
    if isinstance(item, int):
      the_list[index] = str(item)
    elif isinstance(item, dict):
      TurnIntIntoStrInDict(item)
    elif isinstance(item, list):
      TurnIntIntoStrInList(item)


def VerifyNoCollidingTargets(targets):
  """Verify that no two targets in the same directory share the same name.

  Arguments:
    targets: A list of targets in the form 'path/to/file.gyp:target_name'.
  """
  # Keep a dict going from 'subdirectory:target_name' to 'foo.gyp'.
  used = {}
  for target in targets:
    # Separate out 'path/to/file.gyp, 'target_name' from
    # 'path/to/file.gyp:target_name'.
    path, name = target.rsplit(':', 1)
    # Separate out 'path/to', 'file.gyp' from 'path/to/file.gyp'.
    subdir, gyp = os.path.split(path)
    # Use '.' for the current directory '', so that the error messages make
    # more sense.
    if not subdir:
      subdir = '.'
    # Prepare a key like 'path/to:target_name'.
    key = subdir + ':' + name
    if key in used:
      # Complain if this target is already used.
      raise GypError('Duplicate target name "%s" in directory "%s" used both '
                     'in "%s" and "%s".' % (name, subdir, gyp, used[key]))
    used[key] = gyp


def Load(build_files, variables, includes, depth, generator_input_info, check,
         circular_check, parallel):
  # Set up path_sections and non_configuration_keys with the default data plus
  # the generator-specifc data.
  global path_sections
  path_sections = base_path_sections[:]
  path_sections.extend(generator_input_info['path_sections'])

  global non_configuration_keys
  non_configuration_keys = base_non_configuration_keys[:]
  non_configuration_keys.extend(generator_input_info['non_configuration_keys'])

  # TODO(mark) handle variants if the generator doesn't want them directly.
  generator_handles_variants = \
      generator_input_info['generator_handles_variants']

  global absolute_build_file_paths
  absolute_build_file_paths = \
      generator_input_info['generator_wants_absolute_build_file_paths']

  global multiple_toolsets
  multiple_toolsets = generator_input_info[
      'generator_supports_multiple_toolsets']

  # A generator can have other lists (in addition to sources) be processed
  # for rules.
  extra_sources_for_rules = generator_input_info['extra_sources_for_rules']

  # Load build files.  This loads every target-containing build file into
  # the |data| dictionary such that the keys to |data| are build file names,
  # and the values are the entire build file contents after "early" or "pre"
  # processing has been done and includes have been resolved.
  # NOTE: data contains both "target" files (.gyp) and "includes" (.gypi), as
  # well as meta-data (e.g. 'included_files' key). 'target_build_files' keeps
  # track of the keys corresponding to "target" files.
  data = {'target_build_files': set()}
  aux_data = {}
  for build_file in build_files:
    # Normalize paths everywhere.  This is important because paths will be
    # used as keys to the data dict and for references between input files.
    build_file = os.path.normpath(build_file)
    try:
      if parallel:
        print >>sys.stderr, 'Using parallel processing (experimental).'
        LoadTargetBuildFileParallel(build_file, data, aux_data,
                                    variables, includes, depth, check)
      else:
        LoadTargetBuildFile(build_file, data, aux_data,
                            variables, includes, depth, check, True)
    except Exception, e:
      gyp.common.ExceptionAppend(e, 'while trying to load %s' % build_file)
      raise

  # Build a dict to access each target's subdict by qualified name.
  targets = BuildTargetsDict(data)

  # Fully qualify all dependency links.
  QualifyDependencies(targets)

  # Expand dependencies specified as build_file:*.
  ExpandWildcardDependencies(targets, data)

  # Apply exclude (!) and regex (/) list filters only for dependency_sections.
  for target_name, target_dict in targets.iteritems():
    tmp_dict = {}
    for key_base in dependency_sections:
      for op in ('', '!', '/'):
        key = key_base + op
        if key in target_dict:
          tmp_dict[key] = target_dict[key]
          del target_dict[key]
    ProcessListFiltersInDict(target_name, tmp_dict)
    # Write the results back to |target_dict|.
    for key in tmp_dict:
      target_dict[key] = tmp_dict[key]

  # Make sure every dependency appears at most once.
  RemoveDuplicateDependencies(targets)

  if circular_check:
    # Make sure that any targets in a.gyp don't contain dependencies in other
    # .gyp files that further depend on a.gyp.
    VerifyNoGYPFileCircularDependencies(targets)

  [dependency_nodes, flat_list] = BuildDependencyList(targets)

  # Check that no two targets in the same directory have the same name.
  VerifyNoCollidingTargets(flat_list)

  # now that we have the entire dependency graph we can print it if asked
  # we print it to stdout in completely dry python dictionary syntax
  # each key in the dictionary is a target, the value is a list of direct
  # dependencies that target has
  if gyp.DEBUG_DEPENDENCIES in gyp.debug.keys():
    depends_dict = {}
    def clean_node_name(node_name):
      # remove the '#target' suffix from all names
      # and add the product_name
      colon = node_name.index(':')
      target_name = node_name[colon+1:-len('#target')]
      gyp_path = node_name[:colon]
      product_name = targets[node_name].get('product_name', target_name)
      return gyp_path + ':' + target_name + ':' + product_name
    for node_name, node in dependency_nodes.iteritems():
      cleaned_list = [clean_node_name(i) for i in node.DirectDependencies()]
      depends_dict[clean_node_name(node_name)] = cleaned_list
    print 'depends_dict = %s' % depends_dict

  # Handle dependent settings of various types.
  for settings_type in ['all_dependent_settings',
                        'direct_dependent_settings',
                        'link_settings']:
    DoDependentSettings(settings_type, flat_list, targets, dependency_nodes)

    # Take out the dependent settings now that they've been published to all
    # of the targets that require them.
    for target in flat_list:
      if settings_type in targets[target]:
        del targets[target][settings_type]

  # Make sure static libraries don't declare dependencies on other static
  # libraries, but that linkables depend on all unlinked static libraries
  # that they need so that their link steps will be correct.
  gii = generator_input_info
  if gii['generator_wants_static_library_dependencies_adjusted']:
    AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes,
                                    gii['generator_wants_sorted_dependencies'])

  # Apply "post"/"late"/"target" variable expansions and condition evaluations.
  for target in flat_list:
    target_dict = targets[target]
    build_file = gyp.common.BuildFile(target)
    ProcessVariablesAndConditionsInDict(
        target_dict, PHASE_LATE, variables, build_file)

  # Move everything that can go into a "configurations" section into one.
  for target in flat_list:
    target_dict = targets[target]
    SetUpConfigurations(target, target_dict)

  # Apply exclude (!) and regex (/) list filters.
  for target in flat_list:
    target_dict = targets[target]
    ProcessListFiltersInDict(target, target_dict)

  # Apply "latelate" variable expansions and condition evaluations.
  for target in flat_list:
    target_dict = targets[target]
    build_file = gyp.common.BuildFile(target)
    ProcessVariablesAndConditionsInDict(
        target_dict, PHASE_LATELATE, variables, build_file)

  # Make sure that the rules make sense, and build up rule_sources lists as
  # needed.  Not all generators will need to use the rule_sources lists, but
  # some may, and it seems best to build the list in a common spot.
  # Also validate actions and run_as elements in targets.
  for target in flat_list:
    target_dict = targets[target]
    build_file = gyp.common.BuildFile(target)
    ValidateTargetType(target, target_dict)
    # TODO(thakis): Get vpx_scale/arm/scalesystemdependent.c to be renamed to
    #               scalesystemdependent_arm_additions.c or similar.
    if 'arm' not in variables.get('target_arch', ''):
      ValidateSourcesInTarget(target, target_dict, build_file)
    ValidateRulesInTarget(target, target_dict, extra_sources_for_rules)
    ValidateRunAsInTarget(target, target_dict, build_file)
    ValidateActionsInTarget(target, target_dict, build_file)

  # Generators might not expect ints.  Turn them into strs.
  TurnIntIntoStrInDict(data)

  # TODO(mark): Return |data| for now because the generator needs a list of
  # build files that came in.  In the future, maybe it should just accept
  # a list, and not the whole data dict.
  return [flat_list, targets, data]
